summaryrefslogtreecommitdiff
path: root/src/libfreeswan
diff options
context:
space:
mode:
Diffstat (limited to 'src/libfreeswan')
-rw-r--r--src/libfreeswan/Makefile.am19
-rw-r--r--src/libfreeswan/Makefile.in574
-rw-r--r--src/libfreeswan/addrtoa.c68
-rw-r--r--src/libfreeswan/addrtot.c302
-rw-r--r--src/libfreeswan/addrtypeof.c94
-rw-r--r--src/libfreeswan/anyaddr.387
-rw-r--r--src/libfreeswan/anyaddr.c146
-rw-r--r--src/libfreeswan/atoaddr.3294
-rw-r--r--src/libfreeswan/atoaddr.c238
-rw-r--r--src/libfreeswan/atoasr.3186
-rw-r--r--src/libfreeswan/atoasr.c212
-rw-r--r--src/libfreeswan/atosa.3218
-rw-r--r--src/libfreeswan/atosa.c200
-rw-r--r--src/libfreeswan/atosubnet.c216
-rw-r--r--src/libfreeswan/atoul.3161
-rw-r--r--src/libfreeswan/atoul.c90
-rw-r--r--src/libfreeswan/copyright.c56
-rw-r--r--src/libfreeswan/datatot.c233
-rw-r--r--src/libfreeswan/freeswan.h470
-rw-r--r--src/libfreeswan/goodmask.357
-rw-r--r--src/libfreeswan/goodmask.c97
-rw-r--r--src/libfreeswan/initaddr.3129
-rw-r--r--src/libfreeswan/initaddr.c51
-rw-r--r--src/libfreeswan/initsaid.c33
-rw-r--r--src/libfreeswan/initsubnet.3137
-rw-r--r--src/libfreeswan/initsubnet.c95
-rw-r--r--src/libfreeswan/internal.h81
-rw-r--r--src/libfreeswan/ipcomp.h61
-rw-r--r--src/libfreeswan/ipsec_ah.h235
-rw-r--r--src/libfreeswan/ipsec_alg.h254
-rw-r--r--src/libfreeswan/ipsec_encap.h143
-rw-r--r--src/libfreeswan/ipsec_eroute.h103
-rw-r--r--src/libfreeswan/ipsec_errs.h53
-rw-r--r--src/libfreeswan/ipsec_esp.h220
-rw-r--r--src/libfreeswan/ipsec_ipe4.h68
-rw-r--r--src/libfreeswan/ipsec_kversion.h227
-rw-r--r--src/libfreeswan/ipsec_life.h112
-rw-r--r--src/libfreeswan/ipsec_md5h.h140
-rw-r--r--src/libfreeswan/ipsec_param.h226
-rw-r--r--src/libfreeswan/ipsec_policy.h225
-rw-r--r--src/libfreeswan/ipsec_proto.h111
-rw-r--r--src/libfreeswan/ipsec_radij.h63
-rw-r--r--src/libfreeswan/ipsec_rcv.h196
-rw-r--r--src/libfreeswan/ipsec_sa.h338
-rw-r--r--src/libfreeswan/ipsec_sha1.h79
-rw-r--r--src/libfreeswan/ipsec_stats.h38
-rw-r--r--src/libfreeswan/ipsec_tunnel.h265
-rw-r--r--src/libfreeswan/ipsec_xform.h274
-rw-r--r--src/libfreeswan/ipsec_xmit.h140
-rw-r--r--src/libfreeswan/keyblobtoid.3103
-rw-r--r--src/libfreeswan/keyblobtoid.c148
-rw-r--r--src/libfreeswan/optionsfrom.3182
-rw-r--r--src/libfreeswan/optionsfrom.c301
-rw-r--r--src/libfreeswan/pfkey.h498
-rw-r--r--src/libfreeswan/pfkey_v2_build.c1435
-rw-r--r--src/libfreeswan/pfkey_v2_debug.c177
-rw-r--r--src/libfreeswan/pfkey_v2_ext_bits.c789
-rw-r--r--src/libfreeswan/pfkey_v2_parse.c1824
-rw-r--r--src/libfreeswan/pfkeyv2.h375
-rw-r--r--src/libfreeswan/portof.370
-rw-r--r--src/libfreeswan/portof.c96
-rw-r--r--src/libfreeswan/prng.3121
-rw-r--r--src/libfreeswan/prng.c202
-rw-r--r--src/libfreeswan/radij.h280
-rw-r--r--src/libfreeswan/rangetoa.c61
-rw-r--r--src/libfreeswan/rangetosubnet.359
-rw-r--r--src/libfreeswan/rangetosubnet.c226
-rw-r--r--src/libfreeswan/sameaddr.3165
-rw-r--r--src/libfreeswan/sameaddr.c190
-rw-r--r--src/libfreeswan/satoa.c102
-rw-r--r--src/libfreeswan/satot.c132
-rw-r--r--src/libfreeswan/subnetof.347
-rw-r--r--src/libfreeswan/subnetof.c60
-rw-r--r--src/libfreeswan/subnettoa.c62
-rw-r--r--src/libfreeswan/subnettot.c56
-rw-r--r--src/libfreeswan/subnettypeof.c109
-rw-r--r--src/libfreeswan/ttoaddr.3377
-rw-r--r--src/libfreeswan/ttoaddr.c426
-rw-r--r--src/libfreeswan/ttodata.3281
-rw-r--r--src/libfreeswan/ttodata.c722
-rw-r--r--src/libfreeswan/ttoprotoport.c103
-rw-r--r--src/libfreeswan/ttosa.3288
-rw-r--r--src/libfreeswan/ttosa.c280
-rw-r--r--src/libfreeswan/ttosubnet.c296
-rw-r--r--src/libfreeswan/ttoul.3192
-rw-r--r--src/libfreeswan/ttoul.c91
-rw-r--r--src/libfreeswan/ultoa.c67
-rw-r--r--src/libfreeswan/ultot.c83
-rw-r--r--src/libfreeswan/version.344
-rw-r--r--src/libfreeswan/version.c43
90 files changed, 19278 insertions, 0 deletions
diff --git a/src/libfreeswan/Makefile.am b/src/libfreeswan/Makefile.am
new file mode 100644
index 000000000..d916fca17
--- /dev/null
+++ b/src/libfreeswan/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LIBRARIES = libfreeswan.a
+libfreeswan_a_SOURCES = addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
+ atosa.c atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
+ goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipcomp.h \
+ ipsec_ah.h ipsec_alg.h ipsec_encap.h ipsec_eroute.h ipsec_errs.h \
+ ipsec_esp.h ipsec_ipe4.h ipsec_kversion.h ipsec_life.h ipsec_md5h.h \
+ ipsec_param.h ipsec_policy.h ipsec_proto.h ipsec_radij.h ipsec_rcv.h \
+ ipsec_sa.h ipsec_sha1.h ipsec_stats.h ipsec_tunnel.h ipsec_xform.h \
+ ipsec_xmit.h keyblobtoid.c optionsfrom.c pfkey_v2_build.c pfkey_v2_debug.c \
+ pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c prng.c radij.h rangetoa.c \
+ pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c satoa.c \
+ satot.c subnetof.c subnettoa.c subnettot.c \
+ subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
+ ultoa.c ultot.c version.c
+INCLUDES = -I$(top_srcdir)/src/pluto
+dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atosa.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
+ keyblobtoid.3 optionsfrom.3 portof.3 prng.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
+ ttoaddr.3 ttodata.3 ttosa.3 ttoul.3 version.3
+
diff --git a/src/libfreeswan/Makefile.in b/src/libfreeswan/Makefile.in
new file mode 100644
index 000000000..97b53d7c0
--- /dev/null
+++ b/src/libfreeswan/Makefile.in
@@ -0,0 +1,574 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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/libfreeswan
+DIST_COMMON = $(dist_man3_MANS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libfreeswan_a_AR = $(AR) $(ARFLAGS)
+libfreeswan_a_LIBADD =
+am_libfreeswan_a_OBJECTS = addrtoa.$(OBJEXT) addrtot.$(OBJEXT) \
+ addrtypeof.$(OBJEXT) anyaddr.$(OBJEXT) atoaddr.$(OBJEXT) \
+ atoasr.$(OBJEXT) atosa.$(OBJEXT) atosubnet.$(OBJEXT) \
+ atoul.$(OBJEXT) copyright.$(OBJEXT) datatot.$(OBJEXT) \
+ goodmask.$(OBJEXT) initaddr.$(OBJEXT) initsaid.$(OBJEXT) \
+ initsubnet.$(OBJEXT) keyblobtoid.$(OBJEXT) \
+ optionsfrom.$(OBJEXT) pfkey_v2_build.$(OBJEXT) \
+ pfkey_v2_debug.$(OBJEXT) pfkey_v2_ext_bits.$(OBJEXT) \
+ pfkey_v2_parse.$(OBJEXT) portof.$(OBJEXT) prng.$(OBJEXT) \
+ rangetoa.$(OBJEXT) rangetosubnet.$(OBJEXT) sameaddr.$(OBJEXT) \
+ satoa.$(OBJEXT) satot.$(OBJEXT) subnetof.$(OBJEXT) \
+ subnettoa.$(OBJEXT) subnettot.$(OBJEXT) subnettypeof.$(OBJEXT) \
+ ttoaddr.$(OBJEXT) ttodata.$(OBJEXT) ttoprotoport.$(OBJEXT) \
+ ttosa.$(OBJEXT) ttosubnet.$(OBJEXT) ttoul.$(OBJEXT) \
+ ultoa.$(OBJEXT) ultot.$(OBJEXT) version.$(OBJEXT)
+libfreeswan_a_OBJECTS = $(am_libfreeswan_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+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 --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libfreeswan_a_SOURCES)
+DIST_SOURCES = $(libfreeswan_a_SOURCES)
+man3dir = $(mandir)/man3
+am__installdirs = "$(DESTDIR)$(man3dir)"
+NROFF = nroff
+MANS = $(dist_man3_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EAP_SIM_FALSE = @BUILD_EAP_SIM_FALSE@
+BUILD_EAP_SIM_TRUE = @BUILD_EAP_SIM_TRUE@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+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@
+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@
+PERL = @PERL@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_CISCO_QUIRKS_FALSE = @USE_CISCO_QUIRKS_FALSE@
+USE_CISCO_QUIRKS_TRUE = @USE_CISCO_QUIRKS_TRUE@
+USE_LEAK_DETECTIVE_FALSE = @USE_LEAK_DETECTIVE_FALSE@
+USE_LEAK_DETECTIVE_TRUE = @USE_LEAK_DETECTIVE_TRUE@
+USE_LIBCURL_FALSE = @USE_LIBCURL_FALSE@
+USE_LIBCURL_TRUE = @USE_LIBCURL_TRUE@
+USE_LIBLDAP_FALSE = @USE_LIBLDAP_FALSE@
+USE_LIBLDAP_TRUE = @USE_LIBLDAP_TRUE@
+USE_NAT_TRANSPORT_FALSE = @USE_NAT_TRANSPORT_FALSE@
+USE_NAT_TRANSPORT_TRUE = @USE_NAT_TRANSPORT_TRUE@
+USE_SMARTCARD_FALSE = @USE_SMARTCARD_FALSE@
+USE_SMARTCARD_TRUE = @USE_SMARTCARD_TRUE@
+USE_VENDORID_FALSE = @USE_VENDORID_FALSE@
+USE_VENDORID_TRUE = @USE_VENDORID_TRUE@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+eapdir = @eapdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+noinst_LIBRARIES = libfreeswan.a
+libfreeswan_a_SOURCES = addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
+ atosa.c atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
+ goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipcomp.h \
+ ipsec_ah.h ipsec_alg.h ipsec_encap.h ipsec_eroute.h ipsec_errs.h \
+ ipsec_esp.h ipsec_ipe4.h ipsec_kversion.h ipsec_life.h ipsec_md5h.h \
+ ipsec_param.h ipsec_policy.h ipsec_proto.h ipsec_radij.h ipsec_rcv.h \
+ ipsec_sa.h ipsec_sha1.h ipsec_stats.h ipsec_tunnel.h ipsec_xform.h \
+ ipsec_xmit.h keyblobtoid.c optionsfrom.c pfkey_v2_build.c pfkey_v2_debug.c \
+ pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c prng.c radij.h rangetoa.c \
+ pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c satoa.c \
+ satot.c subnetof.c subnettoa.c subnettot.c \
+ subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
+ ultoa.c ultot.c version.c
+
+INCLUDES = -I$(top_srcdir)/src/pluto
+dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atosa.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
+ keyblobtoid.3 optionsfrom.3 portof.3 prng.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
+ ttoaddr.3 ttodata.3 ttosa.3 ttoul.3 version.3
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(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) --gnu src/libfreeswan/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libfreeswan/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
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libfreeswan.a: $(libfreeswan_a_OBJECTS) $(libfreeswan_a_DEPENDENCIES)
+ -rm -f libfreeswan.a
+ $(libfreeswan_a_AR) libfreeswan.a $(libfreeswan_a_OBJECTS) $(libfreeswan_a_LIBADD)
+ $(RANLIB) libfreeswan.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtypeof.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/anyaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoasr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atosa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atosubnet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoul.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copyright.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/goodmask.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsaid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsubnet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyblobtoid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optionsfrom.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_build.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_ext_bits.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/portof.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prng.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetosubnet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sameaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/satoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/satot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnetof.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettypeof.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttodata.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoprotoport.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttosa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttosubnet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoul.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ultoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ultot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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 $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+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
+
+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; } \
+ END { 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; } \
+ END { 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=; \
+ 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; } \
+ END { 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)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ 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 $(LIBRARIES) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(man3dir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+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)
+
+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 clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man: install-man3
+
+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-info-am uninstall-man
+
+uninstall-man: uninstall-man3
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES 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-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-man3 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-info-am 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/libfreeswan/addrtoa.c b/src/libfreeswan/addrtoa.c
new file mode 100644
index 000000000..b1cc038ed
--- /dev/null
+++ b/src/libfreeswan/addrtoa.c
@@ -0,0 +1,68 @@
+/*
+ * addresses to ASCII
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: addrtoa.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#define NBYTES 4 /* bytes in an address */
+#define PERBYTE 4 /* three digits plus a dot or NUL */
+#define BUFLEN (NBYTES*PERBYTE)
+
+#if BUFLEN != ADDRTOA_BUF
+#error "ADDRTOA_BUF in freeswan.h inconsistent with addrtoa() code"
+#endif
+
+/*
+ - addrtoa - convert binary address to ASCII dotted decimal
+ */
+size_t /* space needed for full conversion */
+addrtoa(addr, format, dst, dstlen)
+struct in_addr addr;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ unsigned long a = ntohl(addr.s_addr);
+ int i;
+ size_t n;
+ unsigned long byte;
+ char buf[BUFLEN];
+ char *p;
+
+ switch (format) {
+ case 0:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ p = buf;
+ for (i = NBYTES-1; i >= 0; i--) {
+ byte = (a >> (i*8)) & 0xff;
+ p += ultoa(byte, 10, p, PERBYTE);
+ if (i != 0)
+ *(p-1) = '.';
+ }
+ n = p - buf;
+
+ if (dstlen > 0) {
+ if (n > dstlen)
+ buf[dstlen - 1] = '\0';
+ strcpy(dst, buf);
+ }
+ return n;
+}
diff --git a/src/libfreeswan/addrtot.c b/src/libfreeswan/addrtot.c
new file mode 100644
index 000000000..f229789f0
--- /dev/null
+++ b/src/libfreeswan/addrtot.c
@@ -0,0 +1,302 @@
+/*
+ * addresses to text
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: addrtot.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#define IP4BYTES 4 /* bytes in an IPv4 address */
+#define PERBYTE 4 /* three digits plus a dot or NUL */
+#define IP6BYTES 16 /* bytes in an IPv6 address */
+
+/* forwards */
+static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
+static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
+
+/*
+ - addrtot - convert binary address to text (dotted decimal or IPv6 string)
+ */
+size_t /* space needed for full conversion */
+addrtot(src, format, dst, dstlen)
+const ip_address *src;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ const unsigned char *b;
+ size_t n;
+ char buf[1+ADDRTOT_BUF+1]; /* :address: */
+ char *p;
+ int t = addrtypeof(src);
+# define TF(t, f) (((t)<<8) | (f))
+
+ n = addrbytesptr(src, &b);
+ if (n == 0)
+ return 0;
+
+ switch (TF(t, format)) {
+ case TF(AF_INET, 0):
+ n = normal4(b, n, buf, &p);
+ break;
+ case TF(AF_INET6, 0):
+ n = normal6(b, n, buf, &p, 1);
+ break;
+ case TF(AF_INET, 'Q'):
+ n = normal4(b, n, buf, &p);
+ break;
+ case TF(AF_INET6, 'Q'):
+ n = normal6(b, n, buf, &p, 0);
+ break;
+ case TF(AF_INET, 'r'):
+ n = reverse4(b, n, buf, &p);
+ break;
+ case TF(AF_INET6, 'r'):
+ n = reverse6(b, n, buf, &p);
+ break;
+ default: /* including (AF_INET, 'R') */
+ return 0;
+ break;
+ }
+
+ if (dstlen > 0) {
+ if (dstlen < n)
+ p[dstlen - 1] = '\0';
+ strcpy(dst, p);
+ }
+ return n;
+}
+
+/*
+ - normal4 - normal IPv4 address-text conversion
+ */
+static size_t /* size of text, including NUL */
+normal4(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf; /* guaranteed large enough */
+char **dstp; /* where to put result pointer */
+{
+ int i;
+ char *p;
+
+ if (srclen != IP4BYTES) /* "can't happen" */
+ return 0;
+ p = buf;
+ for (i = 0; i < IP4BYTES; i++) {
+ p += ultot(srcp[i], 10, p, PERBYTE);
+ if (i != IP4BYTES - 1)
+ *(p-1) = '.'; /* overwrites the NUL */
+ }
+ *dstp = buf;
+ return p - buf;
+}
+
+/*
+ - normal6 - normal IPv6 address-text conversion
+ */
+static size_t /* size of text, including NUL */
+normal6(srcp, srclen, buf, dstp, squish)
+const unsigned char *srcp;
+size_t srclen;
+char *buf; /* guaranteed large enough, plus 2 */
+char **dstp; /* where to put result pointer */
+int squish; /* whether to squish out 0:0 */
+{
+ int i;
+ unsigned long piece;
+ char *p;
+ char *q;
+
+ if (srclen != IP6BYTES) /* "can't happen" */
+ return 0;
+ p = buf;
+ *p++ = ':';
+ for (i = 0; i < IP6BYTES/2; i++) {
+ piece = (srcp[2*i] << 8) + srcp[2*i + 1];
+ p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */
+ *(p-1) = ':'; /* overwrites the NUL */
+ }
+ *p = '\0';
+ q = strstr(buf, ":0:0:");
+ if (squish && q != NULL) { /* zero squishing is possible */
+ p = q + 1;
+ while (*p == '0' && *(p+1) == ':')
+ p += 2;
+ q++;
+ *q++ = ':'; /* overwrite first 0 */
+ while (*p != '\0')
+ *q++ = *p++;
+ *q = '\0';
+ if (!(*(q-1) == ':' && *(q-2) == ':'))
+ *--q = '\0'; /* strip final : unless :: */
+ p = buf;
+ if (!(*p == ':' && *(p+1) == ':'))
+ p++; /* skip initial : unless :: */
+ } else {
+ q = p;
+ *--q = '\0'; /* strip final : */
+ p = buf + 1; /* skip initial : */
+ }
+ *dstp = p;
+ return q - p + 1;
+}
+
+/*
+ - reverse4 - IPv4 reverse-lookup conversion
+ */
+static size_t /* size of text, including NUL */
+reverse4(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf; /* guaranteed large enough */
+char **dstp; /* where to put result pointer */
+{
+ int i;
+ char *p;
+
+ if (srclen != IP4BYTES) /* "can't happen" */
+ return 0;
+ p = buf;
+ for (i = IP4BYTES-1; i >= 0; i--) {
+ p += ultot(srcp[i], 10, p, PERBYTE);
+ *(p-1) = '.'; /* overwrites the NUL */
+ }
+ strcpy(p, "IN-ADDR.ARPA.");
+ *dstp = buf;
+ return strlen(buf) + 1;
+}
+
+/*
+ - reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
+ * A trifle inefficient, really shouldn't use ultot...
+ */
+static size_t /* size of text, including NUL */
+reverse6(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf; /* guaranteed large enough */
+char **dstp; /* where to put result pointer */
+{
+ int i;
+ unsigned long piece;
+ char *p;
+
+ if (srclen != IP6BYTES) /* "can't happen" */
+ return 0;
+ p = buf;
+ for (i = IP6BYTES-1; i >= 0; i--) {
+ piece = srcp[i];
+ p += ultot(piece&0xf, 16, p, 2);
+ *(p-1) = '.';
+ p += ultot(piece>>4, 16, p, 2);
+ *(p-1) = '.';
+ }
+ strcpy(p, "IP6.ARPA.");
+ *dstp = buf;
+ return strlen(buf) + 1;
+}
+
+/*
+ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
+ * this version removed as it was obsoleted in the end.
+ */
+
+#ifdef ADDRTOT_MAIN
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
+ argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+ exit(0);
+}
+
+struct rtab {
+ char *input;
+ char format;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {"1.2.3.0", 0, "1.2.3.0"},
+ {"1:2::3:4", 0, "1:2::3:4"},
+ {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"},
+ {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"},
+ {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."},
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
+ {NULL, 0, NULL}
+};
+
+void
+regress()
+{
+ struct rtab *r;
+ int status = 0;
+ ip_address a;
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ for (r = rtab; r->input != NULL; r++) {
+ strcpy(in, r->input);
+
+ /* convert it *to* internal format */
+ oops = ttoaddr(in, strlen(in), 0, &a);
+
+ /* now convert it back */
+
+ n = addrtot(&a, r->format, buf, sizeof(buf));
+
+ if (n == 0 && r->output == NULL)
+ {} /* okay, error expected */
+
+ else if (n == 0) {
+ printf("`%s' atoasr failed\n", r->input);
+ status = 1;
+
+ } else if (r->output == NULL) {
+ printf("`%s' atoasr succeeded unexpectedly '%c'\n",
+ r->input, r->format);
+ status = 1;
+ } else {
+ if (strcasecmp(r->output, buf) != 0) {
+ printf("`%s' '%c' gave `%s', expected `%s'\n",
+ r->input, r->format, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* ADDRTOT_MAIN */
diff --git a/src/libfreeswan/addrtypeof.c b/src/libfreeswan/addrtypeof.c
new file mode 100644
index 000000000..e63509911
--- /dev/null
+++ b/src/libfreeswan/addrtypeof.c
@@ -0,0 +1,94 @@
+/*
+ * extract parts of an ip_address
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: addrtypeof.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - addrtypeof - get the type of an ip_address
+ */
+int
+addrtypeof(src)
+const ip_address *src;
+{
+ return src->u.v4.sin_family;
+}
+
+/*
+ - addrbytesptr - get pointer to the address bytes of an ip_address
+ */
+size_t /* 0 for error */
+addrbytesptr(src, dstp)
+const ip_address *src;
+const unsigned char **dstp; /* NULL means just a size query */
+{
+ const unsigned char *p;
+ size_t n;
+
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
+ n = 4;
+ break;
+ case AF_INET6:
+ p = (const unsigned char *)&src->u.v6.sin6_addr;
+ n = 16;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ if (dstp != NULL)
+ *dstp = p;
+ return n;
+}
+
+/*
+ - addrlenof - get length of the address bytes of an ip_address
+ */
+size_t /* 0 for error */
+addrlenof(src)
+const ip_address *src;
+{
+ return addrbytesptr(src, NULL);
+}
+
+/*
+ - addrbytesof - get the address bytes of an ip_address
+ */
+size_t /* 0 for error */
+addrbytesof(src, dst, dstlen)
+const ip_address *src;
+unsigned char *dst;
+size_t dstlen;
+{
+ const unsigned char *p;
+ size_t n;
+ size_t ncopy;
+
+ n = addrbytesptr(src, &p);
+ if (n == 0)
+ return 0;
+
+ if (dstlen > 0) {
+ ncopy = n;
+ if (ncopy > dstlen)
+ ncopy = dstlen;
+ memcpy(dst, p, ncopy);
+ }
+ return n;
+}
diff --git a/src/libfreeswan/anyaddr.3 b/src/libfreeswan/anyaddr.3
new file mode 100644
index 000000000..4594a9ff9
--- /dev/null
+++ b/src/libfreeswan/anyaddr.3
@@ -0,0 +1,87 @@
+.TH IPSEC_ANYADDR 3 "8 Sept 2000"
+.\" RCSID $Id: anyaddr.3,v 1.1 2004/03/15 20:35:25 as Exp $
+.SH NAME
+ipsec anyaddr \- get "any" address
+.br
+ipsec isanyaddr \- test address for equality to "any" address
+.br
+ipsec unspecaddr \- get "unspecified" address
+.br
+ipsec isunspecaddr \- test address for equality to "unspecified" address
+.br
+ipsec loopbackaddr \- get loopback address
+.br
+ipsec isloopbackaddr \- test address for equality to loopback address
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *anyaddr(int af, ip_address *dst);"
+.br
+.B "int isanyaddr(const ip_address *src);"
+.br
+.B "const char *unspecaddr(int af, ip_address *dst);"
+.br
+.B "int isunspecaddr(const ip_address *src);"
+.br
+.B "const char *loopbackaddr(int af, ip_address *dst);"
+.br
+.B "int isloopbackaddr(const ip_address *src);"
+.SH DESCRIPTION
+These functions fill in, and test for, special values of the
+.I ip_address
+type.
+.PP
+.I Anyaddr
+fills in the destination
+.I *dst
+with the ``any'' address of address family
+.IR af
+(normally
+.B AF_INET
+or
+.BR AF_INET6 ).
+The IPv4 ``any'' address is the one embodied in the old
+.B INADDR_ANY
+macro.
+.PP
+.I Isanyaddr
+returns
+.B 1
+if the
+.I src
+address equals the ``any'' address,
+and
+.B 0
+otherwise.
+.PP
+Similarly,
+.I unspecaddr
+supplies, and
+.I isunspecaddr
+tests for,
+the ``unspecified'' address,
+which may be the same as the ``any'' address.
+.PP
+Similarly,
+.I loopbackaddr
+supplies, and
+.I islookbackaddr
+tests for,
+the loopback address.
+.PP
+.IR Anyaddr ,
+.IR unspecaddr ,
+and
+.I loopbackaddr
+return
+.B NULL
+for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.SH SEE ALSO
+inet(3), ipsec_addrtot(3), ipsec_sameaddr(3)
+.SH DIAGNOSTICS
+Fatal errors in the address-supplying functions are:
+unknown address family.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/anyaddr.c b/src/libfreeswan/anyaddr.c
new file mode 100644
index 000000000..08aae6334
--- /dev/null
+++ b/src/libfreeswan/anyaddr.c
@@ -0,0 +1,146 @@
+/*
+ * special addresses
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: anyaddr.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/* these are mostly fallbacks for the no-IPv6-support-in-library case */
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
+#endif
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
+#endif
+
+static struct in6_addr v6any = IN6ADDR_ANY_INIT;
+static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
+
+/*
+ - anyaddr - initialize to the any-address value
+ */
+err_t /* NULL for success, else string literal */
+anyaddr(af, dst)
+int af; /* address family */
+ip_address *dst;
+{
+ uint32_t v4any = htonl(INADDR_ANY);
+
+ switch (af) {
+ case AF_INET:
+ return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
+ break;
+ case AF_INET6:
+ return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
+ break;
+ default:
+ return "unknown address family in anyaddr/unspecaddr";
+ break;
+ }
+}
+
+/*
+ - unspecaddr - initialize to the unspecified-address value
+ */
+err_t /* NULL for success, else string literal */
+unspecaddr(af, dst)
+int af; /* address family */
+ip_address *dst;
+{
+ return anyaddr(af, dst);
+}
+
+/*
+ - loopbackaddr - initialize to the loopback-address value
+ */
+err_t /* NULL for success, else string literal */
+loopbackaddr(af, dst)
+int af; /* address family */
+ip_address *dst;
+{
+ uint32_t v4loop = htonl(INADDR_LOOPBACK);
+
+ switch (af) {
+ case AF_INET:
+ return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
+ break;
+ case AF_INET6:
+ return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
+ break;
+ default:
+ return "unknown address family in loopbackaddr";
+ break;
+ }
+}
+
+/*
+ - isanyaddr - test for the any-address value
+ */
+int
+isanyaddr(src)
+const ip_address *src;
+{
+ uint32_t v4any = htonl(INADDR_ANY);
+ int cmp;
+
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
+ break;
+ case AF_INET6:
+ cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return (cmp == 0) ? 1 : 0;
+}
+
+/*
+ - isunspecaddr - test for the unspecified-address value
+ */
+int
+isunspecaddr(src)
+const ip_address *src;
+{
+ return isanyaddr(src);
+}
+
+/*
+ - isloopbackaddr - test for the loopback-address value
+ */
+int
+isloopbackaddr(src)
+const ip_address *src;
+{
+ uint32_t v4loop = htonl(INADDR_LOOPBACK);
+ int cmp;
+
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
+ break;
+ case AF_INET6:
+ cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return (cmp == 0) ? 1 : 0;
+}
diff --git a/src/libfreeswan/atoaddr.3 b/src/libfreeswan/atoaddr.3
new file mode 100644
index 000000000..a7dc8dca3
--- /dev/null
+++ b/src/libfreeswan/atoaddr.3
@@ -0,0 +1,294 @@
+.TH IPSEC_ATOADDR 3 "11 June 2001"
+.\" RCSID $Id: atoaddr.3,v 1.1 2004/03/15 20:35:25 as Exp $
+.SH NAME
+ipsec atoaddr, addrtoa \- convert Internet addresses to and from ASCII
+.br
+ipsec atosubnet, subnettoa \- convert subnet/mask ASCII form to and from addresses
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *atoaddr(const char *src, size_t srclen,"
+.ti +1c
+.B "struct in_addr *addr);"
+.br
+.B "size_t addrtoa(struct in_addr addr, int format,"
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.sp
+.B "const char *atosubnet(const char *src, size_t srclen,"
+.ti +1c
+.B "struct in_addr *addr, struct in_addr *mask);"
+.br
+.B "size_t subnettoa(struct in_addr addr, struct in_addr mask,"
+.ti +1c
+.B "int format, char *dst, size_t dstlen);"
+.SH DESCRIPTION
+These functions are obsolete; see
+.IR ipsec_ttoaddr (3)
+for their replacements.
+.PP
+.I Atoaddr
+converts an ASCII name or dotted-decimal address into a binary address
+(in network byte order).
+.I Addrtoa
+does the reverse conversion, back to an ASCII dotted-decimal address.
+.I Atosubnet
+and
+.I subnettoa
+do likewise for the ``address/mask'' ASCII form used to write a
+specification of a subnet.
+.PP
+An address is specified in ASCII as a
+dotted-decimal address (e.g.
+.BR 1.2.3.4 ),
+an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
+.BR 0x01020304 ,
+which is synonymous with
+.BR 1.2.3.4 ),
+an eight-digit host-order hexadecimal number with a
+.B 0h
+prefix (e.g.
+.BR 0h01020304 ,
+which is synonymous with
+.B 1.2.3.4
+on a big-endian host and
+.B 4.3.2.1
+on a little-endian host),
+a DNS name to be looked up via
+.IR gethostbyname (3),
+or an old-style network name to be looked up via
+.IR getnetbyname (3).
+.PP
+A dotted-decimal address may be incomplete, in which case
+ASCII-to-binary conversion implicitly appends
+as many instances of
+.B .0
+as necessary to bring it up to four components.
+The components of a dotted-decimal address are always taken as
+decimal, and leading zeros are ignored.
+For example,
+.B 10
+is synonymous with
+.BR 10.0.0.0 ,
+and
+.B 128.009.000.032
+is synonymous with
+.BR 128.9.0.32
+(the latter example is verbatim from RFC 1166).
+The result of
+.I addrtoa
+is always complete and does not contain leading zeros.
+.PP
+The letters in
+a hexadecimal address may be uppercase or lowercase or any mixture thereof.
+Use of hexadecimal addresses is
+.B strongly
+.BR discouraged ;
+they are included only to save hassles when dealing with
+the handful of perverted programs which already print
+network addresses in hexadecimal.
+.PP
+DNS names may be complete (optionally terminated with a ``.'')
+or incomplete, and are looked up as specified by local system configuration
+(see
+.IR resolver (5)).
+The
+.I h_addr
+value returned by
+.IR gethostbyname (3)
+is used,
+so with current DNS implementations,
+the result when the name corresponds to more than one address is
+difficult to predict.
+Name lookup resorts to
+.IR getnetbyname (3)
+only if
+.IR gethostbyname (3)
+fails.
+.PP
+A subnet specification is of the form \fInetwork\fB/\fImask\fR.
+The
+.I network
+and
+.I mask
+can be any form acceptable to
+.IR atoaddr .
+In addition, the
+.I mask
+can be a decimal integer (leading zeros ignored) giving a bit count,
+in which case
+it stands for a mask with that number of high bits on and all others off
+(e.g.,
+.B 24
+means
+.BR 255.255.255.0 ).
+In any case, the mask must be contiguous
+(a sequence of high bits on and all remaining low bits off).
+As a special case, the subnet specification
+.B %default
+is a synonym for
+.BR 0.0.0.0/0 .
+.PP
+.I Atosubnet
+ANDs the mask with the address before returning,
+so that any non-network bits in the address are turned off
+(e.g.,
+.B 10.1.2.3/24
+is synonymous with
+.BR 10.1.2.0/24 ).
+.I Subnettoa
+generates the decimal-integer-bit-count
+form of the mask,
+with no leading zeros,
+unless the mask is non-contiguous.
+.PP
+The
+.I srclen
+parameter of
+.I atoaddr
+and
+.I atosubnet
+specifies the length of the ASCII string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I dstlen
+parameter of
+.I addrtoa
+and
+.I subnettoa
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines constants,
+.B ADDRTOA_BUF
+and
+.BR SUBNETTOA_BUF ,
+which are the sizes of buffers just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I addrtoa
+and
+.I subnettoa
+specifies what format is to be used for the conversion.
+The value
+.B 0
+(not the ASCII character
+.BR '0' ,
+but a zero value)
+specifies a reasonable default,
+and is in fact the only format currently available.
+This parameter is a hedge against future needs.
+.PP
+The ASCII-to-binary functions return NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+The binary-to-ASCII functions return
+.B 0
+for a failure, and otherwise
+always return the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.SH SEE ALSO
+inet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I atoaddr
+are:
+empty input;
+attempt to allocate temporary storage for a very long name failed;
+name lookup failed;
+syntax error in dotted-decimal form;
+dotted-decimal component too large to fit in 8 bits.
+.PP
+Fatal errors in
+.I atosubnet
+are:
+no
+.B /
+in
+.IR src ;
+.I atoaddr
+error in conversion of
+.I network
+or
+.IR mask ;
+bit-count mask too big;
+mask non-contiguous.
+.PP
+Fatal errors in
+.I addrtoa
+and
+.I subnettoa
+are:
+unknown format.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The interpretation of incomplete dotted-decimal addresses
+(e.g.
+.B 10/24
+means
+.BR 10.0.0.0/24 )
+differs from that of some older conversion
+functions, e.g. those of
+.IR inet (3).
+The behavior of the older functions has never been
+particularly consistent or particularly useful.
+.PP
+Ignoring leading zeros in dotted-decimal components and bit counts
+is arguably the most useful behavior in this application,
+but it might occasionally cause confusion with the historical use of leading
+zeros to denote octal numbers.
+.PP
+It is barely possible that somebody, somewhere,
+might have a legitimate use for non-contiguous subnet masks.
+.PP
+.IR Getnetbyname (3)
+is a historical dreg.
+.PP
+The restriction of ASCII-to-binary error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The ASCII-to-binary error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = atoaddr( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/atoaddr.c b/src/libfreeswan/atoaddr.c
new file mode 100644
index 000000000..0c787b10d
--- /dev/null
+++ b/src/libfreeswan/atoaddr.c
@@ -0,0 +1,238 @@
+/*
+ * conversion from ASCII forms of addresses to internal ones
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: atoaddr.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * Define NOLEADINGZEROS to interpret 032 as an error, not as 32. There
+ * is deliberately no way to interpret it as 26 (i.e., as octal).
+ */
+
+/*
+ * Legal characters in a domain name. Underscore technically is not,
+ * but is a common misunderstanding.
+ */
+static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
+
+static const char *try8hex(const char *, size_t, struct in_addr *);
+static const char *try8hosthex(const char *, size_t, struct in_addr *);
+static const char *trydotted(const char *, size_t, struct in_addr *);
+static const char *getbyte(const char **, const char *, int *);
+
+/*
+ - atoaddr - convert ASCII name or dotted-decimal address to binary address
+ */
+const char * /* NULL for success, else string literal */
+atoaddr(src, srclen, addrp)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+struct in_addr *addrp;
+{
+ struct hostent *h;
+ struct netent *ne = NULL;
+ const char *oops;
+# define HEXLEN 10 /* strlen("0x11223344") */
+# ifndef ATOADDRBUF
+# define ATOADDRBUF 100
+# endif
+ char namebuf[ATOADDRBUF];
+ char *p = namebuf;
+ char *q;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ /* might it be hex? */
+ if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'x'))
+ return try8hex(src+2, srclen-2, addrp);
+ if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'h'))
+ return try8hosthex(src+2, srclen-2, addrp);
+
+ /* try it as dotted decimal */
+ oops = trydotted(src, srclen, addrp);
+ if (oops == NULL)
+ return NULL; /* it worked */
+ if (*oops != '?')
+ return oops; /* it *was* probably meant as a d.q. */
+
+ /* try it as a name -- first, NUL-terminate it */
+ if (srclen > sizeof(namebuf)-1) {
+ p = (char *) MALLOC(srclen+1);
+ if (p == NULL)
+ return "unable to allocate temporary space for name";
+ }
+ p[0] = '\0';
+ strncat(p, src, srclen);
+
+ /* next, check that it's a vaguely legal name */
+ for (q = p; *q != '\0'; q++)
+ if (!isprint(*q))
+ return "unprintable character in name";
+ if (strspn(p, namechars) != srclen)
+ return "illegal (non-DNS-name) character in name";
+
+ /* try as host name, failing that as /etc/networks network name */
+ h = gethostbyname(p);
+ if (h == NULL)
+ ne = getnetbyname(p);
+ if (p != namebuf)
+ FREE(p);
+ if (h == NULL && ne == NULL)
+ return "name lookup failed";
+
+ if (h != NULL)
+ memcpy(&addrp->s_addr, h->h_addr, sizeof(addrp->s_addr));
+ else
+ addrp->s_addr = htonl(ne->n_net);
+ return NULL;
+}
+
+/*
+ - try8hosthex - try conversion as an eight-digit host-order hex number
+ */
+const char * /* NULL for success, else string literal */
+try8hosthex(src, srclen, addrp)
+const char *src;
+size_t srclen; /* should be 8 */
+struct in_addr *addrp;
+{
+ const char *oops;
+ unsigned long addr;
+
+ if (srclen != 8)
+ return "internal error, try8hex called with bad length";
+
+ oops = atoul(src, srclen, 16, &addr);
+ if (oops != NULL)
+ return oops;
+
+ addrp->s_addr = addr;
+ return NULL;
+}
+
+/*
+ - try8hex - try conversion as an eight-digit network-order hex number
+ */
+const char * /* NULL for success, else string literal */
+try8hex(src, srclen, addrp)
+const char *src;
+size_t srclen; /* should be 8 */
+struct in_addr *addrp;
+{
+ const char *oops;
+
+ oops = try8hosthex(src, srclen, addrp);
+ if (oops != NULL)
+ return oops;
+
+ addrp->s_addr = htonl(addrp->s_addr);
+ return NULL;
+}
+
+/*
+ - trydotted - try conversion as dotted decimal
+ *
+ * If the first char of a complaint is '?', that means "didn't look like
+ * dotted decimal at all".
+ */
+const char * /* NULL for success, else string literal */
+trydotted(src, srclen, addrp)
+const char *src;
+size_t srclen;
+struct in_addr *addrp;
+{
+ const char *stop = src + srclen; /* just past end */
+ int byte;
+ const char *oops;
+ unsigned long addr;
+ int i;
+# define NBYTES 4
+# define BYTE 8
+
+ addr = 0;
+ for (i = 0; i < NBYTES && src < stop; i++) {
+ oops = getbyte(&src, stop, &byte);
+ if (oops != NULL) {
+ if (*oops != '?')
+ return oops; /* bad number */
+ if (i > 1)
+ return oops+1; /* failed number */
+ return oops; /* with leading '?' */
+ }
+ addr = (addr << BYTE) | byte;
+ if (i < 3 && src < stop && *src++ != '.') {
+ if (i == 0)
+ return "?syntax error in dotted-decimal address";
+ else
+ return "syntax error in dotted-decimal address";
+ }
+ }
+ addr <<= (NBYTES - i) * BYTE;
+ if (src != stop)
+ return "extra garbage on end of dotted-decimal address";
+
+ addrp->s_addr = htonl(addr);
+ return NULL;
+}
+
+/*
+ - getbyte - try to scan a byte in dotted decimal
+ * A subtlety here is that all this arithmetic on ASCII digits really is
+ * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
+ * It's easier to just do it ourselves than set up for a call to atoul().
+ *
+ * If the first char of a complaint is '?', that means "didn't look like a
+ * number at all".
+ */
+const char * /* NULL for success, else string literal */
+getbyte(srcp, stop, retp)
+const char **srcp; /* *srcp is updated */
+const char *stop; /* first untouchable char */
+int *retp; /* return-value pointer */
+{
+ char c;
+ const char *p;
+ int no;
+
+ if (*srcp >= stop)
+ return "?empty number in dotted-decimal address";
+
+ if (stop - *srcp >= 3 && **srcp == '0' && CIEQ(*(*srcp+1), 'x'))
+ return "hex numbers not supported in dotted-decimal addresses";
+#ifdef NOLEADINGZEROS
+ if (stop - *srcp >= 2 && **srcp == '0' && isdigit(*(*srcp+1)))
+ return "octal numbers not supported in dotted-decimal addresses";
+#endif /* NOLEADINGZEROS */
+
+ /* must be decimal, if it's numeric at all */
+ no = 0;
+ p = *srcp;
+ while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
+ no = no*10 + (c - '0');
+ p++;
+ }
+ if (p == *srcp)
+ return "?non-numeric component in dotted-decimal address";
+ *srcp = p;
+ if (no > 255)
+ return "byte overflow in dotted-decimal address";
+ *retp = no;
+ return NULL;
+}
diff --git a/src/libfreeswan/atoasr.3 b/src/libfreeswan/atoasr.3
new file mode 100644
index 000000000..1bd805db1
--- /dev/null
+++ b/src/libfreeswan/atoasr.3
@@ -0,0 +1,186 @@
+.TH IPSEC_ATOASR 3 "11 June 2001"
+.\" RCSID $Id: atoasr.3,v 1.1 2004/03/15 20:35:25 as Exp $
+.SH NAME
+ipsec atoasr \- convert ASCII to Internet address, subnet, or range
+.br
+ipsec rangetoa \- convert Internet address range to ASCII
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *atoasr(const char *src, size_t srclen,"
+.ti +1c
+.B "char *type, struct in_addr *addrs);"
+.br
+.B "size_t rangetoa(struct in_addr *addrs, int format,
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.SH DESCRIPTION
+These functions are obsolete;
+there is no current equivalent,
+because so far they have not proved useful.
+.PP
+.I Atoasr
+converts an ASCII address, subnet, or address range
+into a suitable combination of binary addresses
+(in network byte order).
+.I Rangetoa
+converts an address range back into ASCII,
+using dotted-decimal form for the addresses
+(the other reverse conversions are handled by
+.IR ipsec_addrtoa (3)
+and
+.IR ipsec_subnettoa (3)).
+.PP
+A single address can be any form acceptable to
+.IR ipsec_atoaddr (3):
+dotted decimal, DNS name, or hexadecimal number.
+A subnet
+specification uses the form \fInetwork\fB/\fImask\fR
+interpreted by
+.IR ipsec_atosubnet (3).
+.PP
+An address range is two
+.IR ipsec_atoaddr (3)
+addresses separated by a
+.B ...
+delimiter.
+If there are four dots rather than three, the first is taken as
+part of the begin address,
+e.g. for a complete DNS name which ends with
+.B .
+to suppress completion attempts.
+The begin address of a range must be
+less than or equal to the end address.
+.PP
+The
+.I srclen
+parameter of
+.I atoasr
+specifies the length of the ASCII string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I type
+parameter of
+.I atoasr
+must point to a
+.B char
+variable used to record which form was found.
+The
+.I addrs
+parameter must point to a two-element array of
+.B "struct in_addr"
+which receives the results.
+The values stored into
+.BR *type ,
+and the corresponding values in the array, are:
+.PP
+.ta 3c +2c +3c
+ *type addrs[0] addrs[1]
+.sp 0.8
+address \&\fB'a'\fR address -
+.br
+subnet \&\fB's'\fR network mask
+.br
+range \&\fB'r'\fR begin end
+.PP
+The
+.I dstlen
+parameter of
+.I rangetoa
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines a constant,
+.BR RANGETOA_BUF ,
+which is the size of a buffer just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I rangetoa
+specifies what format is to be used for the conversion.
+The value
+.B 0
+(not the ASCII character
+.BR '0' ,
+but a zero value)
+specifies a reasonable default,
+and is in fact the only format currently available.
+This parameter is a hedge against future needs.
+.PP
+.I Atoasr
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.I Rangetoa
+returns
+.B 0
+for a failure, and otherwise
+always returns the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.SH SEE ALSO
+ipsec_atoaddr(3), ipsec_atosubnet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I atoasr
+are:
+empty input;
+error in
+.IR ipsec_atoaddr (3)
+or
+.IR ipsec_atosubnet (3)
+during conversion;
+begin address of range exceeds end address.
+.PP
+Fatal errors in
+.I rangetoa
+are:
+unknown format.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The restriction of error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = atoasr( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/atoasr.c b/src/libfreeswan/atoasr.c
new file mode 100644
index 000000000..a68409bfb
--- /dev/null
+++ b/src/libfreeswan/atoasr.c
@@ -0,0 +1,212 @@
+/*
+ * convert from ASCII form of address/subnet/range to binary
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: atoasr.c,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - atoasr - convert ASCII to address, subnet, or range
+ */
+const char * /* NULL for success, else string literal */
+atoasr(src, srclen, typep, addrsp)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+char *typep; /* return type code: 'a', 's', 'r' */
+struct in_addr addrsp[2];
+{
+ const char *punct;
+ const char *stop;
+ const char *oops;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ /* subnet is easy to spot */
+ punct = memchr(src, '/', srclen);
+ if (punct != NULL) {
+ *typep = 's';
+ return atosubnet(src, srclen, &addrsp[0], &addrsp[1]);
+ }
+
+ /* try for a range */
+ stop = src + srclen;
+ for (punct = src; (punct = memchr(punct, '.', stop - punct)) != NULL;
+ punct++)
+ if (stop - punct > 3 && *(punct+1) == '.' && *(punct+2) == '.')
+ break; /* NOTE BREAK OUT */
+ if (punct == NULL) {
+ /* didn't find the range delimiter, must be plain address */
+ *typep = 'a';
+ return atoaddr(src, srclen, &addrsp[0]);
+ }
+
+ /* looks like a range */
+ *typep = 'r';
+ if (stop - punct > 4 && *(punct+3) == '.')
+ punct++; /* first dot is trailing dot of name */
+ oops = atoaddr(src, punct - src, &addrsp[0]);
+ if (oops != NULL)
+ return oops;
+ oops = atoaddr(punct+3, stop - (punct+3), &addrsp[1]);
+ if (oops != NULL)
+ return oops;
+ if (ntohl(addrsp[0].s_addr) > ntohl(addrsp[1].s_addr))
+ return "invalid range, begin > end";
+ return NULL;
+}
+
+
+
+#ifdef ATOASR_MAIN
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct in_addr a[2];
+ char buf[100];
+ const char *oops;
+ size_t n;
+ char type;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
+ argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ oops = atoasr(argv[1], 0, &type, a);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ switch (type) {
+ case 'a':
+ n = addrtoa(a[0], 0, buf, sizeof(buf));
+ break;
+ case 's':
+ n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
+ break;
+ case 'r':
+ n = rangetoa(a, 0, buf, sizeof(buf));
+ break;
+ default:
+ fprintf(stderr, "%s: unknown type '%c'\n", argv[0], type);
+ exit(1);
+ break;
+ }
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+ fprintf(stderr, "%s ", inet_ntoa(a[0]));
+ fprintf(stderr, "%s", inet_ntoa(a[1]));
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ char *input;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {"1.2.3.0", "1.2.3.0"},
+ {"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
+ {"1.2.3.0...1.2.3.5", "1.2.3.0...1.2.3.5"},
+ {"1.2.3.4.5", NULL},
+ {"1.2.3.4/", NULL},
+ {"1.2.3.4...", NULL},
+ {"1.2.3.4....", NULL},
+ {"localhost/32", "127.0.0.1/32"},
+ {"localhost...127.0.0.3", "127.0.0.1...127.0.0.3"},
+ {"127.0.0.0...localhost", "127.0.0.0...127.0.0.1"},
+ {"127.0.0.3...localhost", NULL},
+ {NULL, NULL}
+};
+
+void
+regress(void)
+{
+ struct rtab *r;
+ int status = 0;
+ struct in_addr a[2];
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+ char type;
+
+ for (r = rtab; r->input != NULL; r++) {
+ strcpy(in, r->input);
+ oops = atoasr(in, 0, &type, a);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s' atoasr failed: %s\n", r->input, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s' atoasr succeeded unexpectedly '%c'\n",
+ r->input, type);
+ status = 1;
+ } else {
+ switch (type) {
+ case 'a':
+ n = addrtoa(a[0], 0, buf, sizeof(buf));
+ break;
+ case 's':
+ n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
+ break;
+ case 'r':
+ n = rangetoa(a, 0, buf, sizeof(buf));
+ break;
+ default:
+ fprintf(stderr, "`%s' unknown type '%c'\n",
+ r->input, type);
+ n = 0;
+ status = 1;
+ break;
+ }
+ if (n > sizeof(buf)) {
+ printf("`%s' '%c' reverse failed: need %ld\n",
+ r->input, type, (long)n);
+ status = 1;
+ } else if (n > 0 && strcmp(r->output, buf) != 0) {
+ printf("`%s' '%c' gave `%s', expected `%s'\n",
+ r->input, type, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* ATOASR_MAIN */
diff --git a/src/libfreeswan/atosa.3 b/src/libfreeswan/atosa.3
new file mode 100644
index 000000000..116483a73
--- /dev/null
+++ b/src/libfreeswan/atosa.3
@@ -0,0 +1,218 @@
+.TH IPSEC_ATOSA 3 "11 June 2001"
+.\" RCSID $Id: atosa.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec atosa, satoa \- convert IPsec Security Association IDs to and from ASCII
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *atosa(const char *src, size_t srclen,"
+.ti +1c
+.B "struct sa_id *sa);
+.br
+.B "size_t satoa(struct sa_id sa, int format,"
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.sp
+.B "struct sa_id {"
+.ti +1c
+.B "struct in_addr dst;"
+.ti +1c
+.B "ipsec_spi_t spi;"
+.ti +1c
+.B "int proto;"
+.br
+.B "};"
+.SH DESCRIPTION
+These functions are obsolete; see
+.IR ipsec_ttosa (3)
+for their replacements.
+.PP
+.I Atosa
+converts an ASCII Security Association (SA) specifier into an
+.B sa_id
+structure (containing
+a destination-host address
+in network byte order,
+an SPI number in network byte order, and
+a protocol code).
+.I Satoa
+does the reverse conversion, back to an ASCII SA specifier.
+.PP
+An SA is specified in ASCII with a mail-like syntax, e.g.
+.BR esp507@1.2.3.4 .
+An SA specifier contains
+a protocol prefix (currently
+.BR ah ,
+.BR esp ,
+or
+.BR tun ),
+an unsigned integer SPI number,
+and an IP address.
+The SPI number can be decimal or hexadecimal
+(with
+.B 0x
+prefix), as accepted by
+.IR ipsec_atoul (3).
+The IP address can be any form accepted by
+.IR ipsec_atoaddr (3),
+e.g. dotted-decimal address or DNS name.
+.PP
+As a special case, the SA specifier
+.B %passthrough
+signifies the special SA used to indicate that packets should be
+passed through unaltered.
+(At present, this is a synonym for
+.BR tun0x0@0.0.0.0 ,
+but that is subject to change without notice.)
+This form is known to both
+.I atosa
+and
+.IR satoa ,
+so the internal form of
+.B %passthrough
+is never visible.
+.PP
+The
+.B <freeswan.h>
+header file supplies the
+.B sa_id
+structure, as well as a data type
+.B ipsec_spi_t
+which is an unsigned 32-bit integer.
+(There is no consistency between kernel and user on what such a type
+is called, hence the header hides the differences.)
+.PP
+The protocol code uses the same numbers that IP does.
+For user convenience, given the difficulty in acquiring the exact set of
+protocol names used by the kernel,
+.B <freeswan.h>
+defines the names
+.BR SA_ESP ,
+.BR SA_AH ,
+and
+.B SA_IPIP
+to have the same values as the kernel names
+.BR IPPROTO_ESP ,
+.BR IPPROTO_AH ,
+and
+.BR IPPROTO_IPIP .
+.PP
+The
+.I srclen
+parameter of
+.I atosa
+specifies the length of the ASCII string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I dstlen
+parameter of
+.I satoa
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines a constant,
+.BR SATOA_BUF ,
+which is the size of a buffer just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I satoa
+specifies what format is to be used for the conversion.
+The value
+.B 0
+(not the ASCII character
+.BR '0' ,
+but a zero value)
+specifies a reasonable default
+(currently
+lowercase protocol prefix, lowercase hexadecimal SPI, dotted-decimal address).
+The value
+.B d
+causes the SPI to be generated in decimal instead.
+.PP
+.I Atosa
+returns
+.B NULL
+for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.I Satoa
+returns
+.B 0
+for a failure, and otherwise
+always returns the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.SH SEE ALSO
+ipsec_atoul(3), ipsec_atoaddr(3), inet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I atosa
+are:
+empty input;
+input too small to be a legal SA specifier;
+no
+.B @
+in input;
+unknown protocol prefix;
+conversion error in
+.I atoul
+or
+.IR atoaddr .
+.PP
+Fatal errors in
+.I satoa
+are:
+unknown format; unknown protocol code.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The
+.B tun
+protocol code is a FreeS/WANism which may eventually disappear.
+.PP
+The restriction of ASCII-to-binary error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The ASCII-to-binary error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = atoaddr( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/atosa.c b/src/libfreeswan/atosa.c
new file mode 100644
index 000000000..cc3b055d0
--- /dev/null
+++ b/src/libfreeswan/atosa.c
@@ -0,0 +1,200 @@
+/*
+ * convert from ASCII form of SA ID to binary
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: atosa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct satype {
+ char *prefix;
+ size_t prelen; /* strlen(prefix) */
+ int proto;
+} satypes[] = {
+ { "ah", 2, SA_AH },
+ { "esp", 3, SA_ESP },
+ { "tun", 3, SA_IPIP },
+ { "comp", 4, SA_COMP },
+ { NULL, 0, 0, }
+};
+
+/*
+ - atosa - convert ASCII "ah507@10.0.0.1" to SA identifier
+ */
+const char * /* NULL for success, else string literal */
+atosa(src, srclen, sa)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+struct sa_id *sa;
+{
+ const char *at;
+ const char *addr;
+ const char *spi = NULL;
+ struct satype *sat;
+ unsigned long ul;
+ const char *oops;
+# define MINLEN 5 /* ah0@0 is as short as it can get */
+ static char ptname[] = PASSTHROUGHNAME;
+# define PTNLEN (sizeof(ptname)-1) /* -1 for NUL */
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+ if (srclen < MINLEN)
+ return "string too short to be SA specifier";
+ if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) {
+ src = PASSTHROUGHIS;
+ srclen = strlen(src);
+ }
+
+ at = memchr(src, '@', srclen);
+ if (at == NULL)
+ return "no @ in SA specifier";
+
+ for (sat = satypes; sat->prefix != NULL; sat++)
+ if (sat->prelen < srclen &&
+ strncmp(src, sat->prefix, sat->prelen) == 0) {
+ sa->proto = sat->proto;
+ spi = src + sat->prelen;
+ break; /* NOTE BREAK OUT */
+ }
+ if (sat->prefix == NULL)
+ return "SA specifier lacks valid protocol prefix";
+
+ if (spi >= at)
+ return "no SPI in SA specifier";
+ oops = atoul(spi, at - spi, 13, &ul);
+ if (oops != NULL)
+ return oops;
+ sa->spi = htonl(ul);
+
+ addr = at + 1;
+ oops = atoaddr(addr, srclen - (addr - src), &sa->dst);
+ if (oops != NULL)
+ return oops;
+
+ return NULL;
+}
+
+
+
+#ifdef ATOSA_MAIN
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct sa_id sa;
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ oops = atosa(argv[1], 0, &sa);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ n = satoa(sa, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
+ fprintf(stderr, "%lu@", (long unsigned int)sa.spi);
+ fprintf(stderr, "%s", inet_ntoa(sa.dst));
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ char *input;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {"esp257@1.2.3.0", "esp257@1.2.3.0"},
+ {"ah0x20@1.2.3.4", "ah32@1.2.3.4"},
+ {"tun011@111.2.3.99", "tun11@111.2.3.99"},
+ {"", NULL},
+ {"_", NULL},
+ {"ah2.2", NULL},
+ {"goo2@1.2.3.4", NULL},
+ {"esp9@1.2.3.4", "esp9@1.2.3.4"},
+ {"espp9@1.2.3.4", NULL},
+ {"es9@1.2.3.4", NULL},
+ {"ah@1.2.3.4", NULL},
+ {"esp7x7@1.2.3.4", NULL},
+ {"esp77@1.0x2.3.4", NULL},
+ {PASSTHROUGHNAME, PASSTHROUGHNAME},
+ {NULL, NULL}
+};
+
+void
+regress(void)
+{
+ struct rtab *r;
+ int status = 0;
+ struct sa_id sa;
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ for (r = rtab; r->input != NULL; r++) {
+ strcpy(in, r->input);
+ oops = atosa(in, 0, &sa);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s' atosa failed: %s\n", r->input, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s' atosa succeeded unexpectedly\n",
+ r->input);
+ status = 1;
+ } else {
+ n = satoa(sa, 'd', buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ printf("`%s' satoa failed: need %ld\n",
+ r->input, (long)n);
+ status = 1;
+ } else if (strcmp(r->output, buf) != 0) {
+ printf("`%s' gave `%s', expected `%s'\n",
+ r->input, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* ATOSA_MAIN */
diff --git a/src/libfreeswan/atosubnet.c b/src/libfreeswan/atosubnet.c
new file mode 100644
index 000000000..9300c2895
--- /dev/null
+++ b/src/libfreeswan/atosubnet.c
@@ -0,0 +1,216 @@
+/*
+ * convert from ASCII form of subnet specification to binary
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: atosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#ifndef DEFAULTSUBNET
+#define DEFAULTSUBNET "%default"
+#endif
+
+/*
+ - atosubnet - convert ASCII "addr/mask" to address and mask
+ * Mask can be integer bit count.
+ */
+const char * /* NULL for success, else string literal */
+atosubnet(src, srclen, addrp, maskp)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+struct in_addr *addrp;
+struct in_addr *maskp;
+{
+ const char *slash;
+ const char *mask;
+ size_t mlen;
+ const char *oops;
+ unsigned long bc;
+ static char def[] = DEFAULTSUBNET;
+# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
+ static char defis[] = "0/0";
+# define DEFILEN (sizeof(defis) - 1)
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
+ src = defis;
+ srclen = DEFILEN;
+ }
+
+ slash = memchr(src, '/', srclen);
+ if (slash == NULL)
+ return "no / in subnet specification";
+ mask = slash + 1;
+ mlen = srclen - (mask - src);
+
+ oops = atoaddr(src, slash-src, addrp);
+ if (oops != NULL)
+ return oops;
+
+ oops = atoul(mask, mlen, 10, &bc);
+ if (oops == NULL) {
+ /* atoul succeeded, it's a bit-count mask */
+ if (bc > ABITS)
+ return "bit-count mask too large";
+#ifdef NOLEADINGZEROS
+ if (mlen > 1 && *mask == '0')
+ return "octal not allowed in mask";
+#endif /* NOLEADINGZEROS */
+ *maskp = bitstomask((int)bc);
+ } else {
+ oops = atoaddr(mask, mlen, maskp);
+ if (oops != NULL)
+ return oops;
+ if (!goodmask(*maskp))
+ return "non-contiguous mask";
+ }
+
+ addrp->s_addr &= maskp->s_addr;
+ return NULL;
+}
+
+
+
+#ifdef ATOSUBNET_MAIN
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct in_addr a;
+ struct in_addr m;
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ oops = atosubnet(argv[1], 0, &a, &m);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ n = subnettoa(a, m, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+ fprintf(stderr, "%s/", inet_ntoa(a));
+ fprintf(stderr, "%s", inet_ntoa(m));
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ char *input;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
+ {"1.2.3.0/24", "1.2.3.0/24"},
+ {"1.2.3.1/255.255.255.240", "1.2.3.0/28"},
+ {"1.2.3.1/32", "1.2.3.1/32"},
+ {"1.2.3.1/0", "0.0.0.0/0"},
+/* "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0", */
+ {"1.2.3.1/255.255.127.0", NULL},
+ {"128.009.000.032/32", "128.9.0.32/32"},
+ {"128.0x9.0.32/32", NULL},
+ {"0x80090020/32", "128.9.0.32/32"},
+ {"0x800x0020/32", NULL},
+ {"128.9.0.32/0xffFF0000", "128.9.0.0/16"},
+ {"128.9.0.32/0xff0000FF", NULL},
+ {"128.9.0.32/0x0000ffFF", NULL},
+ {"128.9.0.32/0x00ffFF0000", NULL},
+ {"128.9.0.32/0xffFF", NULL},
+ {"128.9.0.32.27/32", NULL},
+ {"128.9.0k32/32", NULL},
+ {"328.9.0.32/32", NULL},
+ {"128.9..32/32", NULL},
+ {"10/8", "10.0.0.0/8"},
+ {"10.0/8", "10.0.0.0/8"},
+ {"10.0.0/8", "10.0.0.0/8"},
+ {"10.0.1/24", "10.0.1.0/24"},
+ {"_", NULL},
+ {"_/_", NULL},
+ {"1.2.3.1", NULL},
+ {"1.2.3.1/_", NULL},
+ {"1.2.3.1/24._", NULL},
+ {"1.2.3.1/99", NULL},
+ {"localhost/32", "127.0.0.1/32"},
+ {"%default", "0.0.0.0/0"},
+ {NULL, NULL}
+};
+
+void
+regress()
+{
+ struct rtab *r;
+ int status = 0;
+ struct in_addr a;
+ struct in_addr m;
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ for (r = rtab; r->input != NULL; r++) {
+ strcpy(in, r->input);
+ oops = atosubnet(in, 0, &a, &m);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s' atosubnet failed: %s\n", r->input, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s' atosubnet succeeded unexpectedly\n",
+ r->input);
+ status = 1;
+ } else {
+ n = subnettoa(a, m, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ printf("`%s' subnettoa failed: need %ld\n",
+ r->input, (long)n);
+ status = 1;
+ } else if (strcmp(r->output, buf) != 0) {
+ printf("`%s' gave `%s', expected `%s'\n",
+ r->input, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* ATOSUBNET_MAIN */
diff --git a/src/libfreeswan/atoul.3 b/src/libfreeswan/atoul.3
new file mode 100644
index 000000000..a606fa4a9
--- /dev/null
+++ b/src/libfreeswan/atoul.3
@@ -0,0 +1,161 @@
+.TH IPSEC_ATOUL 3 "11 June 2001"
+.\" RCSID $Id: atoul.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec atoul, ultoa \- convert unsigned-long numbers to and from ASCII
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *atoul(const char *src, size_t srclen,"
+.ti +1c
+.B "int base, unsigned long *n);"
+.br
+.B "size_t ultoa(unsigned long n, int base, char *dst,"
+.ti +1c
+.B "size_t dstlen);"
+.SH DESCRIPTION
+These functions are obsolete; see
+.IR ipsec_ttoul (3)
+for their replacements.
+.PP
+.I Atoul
+converts an ASCII number into a binary
+.B "unsigned long"
+value.
+.I Ultoa
+does the reverse conversion, back to an ASCII version.
+.PP
+Numbers are specified in ASCII as
+decimal (e.g.
+.BR 123 ),
+octal with a leading zero (e.g.
+.BR 012 ,
+which has value 10),
+or hexadecimal with a leading
+.B 0x
+(e.g.
+.BR 0x1f ,
+which has value 31)
+in either upper or lower case.
+.PP
+The
+.I srclen
+parameter of
+.I atoul
+specifies the length of the ASCII string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I base
+parameter of
+.I atoul
+can be
+.BR 8 ,
+.BR 10 ,
+or
+.BR 16 ,
+in which case the number supplied is assumed to be of that form
+(and in the case of
+.BR 16 ,
+to lack any
+.B 0x
+prefix).
+It can also be
+.BR 0 ,
+in which case the number is examined for a leading zero
+or a leading
+.B 0x
+to determine its base,
+or
+.B 13
+(halfway between 10 and 16),
+which has the same effect as
+.B 0
+except that a non-hexadecimal
+number is considered decimal regardless of any leading zero.
+.PP
+The
+.I dstlen
+parameter of
+.I ultoa
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+.PP
+The
+.I base
+parameter of
+.I ultoa
+must be
+.BR 8 ,
+.BR 10 ,
+or
+.BR 16 .
+.PP
+.I Atoul
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.I Ultoa
+returns the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.SH SEE ALSO
+atol(3), strtoul(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I atoul
+are:
+empty input;
+unknown
+.IR base ;
+non-digit character found;
+number too large for an
+.BR "unsigned long" .
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+There is no provision for reporting an invalid
+.I base
+parameter given to
+.IR ultoa .
+.PP
+The restriction of error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The error-reporting convention lends itself to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = atoul( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/atoul.c b/src/libfreeswan/atoul.c
new file mode 100644
index 000000000..e32a8cdab
--- /dev/null
+++ b/src/libfreeswan/atoul.c
@@ -0,0 +1,90 @@
+/*
+ * convert from ASCII form of unsigned long to binary
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: atoul.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - atoul - convert ASCII substring to unsigned long number
+ */
+const char * /* NULL for success, else string literal */
+atoul(src, srclen, base, resultp)
+const char *src;
+size_t srclen; /* 0 means strlen(src) */
+int base; /* 0 means figure it out */
+unsigned long *resultp;
+{
+ const char *stop;
+ static char hex[] = "0123456789abcdef";
+ static char uchex[] = "0123456789ABCDEF";
+ int d;
+ char c;
+ char *p;
+ unsigned long r;
+ unsigned long rlimit;
+ int dlimit;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ if (base == 0 || base == 13) {
+ if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
+ return atoul(src+2, srclen-2, 16, resultp);
+ if (srclen > 1 && *src == '0' && base != 13)
+ return atoul(src+1, srclen-1, 8, resultp);
+ return atoul(src, srclen, 10, resultp);
+ }
+ if (base != 8 && base != 10 && base != 16)
+ return "unsupported number base";
+
+ r = 0;
+ stop = src + srclen;
+ if (base == 16) {
+ while (src < stop) {
+ c = *src++;
+ p = strchr(hex, c);
+ if (p != NULL)
+ d = p - hex;
+ else {
+ p = strchr(uchex, c);
+ if (p == NULL)
+ return "non-hex-digit in hex number";
+ d = p - uchex;
+ }
+ r = (r << 4) | d;
+ }
+ /* defer length check to catch invalid digits first */
+ if (srclen > sizeof(unsigned long) * 2)
+ return "hex number too long";
+ } else {
+ rlimit = ULONG_MAX / base;
+ dlimit = (int)(ULONG_MAX - rlimit*base);
+ while (src < stop) {
+ c = *src++;
+ d = c - '0';
+ if (d < 0 || d >= base)
+ return "non-digit in number";
+ if (r > rlimit || (r == rlimit && d > dlimit))
+ return "unsigned-long overflow";
+ r = r*base + d;
+ }
+ }
+
+ *resultp = r;
+ return NULL;
+}
diff --git a/src/libfreeswan/copyright.c b/src/libfreeswan/copyright.c
new file mode 100644
index 000000000..0e836f6c2
--- /dev/null
+++ b/src/libfreeswan/copyright.c
@@ -0,0 +1,56 @@
+/*
+ * return IPsec copyright notice
+ * Copyright (C) 2001, 2002 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: copyright.c,v 1.6 2005/11/02 21:51:13 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static const char *co[] = {
+ "Copyright (C) 1999-2005 Henry Spencer, Richard Guy Briggs,",
+ " D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,",
+ " Michael Richardson, Angelos D. Keromytis, John Ioannidis,",
+ "",
+ " Ken Bantoft, Stephen J. Bevan, JuanJo Ciarlante, Mathieu Lafon,",
+ " Stephane Laroche, Kai Martius, Tuomo Soini, Herbert Xu,",
+ "",
+ " Andreas Steffen, Martin Berner, Marco Bertossa, David Buechi,",
+ " Ueli Galizzi, Christoph Gysin, Andreas Hess, Patric Lichtsteiner,",
+ " Michael Meier, Andreas Schleiss, Ariane Seiler,",
+ " Mario Strasser, Lukas Suter, Roger Wegmann, Simon Zwahlen,",
+ " Zuercher Hochschule Winterthur (Switzerland).",
+ "",
+ " Jan Hutter, Martin Willi, Andreas Steffen,",
+ " Hochschule fuer Technik Rapperswil (Switzerland).",
+ "",
+ "This program is free software; you can redistribute it and/or modify it",
+ "under the terms of the GNU General Public License as published by the",
+ "Free Software Foundation; either version 2 of the License, or (at your",
+ "option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.",
+ "",
+ "This program is distributed in the hope that it will be useful, but",
+ "WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General",
+ "Public License (file COPYING in the distribution) for more details.",
+ NULL
+};
+
+/*
+ - ipsec_copyright_notice - return copyright notice, as a vector of strings
+ */
+const char **
+ipsec_copyright_notice()
+{
+ return co;
+}
diff --git a/src/libfreeswan/datatot.c b/src/libfreeswan/datatot.c
new file mode 100644
index 000000000..fbeb35fa9
--- /dev/null
+++ b/src/libfreeswan/datatot.c
@@ -0,0 +1,233 @@
+/*
+ * convert from binary data (e.g. key) to text form
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: datatot.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static void convert(const char *src, size_t nreal, int format, char *out);
+
+/*
+ - datatot - convert data bytes to text
+ */
+size_t /* true length (with NUL) for success */
+datatot(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format; /* character indicating what format */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t inblocksize; /* process this many bytes at a time */
+ size_t outblocksize; /* producing this many */
+ size_t breakevery; /* add a _ every this many (0 means don't) */
+ size_t sincebreak; /* output bytes since last _ */
+ char breakchar; /* character used to break between groups */
+ char inblock[10]; /* enough for any format */
+ char outblock[10]; /* enough for any format */
+ char fake[1]; /* fake output area for dstlen == 0 */
+ size_t needed; /* return value */
+ char *stop; /* where the terminating NUL will go */
+ size_t ntodo; /* remaining input */
+ size_t nreal;
+ char *out;
+ char *prefix;
+
+ breakevery = 0;
+ breakchar = '_';
+
+ switch (format) {
+ case 0:
+ case 'h':
+ format = 'x';
+ breakevery = 8;
+ /* FALLTHROUGH */
+ case 'x':
+ inblocksize = 1;
+ outblocksize = 2;
+ prefix = "0x";
+ break;
+ case ':':
+ format = 'x';
+ breakevery = 2;
+ breakchar = ':';
+ /* FALLTHROUGH */
+ case 16:
+ inblocksize = 1;
+ outblocksize = 2;
+ prefix = "";
+ format = 'x';
+ break;
+ case 's':
+ inblocksize = 3;
+ outblocksize = 4;
+ prefix = "0s";
+ break;
+ case 64: /* beware, equals ' ' */
+ inblocksize = 3;
+ outblocksize = 4;
+ prefix = "";
+ format = 's';
+ break;
+ default:
+ return 0;
+ break;
+ }
+ assert(inblocksize < sizeof(inblock));
+ assert(outblocksize < sizeof(outblock));
+ assert(breakevery % outblocksize == 0);
+
+ if (srclen == 0)
+ return 0;
+ ntodo = srclen;
+
+ if (dstlen == 0) { /* dispose of awkward special case */
+ dst = fake;
+ dstlen = 1;
+ }
+ stop = dst + dstlen - 1;
+
+ nreal = strlen(prefix);
+ needed = nreal; /* for starters */
+ if (dstlen <= nreal) { /* prefix won't fit */
+ strncpy(dst, prefix, dstlen - 1);
+ dst += dstlen - 1;
+ } else {
+ strcpy(dst, prefix);
+ dst += nreal;
+ }
+ assert(dst <= stop);
+ sincebreak = 0;
+
+ while (ntodo > 0) {
+ if (ntodo < inblocksize) { /* incomplete input */
+ memset(inblock, 0, sizeof(inblock));
+ memcpy(inblock, src, ntodo);
+ src = inblock;
+ nreal = ntodo;
+ ntodo = inblocksize;
+ } else
+ nreal = inblocksize;
+ out = (outblocksize > stop - dst) ? outblock : dst;
+
+ convert(src, nreal, format, out);
+ needed += outblocksize;
+ sincebreak += outblocksize;
+ if (dst < stop) {
+ if (out != dst) {
+ assert(outblocksize > stop - dst);
+ memcpy(dst, out, stop - dst);
+ dst = stop;
+ } else
+ dst += outblocksize;
+ }
+
+ src += inblocksize;
+ ntodo -= inblocksize;
+ if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
+ if (dst < stop)
+ *dst++ = breakchar;
+ needed++;
+ sincebreak = 0;
+ }
+ }
+
+ assert(dst <= stop);
+ *dst++ = '\0';
+ needed++;
+
+ return needed;
+}
+
+/*
+ - convert - convert one input block to one output block
+ */
+static void
+convert(src, nreal, format, out)
+const char *src;
+size_t nreal; /* how much of the input block is real */
+int format;
+char *out;
+{
+ static char hex[] = "0123456789abcdef";
+ static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ unsigned char c;
+ unsigned char c1, c2, c3;
+
+ assert(nreal > 0);
+ switch (format) {
+ case 'x':
+ assert(nreal == 1);
+ c = (unsigned char)*src;
+ *out++ = hex[c >> 4];
+ *out++ = hex[c & 0xf];
+ break;
+ case 's':
+ c1 = (unsigned char)*src++;
+ c2 = (unsigned char)*src++;
+ c3 = (unsigned char)*src++;
+ *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */
+ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */
+ c |= c2 >> 4; /* ...top 4 of c2 */
+ *out++ = base64[c];
+ if (nreal == 1)
+ *out++ = '=';
+ else {
+ c = (c2 & 0xf) << 2; /* bottom 4 of c2... */
+ c |= c3 >> 6; /* ...top 2 of c3 */
+ *out++ = base64[c];
+ }
+ if (nreal <= 2)
+ *out++ = '=';
+ else
+ *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */
+ break;
+ default:
+ assert(nreal == 0); /* unknown format */
+ break;
+ }
+}
+
+/*
+ - datatoa - convert data to ASCII
+ * backward-compatibility synonym for datatot
+ */
+size_t /* true length (with NUL) for success */
+datatoa(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format; /* character indicating what format */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ return datatot(src, srclen, format, dst, dstlen);
+}
+
+/*
+ - bytestoa - convert data bytes to ASCII
+ * backward-compatibility synonym for datatot
+ */
+size_t /* true length (with NUL) for success */
+bytestoa(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format; /* character indicating what format */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ return datatot(src, srclen, format, dst, dstlen);
+}
diff --git a/src/libfreeswan/freeswan.h b/src/libfreeswan/freeswan.h
new file mode 100644
index 000000000..b1bca870d
--- /dev/null
+++ b/src/libfreeswan/freeswan.h
@@ -0,0 +1,470 @@
+#ifndef _FREESWAN_H
+/*
+ * header file for FreeS/WAN library functions
+ * Copyright (C) 1998, 1999, 2000 Henry Spencer.
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: freeswan.h,v 1.2 2004/03/22 21:53:17 as Exp $
+ */
+#define _FREESWAN_H /* seen it, no need to see it again */
+
+
+
+/*
+ * We've just got to have some datatypes defined... And annoyingly, just
+ * where we get them depends on whether we're in userland or not.
+ */
+#ifdef __KERNEL__
+
+# include <linux/types.h>
+# include <linux/in.h>
+
+#else /* __KERNEL__ */
+
+# include <stdio.h>
+# include <netinet/in.h>
+
+# define uint8_t u_int8_t
+# define uint16_t u_int16_t
+# define uint32_t u_int32_t
+# define uint64_t u_int64_t
+
+# define DEBUG_NO_STATIC static
+
+#endif /* __KERNEL__ */
+
+#include <ipsec_param.h>
+
+
+/*
+ * Grab the kernel version to see if we have NET_21, and therefore
+ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course,
+ * we aren't really testing if the kernel has IPv6, but rather if the
+ * the include files do.
+ */
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define NET_21
+#endif
+
+#ifndef IPPROTO_COMP
+# define IPPROTO_COMP 108
+#endif /* !IPPROTO_COMP */
+
+#ifndef IPPROTO_INT
+# define IPPROTO_INT 61
+#endif /* !IPPROTO_INT */
+
+#ifdef CONFIG_IPSEC_DEBUG
+# define DEBUG_NO_STATIC
+#else /* CONFIG_IPSEC_DEBUG */
+# define DEBUG_NO_STATIC static
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
+#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */
+
+/*
+ * Basic data types for the address-handling functions.
+ * ip_address and ip_subnet are supposed to be opaque types; do not
+ * use their definitions directly, they are subject to change!
+ */
+
+/* first, some quick fakes in case we're on an old system with no IPv6 */
+#ifndef s6_addr16
+struct in6_addr {
+ union
+ {
+ __u8 u6_addr8[16];
+ __u16 u6_addr16[8];
+ __u32 u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+};
+struct sockaddr_in6 {
+ unsigned short int sin6_family; /* AF_INET6 */
+ __u16 sin6_port; /* Transport layer port # */
+ __u32 sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ __u32 sin6_scope_id; /* scope id (new in RFC2553) */
+};
+#endif /* !s6_addr16 */
+
+/* then the main types */
+typedef struct {
+ union {
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } u;
+} ip_address;
+typedef struct {
+ ip_address addr;
+ int maskbits;
+} ip_subnet;
+
+/* and the SA ID stuff */
+#ifdef __KERNEL__
+typedef __u32 ipsec_spi_t;
+#else
+typedef u_int32_t ipsec_spi_t;
+#endif
+typedef struct { /* to identify an SA, we need: */
+ ip_address dst; /* A. destination host */
+ ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */
+# define SPI_PASS 256 /* magic values... */
+# define SPI_DROP 257 /* ...for use... */
+# define SPI_REJECT 258 /* ...with SA_INT */
+# define SPI_HOLD 259
+# define SPI_TRAP 260
+# define SPI_TRAPSUBNET 261
+ int proto; /* C. protocol */
+# define SA_ESP 50 /* IPPROTO_ESP */
+# define SA_AH 51 /* IPPROTO_AH */
+# define SA_IPIP 4 /* IPPROTO_IPIP */
+# define SA_COMP 108 /* IPPROTO_COMP */
+# define SA_INT 61 /* IANA reserved for internal use */
+} ip_said;
+struct sa_id { /* old v4-only version */
+ struct in_addr dst;
+ ipsec_spi_t spi;
+ int proto;
+};
+
+/* misc */
+typedef const char *err_t; /* error message, or NULL for success */
+struct prng { /* pseudo-random-number-generator guts */
+ unsigned char sbox[256];
+ int i, j;
+ unsigned long count;
+};
+
+
+/*
+ * definitions for user space, taken from freeswan/ipsec_sa.h
+ */
+typedef uint32_t IPsecSAref_t;
+
+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
+
+#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
+#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
+
+#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0))
+
+/* GCC magic for use in function definitions! */
+#ifdef GCC_LINT
+# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1)))
+# define NEVER_RETURNS __attribute__ ((noreturn))
+# define UNUSED __attribute__ ((unused))
+# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
+#else
+# define PRINTF_LIKE(n) /* ignore */
+# define NEVER_RETURNS /* ignore */
+# define UNUSED /* ignore */
+# define BLANK_FORMAT ""
+#endif
+
+
+
+
+
+/*
+ * new IPv6-compatible functions
+ */
+
+/* text conversions */
+err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst);
+size_t ultot(unsigned long src, int format, char *buf, size_t buflen);
+#define ULTOT_BUF (22+1) /* holds 64 bits in octal */
+err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst);
+err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst);
+size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen);
+/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */
+#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1)
+err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst);
+size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen);
+#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3)
+err_t ttosa(const char *src, size_t srclen, ip_said *dst);
+size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen);
+#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF)
+err_t ttodata(const char *src, size_t srclen, int base, char *buf,
+ size_t buflen, size_t *needed);
+err_t ttodatav(const char *src, size_t srclen, int base,
+ char *buf, size_t buflen, size_t *needed,
+ char *errp, size_t errlen, unsigned int flags);
+#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */
+#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/
+#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */
+
+size_t datatot(const char *src, size_t srclen, int format, char *buf,
+ size_t buflen);
+size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst,
+ size_t dstlen);
+size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m,
+ size_t mlen, char *dst, size_t dstlen);
+#define KEYID_BUF 10 /* up to 9 text digits plus NUL */
+err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port,
+ int *has_port_wildcard);
+
+/* initializations */
+void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst);
+err_t loopbackaddr(int af, ip_address *dst);
+err_t unspecaddr(int af, ip_address *dst);
+err_t anyaddr(int af, ip_address *dst);
+err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst);
+err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst);
+err_t addrtosubnet(const ip_address *addr, ip_subnet *dst);
+
+/* misc. conversions and related */
+err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst);
+int addrtypeof(const ip_address *src);
+int subnettypeof(const ip_subnet *src);
+size_t addrlenof(const ip_address *src);
+size_t addrbytesptr(const ip_address *src, const unsigned char **dst);
+size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen);
+int masktocount(const ip_address *src);
+void networkof(const ip_subnet *src, ip_address *dst);
+void maskof(const ip_subnet *src, ip_address *dst);
+
+/* tests */
+int sameaddr(const ip_address *a, const ip_address *b);
+int addrcmp(const ip_address *a, const ip_address *b);
+int samesubnet(const ip_subnet *a, const ip_subnet *b);
+int addrinsubnet(const ip_address *a, const ip_subnet *s);
+int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);
+int subnetishost(const ip_subnet *s);
+int samesaid(const ip_said *a, const ip_said *b);
+int sameaddrtype(const ip_address *a, const ip_address *b);
+int samesubnettype(const ip_subnet *a, const ip_subnet *b);
+int isanyaddr(const ip_address *src);
+int isunspecaddr(const ip_address *src);
+int isloopbackaddr(const ip_address *src);
+
+/* low-level grot */
+int portof(const ip_address *src);
+void setportof(int port, ip_address *dst);
+struct sockaddr *sockaddrof(ip_address *src);
+size_t sockaddrlenof(const ip_address *src);
+
+/* PRNG */
+void prng_init(struct prng *prng, const unsigned char *key, size_t keylen);
+void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen);
+unsigned long prng_count(struct prng *prng);
+void prng_final(struct prng *prng);
+
+/* odds and ends */
+const char *ipsec_version_code(void);
+const char *ipsec_version_string(void);
+const char **ipsec_copyright_notice(void);
+
+const char *dns_string_rr(int rr, char *buf, int bufsize);
+const char *dns_string_datetime(time_t seconds,
+ char *buf,
+ int bufsize);
+
+
+/*
+ * old functions, to be deleted eventually
+ */
+
+/* unsigned long */
+const char * /* NULL for success, else string literal */
+atoul(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ int base, /* 0 means figure it out */
+ unsigned long *resultp
+);
+size_t /* space needed for full conversion */
+ultoa(
+ unsigned long n,
+ int base,
+ char *dst,
+ size_t dstlen
+);
+#define ULTOA_BUF 21 /* just large enough for largest result, */
+ /* assuming 64-bit unsigned long! */
+
+/* Internet addresses */
+const char * /* NULL for success, else string literal */
+atoaddr(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ struct in_addr *addr
+);
+size_t /* space needed for full conversion */
+addrtoa(
+ struct in_addr addr,
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+#define ADDRTOA_BUF 16 /* just large enough for largest result */
+
+/* subnets */
+const char * /* NULL for success, else string literal */
+atosubnet(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ struct in_addr *addr,
+ struct in_addr *mask
+);
+size_t /* space needed for full conversion */
+subnettoa(
+ struct in_addr addr,
+ struct in_addr mask,
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+#define SUBNETTOA_BUF 32 /* large enough for worst case result */
+
+/* ranges */
+const char * /* NULL for success, else string literal */
+atoasr(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ char *type, /* 'a', 's', 'r' */
+ struct in_addr *addrs /* two-element array */
+);
+size_t /* space needed for full conversion */
+rangetoa(
+ struct in_addr *addrs, /* two-element array */
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+#define RANGETOA_BUF 34 /* large enough for worst case result */
+
+/* data types for SA conversion functions */
+
+/* SAs */
+const char * /* NULL for success, else string literal */
+atosa(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ struct sa_id *sa
+);
+size_t /* space needed for full conversion */
+satoa(
+ struct sa_id sa,
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+#define SATOA_BUF (3+ULTOA_BUF+ADDRTOA_BUF)
+
+/* generic data, e.g. keys */
+const char * /* NULL for success, else string literal */
+atobytes(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ char *dst,
+ size_t dstlen,
+ size_t *lenp /* NULL means don't bother telling me */
+);
+size_t /* 0 failure, else true size */
+bytestoa(
+ const char *src,
+ size_t srclen,
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+
+/* old versions of generic-data functions; deprecated */
+size_t /* 0 failure, else true size */
+atodata(
+ const char *src,
+ size_t srclen, /* 0 means strlen(src) */
+ char *dst,
+ size_t dstlen
+);
+size_t /* 0 failure, else true size */
+datatoa(
+ const char *src,
+ size_t srclen,
+ int format, /* character; 0 means default */
+ char *dst,
+ size_t dstlen
+);
+
+/* part extraction and special addresses */
+struct in_addr
+subnetof(
+ struct in_addr addr,
+ struct in_addr mask
+);
+struct in_addr
+hostof(
+ struct in_addr addr,
+ struct in_addr mask
+);
+struct in_addr
+broadcastof(
+ struct in_addr addr,
+ struct in_addr mask
+);
+
+/* mask handling */
+int
+goodmask(
+ struct in_addr mask
+);
+int
+masktobits(
+ struct in_addr mask
+);
+struct in_addr
+bitstomask(
+ int n
+);
+
+
+
+/*
+ * general utilities
+ */
+
+#ifndef __KERNEL__
+/* option pickup from files (userland only because of use of FILE) */
+const char *optionsfrom(const char *filename, int *argcp, char ***argvp,
+ int optind, FILE *errorreport);
+#endif
+
+/*
+ * Debugging levels for pfkey_lib_debug
+ */
+#define PF_KEY_DEBUG_PARSE_NONE 0
+#define PF_KEY_DEBUG_PARSE_PROBLEM 1
+#define PF_KEY_DEBUG_PARSE_STRUCT 2
+#define PF_KEY_DEBUG_PARSE_FLOW 4
+#define PF_KEY_DEBUG_PARSE_MAX 7
+
+extern unsigned int pfkey_lib_debug; /* bits selecting what to report */
+
+/*
+ * pluto and lwdnsq need to know the maximum size of the commands to,
+ * and replies from lwdnsq.
+ */
+
+#define LWDNSQ_CMDBUF_LEN 1024
+#define LWDNSQ_RESULT_LEN_MAX 4096
+
+#endif /* _FREESWAN_H */
diff --git a/src/libfreeswan/goodmask.3 b/src/libfreeswan/goodmask.3
new file mode 100644
index 000000000..4a573e51e
--- /dev/null
+++ b/src/libfreeswan/goodmask.3
@@ -0,0 +1,57 @@
+.TH IPSEC_GOODMASK 3 "11 June 2001"
+.\" RCSID $Id: goodmask.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec goodmask \- is this Internet subnet mask a valid one?
+.br
+ipsec masktobits \- convert Internet subnet mask to bit count
+.br
+ipsec bitstomask \- convert bit count to Internet subnet mask
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "int goodmask(struct in_addr mask);"
+.br
+.B "int masktobits(struct in_addr mask);"
+.br
+.B "struct in_addr bitstomask(int n);"
+.SH DESCRIPTION
+These functions are obsolete;
+see
+.IR ipsec_masktocount (3)
+for a partial replacement.
+.PP
+.I Goodmask
+reports whether the subnet
+.I mask
+is a valid one,
+i.e. consists of a (possibly empty) sequence of
+.BR 1 s
+followed by a (possibly empty) sequence of
+.BR 0 s.
+.I Masktobits
+takes a (valid) subnet mask and returns the number of
+.B 1
+bits in it.
+.I Bitstomask
+reverses this,
+returning the subnet mask corresponding to bit count
+.IR n .
+.PP
+All masks are in network byte order.
+.SH SEE ALSO
+inet(3), ipsec_atosubnet(3)
+.SH DIAGNOSTICS
+.I Masktobits
+returns
+.B \-1
+for an invalid mask.
+.I Bitstomask
+returns an all-zeros mask for a negative or out-of-range
+.IR n .
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The error-reporting convention of
+.I bitstomask
+is less than ideal;
+zero is sometimes a legitimate mask.
diff --git a/src/libfreeswan/goodmask.c b/src/libfreeswan/goodmask.c
new file mode 100644
index 000000000..fe7a42335
--- /dev/null
+++ b/src/libfreeswan/goodmask.c
@@ -0,0 +1,97 @@
+/*
+ * minor utilities for subnet-mask manipulation
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: goodmask.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - goodmask - is this a good (^1*0*$) subnet mask?
+ * You are not expected to understand this. See Henry S. Warren Jr,
+ * "Functions realizable with word-parallel logical and two's-complement
+ * addition instructions", CACM 20.6 (June 1977), p.439.
+ */
+int /* predicate */
+goodmask(mask)
+struct in_addr mask;
+{
+ unsigned long x = ntohl(mask.s_addr);
+ /* clear rightmost contiguous string of 1-bits */
+# define CRCS1B(x) (((x|(x-1))+1)&x)
+# define TOPBIT (1UL << 31)
+
+ /* either zero, or has one string of 1-bits which is left-justified */
+ if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
+ return 1;
+ return 0;
+}
+
+/*
+ - masktobits - how many bits in this mask?
+ * The algorithm is essentially a binary search, but highly optimized
+ * for this particular task.
+ */
+int /* -1 means !goodmask() */
+masktobits(mask)
+struct in_addr mask;
+{
+ unsigned long m = ntohl(mask.s_addr);
+ int masklen;
+
+ if (!goodmask(mask))
+ return -1;
+
+ if (m&0x00000001UL)
+ return 32;
+ masklen = 0;
+ if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */
+ masklen |= 0x10;
+ m <<= 16;
+ }
+ if (m&(0x00ff0000UL<<1)) {
+ masklen |= 0x08;
+ m <<= 8;
+ }
+ if (m&(0x0f000000UL<<1)) {
+ masklen |= 0x04;
+ m <<= 4;
+ }
+ if (m&(0x30000000UL<<1)) {
+ masklen |= 0x02;
+ m <<= 2;
+ }
+ if (m&(0x40000000UL<<1))
+ masklen |= 0x01;
+
+ return masklen;
+}
+
+/*
+ - bitstomask - return a mask with this many high bits on
+ */
+struct in_addr
+bitstomask(n)
+int n;
+{
+ struct in_addr result;
+
+ if (n > 0 && n <= ABITS)
+ result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
+ else if (n == 0)
+ result.s_addr = 0;
+ else
+ result.s_addr = 0; /* best error report we can do */
+ return result;
+}
diff --git a/src/libfreeswan/initaddr.3 b/src/libfreeswan/initaddr.3
new file mode 100644
index 000000000..b963f21cc
--- /dev/null
+++ b/src/libfreeswan/initaddr.3
@@ -0,0 +1,129 @@
+.TH IPSEC_INITADDR 3 "11 Sept 2000"
+.\" RCSID $Id: initaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec initaddr \- initialize an ip_address
+.br
+ipsec addrtypeof \- get address type of an ip_address
+.br
+ipsec addrlenof \- get length of address within an ip_address
+.br
+ipsec addrbytesof \- get copy of address within an ip_address
+.br
+ipsec addrbytesptr \- get pointer to address within an ip_address
+.SH SYNOPSIS
+.B "#include <freeswan.h>"
+.sp
+.B "const char *initaddr(const char *src, size_t srclen,"
+.ti +1c
+.B "int af, ip_address *dst);"
+.br
+.B "int addrtypeof(const ip_address *src);"
+.br
+.B "size_t addrlenof(const ip_address *src);"
+.br
+.B "size_t addrbytesof(const ip_address *src,"
+.ti +1c
+.B "unsigned char *dst, size_t dstlen);"
+.br
+.B "size_t addrbytesptr(const ip_address *src,"
+.ti +1c
+.B "const unsigned char **dst);"
+.SH DESCRIPTION
+The
+.B <freeswan.h>
+library uses an internal type
+.I ip_address
+to contain one of the (currently two) types of IP address.
+These functions provide basic tools for creating and examining this type.
+.PP
+.I Initaddr
+initializes a variable
+.I *dst
+of type
+.I ip_address
+from an address
+(in network byte order,
+indicated by a pointer
+.I src
+and a length
+.IR srclen )
+and an address family
+.I af
+(typically
+.B AF_INET
+or
+.BR AF_INET6 ).
+The length must be consistent with the address family.
+.PP
+.I Addrtypeof
+returns the address type of an address,
+normally
+.B AF_INET
+or
+.BR AF_INET6 .
+(The
+.B <freeswan.h>
+header file arranges to include the necessary headers for these
+names to be known.)
+.PP
+.I Addrlenof
+returns the size (in bytes) of the address within an
+.IR ip_address ,
+to permit storage allocation etc.
+.PP
+.I Addrbytesof
+copies the address within the
+.I ip_address
+.I src
+to the buffer indicated by the pointer
+.I dst
+and the length
+.IR dstlen ,
+and returns the address length (in bytes).
+If the address will not fit,
+as many bytes as will fit are copied;
+the returned length is still the full length.
+It is the caller's responsibility to check the
+returned value to ensure that there was enough room.
+.PP
+.I Addrbytesptr
+sets
+.I *dst
+to a pointer to the internal address within the
+.IR ip_address ,
+and returns the address length (in bytes).
+If
+.I dst
+is
+.BR NULL ,
+it just returns the address length.
+The pointer points to
+.B const
+to discourage misuse.
+.PP
+.I Initaddr
+returns
+.B NULL
+for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.PP
+The functions which return
+.I size_t
+return
+.B 0
+for a failure.
+.SH SEE ALSO
+inet(3), ipsec_ttoaddr(3)
+.SH DIAGNOSTICS
+An unknown address family is a fatal error for any of these functions
+except
+.IR addrtypeof .
+An address-size mismatch is a fatal error for
+.IR initaddr .
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+.I Addrtypeof
+should probably have been named
+.IR addrfamilyof .
diff --git a/src/libfreeswan/initaddr.c b/src/libfreeswan/initaddr.c
new file mode 100644
index 000000000..c215f6bdf
--- /dev/null
+++ b/src/libfreeswan/initaddr.c
@@ -0,0 +1,51 @@
+/*
+ * initialize address structure
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: initaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initaddr - initialize ip_address from bytes
+ */
+err_t /* NULL for success, else string literal */
+initaddr(src, srclen, af, dst)
+const unsigned char *src;
+size_t srclen;
+int af; /* address family */
+ip_address *dst;
+{
+ switch (af) {
+ case AF_INET:
+ if (srclen != 4)
+ return "IPv4 address must be exactly 4 bytes";
+ dst->u.v4.sin_family = af;
+ dst->u.v4.sin_port = 0; /* unused */
+ memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
+ break;
+ case AF_INET6:
+ if (srclen != 16)
+ return "IPv6 address must be exactly 16 bytes";
+ dst->u.v6.sin6_family = af;
+ dst->u.v6.sin6_flowinfo = 0; /* unused */
+ dst->u.v6.sin6_port = 0; /* unused */
+ memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
+ break;
+ default:
+ return "unknown address family in initaddr";
+ break;
+ }
+ return NULL;
+}
diff --git a/src/libfreeswan/initsaid.c b/src/libfreeswan/initsaid.c
new file mode 100644
index 000000000..4790f6981
--- /dev/null
+++ b/src/libfreeswan/initsaid.c
@@ -0,0 +1,33 @@
+/*
+ * initialize SA ID structure
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: initsaid.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initsaid - initialize SA ID from bits
+ */
+void
+initsaid(addr, spi, proto, dst)
+const ip_address *addr;
+ipsec_spi_t spi;
+int proto;
+ip_said *dst;
+{
+ dst->dst = *addr;
+ dst->spi = spi;
+ dst->proto = proto;
+}
diff --git a/src/libfreeswan/initsubnet.3 b/src/libfreeswan/initsubnet.3
new file mode 100644
index 000000000..670f71778
--- /dev/null
+++ b/src/libfreeswan/initsubnet.3
@@ -0,0 +1,137 @@
+.TH IPSEC_INITSUBNET 3 "12 March 2002"
+.\" RCSID $Id: initsubnet.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec initsubnet \- initialize an ip_subnet
+.br
+ipsec addrtosubnet \- initialize a singleton ip_subnet
+.br
+ipsec subnettypeof \- get address type of an ip_subnet
+.br
+ipsec masktocount \- convert subnet mask to bit count
+.br
+ipsec networkof \- get base address of an ip_subnet
+.br
+ipsec maskof \- get subnet mask of an ip_subnet
+.SH SYNOPSIS
+.B "#include <freeswan.h>"
+.sp
+.B "const char *initsubnet(const ip_address *addr,"
+.ti +1c
+.B "int maskbits, int clash, ip_subnet *dst);"
+.br
+.B "const char *addrtosubnet(const ip_address *addr,"
+.ti +1c
+.B "ip_subnet *dst);"
+.sp
+.B "int subnettypeof(const ip_subnet *src);"
+.br
+.B "int masktocount(const ip_address *src);"
+.br
+.B "void networkof(const ip_subnet *src, ip_address *dst);"
+.br
+.B "void maskof(const ip_subnet *src, ip_address *dst);"
+.SH DESCRIPTION
+The
+.B <freeswan.h>
+library uses an internal type
+.I ip_subnet
+to contain a description of an IP subnet
+(base address plus mask).
+These functions provide basic tools for creating and examining this type.
+.PP
+.I Initsubnet
+initializes a variable
+.I *dst
+of type
+.I ip_subnet
+from a base address and
+a count of mask bits.
+The
+.I clash
+parameter specifies what to do if the base address includes
+.B 1
+bits outside the prefix specified by the mask
+(that is, in the ``host number'' part of the address):
+.RS
+.IP '0' 5
+zero out host-number bits
+.IP 'x'
+non-zero host-number bits are an error
+.RE
+.PP
+.I Initsubnet
+returns
+.B NULL
+for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.PP
+.I Addrtosubnet
+initializes an
+.I ip_subnet
+variable
+.I *dst
+to a ``singleton subnet'' containing the single address
+.IR *addr .
+It returns
+.B NULL
+for success and
+a pointer to a string-literal error message for failure.
+.PP
+.I Subnettypeof
+returns the address type of a subnet,
+normally
+.B AF_INET
+or
+.BR AF_INET6 .
+(The
+.B <freeswan.h>
+header file arranges to include the necessary headers for these
+names to be known.)
+.PP
+.I Masktocount
+converts a subnet mask, expressed as an address, to a bit count
+suitable for use with
+.IR initsubnet .
+It returns
+.B \-1
+for error; see DIAGNOSTICS.
+.PP
+.I Networkof
+fills in
+.I *dst
+with the base address of subnet
+.IR src .
+.PP
+.I Maskof
+fills in
+.I *dst
+with the subnet mask of subnet
+.IR src ,
+expressed as an address.
+.SH SEE ALSO
+inet(3), ipsec_ttosubnet(3), ipsec_rangetosubnet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I initsubnet
+are:
+unknown address family;
+unknown
+.I clash
+value;
+impossible mask bit count;
+non-zero host-number bits and
+.I clash
+is
+.BR 'x' .
+Fatal errors in
+.I addrtosubnet
+are:
+unknown address family.
+Fatal errors in
+.I masktocount
+are:
+unknown address family;
+mask bits not contiguous.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/initsubnet.c b/src/libfreeswan/initsubnet.c
new file mode 100644
index 000000000..75ca72f36
--- /dev/null
+++ b/src/libfreeswan/initsubnet.c
@@ -0,0 +1,95 @@
+/*
+ * initialize subnet structure
+ * Copyright (C) 2000, 2002 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: initsubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initsubnet - initialize ip_subnet from address and count
+ *
+ * The only hard part is checking for host-part bits turned on.
+ */
+err_t /* NULL for success, else string literal */
+initsubnet(addr, count, clash, dst)
+const ip_address *addr;
+int count;
+int clash; /* '0' zero host-part bits, 'x' die on them */
+ip_subnet *dst;
+{
+ unsigned char *p;
+ int n;
+ int c;
+ unsigned m;
+ int die;
+
+ dst->addr = *addr;
+ n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
+ if (n == 0)
+ return "unknown address family";
+
+ switch (clash) {
+ case '0':
+ die = 0;
+ break;
+ case 'x':
+ die = 1;
+ break;
+ default:
+ return "unknown clash-control value in initsubnet";
+ break;
+ }
+
+ c = count / 8;
+ if (c > n)
+ return "impossible mask count";
+ p += c;
+ n -= c;
+
+ m = 0xff;
+ c = count % 8;
+ if (n > 0 && c != 0) /* partial byte */
+ m >>= c;
+ for (; n > 0; n--) {
+ if ((*p & m) != 0) {
+ if (die)
+ return "improper subnet, host-part bits on";
+ *p &= ~m;
+ }
+ m = 0xff;
+ p++;
+ }
+
+ dst->maskbits = count;
+ return NULL;
+}
+
+/*
+ - addrtosubnet - initialize ip_subnet from a single address
+ */
+err_t /* NULL for success, else string literal */
+addrtosubnet(addr, dst)
+const ip_address *addr;
+ip_subnet *dst;
+{
+ int n;
+
+ dst->addr = *addr;
+ n = addrbytesptr(&dst->addr, (const unsigned char **)NULL);
+ if (n == 0)
+ return "unknown address family";
+ dst->maskbits = n*8;
+ return NULL;
+}
diff --git a/src/libfreeswan/internal.h b/src/libfreeswan/internal.h
new file mode 100644
index 000000000..16ad78da0
--- /dev/null
+++ b/src/libfreeswan/internal.h
@@ -0,0 +1,81 @@
+/*
+ * internal definitions for use within the library; do not export!
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: internal.h,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+
+#ifndef ABITS
+#define ABITS 32 /* bits in an IPv4 address */
+#endif
+
+/* case-independent ASCII character equality comparison */
+#define CIEQ(c1, c2) ( ((c1)&~040) == ((c2)&~040) )
+
+/* syntax for passthrough SA */
+#ifndef PASSTHROUGHNAME
+#define PASSTHROUGHNAME "%passthrough"
+#define PASSTHROUGH4NAME "%passthrough4"
+#define PASSTHROUGH6NAME "%passthrough6"
+#define PASSTHROUGHIS "tun0@0.0.0.0"
+#define PASSTHROUGH4IS "tun0@0.0.0.0"
+#define PASSTHROUGH6IS "tun0@::"
+#define PASSTHROUGHTYPE "tun"
+#define PASSTHROUGHSPI 0
+#define PASSTHROUGHDST 0
+#endif
+
+/*
+ * Headers, greatly complicated by stupid and unnecessary inconsistencies
+ * between the user environment and the kernel environment. These are done
+ * here so that this mess need exist in only one place.
+ *
+ * It may seem like a -I or two could avoid most of this, but on closer
+ * inspection it is not quite that easy.
+ */
+
+/* things that need to come from one place or the other, depending */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#define assert(foo) /* nothing */
+#else
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#endif
+
+/* things that exist only in userland */
+#ifndef __KERNEL__
+
+/* You'd think this would be okay in the kernel too -- it's just a */
+/* bunch of constants -- but no, in RH5.1 it screws up other things. */
+/* (Credit: Mike Warfield tracked this problem down. Thanks Mike!) */
+/* Fortunately, we don't need it in the kernel subset of the library. */
+#include <limits.h>
+
+/* header files for things that should never be called in kernel */
+#include <netdb.h>
+
+/* memory allocation, currently user-only, macro-ized just in case */
+#include <stdlib.h>
+#define MALLOC(n) malloc(n)
+#define FREE(p) free(p)
+
+#endif /* __KERNEL__ */
+
diff --git a/src/libfreeswan/ipcomp.h b/src/libfreeswan/ipcomp.h
new file mode 100644
index 000000000..ed8095517
--- /dev/null
+++ b/src/libfreeswan/ipcomp.h
@@ -0,0 +1,61 @@
+/*
+ * IPCOMP zlib interface code.
+ * Copyright (C) 2000 Svenning Soerensen <svenning@post5.tele.dk>
+ * Copyright (C) 2000, 2001 Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+
+ RCSID $Id: ipcomp.h,v 1.1 2004/03/15 20:35:25 as Exp $
+
+ */
+
+/* SSS */
+
+#ifndef _IPCOMP_H
+#define _IPCOMP_H
+
+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */
+#ifndef IPCOMP_PREFIX
+#define IPCOMP_PREFIX
+#endif /* IPCOMP_PREFIX */
+
+#ifndef IPPROTO_COMP
+#define IPPROTO_COMP 108
+#endif /* IPPROTO_COMP */
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int sysctl_ipsec_debug_ipcomp;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+struct ipcomphdr { /* IPCOMP header */
+ __u8 ipcomp_nh; /* Next header (protocol) */
+ __u8 ipcomp_flags; /* Reserved, must be 0 */
+ __u16 ipcomp_cpi; /* Compression Parameter Index */
+};
+
+extern struct inet_protocol comp_protocol;
+extern int sysctl_ipsec_debug_ipcomp;
+
+#define IPCOMP_UNCOMPRESSABLE 0x000000001
+#define IPCOMP_COMPRESSIONERROR 0x000000002
+#define IPCOMP_PARMERROR 0x000000004
+#define IPCOMP_DECOMPRESSIONERROR 0x000000008
+
+#define IPCOMP_ADAPT_INITIAL_TRIES 8
+#define IPCOMP_ADAPT_INITIAL_SKIP 4
+#define IPCOMP_ADAPT_SUBSEQ_TRIES 2
+#define IPCOMP_ADAPT_SUBSEQ_SKIP 8
+
+/* Function prototypes */
+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
+
+#endif /* _IPCOMP_H */
diff --git a/src/libfreeswan/ipsec_ah.h b/src/libfreeswan/ipsec_ah.h
new file mode 100644
index 000000000..e088288d3
--- /dev/null
+++ b/src/libfreeswan/ipsec_ah.h
@@ -0,0 +1,235 @@
+/*
+ * Authentication Header declarations
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_ah.h,v 1.2 2004/03/22 21:53:18 as Exp $
+ */
+
+#include "ipsec_md5h.h"
+#include "ipsec_sha1.h"
+
+#ifndef IPPROTO_AH
+#define IPPROTO_AH 51
+#endif /* IPPROTO_AH */
+
+#define AH_FLENGTH 12 /* size of fixed part */
+#define AHMD5_KMAX 64 /* MD5 max 512 bits key */
+#define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */
+
+#define AHMD596_KLEN 16 /* MD5 128 bits key */
+#define AHSHA196_KLEN 20 /* SHA1 160 bits key */
+
+#define AHMD596_ALEN 16 /* MD5 128 bits authentication length */
+#define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */
+
+#define AHMD596_BLKLEN 64 /* MD5 block length */
+#define AHSHA196_BLKLEN 64 /* SHA1 block length */
+#define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */
+#define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */
+#define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */
+
+#define AH_BLKLEN_MAX 128 /* keep up to date! */
+
+#define AH_AMAX AHSHA196_ALEN /* keep up to date! */
+#define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */
+#define AHHMAC_RPLLEN 4 /* 32 bit replay counter */
+
+#define DB_AH_PKTRX 0x0001
+#define DB_AH_PKTRX2 0x0002
+#define DB_AH_DMP 0x0004
+#define DB_AH_IPSA 0x0010
+#define DB_AH_XF 0x0020
+#define DB_AH_INAU 0x0040
+#define DB_AH_REPLAY 0x0100
+
+#ifdef __KERNEL__
+
+/* General HMAC algorithm is described in RFC 2104 */
+
+#define HMAC_IPAD 0x36
+#define HMAC_OPAD 0x5C
+
+struct md5_ctx {
+ MD5_CTX ictx; /* context after H(K XOR ipad) */
+ MD5_CTX octx; /* context after H(K XOR opad) */
+};
+
+struct sha1_ctx {
+ SHA1_CTX ictx; /* context after H(K XOR ipad) */
+ SHA1_CTX octx; /* context after H(K XOR opad) */
+};
+
+struct auth_alg {
+ void (*init)(void *ctx);
+ void (*update)(void *ctx, unsigned char *bytes, __u32 len);
+ void (*final)(unsigned char *hash, void *ctx);
+ int hashlen;
+};
+
+extern struct inet_protocol ah_protocol;
+
+struct options;
+
+extern int
+ah_rcv(struct sk_buff *skb,
+ struct device *dev,
+ struct options *opt,
+ __u32 daddr,
+ unsigned short len,
+ __u32 saddr,
+ int redo,
+ struct inet_protocol *protocol);
+
+struct ahhdr /* Generic AH header */
+{
+ __u8 ah_nh; /* Next header (protocol) */
+ __u8 ah_hl; /* AH length, in 32-bit words */
+ __u16 ah_rv; /* reserved, must be 0 */
+ __u32 ah_spi; /* Security Parameters Index */
+ __u32 ah_rpl; /* Replay prevention */
+ __u8 ah_data[AHHMAC_HASHLEN];/* Authentication hash */
+};
+#define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi
+ * and the ah_hl, says how many bytes after that
+ * to cover. */
+
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_ah;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: ipsec_ah.h,v $
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.4.1 2004/03/16 09:48:18 as
+ * alg-0.8.1rc12 patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.20 2003/02/06 02:21:34 rgb
+ *
+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
+ *
+ * Revision 1.19 2002/09/16 21:19:13 mcr
+ * fixes for west-ah-icmp-01 - length of AH header must be
+ * calculated properly, and next_header field properly copied.
+ *
+ * Revision 1.18 2002/05/14 02:37:02 rgb
+ * Change reference from _TDB to _IPSA.
+ *
+ * Revision 1.17 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_ah.h,v
+ *
+ * Revision 1.16 2002/02/20 01:27:06 rgb
+ * Ditched a pile of structs only used by the old Netlink interface.
+ *
+ * Revision 1.15 2001/12/11 02:35:57 rgb
+ * Change "struct net_device" to "struct device" for 2.2 compatibility.
+ *
+ * Revision 1.14 2001/11/26 09:23:47 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.13.2.1 2001/09/25 02:18:24 mcr
+ * replace "struct device" with "struct netdevice"
+ *
+ * Revision 1.13 2001/06/14 19:35:08 rgb
+ * Update copyright date.
+ *
+ * Revision 1.12 2000/09/12 03:21:20 rgb
+ * Cleared out unused htonq.
+ *
+ * Revision 1.11 2000/09/08 19:12:55 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.10 2000/01/21 06:13:10 rgb
+ * Tidied up spacing.
+ * Added macros for HMAC padding magic numbers.(kravietz)
+ *
+ * Revision 1.9 1999/12/07 18:16:23 rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.8 1999/04/11 00:28:56 henry
+ * GPL boilerplate
+ *
+ * Revision 1.7 1999/04/06 04:54:25 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.6 1999/01/26 02:06:01 rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ *
+ * Revision 1.5 1999/01/22 06:17:49 rgb
+ * Updated macro comments.
+ * Added context types to support algorithm switch code.
+ * 64-bit clean-up -- converting 'u long long' to __u64.
+ *
+ * Revision 1.4 1998/07/14 15:54:56 rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.3 1998/06/30 18:05:16 rgb
+ * Comment out references to htonq.
+ *
+ * Revision 1.2 1998/06/25 19:33:46 rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1 1998/06/18 21:27:43 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.4 1998/05/18 22:28:43 rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3 1998/04/21 21:29:07 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2 1998/04/12 22:03:17 rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * ESP-DES-HMAC-MD5-96,
+ * AH-HMAC-MD5-96,
+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1 1998/04/09 03:05:55 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * Added definitions for new AH transforms.
+ *
+ * Revision 0.3 1996/11/20 14:35:48 ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_alg.h b/src/libfreeswan/ipsec_alg.h
new file mode 100644
index 000000000..a393784b1
--- /dev/null
+++ b/src/libfreeswan/ipsec_alg.h
@@ -0,0 +1,254 @@
+/*
+ * Modular extensions service and registration functions interface
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * $Id: ipsec_alg.h,v 1.2 2004/03/22 21:53:18 as Exp $
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ */
+#ifndef IPSEC_ALG_H
+#define IPSEC_ALG_H
+
+/*
+ * gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__
+ * *BUT* its a compiler variable.
+ */
+#if (__GNUC__ >= 3)
+#ifndef __FUNCTION__
+#define __FUNCTION__ __func__
+#endif
+#endif
+
+/* Version 0.8.1-0 */
+#define IPSEC_ALG_VERSION 0x00080100
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+/*
+ * The following structs are used via pointers in ipsec_alg object to
+ * avoid ipsec_alg.h coupling with freeswan headers, thus simplifying
+ * module development
+ */
+struct ipsec_sa;
+struct esp;
+
+/**************************************
+ *
+ * Main registration object
+ *
+ *************************************/
+#define IPSEC_ALG_VERSION_QUAD(v) \
+ (v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff)
+/*
+ * Main ipsec_alg objects: "OOPrograming wannabe"
+ * Hierachy (carefully handled with _minimal_ cast'ing):
+ *
+ * ipsec_alg+
+ * +->ipsec_alg_enc (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT)
+ * +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH)
+ */
+
+/***************************************************************
+ *
+ * INTERFACE object: struct ipsec_alg
+ *
+ ***************************************************************/
+
+/*
+ * common part for every struct ipsec_alg_*
+ * (sortof poor's man OOP)
+ */
+#define IPSEC_ALG_STRUCT_COMMON \
+ unsigned ixt_version; /* only allow this version (or 'near')*/ \
+ struct list_head ixt_list; /* dlinked list */ \
+ struct module *ixt_module; /* THIS_MODULE */ \
+ unsigned ixt_state; /* state flags */ \
+ atomic_t ixt_refcnt; /* ref. count when pointed from ipsec_sa */ \
+ char ixt_name[16]; /* descriptive short name, eg. "3des" */ \
+ void *ixt_data; /* private for algo implementation */ \
+ uint8_t ixt_blocksize; /* blocksize in bytes */ \
+ \
+ /* THIS IS A COPY of struct supported (lib/pfkey.h) \
+ * please keep in sync until we migrate 'supported' stuff \
+ * to ipsec_alg \
+ */ \
+ uint16_t ixt_alg_type; /* correspond to IPSEC_ALG_{ENCRYPT,AUTH} */ \
+ uint8_t ixt_alg_id; /* enc. alg. number, eg. ESP_3DES */ \
+ uint8_t ixt_ivlen; /* ivlen in bits, expected to be multiple of 8! */ \
+ uint16_t ixt_keyminbits;/* min. keybits (of entropy) */ \
+ uint16_t ixt_keymaxbits;/* max. keybits (of entropy) */
+
+#define ixt_support ixt_alg_type
+
+#define IPSEC_ALG_ST_SUPP 0x01
+#define IPSEC_ALG_ST_REGISTERED 0x02
+#define IPSEC_ALG_ST_EXCL 0x04
+struct ipsec_alg {
+ IPSEC_ALG_STRUCT_COMMON
+};
+/*
+ * Note the const in cbc_encrypt IV arg:
+ * some ciphers like to toast passed IV (eg. 3DES): make a local IV copy
+ */
+struct ipsec_alg_enc {
+ IPSEC_ALG_STRUCT_COMMON
+ unsigned ixt_e_keylen; /* raw key length in bytes */
+ unsigned ixt_e_ctx_size; /* sa_p->key_e_size */
+ int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize);
+ __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize);
+ void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e);
+ int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt);
+};
+struct ipsec_alg_auth {
+ IPSEC_ALG_STRUCT_COMMON
+ unsigned ixt_a_keylen; /* raw key length in bytes */
+ unsigned ixt_a_ctx_size; /* sa_p->key_a_size */
+ unsigned ixt_a_authlen; /* 'natural' auth. hash len (bytes) */
+ int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen);
+ int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen);
+};
+/*
+ * These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT},
+ * to avoid header coupling for true constants
+ * about headers ... "cp is your friend" --Linus
+ */
+#define IPSEC_ALG_TYPE_AUTH 14
+#define IPSEC_ALG_TYPE_ENCRYPT 15
+
+/***************************************************************
+ *
+ * INTERFACE for module loading,testing, and unloading
+ *
+ ***************************************************************/
+/* - registration calls */
+int register_ipsec_alg(struct ipsec_alg *);
+int unregister_ipsec_alg(struct ipsec_alg *);
+/* - optional (simple test) for algos */
+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm);
+/* inline wrappers (usefull for type validation */
+static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
+ return register_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
+ return unregister_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
+ return register_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
+ return unregister_ipsec_alg((struct ipsec_alg*)ixt);
+}
+
+/*****************************************************************
+ *
+ * INTERFACE for ENC services: key creation, encrypt function
+ *
+ *****************************************************************/
+
+#define IPSEC_ALG_ENCRYPT 1
+#define IPSEC_ALG_DECRYPT 0
+
+/* encryption key context creation function */
+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p);
+/*
+ * ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns
+ * 0 or ERR<0
+ */
+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action);
+
+/***************************************************************
+ *
+ * INTERFACE for AUTH services: key creation, hash functions
+ *
+ ***************************************************************/
+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p);
+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ;
+#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0)
+
+/* only called from ipsec_init.c */
+int ipsec_alg_init(void);
+
+/* algo module glue for static algos */
+void ipsec_alg_static_init(void);
+typedef int (*ipsec_alg_init_func_t) (void);
+
+/**********************************************
+ *
+ * INTERFACE for ipsec_sa init and wipe
+ *
+ **********************************************/
+
+/* returns true if ipsec_sa has ipsec_alg obj attached */
+/*
+ * Initializes ipsec_sa's ipsec_alg object, using already loaded
+ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth)
+ */
+int ipsec_alg_sa_init(struct ipsec_sa *sa_p);
+/*
+ * Destroys ipsec_sa's ipsec_alg object
+ * unlinking ipsec_alg objects
+ */
+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p);
+
+/**********************************************
+ *
+ * 2.2 backport for some 2.4 useful module stuff
+ *
+ **********************************************/
+#ifdef MODULE
+#ifndef THIS_MODULE
+#define THIS_MODULE (&__this_module)
+#endif
+#ifndef module_init
+typedef int (*__init_module_func_t)(void);
+typedef void (*__cleanup_module_func_t)(void);
+
+#define module_init(x) \
+ int init_module(void) __attribute__((alias(#x))); \
+ static inline __init_module_func_t __init_module_inline(void) \
+ { return x; }
+#define module_exit(x) \
+ void cleanup_module(void) __attribute__((alias(#x))); \
+ static inline __cleanup_module_func_t __cleanup_module_inline(void) \
+ { return x; }
+#endif
+
+#define IPSEC_ALG_MODULE_INIT( func_name ) \
+ static int func_name(void); \
+ module_init(func_name); \
+ static int __init func_name(void)
+#define IPSEC_ALG_MODULE_EXIT( func_name ) \
+ static void func_name(void); \
+ module_exit(func_name); \
+ static void __exit func_name(void)
+#else /* not MODULE */
+#ifndef THIS_MODULE
+#define THIS_MODULE NULL
+#endif
+/*
+ * I only want module_init() magic
+ * when algo.c file *is THE MODULE*, in all other
+ * cases, initialization is called explicitely from ipsec_alg_init()
+ */
+#define IPSEC_ALG_MODULE_INIT( func_name ) \
+ extern int func_name(void); \
+ int func_name(void)
+#define IPSEC_ALG_MODULE_EXIT( func_name ) \
+ extern void func_name(void); \
+ void func_name(void)
+#endif
+
+#endif /* IPSEC_ALG_H */
diff --git a/src/libfreeswan/ipsec_encap.h b/src/libfreeswan/ipsec_encap.h
new file mode 100644
index 000000000..17cd69269
--- /dev/null
+++ b/src/libfreeswan/ipsec_encap.h
@@ -0,0 +1,143 @@
+/*
+ * declarations relevant to encapsulation-like operations
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_encap.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+#ifndef _IPSEC_ENCAP_H_
+
+#define SENT_IP4 16 /* data is two struct in_addr + proto + ports*/
+ /* (2 * sizeof(struct in_addr)) */
+ /* sizeof(struct sockaddr_encap)
+ - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
+
+struct sockaddr_encap
+{
+ __u8 sen_len; /* length */
+ __u8 sen_family; /* AF_ENCAP */
+ __u16 sen_type; /* see SENT_* */
+ union
+ {
+ struct /* SENT_IP4 */
+ {
+ struct in_addr Src;
+ struct in_addr Dst;
+ __u8 Proto;
+ __u16 Sport;
+ __u16 Dport;
+ } Sip4;
+ } Sen;
+};
+
+#define sen_ip_src Sen.Sip4.Src
+#define sen_ip_dst Sen.Sip4.Dst
+#define sen_proto Sen.Sip4.Proto
+#define sen_sport Sen.Sip4.Sport
+#define sen_dport Sen.Sip4.Dport
+
+#ifndef AF_ENCAP
+#define AF_ENCAP 26
+#endif /* AF_ENCAP */
+
+#define _IPSEC_ENCAP_H_
+#endif /* _IPSEC_ENCAP_H_ */
+
+/*
+ * $Log: ipsec_encap.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.17 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_encap.h,v
+ *
+ * Revision 1.16 2001/11/26 09:23:47 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.15.2.1 2001/09/25 02:18:54 mcr
+ * struct eroute moved to ipsec_eroute.h
+ *
+ * Revision 1.15 2001/09/14 16:58:36 rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.14 2001/09/08 21:13:31 rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.13 2001/06/14 19:35:08 rgb
+ * Update copyright date.
+ *
+ * Revision 1.12 2001/05/27 06:12:10 rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.11 2000/09/08 19:12:56 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.10 2000/03/22 16:15:36 rgb
+ * Fixed renaming of dev_get (MB).
+ *
+ * Revision 1.9 2000/01/21 06:13:26 rgb
+ * Added a macro for AF_ENCAP
+ *
+ * Revision 1.8 1999/12/31 14:56:55 rgb
+ * MB fix for 2.3 dev-use-count.
+ *
+ * Revision 1.7 1999/11/18 04:09:18 rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.6 1999/09/24 00:34:13 rgb
+ * Add Marc Boucher's support for 2.3.xx+.
+ *
+ * Revision 1.5 1999/04/11 00:28:57 henry
+ * GPL boilerplate
+ *
+ * Revision 1.4 1999/04/06 04:54:25 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.3 1998/10/19 14:44:28 rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.2 1998/07/14 18:19:33 rgb
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.1 1998/06/18 21:27:44 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2 1998/04/21 21:29:10 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1 1998/04/09 03:05:58 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * Minor cosmetic changes.
+ *
+ * Revision 0.3 1996/11/20 14:35:48 ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_eroute.h b/src/libfreeswan/ipsec_eroute.h
new file mode 100644
index 000000000..2ee2a10b8
--- /dev/null
+++ b/src/libfreeswan/ipsec_eroute.h
@@ -0,0 +1,103 @@
+/*
+ * @(#) declarations of eroute structures
+ *
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * Copyright (C) 2001 Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_eroute.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ *
+ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr.
+ *
+ */
+
+#ifndef _IPSEC_EROUTE_H_
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+
+/*
+ * The "type" is really part of the address as far as the routing
+ * system is concerned. By using only one bit in the type field
+ * for each type, we sort-of make sure that different types of
+ * encapsulation addresses won't be matched against the wrong type.
+ */
+
+/*
+ * An entry in the radix tree
+ */
+
+struct rjtentry
+{
+ struct radij_node rd_nodes[2]; /* tree glue, and other values */
+#define rd_key(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_key))
+#define rd_mask(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask))
+ short rd_flags;
+ short rd_count;
+};
+
+struct ident
+{
+ __u16 type; /* identity type */
+ __u64 id; /* identity id */
+ __u8 len; /* identity len */
+ caddr_t data; /* identity data */
+};
+
+/*
+ * An encapsulation route consists of a pointer to a
+ * radix tree entry and a SAID (a destination_address/SPI/protocol triple).
+ */
+
+struct eroute
+{
+ struct rjtentry er_rjt;
+ struct sa_id er_said;
+ uint32_t er_pid;
+ uint32_t er_count;
+ uint64_t er_lasttime;
+ struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/
+ struct sockaddr_encap er_emask;
+ struct ident er_ident_s;
+ struct ident er_ident_d;
+ struct sk_buff* er_first;
+ struct sk_buff* er_last;
+};
+
+#define er_dst er_said.dst
+#define er_spi er_said.spi
+
+#define _IPSEC_EROUTE_H_
+#endif /* _IPSEC_EROUTE_H_ */
+
+/*
+ * $Log: ipsec_eroute.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.3 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_eroute.h,v
+ *
+ * Revision 1.2 2001/11/26 09:16:13 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1 2001/09/25 02:18:54 mcr
+ * struct eroute moved to ipsec_eroute.h
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/ipsec_errs.h b/src/libfreeswan/ipsec_errs.h
new file mode 100644
index 000000000..f14b5e675
--- /dev/null
+++ b/src/libfreeswan/ipsec_errs.h
@@ -0,0 +1,53 @@
+/*
+ * @(#) definition of ipsec_errs structure
+ *
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_errs.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ *
+ */
+
+/*
+ * This file describes the errors/statistics that FreeSWAN collects.
+ *
+ */
+
+struct ipsec_errs {
+ __u32 ips_alg_errs; /* number of algorithm errors */
+ __u32 ips_auth_errs; /* # of authentication errors */
+ __u32 ips_encsize_errs; /* # of encryption size errors*/
+ __u32 ips_encpad_errs; /* # of encryption pad errors*/
+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */
+};
+
+/*
+ * $Log: ipsec_errs.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.3 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_errs.h,v
+ *
+ * Revision 1.2 2001/11/26 09:16:13 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1 2001/09/25 02:25:57 mcr
+ * lifetime structure created and common functions created.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/ipsec_esp.h b/src/libfreeswan/ipsec_esp.h
new file mode 100644
index 000000000..c7d5ea15d
--- /dev/null
+++ b/src/libfreeswan/ipsec_esp.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_esp.h,v 1.2 2004/03/22 21:53:18 as Exp $
+ */
+
+#include "freeswan/ipsec_md5h.h"
+#include "freeswan/ipsec_sha1.h"
+
+#include "crypto/des.h"
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP 50
+#endif /* IPPROTO_ESP */
+
+#define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/
+
+#define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */
+#define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */
+#define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */
+#define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */
+#define EMT_ESPDES_IV_SZ 8 /* IV size */
+#define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */
+
+#define ESP_IV_MAXSZ 16 /* This is _critical_ */
+#define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ/sizeof(int))
+
+#define DB_ES_PKTRX 0x0001
+#define DB_ES_PKTRX2 0x0002
+#define DB_ES_IPSA 0x0010
+#define DB_ES_XF 0x0020
+#define DB_ES_IPAD 0x0040
+#define DB_ES_INAU 0x0080
+#define DB_ES_OINFO 0x0100
+#define DB_ES_OINFO2 0x0200
+#define DB_ES_OH 0x0400
+#define DB_ES_REPLAY 0x0800
+
+#ifdef __KERNEL__
+struct des_eks {
+ des_key_schedule ks;
+};
+
+extern struct inet_protocol esp_protocol;
+
+struct options;
+
+extern int
+esp_rcv(struct sk_buff *skb,
+ struct device *dev,
+ struct options *opt,
+ __u32 daddr,
+ unsigned short len,
+ __u32 saddr,
+ int redo,
+ struct inet_protocol *protocol);
+
+/* Only for 64 bits IVs, eg. ESP_3DES :P */
+struct esphdr
+{
+ __u32 esp_spi; /* Security Parameters Index */
+ __u32 esp_rpl; /* Replay counter */
+ __u8 esp_iv[8]; /* iv */
+};
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_esp;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: ipsec_esp.h,v $
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.4.1 2004/03/16 09:48:18 as
+ * alg-0.8.1rc12 patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.21 2003/02/06 02:21:34 rgb
+ *
+ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
+ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
+ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
+ *
+ * Revision 1.20 2002/05/14 02:37:02 rgb
+ * Change reference from _TDB to _IPSA.
+ *
+ * Revision 1.19 2002/04/24 07:55:32 mcr
+ * #include patches and Makefiles for post-reorg compilation.
+ *
+ * Revision 1.18 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_esp.h,v
+ *
+ * Revision 1.17 2002/02/20 01:27:07 rgb
+ * Ditched a pile of structs only used by the old Netlink interface.
+ *
+ * Revision 1.16 2001/12/11 02:35:57 rgb
+ * Change "struct net_device" to "struct device" for 2.2 compatibility.
+ *
+ * Revision 1.15 2001/11/26 09:23:48 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.14.2.3 2001/10/23 04:16:42 mcr
+ * get definition of des_key_schedule from des.h
+ *
+ * Revision 1.14.2.2 2001/10/22 20:33:13 mcr
+ * use "des_key_schedule" structure instead of cooking our own.
+ *
+ * Revision 1.14.2.1 2001/09/25 02:18:25 mcr
+ * replace "struct device" with "struct netdevice"
+ *
+ * Revision 1.14 2001/06/14 19:35:08 rgb
+ * Update copyright date.
+ *
+ * Revision 1.13 2000/09/08 19:12:56 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.12 2000/08/01 14:51:50 rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.11 2000/01/10 16:36:20 rgb
+ * Ditch last of EME option flags, including initiator.
+ *
+ * Revision 1.10 1999/12/07 18:16:22 rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.9 1999/04/11 00:28:57 henry
+ * GPL boilerplate
+ *
+ * Revision 1.8 1999/04/06 04:54:25 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.7 1999/01/26 02:06:00 rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ *
+ * Revision 1.6 1999/01/22 15:22:05 rgb
+ * Re-enable IV in the espblkrply_edata structure to avoid breaking pluto
+ * until pluto can be fixed properly.
+ *
+ * Revision 1.5 1999/01/22 06:18:16 rgb
+ * Updated macro comments.
+ * Added key schedule types to support algorithm switch code.
+ *
+ * Revision 1.4 1998/08/12 00:07:32 rgb
+ * Added data structures for new xforms: null, {,3}dessha1.
+ *
+ * Revision 1.3 1998/07/14 15:57:01 rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.2 1998/06/25 19:33:46 rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1 1998/06/18 21:27:45 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.6 1998/06/05 02:28:08 rgb
+ * Minor comment fix.
+ *
+ * Revision 1.5 1998/05/27 22:34:00 rgb
+ * Changed structures to accomodate key separation.
+ *
+ * Revision 1.4 1998/05/18 22:28:43 rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3 1998/04/21 21:29:07 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2 1998/04/12 22:03:20 rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * ESP-DES-HMAC-MD5-96,
+ * AH-HMAC-MD5-96,
+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1 1998/04/09 03:06:00 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5 1997/06/03 04:24:48 ji
+ * Added ESP-3DES-MD5-96 transform.
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * Added definitions for new ESP transforms.
+ *
+ * Revision 0.3 1996/11/20 14:35:48 ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_ipe4.h b/src/libfreeswan/ipsec_ipe4.h
new file mode 100644
index 000000000..73b6ae899
--- /dev/null
+++ b/src/libfreeswan/ipsec_ipe4.h
@@ -0,0 +1,68 @@
+/*
+ * IP-in-IP Header declarations
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_ipe4.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+/* The packet header is an IP header! */
+
+struct ipe4_xdata /* transform table data */
+{
+ struct in_addr i4_src;
+ struct in_addr i4_dst;
+};
+
+#define EMT_IPE4_ULEN 8 /* coming from user mode */
+
+
+/*
+ * $Log: ipsec_ipe4.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.5 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_ipe4.h,v
+ *
+ * Revision 1.4 2001/06/14 19:35:08 rgb
+ * Update copyright date.
+ *
+ * Revision 1.3 1999/04/11 00:28:57 henry
+ * GPL boilerplate
+ *
+ * Revision 1.2 1999/04/06 04:54:25 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.1 1998/06/18 21:27:47 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.1 1998/04/09 03:06:07 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * No changes.
+ *
+ * Revision 0.3 1996/11/20 14:48:53 ji
+ * Release update only.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_kversion.h b/src/libfreeswan/ipsec_kversion.h
new file mode 100644
index 000000000..7bf56ac7f
--- /dev/null
+++ b/src/libfreeswan/ipsec_kversion.h
@@ -0,0 +1,227 @@
+#ifndef _FREESWAN_KVERSIONS_H
+/*
+ * header file for FreeS/WAN library functions
+ * Copyright (C) 1998, 1999, 2000 Henry Spencer.
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ipsec_kversion.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+#define _FREESWAN_KVERSIONS_H /* seen it, no need to see it again */
+
+/*
+ * this file contains a series of atomic defines that depend upon
+ * kernel version numbers. The kernel versions are arranged
+ * in version-order number (which is often not chronological)
+ * and each clause enables or disables a feature.
+ */
+
+/*
+ * First, assorted kernel-version-dependent trickery.
+ */
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#define HEADER_CACHE_BIND_21
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define SPINLOCK
+#define PROC_FS_21
+#define NETLINK_SOCK
+#define NET_21
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19)
+#define net_device_stats enet_statistics
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#define SPINLOCK_23
+#define NETDEV_23
+# ifndef CONFIG_IP_ALIAS
+# define CONFIG_IP_ALIAS
+# endif
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+# ifdef NETLINK_XFRM
+# define NETDEV_25
+# endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25)
+#define PROC_FS_2325
+#undef PROC_FS_21
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
+#define PROC_NO_DUMMY
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35)
+#define SKB_COPY_EXPAND
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37)
+#define IP_SELECT_IDENT
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER)
+#define SKB_RESET_NFCT
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2)
+#define IP_SELECT_IDENT_NEW
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
+#define IPH_is_SKB_PULLED
+#define SKB_COW_NEW
+#define PROTO_HANDLER_SINGLE_PARM
+#define IP_FRAGMENT_LINEARIZE 1
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
+# ifdef REDHAT_BOGOSITY
+# define IP_SELECT_IDENT_NEW
+# define IPH_is_SKB_PULLED
+# define SKB_COW_NEW
+# define PROTO_HANDLER_SINGLE_PARM
+# endif /* REDHAT_BOGOSITY */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
+#define MALLOC_SLAB
+#define LINUX_KERNEL_HAS_SNPRINTF
+#endif
+
+#ifdef NET_21
+# include <linux/in6.h>
+#else
+ /* old kernel in.h has some IPv6 stuff, but not quite enough */
+# define s6_addr16 s6_addr
+# define AF_INET6 10
+# define uint8_t __u8
+# define uint16_t __u16
+# define uint32_t __u32
+# define uint64_t __u64
+#endif
+
+#ifdef NET_21
+# define ipsec_kfree_skb(a) kfree_skb(a)
+#else /* NET_21 */
+# define ipsec_kfree_skb(a) kfree_skb(a, FREE_WRITE)
+#endif /* NET_21 */
+
+#ifdef NETDEV_23
+# define device net_device
+# define ipsec_dev_get dev_get_by_name
+# define __ipsec_dev_get __dev_get_by_name
+# define ipsec_dev_put(x) dev_put(x)
+# define __ipsec_dev_put(x) __dev_put(x)
+# define ipsec_dev_hold(x) dev_hold(x)
+#else /* NETDEV_23 */
+# define ipsec_dev_get dev_get
+# define __ipsec_dev_put(x)
+# define ipsec_dev_put(x)
+# define ipsec_dev_hold(x)
+#endif /* NETDEV_23 */
+
+#ifndef SPINLOCK
+# include <linux/bios32.h>
+ /* simulate spin locks and read/write locks */
+ typedef struct {
+ volatile char lock;
+ } spinlock_t;
+
+ typedef struct {
+ volatile unsigned int lock;
+ } rwlock_t;
+
+# define spin_lock_init(x) { (x)->lock = 0;}
+# define rw_lock_init(x) { (x)->lock = 0; }
+
+# define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;}
+# define spin_lock_irq(x) { cli(); spin_lock(x);}
+# define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);}
+
+# define spin_unlock(x) { (x)->lock=0;}
+# define spin_unlock_irq(x) { spin_unlock(x); sti();}
+# define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);}
+
+# define read_lock(x) spin_lock(x)
+# define read_lock_irq(x) spin_lock_irq(x)
+# define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
+
+# define read_unlock(x) spin_unlock(x)
+# define read_unlock_irq(x) spin_unlock_irq(x)
+# define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
+
+# define write_lock(x) spin_lock(x)
+# define write_lock_irq(x) spin_lock_irq(x)
+# define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
+
+# define write_unlock(x) spin_unlock(x)
+# define write_unlock_irq(x) spin_unlock_irq(x)
+# define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
+#endif /* !SPINLOCK */
+
+#ifndef SPINLOCK_23
+# define spin_lock_bh(x) spin_lock_irq(x)
+# define spin_unlock_bh(x) spin_unlock_irq(x)
+
+# define read_lock_bh(x) read_lock_irq(x)
+# define read_unlock_bh(x) read_unlock_irq(x)
+
+# define write_lock_bh(x) write_lock_irq(x)
+# define write_unlock_bh(x) write_unlock_irq(x)
+#endif /* !SPINLOCK_23 */
+
+#endif /* _FREESWAN_KVERSIONS_H */
+
+/*
+ * $Log: ipsec_kversion.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.7 2003/07/31 22:48:08 mcr
+ * derive NET25-ness from presence of NETLINK_XFRM macro.
+ *
+ * Revision 1.6 2003/06/24 20:22:32 mcr
+ * added new global: ipsecdevices[] so that we can keep track of
+ * the ipsecX devices. They will be referenced with dev_hold(),
+ * so 2.2 may need this as well.
+ *
+ * Revision 1.5 2003/04/03 17:38:09 rgb
+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
+ *
+ * Revision 1.4 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_kversion.h,v
+ *
+ * Revision 1.3 2002/04/12 03:21:17 mcr
+ * three parameter version of ip_select_ident appears first
+ * in 2.4.2 (RH7.1) not 2.4.4.
+ *
+ * Revision 1.2 2002/03/08 21:35:22 rgb
+ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after
+ * 2.4.9. (Andreas Piesk).
+ *
+ * Revision 1.1 2002/01/29 02:11:42 mcr
+ * removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * updating of IPv6 structures to match latest in6.h version.
+ * removed dead code from freeswan.h that also duplicated kversions.h
+ * code.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_life.h b/src/libfreeswan/ipsec_life.h
new file mode 100644
index 000000000..4cf270272
--- /dev/null
+++ b/src/libfreeswan/ipsec_life.h
@@ -0,0 +1,112 @@
+/*
+ * Definitions relevant to IPSEC lifetimes
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_life.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ *
+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
+ *
+ */
+
+/*
+ * This file describes the book keeping fields for the
+ * IPsec Security Association Structure. ("ipsec_sa")
+ *
+ * This structure is never allocated directly by kernel code,
+ * (it is always a static/auto or is part of a structure)
+ * so it does not have a reference count.
+ *
+ */
+
+#ifndef _IPSEC_LIFE_H_
+
+/*
+ * _count is total count.
+ * _hard is hard limit (kill SA after this number)
+ * _soft is soft limit (try to renew SA after this number)
+ * _last is used in some special cases.
+ *
+ */
+
+struct ipsec_lifetime64
+{
+ __u64 ipl_count;
+ __u64 ipl_soft;
+ __u64 ipl_hard;
+ __u64 ipl_last;
+};
+
+struct ipsec_lifetimes
+{
+ /* number of bytes processed */
+ struct ipsec_lifetime64 ipl_bytes;
+
+ /* number of packets processed */
+ struct ipsec_lifetime64 ipl_packets;
+
+ /* time since SA was added */
+ struct ipsec_lifetime64 ipl_addtime;
+
+ /* time since SA was first used */
+ struct ipsec_lifetime64 ipl_usetime;
+
+ /* from rfc2367:
+ * For CURRENT, the number of different connections,
+ * endpoints, or flows that the association has been
+ * allocated towards. For HARD and SOFT, the number of
+ * these the association may be allocated towards
+ * before it expires. The concept of a connection,
+ * flow, or endpoint is system specific.
+ *
+ * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN.
+ * They are maintained for PF_KEY compatibility.
+ */
+ struct ipsec_lifetime64 ipl_allocations;
+};
+
+enum ipsec_life_alive {
+ ipsec_life_harddied = -1,
+ ipsec_life_softdied = 0,
+ ipsec_life_okay = 1
+};
+
+enum ipsec_life_type {
+ ipsec_life_timebased = 1,
+ ipsec_life_countbased= 0
+};
+
+#define _IPSEC_LIFE_H_
+#endif /* _IPSEC_LIFE_H_ */
+
+
+/*
+ * $Log: ipsec_life.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.3 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_life.h,v
+ *
+ * Revision 1.2 2001/11/26 09:16:14 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1 2001/09/25 02:25:58 mcr
+ * lifetime structure created and common functions created.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/ipsec_md5h.h b/src/libfreeswan/ipsec_md5h.h
new file mode 100644
index 000000000..3fc54bc82
--- /dev/null
+++ b/src/libfreeswan/ipsec_md5h.h
@@ -0,0 +1,140 @@
+/*
+ * RCSID $Id: ipsec_md5h.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+/*
+ * The rest of this file is Copyright RSA DSI. See the following comments
+ * for the full Copyright notice.
+ */
+
+#ifndef _IPSEC_MD5H_H_
+#define _IPSEC_MD5H_H_
+
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+ function argument prototyping.
+ The following makes PROTOTYPES default to 0 if it has not already
+ been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 1
+#endif /* !PROTOTYPES */
+
+/* POINTER defines a generic pointer type */
+typedef __u8 *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef __u16 UINT2;
+
+/* UINT4 defines a four byte word */
+typedef __u32 UINT4;
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+ returns an empty list.
+ */
+
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else /* PROTOTYPES */
+#define PROTO_LIST(list) ()
+#endif /* PROTOTYPES */
+
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((void *));
+void MD5Update PROTO_LIST
+ ((void *, unsigned char *, __u32));
+void MD5Final PROTO_LIST ((unsigned char [16], void *));
+
+#endif /* _IPSEC_MD5H_H_ */
+
+/*
+ * $Log: ipsec_md5h.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.8 2002/09/10 01:45:09 mcr
+ * changed type of MD5_CTX and SHA1_CTX to void * so that
+ * the function prototypes would match, and could be placed
+ * into a pointer to a function.
+ *
+ * Revision 1.7 2002/04/24 07:36:46 mcr
+ * Moved from ./klips/net/ipsec/ipsec_md5h.h,v
+ *
+ * Revision 1.6 1999/12/13 13:59:13 rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.5 1999/12/07 18:16:23 rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.4 1999/04/06 04:54:26 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.3 1999/01/22 06:19:58 rgb
+ * 64-bit clean-up.
+ *
+ * Revision 1.2 1998/11/30 13:22:54 rgb
+ * Rationalised all the klips kernel file headers. They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.1 1998/06/18 21:27:48 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2 1998/04/23 20:54:03 rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1 1998/04/09 03:04:21 henry
+ * sources moved up from linux/net/ipsec
+ * these two include files modified not to include others except in kernel
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:03 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * No changes.
+ *
+ * Revision 0.3 1996/11/20 14:48:53 ji
+ * Release update only.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_param.h b/src/libfreeswan/ipsec_param.h
new file mode 100644
index 000000000..02b36e6a3
--- /dev/null
+++ b/src/libfreeswan/ipsec_param.h
@@ -0,0 +1,226 @@
+/*
+ * @(#) FreeSWAN tunable paramaters
+ *
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_param.h,v 1.2 2004/04/28 08:07:11 as Exp $
+ *
+ */
+
+/*
+ * This file provides a set of #define's which may be tuned by various
+ * people/configurations. It keeps all compile-time tunables in one place.
+ *
+ * This file should be included before all other IPsec kernel-only files.
+ *
+ */
+
+#ifndef _IPSEC_PARAM_H_
+
+#ifdef __KERNEL__
+#include "ipsec_kversion.h"
+
+/* Set number of ipsecX virtual devices here. */
+/* This must be < exp(field width of IPSEC_DEV_FORMAT) */
+/* It must also be reasonable so as not to overload the memory and CPU */
+/* constraints of the host. */
+#define IPSEC_NUM_IF 4
+/* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */
+/* With "ipsec" being 5 characters, that means 10 is the max field width */
+/* but machine memory and CPU constraints are not likely to tollerate */
+/* more than 3 digits. The default is one digit. */
+/* Update: userland scripts get upset if they can't find "ipsec0", so */
+/* for now, no "0"-padding should be used (which would have been helpful */
+/* to make text-searches work */
+#define IPSEC_DEV_FORMAT "ipsec%d"
+/* For, say, 500 virtual ipsec devices, I would recommend: */
+/* #define IPSEC_NUM_IF 500 */
+/* #define IPSEC_DEV_FORMAT "ipsec%03d" */
+/* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */
+
+/* use dynamic ipsecX device allocation */
+#ifndef CONFIG_IPSEC_DYNDEV
+#define CONFIG_IPSEC_DYNDEV 1
+#endif /* CONFIG_IPSEC_DYNDEV */
+
+
+#ifdef CONFIG_IPSEC_BIGGATE
+# define SADB_HASHMOD 8069
+#else /* CONFIG_IPSEC_BIGGATE */
+# define SADB_HASHMOD 257
+#endif /* CONFIG_IPSEC_BIGGATE */
+#endif /* __KERNEL__ */
+
+/*
+ * This is for the SA reference table. This number is related to the
+ * maximum number of SAs that KLIPS can concurrently deal with, plus enough
+ * space for keeping expired SAs around.
+ *
+ * TABLE_MAX_WIDTH is the number of bits that we will use.
+ * MAIN_TABLE_WIDTH is the number of bits used for the primary index table.
+ *
+ */
+#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH
+# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16
+#endif
+
+#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH
+# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4
+#endif
+
+#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES
+# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256
+#endif
+
+#ifndef IPSEC_SA_REF_CODE
+# define IPSEC_SA_REF_CODE 1
+#endif
+
+#ifdef __KERNEL__
+/* This is defined for 2.4, but not 2.2.... */
+#ifndef ARPHRD_VOID
+# define ARPHRD_VOID 0xFFFF
+#endif
+
+/*
+ * Worry about PROC_FS stuff
+ */
+#if defined(PROC_FS_2325)
+/* kernel 2.4 */
+# define IPSEC_PROC_LAST_ARG ,int *eof,void *data
+# define IPSEC_PROCFS_DEBUG_NO_STATIC
+# define IPSEC_PROC_SUBDIRS
+#else
+/* kernel <2.4 */
+# define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC
+
+# ifndef PROC_NO_DUMMY
+# define IPSEC_PROC_LAST_ARG , int dummy
+# else
+# define IPSEC_PROC_LAST_ARG
+# endif /* !PROC_NO_DUMMY */
+#endif /* PROC_FS_2325 */
+
+#if !defined(LINUX_KERNEL_HAS_SNPRINTF)
+/* GNU CPP specific! */
+# define snprintf(buf, len, fmt...) sprintf(buf, ##fmt)
+#endif /* !LINUX_KERNEL_HAS_SNPRINTF */
+
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+# include <linux/spinlock.h> /* *lock* */
+# else /* SPINLOCK_23 */
+# include <asm/spinlock.h> /* *lock* */
+# endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+
+#ifndef KLIPS_FIXES_DES_PARITY
+# define KLIPS_FIXES_DES_PARITY 1
+#endif /* !KLIPS_FIXES_DES_PARITY */
+
+/* we don't really want to print these unless there are really big problems */
+#ifndef KLIPS_DIVULGE_CYPHER_KEY
+# define KLIPS_DIVULGE_CYPHER_KEY 0
+#endif /* !KLIPS_DIVULGE_CYPHER_KEY */
+
+#ifndef KLIPS_DIVULGE_HMAC_KEY
+# define KLIPS_DIVULGE_HMAC_KEY 0
+#endif /* !KLIPS_DIVULGE_HMAC_KEY */
+
+#ifndef IPSEC_DISALLOW_IPOPTIONS
+# define IPSEC_DISALLOW_IPOPTIONS 1
+#endif /* !KLIPS_DIVULGE_HMAC_KEY */
+
+/* extra toggles for regression testing */
+#ifdef CONFIG_IPSEC_REGRESS
+
+/*
+ * should pfkey_acquire() become 100% lossy?
+ *
+ */
+extern int sysctl_ipsec_regress_pfkey_lossage;
+#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE
+# ifdef CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE
+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100
+# else /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */
+/* not by default! */
+# define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0
+# endif /* CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE */
+#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */
+
+#endif /* CONFIG_IPSEC_REGRESS */
+
+/*
+ * debugging routines.
+ */
+#ifdef CONFIG_IPSEC_DEBUG
+extern void ipsec_print_ip(struct iphdr *ip);
+
+ #define KLIPS_PRINT(flag, format, args...) \
+ ((flag) ? printk(KERN_INFO format , ## args) : 0)
+ #define KLIPS_PRINTMORE(flag, format, args...) \
+ ((flag) ? printk(format , ## args) : 0)
+ #define KLIPS_IP_PRINT(flag, ip) \
+ ((flag) ? ipsec_print_ip(ip) : 0)
+#else /* CONFIG_IPSEC_DEBUG */
+ #define KLIPS_PRINT(flag, format, args...) do ; while(0)
+ #define KLIPS_PRINTMORE(flag, format, args...) do ; while(0)
+ #define KLIPS_IP_PRINT(flag, ip) do ; while(0)
+#endif /* CONFIG_IPSEC_DEBUG */
+
+
+/*
+ * Stupid kernel API differences in APIs. Not only do some
+ * kernels not have ip_select_ident, but some have differing APIs,
+ * and SuSE has one with one parameter, but no way of checking to
+ * see what is really what.
+ */
+
+#ifdef SUSE_LINUX_2_4_19_IS_STUPID
+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph)
+#else
+
+/* simplest case, nothing */
+#if !defined(IP_SELECT_IDENT)
+#define KLIPS_IP_SELECT_IDENT(iph, skb) do { iph->id = htons(ip_id_count++); } while(0)
+#endif
+
+/* kernels > 2.3.37-ish */
+#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW)
+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst)
+#endif
+
+/* kernels > 2.4.2 */
+#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW)
+#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL)
+#endif
+
+#endif /* SUSE_LINUX_2_4_19_IS_STUPID */
+
+/*
+ * make klips fail test:east-espiv-01.
+ * exploit is at testing/attacks/espiv
+ *
+ */
+#define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0
+
+
+/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */
+#ifndef IP_FRAGMENT_LINEARIZE
+# define IP_FRAGMENT_LINEARIZE 0
+#endif /* IP_FRAGMENT_LINEARIZE */
+#endif /* __KERNEL__ */
+
+#define _IPSEC_PARAM_H_
+#endif /* _IPSEC_PARAM_H_ */
diff --git a/src/libfreeswan/ipsec_policy.h b/src/libfreeswan/ipsec_policy.h
new file mode 100644
index 000000000..671919e4b
--- /dev/null
+++ b/src/libfreeswan/ipsec_policy.h
@@ -0,0 +1,225 @@
+#ifndef _IPSEC_POLICY_H
+/*
+ * policy interface file between pluto and applications
+ * Copyright (C) 2003 Michael Richardson <mcr@freeswan.org>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ipsec_policy.h,v 1.4 2004/10/04 22:43:56 as Exp $
+ */
+#define _IPSEC_POLICY_H /* seen it, no need to see it again */
+
+
+/*
+ * this file defines an interface between an application (or rather an
+ * application library) and a key/policy daemon. It provides for inquiries
+ * as to the current state of a connected socket, as well as for general
+ * questions.
+ *
+ * In general, the interface is defined as a series of functional interfaces,
+ * and the policy messages should be internal. However, because this is in
+ * fact an ABI between pieces of the system that may get compiled and revised
+ * seperately, this ABI must be public and revision controlled.
+ *
+ * It is expected that the daemon will always support previous versions.
+ */
+
+#define IPSEC_POLICY_MSG_REVISION (unsigned)200305061
+
+enum ipsec_policy_command {
+ IPSEC_CMD_QUERY_FD = 1,
+ IPSEC_CMD_QUERY_HOSTPAIR = 2,
+ IPSEC_CMD_QUERY_DSTONLY = 3,
+};
+
+struct ipsec_policy_msg_head {
+ u_int32_t ipm_version;
+ u_int32_t ipm_msg_len;
+ u_int32_t ipm_msg_type;
+ u_int32_t ipm_msg_seq;
+};
+
+enum ipsec_privacy_quality {
+ IPSEC_PRIVACY_NONE = 0,
+ IPSEC_PRIVACY_INTEGRAL = 4, /* not private at all. AH-like */
+ IPSEC_PRIVACY_UNKNOWN = 8, /* something is claimed, but details unavail */
+ IPSEC_PRIVACY_ROT13 = 12, /* trivially breakable, i.e. 1DES */
+ IPSEC_PRIVACY_GAK = 16, /* known eavesdroppers */
+ IPSEC_PRIVACY_PRIVATE = 32, /* secure for at least a decade */
+ IPSEC_PRIVACY_STRONG = 64, /* ridiculously secure */
+ IPSEC_PRIVACY_TORTOISE = 192, /* even stronger, but very slow */
+ IPSEC_PRIVACY_OTP = 224, /* some kind of *true* one time pad */
+};
+
+enum ipsec_bandwidth_quality {
+ IPSEC_QOS_UNKNOWN = 0, /* unknown bandwidth */
+ IPSEC_QOS_INTERACTIVE = 16, /* reasonably moderate jitter, moderate fast.
+ Good enough for telnet/ssh. */
+ IPSEC_QOS_VOIP = 32, /* faster crypto, predicable jitter */
+ IPSEC_QOS_FTP = 64, /* higher throughput crypto, perhaps hardware
+ offloaded, but latency/jitter may be bad */
+ IPSEC_QOS_WIRESPEED = 128, /* expect to be able to fill your pipe */
+};
+
+/* moved from programs/pluto/constants.h */
+/* IPsec AH transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3
+ * and in http://www.iana.org/assignments/isakmp-registry
+ */
+enum ipsec_authentication_algo {
+ AH_NONE = 0,
+ AH_MD5 = 2,
+ AH_SHA = 3,
+ AH_DES = 4,
+ AH_SHA2_256 = 5,
+ AH_SHA2_384 = 6,
+ AH_SHA2_512 = 7,
+ AH_RIPEMD = 8
+};
+
+/* IPsec ESP transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4
+ * and from http://www.iana.org/assignments/isakmp-registry
+ */
+
+enum ipsec_cipher_algo {
+ ESP_NONE = 0,
+ ESP_DES_IV64 = 1,
+ ESP_DES = 2,
+ ESP_3DES = 3,
+ ESP_RC5 = 4,
+ ESP_IDEA = 5,
+ ESP_CAST = 6,
+ ESP_BLOWFISH = 7,
+ ESP_3IDEA = 8,
+ ESP_DES_IV32 = 9,
+ ESP_RC4 = 10,
+ ESP_NULL = 11,
+ ESP_AES = 12,
+ ESP_AES_CTR = 13,
+ ESP_AES_CCM_8 = 14,
+ ESP_AES_CCM_12 = 15,
+ ESP_AES_CCM_16 = 16,
+ ESP_SERPENT = 252,
+ ESP_TWOFISH = 253
+};
+
+/* IPCOMP transform values
+ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5
+ */
+
+enum ipsec_comp_algo {
+ IPSCOMP_NONE = 0,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4
+};
+
+/* Identification type values
+ * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1
+ */
+
+enum ipsec_id_type {
+ ID_IMPOSSIBLE= (-2), /* private to Pluto */
+ ID_MYID= (-1), /* private to Pluto */
+ ID_NONE= 0, /* private to Pluto */
+ ID_IPV4_ADDR= 1,
+ ID_FQDN= 2,
+ ID_USER_FQDN= 3,
+ ID_IPV4_ADDR_SUBNET= 4,
+ ID_IPV6_ADDR= 5,
+ ID_IPV6_ADDR_SUBNET= 6,
+ ID_IPV4_ADDR_RANGE= 7,
+ ID_IPV6_ADDR_RANGE= 8,
+ ID_DER_ASN1_DN= 9,
+ ID_DER_ASN1_GN= 10,
+ ID_KEY_ID= 11
+};
+
+/* Certificate type values
+ * RFC 2408 ISAKMP, chapter 3.9
+ */
+enum ipsec_cert_type {
+ CERT_NONE= 0,
+ CERT_PKCS7_WRAPPED_X509= 1,
+ CERT_PGP= 2,
+ CERT_DNS_SIGNED_KEY= 3,
+ CERT_X509_SIGNATURE= 4,
+ CERT_X509_KEY_EXCHANGE= 5,
+ CERT_KERBEROS_TOKENS= 6,
+ CERT_CRL= 7,
+ CERT_ARL= 8,
+ CERT_SPKI= 9,
+ CERT_X509_ATTRIBUTE= 10,
+ CERT_RAW_RSA_KEY= 11
+};
+
+/* a SIG record in ASCII */
+struct ipsec_dns_sig {
+ char fqdn[256];
+ char dns_sig[768]; /* empty string if not signed */
+};
+
+struct ipsec_raw_key {
+ char id_name[256];
+ char fs_keyid[8];
+};
+
+struct ipsec_identity {
+ enum ipsec_id_type ii_type;
+ enum ipsec_cert_type ii_format;
+ union {
+ struct ipsec_dns_sig ipsec_dns_signed;
+ /* some thing for PGP */
+ /* some thing for PKIX */
+ struct ipsec_raw_key ipsec_raw_key;
+ } ii_credential;
+};
+
+#define IPSEC_MAX_CREDENTIALS 32
+
+struct ipsec_policy_cmd_query {
+ struct ipsec_policy_msg_head head;
+
+ /* Query section */
+ ip_address query_local; /* us */
+ ip_address query_remote; /* them */
+ u_short src_port, dst_port;
+
+ /* Answer section */
+ enum ipsec_privacy_quality strength;
+ enum ipsec_bandwidth_quality bandwidth;
+ enum ipsec_authentication_algo auth_detail;
+ enum ipsec_cipher_algo esp_detail;
+ enum ipsec_comp_algo comp_detail;
+
+ int credential_count;
+
+ struct ipsec_identity credentials[IPSEC_MAX_CREDENTIALS];
+};
+
+#define IPSEC_POLICY_SOCKET "/var/run/pluto.info"
+
+/* prototypes */
+extern err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result);
+extern err_t ipsec_policy_init(void);
+extern err_t ipsec_policy_final(void);
+extern err_t ipsec_policy_readmsg(int policysock,
+ unsigned char *buf, size_t buflen);
+extern err_t ipsec_policy_sendrecv(unsigned char *buf, size_t buflen);
+extern err_t ipsec_policy_cgilookup(struct ipsec_policy_cmd_query *result);
+
+
+extern const char *ipsec_policy_version_code(void);
+extern const char *ipsec_policy_version_string(void);
+
+#endif /* _IPSEC_POLICY_H */
diff --git a/src/libfreeswan/ipsec_proto.h b/src/libfreeswan/ipsec_proto.h
new file mode 100644
index 000000000..55f947512
--- /dev/null
+++ b/src/libfreeswan/ipsec_proto.h
@@ -0,0 +1,111 @@
+/*
+ * @(#) prototypes for FreeSWAN functions
+ *
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_proto.h,v 1.3 2004/06/13 19:55:14 as Exp $
+ *
+ */
+
+#ifndef _IPSEC_PROTO_H_
+
+#include "ipsec_param.h"
+
+/*
+ * This file is a kernel only file that declares prototypes for
+ * all intra-module function calls and global data structures.
+ *
+ * Include this file last.
+ *
+ */
+
+/* ipsec_init.c */
+extern struct prng ipsec_prng;
+
+/* ipsec_sa.c */
+extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
+extern spinlock_t tdb_lock;
+extern int ipsec_sadb_init(void);
+
+extern struct ipsec_sa *ipsec_sa_getbyid(struct sa_id*);
+extern int ipsec_sa_put(struct ipsec_sa *);
+extern /* void */ int ipsec_sa_del(struct ipsec_sa *);
+extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *);
+extern /* void */ int ipsec_sa_add(struct ipsec_sa *);
+
+extern int ipsec_sadb_cleanup(__u8);
+extern int ipsec_sa_wipe(struct ipsec_sa *);
+
+/* debug declarations */
+
+/* ipsec_proc.c */
+extern int ipsec_proc_init(void);
+extern void ipsec_proc_cleanup(void);
+
+/* ipsec_radij.c */
+extern int ipsec_makeroute(struct sockaddr_encap *ea,
+ struct sockaddr_encap *em,
+ struct sa_id said,
+ uint32_t pid,
+ struct sk_buff *skb,
+ struct ident *ident_s,
+ struct ident *ident_d);
+
+extern int ipsec_breakroute(struct sockaddr_encap *ea,
+ struct sockaddr_encap *em,
+ struct sk_buff **first,
+ struct sk_buff **last);
+
+int ipsec_radijinit(void);
+int ipsec_cleareroutes(void);
+int ipsec_radijcleanup(void);
+
+/* ipsec_life.c */
+extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64,
+ const char *lifename,
+ const char *saname,
+ enum ipsec_life_type ilt,
+ enum ipsec_direction idir,
+ struct ipsec_sa *ips);
+
+
+extern int ipsec_lifetime_format(char *buffer,
+ int buflen,
+ char *lifename,
+ enum ipsec_life_type timebaselife,
+ struct ipsec_lifetime64 *lifetime);
+
+extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime,
+ __u64 newvalue);
+
+extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime,
+ __u64 newvalue);
+
+
+
+
+#ifdef CONFIG_IPSEC_DEBUG
+
+extern int debug_xform;
+extern int debug_eroute;
+extern int debug_spi;
+extern int debug_netlink;
+
+#endif /* CONFIG_IPSEC_DEBUG */
+
+
+
+
+#define _IPSEC_PROTO_H
+#endif /* _IPSEC_PROTO_H_ */
diff --git a/src/libfreeswan/ipsec_radij.h b/src/libfreeswan/ipsec_radij.h
new file mode 100644
index 000000000..7776dd8e4
--- /dev/null
+++ b/src/libfreeswan/ipsec_radij.h
@@ -0,0 +1,63 @@
+/*
+ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_radij.h,v 1.3 2004/04/28 05:44:29 as Exp $
+ */
+
+#ifndef _IPSEC_RADIJ_H
+
+#include <freeswan.h>
+
+int ipsec_walk(char *);
+
+int ipsec_rj_walker_procprint(struct radij_node *, void *);
+int ipsec_rj_walker_delete(struct radij_node *, void *);
+
+/* This structure is used to pass information between
+ * ipsec_eroute_get_info and ipsec_rj_walker_procprint
+ * (through rj_walktree) and between calls of ipsec_rj_walker_procprint.
+ */
+struct wsbuf
+{
+ /* from caller of ipsec_eroute_get_info: */
+ char *const buffer; /* start of buffer provided */
+ const int length; /* length of buffer provided */
+ const off_t offset; /* file position of first character of interest */
+ /* accumulated by ipsec_rj_walker_procprint: */
+ int len; /* number of character filled into buffer */
+ off_t begin; /* file position contained in buffer[0] (<=offset) */
+};
+
+
+extern struct radij_node_head *rnh;
+extern spinlock_t eroute_lock;
+
+struct eroute * ipsec_findroute(struct sockaddr_encap *);
+
+#define O1(x) (int)(((x)>>24)&0xff)
+#define O2(x) (int)(((x)>>16)&0xff)
+#define O3(x) (int)(((x)>>8)&0xff)
+#define O4(x) (int)(((x))&0xff)
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_radij;
+void rj_dumptrees(void);
+
+#define DB_RJ_DUMPTREES 0x0001
+#define DB_RJ_FINDROUTE 0x0002
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define _IPSEC_RADIJ_H
+#endif
diff --git a/src/libfreeswan/ipsec_rcv.h b/src/libfreeswan/ipsec_rcv.h
new file mode 100644
index 000000000..3ae239bf9
--- /dev/null
+++ b/src/libfreeswan/ipsec_rcv.h
@@ -0,0 +1,196 @@
+/*
+ *
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_rcv.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+#define DB_RX_PKTRX 0x0001
+#define DB_RX_PKTRX2 0x0002
+#define DB_RX_DMP 0x0004
+#define DB_RX_IPSA 0x0010
+#define DB_RX_XF 0x0020
+#define DB_RX_IPAD 0x0040
+#define DB_RX_INAU 0x0080
+#define DB_RX_OINFO 0x0100
+#define DB_RX_OINFO2 0x0200
+#define DB_RX_OH 0x0400
+#define DB_RX_REPLAY 0x0800
+
+#ifdef __KERNEL__
+/* struct options; */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/config.h> /* for CONFIG_IP_FORWARD */
+#include <linux/version.h>
+#include <freeswan.h>
+
+#define IPSEC_BIRTH_TEMPLATE_MAXLEN 256
+
+struct ipsec_birth_reply {
+ int packet_template_len;
+ unsigned char packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN];
+};
+
+extern struct ipsec_birth_reply ipsec_ipv4_birth_packet;
+extern struct ipsec_birth_reply ipsec_ipv6_birth_packet;
+
+extern int
+#ifdef PROTO_HANDLER_SINGLE_PARM
+ipsec_rcv(struct sk_buff *skb);
+#else /* PROTO_HANDLER_SINGLE_PARM */
+ipsec_rcv(struct sk_buff *skb,
+#ifdef NET_21
+ unsigned short xlen);
+#else /* NET_21 */
+ struct device *dev,
+ struct options *opt,
+ __u32 daddr,
+ unsigned short len,
+ __u32 saddr,
+ int redo,
+ struct inet_protocol *protocol);
+#endif /* NET_21 */
+#endif /* PROTO_HANDLER_SINGLE_PARM */
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_rcv;
+#endif /* CONFIG_IPSEC_DEBUG */
+extern int sysctl_ipsec_inbound_policy_check;
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: ipsec_rcv.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.17 2002/09/03 16:32:32 mcr
+ * definitions of ipsec_birth_reply.
+ *
+ * Revision 1.16 2002/05/14 02:36:00 rgb
+ * Change references to _TDB to _IPSA.
+ *
+ * Revision 1.15 2002/04/24 07:36:47 mcr
+ * Moved from ./klips/net/ipsec/ipsec_rcv.h,v
+ *
+ * Revision 1.14 2001/09/07 22:15:48 rgb
+ * Fix for removal of transport layer protocol handler arg in 2.4.4.
+ *
+ * Revision 1.13 2001/06/14 19:35:09 rgb
+ * Update copyright date.
+ *
+ * Revision 1.12 2001/03/16 07:36:44 rgb
+ * Fixed #endif comment to sate compiler.
+ *
+ * Revision 1.11 2000/09/21 04:34:21 rgb
+ * Moved declaration of sysctl_ipsec_inbound_policy_check outside
+ * CONFIG_IPSEC_DEBUG. (MB)
+ *
+ * Revision 1.10 2000/09/18 02:36:10 rgb
+ * Exported sysctl_ipsec_inbound_policy_check for skb_decompress().
+ *
+ * Revision 1.9 2000/09/08 19:12:56 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.8 1999/11/18 04:09:19 rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.7 1999/05/25 01:45:37 rgb
+ * Fix version macros for 2.0.x as a module.
+ *
+ * Revision 1.6 1999/05/08 21:24:27 rgb
+ * Add includes for 2.2.x include into net/ipv4/protocol.c
+ *
+ * Revision 1.5 1999/05/05 22:02:32 rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.4 1999/04/11 00:28:59 henry
+ * GPL boilerplate
+ *
+ * Revision 1.3 1999/04/06 04:54:27 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.2 1999/01/22 20:06:59 rgb
+ * Fixed cut-and-paste error from ipsec_esp.h.
+ *
+ * Revision 1.1 1999/01/21 20:29:12 rgb
+ * Converted from transform switching to algorithm switching.
+ *
+ * Log: ipsec_esp.h,v
+ * Revision 1.4 1998/08/12 00:07:32 rgb
+ * Added data structures for new xforms: null, {,3}dessha1.
+ *
+ * Revision 1.3 1998/07/14 15:57:01 rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.2 1998/06/25 19:33:46 rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1 1998/06/18 21:27:45 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.6 1998/06/05 02:28:08 rgb
+ * Minor comment fix.
+ *
+ * Revision 1.5 1998/05/27 22:34:00 rgb
+ * Changed structures to accomodate key separation.
+ *
+ * Revision 1.4 1998/05/18 22:28:43 rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3 1998/04/21 21:29:07 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2 1998/04/12 22:03:20 rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * ESP-DES-HMAC-MD5-96,
+ * AH-HMAC-MD5-96,
+ * AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1 1998/04/09 03:06:00 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:02 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5 1997/06/03 04:24:48 ji
+ * Added ESP-3DES-MD5-96 transform.
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * Added definitions for new ESP transforms.
+ *
+ * Revision 0.3 1996/11/20 14:35:48 ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
+
+
diff --git a/src/libfreeswan/ipsec_sa.h b/src/libfreeswan/ipsec_sa.h
new file mode 100644
index 000000000..555df42d3
--- /dev/null
+++ b/src/libfreeswan/ipsec_sa.h
@@ -0,0 +1,338 @@
+/*
+ * @(#) Definitions of IPsec Security Association (ipsec_sa)
+ *
+ * Copyright (C) 2001, 2002, 2003
+ * Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_sa.h,v 1.3 2004/04/28 08:07:11 as Exp $
+ *
+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
+ *
+ */
+
+/*
+ * This file describes the IPsec Security Association Structure.
+ *
+ * This structure keeps track of a single transform that may be done
+ * to a set of packets. It can describe applying the transform or
+ * apply the reverse. (e.g. compression vs expansion). However, it
+ * only describes one at a time. To describe both, two structures would
+ * be used, but since the sides of the transform are performed
+ * on different machines typically it is usual to have only one side
+ * of each association.
+ *
+ */
+
+#ifndef _IPSEC_SA_H_
+
+#ifdef __KERNEL__
+#include "ipsec_stats.h"
+#include "ipsec_life.h"
+#include "ipsec_eroute.h"
+#endif /* __KERNEL__ */
+#include "ipsec_param.h"
+
+
+/* SAs are held in a table.
+ * Entries in this table are referenced by IPsecSAref_t values.
+ * IPsecSAref_t values are conceptually subscripts. Because
+ * we want to allocate the table piece-meal, the subscripting
+ * is implemented with two levels, a bit like paged virtual memory.
+ * This representation mechanism is known as an Iliffe Vector.
+ *
+ * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH
+ * pointers to subtables.
+ * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which
+ * is a pointer to an SA.
+ *
+ * An IPsecSAref_t contains either an exceptional value (signified by the
+ * high-order bit being on) or a reference to a table entry. A table entry
+ * reference has the subtable subscript in the low-order
+ * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript
+ * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits.
+ *
+ * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is
+ * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *.
+ *
+ * The pointer to the SA for x is IPsecSAref2SA(x). It is of type
+ * struct ipsec_sa*. The macro definition clearly shows the two-level
+ * access needed to find the SA pointer.
+ *
+ * The Maintable is allocated when IPsec is initialized.
+ * Each subtable is allocated when needed, but the first is allocated
+ * when IPsec is initialized.
+ *
+ * IPsecSAref_t is designed to be smaller than an NFmark so that
+ * they can be stored in NFmarks and still leave a few bits for other
+ * purposes. The spare bits are in the low order of the NFmark
+ * but in the high order of the IPsecSAref_t, so conversion is required.
+ * We pick the upper bits of NFmark on the theory that they are less likely to
+ * interfere with more pedestrian uses of nfmark.
+ */
+
+
+typedef unsigned short int IPsecRefTableUnusedCount;
+
+#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)
+
+#ifdef __KERNEL__
+#if ((IPSEC_SA_REF_TABLE_IDX_WIDTH - (1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) < 0)
+#error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be < 1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")"
+#endif
+
+#define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)
+
+#define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)
+#define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
+
+#ifdef CONFIG_NETFILTER
+#define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark
+#define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL))
+#else /* CONFIG_NETFILTER */
+/* just make it work for now, it doesn't matter, since there is no nfmark */
+#define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long
+#endif /* CONFIG_NETFILTER */
+#define IPSEC_SA_REF_HOST_FIELD_WIDTH (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE))
+#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
+
+#define IPSEC_SA_REF_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
+#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
+#define IPSEC_SA_REF_ENTRY_MASK (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH))
+
+#define IPsecSAref2table(x) (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
+#define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK)
+#define IPsecSArefBuild(x,y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y))
+
+#define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[IPsecSAref2entry(x)])
+#define IPsecSA2SAref(x) ((x)->ips_ref)
+
+#define EMT_INBOUND 0x01 /* SA direction, 1=inbound */
+
+/* 'struct ipsec_sa' should be 64bit aligned when allocated. */
+struct ipsec_sa
+{
+ IPsecSAref_t ips_ref; /* reference table entry number */
+ atomic_t ips_refcount; /* reference count for this struct */
+ struct ipsec_sa *ips_hnext; /* next in hash chain */
+ struct ipsec_sa *ips_inext; /* pointer to next xform */
+ struct ipsec_sa *ips_onext; /* pointer to prev xform */
+
+ struct ifnet *ips_rcvif; /* related rcv encap interface */
+
+ struct sa_id ips_said; /* SA ID */
+
+ __u32 ips_seq; /* seq num of msg that initiated this SA */
+ __u32 ips_pid; /* PID of process that initiated this SA */
+ __u8 ips_authalg; /* auth algorithm for this SA */
+ __u8 ips_encalg; /* enc algorithm for this SA */
+
+ struct ipsec_stats ips_errs;
+
+ __u8 ips_replaywin; /* replay window size */
+ __u8 ips_state; /* state of SA */
+ __u32 ips_replaywin_lastseq; /* last pkt sequence num */
+ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */
+ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */
+
+ __u32 ips_flags; /* generic xform flags */
+
+
+ struct ipsec_lifetimes ips_life; /* lifetime records */
+
+ /* selector information */
+ struct sockaddr*ips_addr_s; /* src sockaddr */
+ struct sockaddr*ips_addr_d; /* dst sockaddr */
+ struct sockaddr*ips_addr_p; /* proxy sockaddr */
+ __u16 ips_addr_s_size;
+ __u16 ips_addr_d_size;
+ __u16 ips_addr_p_size;
+ ip_address ips_flow_s;
+ ip_address ips_flow_d;
+ ip_address ips_mask_s;
+ ip_address ips_mask_d;
+
+ __u16 ips_key_bits_a; /* size of authkey in bits */
+ __u16 ips_auth_bits; /* size of authenticator in bits */
+ __u16 ips_key_bits_e; /* size of enckey in bits */
+ __u16 ips_iv_bits; /* size of IV in bits */
+ __u8 ips_iv_size;
+ __u16 ips_key_a_size;
+ __u16 ips_key_e_size;
+
+ caddr_t ips_key_a; /* authentication key */
+ caddr_t ips_key_e; /* encryption key */
+ caddr_t ips_iv; /* Initialisation Vector */
+
+ struct ident ips_ident_s; /* identity src */
+ struct ident ips_ident_d; /* identity dst */
+
+#ifdef CONFIG_IPSEC_IPCOMP
+ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */
+ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */
+ __u64 ips_comp_ratio_cbytes; /* compressed bytes */
+ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+ __u8 ips_natt_type;
+ __u8 ips_natt_reserved[3];
+ __u16 ips_natt_sport;
+ __u16 ips_natt_dport;
+
+ struct sockaddr *ips_natt_oa;
+ __u16 ips_natt_oa_size;
+ __u16 ips_natt_reserved2;
+#endif
+
+#if 0
+ __u32 ips_sens_dpd;
+ __u8 ips_sens_sens_level;
+ __u8 ips_sens_sens_len;
+ __u64* ips_sens_sens_bitmap;
+ __u8 ips_sens_integ_level;
+ __u8 ips_sens_integ_len;
+ __u64* ips_sens_integ_bitmap;
+#endif
+ struct ipsec_alg_enc *ips_alg_enc;
+ struct ipsec_alg_auth *ips_alg_auth;
+ IPsecSAref_t ips_ref_rel;
+};
+
+struct IPsecSArefSubTable
+{
+ struct ipsec_sa* entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES];
+};
+
+struct ipsec_sadb {
+ struct IPsecSArefSubTable* refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES];
+ IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES];
+ int refFreeListHead;
+ int refFreeListTail;
+ IPsecSAref_t refFreeListCont;
+ IPsecSAref_t said_hash[SADB_HASHMOD];
+ spinlock_t sadb_lock;
+};
+
+extern struct ipsec_sadb ipsec_sadb;
+
+extern int ipsec_SAref_recycle(void);
+extern int ipsec_SArefSubTable_alloc(unsigned table);
+extern int ipsec_saref_freelist_init(void);
+extern int ipsec_sadb_init(void);
+extern struct ipsec_sa *ipsec_sa_alloc(int*error); /* pass in error var by pointer */
+extern IPsecSAref_t ipsec_SAref_alloc(int*erorr); /* pass in error var by pointer */
+extern int ipsec_sa_free(struct ipsec_sa* ips);
+extern struct ipsec_sa *ipsec_sa_getbyid(struct sa_id *said);
+extern int ipsec_sa_put(struct ipsec_sa *ips);
+extern int ipsec_sa_add(struct ipsec_sa *ips);
+extern int ipsec_sa_del(struct ipsec_sa *ips);
+extern int ipsec_sa_delchain(struct ipsec_sa *ips);
+extern int ipsec_sadb_cleanup(__u8 proto);
+extern int ipsec_sadb_free(void);
+extern int ipsec_sa_wipe(struct ipsec_sa *ips);
+#endif /* __KERNEL__ */
+
+enum ipsec_direction {
+ ipsec_incoming = 1,
+ ipsec_outgoing = 2
+};
+
+#define _IPSEC_SA_H_
+#endif /* _IPSEC_SA_H_ */
+
+/*
+ * $Log: ipsec_sa.h,v $
+ * Revision 1.3 2004/04/28 08:07:11 as
+ * added dhr's freeswan-2.06 changes
+ *
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.2.1.2.1 2004/03/16 09:48:18 as
+ * alg-0.8.1rc12 patch merged
+ *
+ * Revision 1.1.2.1 2004/03/15 22:30:06 as
+ * nat-0.6c patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.15 2003/05/11 00:53:09 mcr
+ * IPsecSAref_t and macros were moved to freeswan.h.
+ *
+ * Revision 1.14 2003/02/12 19:31:55 rgb
+ * Fixed bug in "file seen" machinery.
+ * Updated copyright year.
+ *
+ * Revision 1.13 2003/01/30 02:31:52 rgb
+ *
+ * Re-wrote comments describing SAref system for accuracy.
+ * Rename SAref table macro names for clarity.
+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
+ * Transmit error code through to caller from callee for better diagnosis of problems.
+ * Enclose all macro arguments in parens to avoid any possible obscrure bugs.
+ *
+ * Revision 1.12 2002/10/07 18:31:19 rgb
+ * Change comment to reflect the flexible nature of the main and sub-table widths.
+ * Added a counter for the number of unused entries in each subtable.
+ * Further break up host field type macro to host field.
+ * Move field width sanity checks to ipsec_sa.c
+ * Define a mask for an entire saref.
+ *
+ * Revision 1.11 2002/09/20 15:40:33 rgb
+ * Re-write most of the SAref macros and types to eliminate any pointer references to Entrys.
+ * Fixed SAref/nfmark macros.
+ * Rework saref freeslist.
+ * Place all ipsec sadb globals into one struct.
+ * Restrict some bits to kernel context for use to klips utils.
+ *
+ * Revision 1.10 2002/09/20 05:00:34 rgb
+ * Update copyright date.
+ *
+ * Revision 1.9 2002/09/17 17:19:29 mcr
+ * make it compile even if there is no netfilter - we lost
+ * functionality, but it works, especially on 2.2.
+ *
+ * Revision 1.8 2002/07/28 22:59:53 mcr
+ * clarified/expanded one comment.
+ *
+ * Revision 1.7 2002/07/26 08:48:31 rgb
+ * Added SA ref table code.
+ *
+ * Revision 1.6 2002/05/31 17:27:48 rgb
+ * Comment fix.
+ *
+ * Revision 1.5 2002/05/27 18:55:03 rgb
+ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
+ *
+ * Revision 1.4 2002/05/23 07:13:36 rgb
+ * Convert "usecount" to "refcount" to remove ambiguity.
+ *
+ * Revision 1.3 2002/04/24 07:36:47 mcr
+ * Moved from ./klips/net/ipsec/ipsec_sa.h,v
+ *
+ * Revision 1.2 2001/11/26 09:16:15 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1 2001/09/25 02:24:58 mcr
+ * struct tdb -> struct ipsec_sa.
+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
+ * ipsec_xform.c removed. header file still contains useful things.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/ipsec_sha1.h b/src/libfreeswan/ipsec_sha1.h
new file mode 100644
index 000000000..116170e6b
--- /dev/null
+++ b/src/libfreeswan/ipsec_sha1.h
@@ -0,0 +1,79 @@
+/*
+ * RCSID $Id: ipsec_sha1.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+/*
+ * Here is the original comment from the distribution:
+
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+ * Adapted for use by the IPSEC code by John Ioannidis
+ */
+
+
+#ifndef _IPSEC_SHA1_H_
+#define _IPSEC_SHA1_H_
+
+typedef struct
+{
+ __u32 state[5];
+ __u32 count[2];
+ __u8 buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(__u32 state[5], __u8 buffer[64]);
+void SHA1Init(void *context);
+void SHA1Update(void *context, unsigned char *data, __u32 len);
+void SHA1Final(unsigned char digest[20], void *context);
+
+
+#endif /* _IPSEC_SHA1_H_ */
+
+/*
+ * $Log: ipsec_sha1.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.7 2002/09/10 01:45:09 mcr
+ * changed type of MD5_CTX and SHA1_CTX to void * so that
+ * the function prototypes would match, and could be placed
+ * into a pointer to a function.
+ *
+ * Revision 1.6 2002/04/24 07:36:47 mcr
+ * Moved from ./klips/net/ipsec/ipsec_sha1.h,v
+ *
+ * Revision 1.5 1999/12/13 13:59:13 rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.4 1999/12/07 18:16:23 rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.3 1999/04/06 04:54:27 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.2 1998/11/30 13:22:54 rgb
+ * Rationalised all the klips kernel file headers. They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.1 1998/06/18 21:27:50 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2 1998/04/23 20:54:05 rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1 1998/04/09 03:04:21 henry
+ * sources moved up from linux/net/ipsec
+ * these two include files modified not to include others except in kernel
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * New transform
+ *
+ */
diff --git a/src/libfreeswan/ipsec_stats.h b/src/libfreeswan/ipsec_stats.h
new file mode 100644
index 000000000..e4be11d29
--- /dev/null
+++ b/src/libfreeswan/ipsec_stats.h
@@ -0,0 +1,38 @@
+/*
+ * @(#) definition of ipsec_stats structure
+ *
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_stats.h,v 1.2 2004/03/30 19:33:52 as Exp $
+ *
+ */
+
+/*
+ * This file describes the errors/statistics that FreeSWAN collects.
+ */
+
+#ifndef _IPSEC_STATS_H_
+
+struct ipsec_stats {
+ __u32 ips_alg_errs; /* number of algorithm errors */
+ __u32 ips_auth_errs; /* # of authentication errors */
+ __u32 ips_encsize_errs; /* # of encryption size errors*/
+ __u32 ips_encpad_errs; /* # of encryption pad errors*/
+ __u32 ips_replaywin_errs; /* # of pkt sequence errors */
+};
+
+extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...);
+
+#define _IPSEC_STATS_H_
+#endif /* _IPSEC_STATS_H_ */
diff --git a/src/libfreeswan/ipsec_tunnel.h b/src/libfreeswan/ipsec_tunnel.h
new file mode 100644
index 000000000..3b25e95e1
--- /dev/null
+++ b/src/libfreeswan/ipsec_tunnel.h
@@ -0,0 +1,265 @@
+/*
+ * IPSEC tunneling code
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_tunnel.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+
+#ifdef NET_21
+# define DEV_QUEUE_XMIT(skb, device, pri) {\
+ skb->dev = device; \
+ neigh_compat_output(skb); \
+ /* skb->dst->output(skb); */ \
+ }
+# define ICMP_SEND(skb_in, type, code, info, dev) \
+ icmp_send(skb_in, type, code, htonl(info))
+# define IP_SEND(skb, dev) \
+ ip_send(skb);
+#else /* NET_21 */
+# define DEV_QUEUE_XMIT(skb, device, pri) {\
+ dev_queue_xmit(skb, device, pri); \
+ }
+# define ICMP_SEND(skb_in, type, code, info, dev) \
+ icmp_send(skb_in, type, code, info, dev)
+# define IP_SEND(skb, dev) \
+ if(ntohs(iph->tot_len) > physmtu) { \
+ ip_fragment(NULL, skb, dev, 0); \
+ ipsec_kfree_skb(skb); \
+ } else { \
+ dev_queue_xmit(skb, dev, SOPRI_NORMAL); \
+ }
+#endif /* NET_21 */
+
+
+/*
+ * Heavily based on drivers/net/new_tunnel.c. Lots
+ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c
+ */
+
+struct ipsectunnelconf
+{
+ __u32 cf_cmd;
+ union
+ {
+ char cfu_name[12];
+ } cf_u;
+#define cf_name cf_u.cfu_name
+};
+
+#define IPSEC_SET_DEV (SIOCDEVPRIVATE)
+#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1)
+#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2)
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+struct ipsecpriv
+{
+ struct sk_buff_head sendq;
+ struct device *dev;
+ struct wait_queue *wait_queue;
+ char locked;
+ int (*hard_start_xmit) (struct sk_buff *skb,
+ struct device *dev);
+ int (*hard_header) (struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+#ifdef NET_21
+ int (*rebuild_header)(struct sk_buff *skb);
+#else /* NET_21 */
+ int (*rebuild_header)(void *buff, struct device *dev,
+ unsigned long raddr, struct sk_buff *skb);
+#endif /* NET_21 */
+ int (*set_mac_address)(struct device *dev, void *addr);
+#ifndef NET_21
+ void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev,
+ unsigned short htype, __u32 daddr);
+#endif /* !NET_21 */
+ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr);
+ struct net_device_stats *(*get_stats)(struct device *dev);
+ struct net_device_stats mystats;
+ int mtu; /* What is the desired MTU? */
+};
+
+extern char ipsec_tunnel_c_version[];
+
+extern struct device *ipsecdevices[IPSEC_NUM_IF];
+
+int ipsec_tunnel_init_devices(void);
+
+/* void */ int ipsec_tunnel_cleanup_devices(void);
+
+extern /* void */ int ipsec_init(void);
+
+extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev);
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_tunnel;
+extern int sysctl_ipsec_debug_verbose;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_IPSEC_DEBUG
+#define DB_TN_INIT 0x0001
+#define DB_TN_PROCFS 0x0002
+#define DB_TN_XMIT 0x0010
+#define DB_TN_OHDR 0x0020
+#define DB_TN_CROUT 0x0040
+#define DB_TN_OXFS 0x0080
+#define DB_TN_REVEC 0x0100
+#endif /* CONFIG_IPSEC_DEBUG */
+
+/*
+ * $Log: ipsec_tunnel.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.28 2003/06/24 20:22:32 mcr
+ * added new global: ipsecdevices[] so that we can keep track of
+ * the ipsecX devices. They will be referenced with dev_hold(),
+ * so 2.2 may need this as well.
+ *
+ * Revision 1.27 2003/04/03 17:38:09 rgb
+ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
+ *
+ * Revision 1.26 2003/02/12 19:32:20 rgb
+ * Updated copyright year.
+ *
+ * Revision 1.25 2002/05/27 18:56:07 rgb
+ * Convert to dynamic ipsec device allocation.
+ *
+ * Revision 1.24 2002/04/24 07:36:48 mcr
+ * Moved from ./klips/net/ipsec/ipsec_tunnel.h,v
+ *
+ * Revision 1.23 2001/11/06 19:50:44 rgb
+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for
+ * use also by pfkey_v2_parser.c
+ *
+ * Revision 1.22 2001/09/15 16:24:05 rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.21 2001/06/14 19:35:10 rgb
+ * Update copyright date.
+ *
+ * Revision 1.20 2000/09/15 11:37:02 rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.19 2000/09/08 19:12:56 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.18 2000/07/28 13:50:54 rgb
+ * Changed enet_statistics to net_device_stats and added back compatibility
+ * for pre-2.1.19.
+ *
+ * Revision 1.17 1999/11/19 01:12:15 rgb
+ * Purge unneeded proc_info prototypes, now that static linking uses
+ * dynamic proc_info registration.
+ *
+ * Revision 1.16 1999/11/18 18:51:00 rgb
+ * Changed all device registrations for static linking to
+ * dynamic to reduce the number and size of patches.
+ *
+ * Revision 1.15 1999/11/18 04:14:21 rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
+ * Added Marc Boucher's 2.3.25 proc patches.
+ *
+ * Revision 1.14 1999/05/25 02:50:10 rgb
+ * Fix kernel version macros for 2.0.x static linking.
+ *
+ * Revision 1.13 1999/05/25 02:41:06 rgb
+ * Add ipsec_klipsdebug support for static linking.
+ *
+ * Revision 1.12 1999/05/05 22:02:32 rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.11 1999/04/29 15:19:50 rgb
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.10 1999/04/16 16:02:39 rgb
+ * Bump up macro to 4 ipsec I/Fs.
+ *
+ * Revision 1.9 1999/04/15 15:37:25 rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.5.2.1 1999/04/02 04:26:14 rgb
+ * Backcheck from HEAD, pre1.0.
+ *
+ * Revision 1.8 1999/04/11 00:29:01 henry
+ * GPL boilerplate
+ *
+ * Revision 1.7 1999/04/06 04:54:28 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.6 1999/03/31 05:44:48 rgb
+ * Keep PMTU reduction private.
+ *
+ * Revision 1.5 1999/02/10 22:31:20 rgb
+ * Change rebuild_header member to reflect generality of link layer.
+ *
+ * Revision 1.4 1998/12/01 13:22:04 rgb
+ * Added support for debug printing of version info.
+ *
+ * Revision 1.3 1998/07/29 20:42:46 rgb
+ * Add a macro for clearing all tunnel devices.
+ * Rearrange structures and declarations for sharing with userspace.
+ *
+ * Revision 1.2 1998/06/25 20:01:45 rgb
+ * Make prototypes available for ipsec_init and ipsec proc_dir_entries
+ * for static linking.
+ *
+ * Revision 1.1 1998/06/18 21:27:50 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.3 1998/05/18 21:51:50 rgb
+ * Added macros for num of I/F's and a procfs debug switch.
+ *
+ * Revision 1.2 1998/04/21 21:29:09 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1 1998/04/09 03:06:13 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:05 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5 1997/06/03 04:24:48 ji
+ * Added transport mode.
+ * Changed the way routing is done.
+ * Lots of bug fixes.
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * No changes.
+ *
+ * Revision 0.3 1996/11/20 14:39:04 ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/ipsec_xform.h b/src/libfreeswan/ipsec_xform.h
new file mode 100644
index 000000000..1dc6b6083
--- /dev/null
+++ b/src/libfreeswan/ipsec_xform.h
@@ -0,0 +1,274 @@
+/*
+ * Definitions relevant to IPSEC transformations
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_xform.h,v 1.3 2004/09/29 22:26:13 as Exp $
+ */
+
+#ifndef _IPSEC_XFORM_H_
+
+#include <freeswan.h>
+#include "ipsec_policy.h"
+
+#define XF_NONE 0 /* No transform set */
+#define XF_IP4 1 /* IPv4 inside IPv4 */
+#define XF_AHMD5 2 /* AH MD5 */
+#define XF_AHSHA 3 /* AH SHA */
+#define XF_ESP3DES 5 /* ESP DES3-CBC */
+#define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */
+#define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */
+#define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */
+#define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */
+#define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */
+#define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */
+#define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */
+#define XF_IP6 15 /* IPv6 inside IPv6 */
+#define XF_COMPDEFLATE 16 /* IPCOMP deflate */
+
+#define XF_CLR 126 /* Clear SA table */
+#define XF_DEL 127 /* Delete SA */
+
+#define XFT_AUTH 0x0001
+#define XFT_CONF 0x0100
+
+/* available if CONFIG_IPSEC_DEBUG is defined */
+#define DB_XF_INIT 0x0001
+
+#define PROTO2TXT(x) \
+ (x) == IPPROTO_AH ? "AH" : \
+ (x) == IPPROTO_ESP ? "ESP" : \
+ (x) == IPPROTO_IPIP ? "IPIP" : \
+ (x) == IPPROTO_COMP ? "COMP" : \
+ "UNKNOWN_proto"
+static inline const char *enc_name_id (unsigned id) {
+ static char buf[16];
+ snprintf(buf, sizeof(buf), "_ID%d", id);
+ return buf;
+}
+static inline const char *auth_name_id (unsigned id) {
+ static char buf[16];
+ snprintf(buf, sizeof(buf), "_ID%d", id);
+ return buf;
+}
+#define IPS_XFORM_NAME(x) \
+ PROTO2TXT((x)->ips_said.proto), \
+ (x)->ips_said.proto == IPPROTO_COMP ? \
+ ((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \
+ "_DEFLATE" : "_UNKNOWN_comp") : \
+ (x)->ips_encalg == ESP_NONE ? "" : \
+ (x)->ips_encalg == ESP_3DES ? "_3DES" : \
+ (x)->ips_encalg == ESP_AES ? "_AES" : \
+ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \
+ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \
+ enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \
+ (x)->ips_authalg == AH_NONE ? "" : \
+ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \
+ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \
+ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \
+ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \
+ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \
+ auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \
+
+#define _IPSEC_XFORM_H_
+#endif /* _IPSEC_XFORM_H_ */
+
+/*
+ * $Log: ipsec_xform.h,v $
+ * Revision 1.3 2004/09/29 22:26:13 as
+ * included ipsec_policy.h
+ *
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.4.1 2004/03/16 09:48:18 as
+ * alg-0.8.1rc12 patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.36 2002/04/24 07:36:48 mcr
+ * Moved from ./klips/net/ipsec/ipsec_xform.h,v
+ *
+ * Revision 1.35 2001/11/26 09:23:51 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.33.2.1 2001/09/25 02:24:58 mcr
+ * struct tdb -> struct ipsec_sa.
+ * sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
+ * ipsec_xform.c removed. header file still contains useful things.
+ *
+ * Revision 1.34 2001/11/06 19:47:17 rgb
+ * Changed lifetime_packets to uint32 from uint64.
+ *
+ * Revision 1.33 2001/09/08 21:13:34 rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.32 2001/07/06 07:40:01 rgb
+ * Reformatted for readability.
+ * Added inbound policy checking fields for use with IPIP SAs.
+ *
+ * Revision 1.31 2001/06/14 19:35:11 rgb
+ * Update copyright date.
+ *
+ * Revision 1.30 2001/05/30 08:14:03 rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.29 2001/01/30 23:42:47 rgb
+ * Allow pfkey msgs from pid other than user context required for ACQUIRE
+ * and subsequent ADD or UDATE.
+ *
+ * Revision 1.28 2000/11/06 04:30:40 rgb
+ * Add Svenning's adaptive content compression.
+ *
+ * Revision 1.27 2000/09/19 00:38:25 rgb
+ * Fixed algorithm name bugs introduced for ipcomp.
+ *
+ * Revision 1.26 2000/09/17 21:36:48 rgb
+ * Added proto2txt macro.
+ *
+ * Revision 1.25 2000/09/17 18:56:47 rgb
+ * Added IPCOMP support.
+ *
+ * Revision 1.24 2000/09/12 19:34:12 rgb
+ * Defined XF_IP6 from Gerhard for ipv6 tunnel support.
+ *
+ * Revision 1.23 2000/09/12 03:23:14 rgb
+ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb.
+ *
+ * Revision 1.22 2000/09/08 19:12:56 rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.21 2000/09/01 18:32:43 rgb
+ * Added (disabled) sensitivity members to tdb struct.
+ *
+ * Revision 1.20 2000/08/30 05:31:01 rgb
+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
+ * Kill remainder of tdb_xform, tdb_xdata, xformsw.
+ *
+ * Revision 1.19 2000/08/01 14:51:52 rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.18 2000/01/21 06:17:45 rgb
+ * Tidied up spacing.
+ *
+ * Revision 1.17 1999/11/17 15:53:40 rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.16 1999/10/16 04:23:07 rgb
+ * Add stats for replaywin_errs, replaywin_max_sequence_difference,
+ * authentication errors, encryption size errors, encryption padding
+ * errors, and time since last packet.
+ *
+ * Revision 1.15 1999/10/16 00:29:11 rgb
+ * Added SA lifetime packet counting variables.
+ *
+ * Revision 1.14 1999/10/01 00:04:14 rgb
+ * Added tdb structure locking.
+ * Add function to initialize tdb hash table.
+ *
+ * Revision 1.13 1999/04/29 15:20:57 rgb
+ * dd return values to init and cleanup functions.
+ * Eliminate unnessessary usage of tdb_xform member to further switch
+ * away from the transform switch to the algorithm switch.
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
+ *
+ * Revision 1.12 1999/04/15 15:37:25 rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.9.2.2 1999/04/13 20:35:57 rgb
+ * Fix spelling mistake in comment.
+ *
+ * Revision 1.9.2.1 1999/03/30 17:13:52 rgb
+ * Extend struct tdb to support pfkey.
+ *
+ * Revision 1.11 1999/04/11 00:29:01 henry
+ * GPL boilerplate
+ *
+ * Revision 1.10 1999/04/06 04:54:28 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.9 1999/01/26 02:09:31 rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ *
+ * Revision 1.8 1999/01/22 06:29:35 rgb
+ * Added algorithm switch code.
+ * Cruft clean-out.
+ *
+ * Revision 1.7 1998/11/10 05:37:35 rgb
+ * Add support for SA direction flag.
+ *
+ * Revision 1.6 1998/10/19 14:44:29 rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.5 1998/08/12 00:12:30 rgb
+ * Added macros for new xforms. Added prototypes for new xforms.
+ *
+ * Revision 1.4 1998/07/28 00:04:20 rgb
+ * Add macro for clearing the SA table.
+ *
+ * Revision 1.3 1998/07/14 18:06:46 rgb
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.2 1998/06/23 03:02:19 rgb
+ * Created a prototype for ipsec_tdbcleanup when it was moved from
+ * ipsec_init.c.
+ *
+ * Revision 1.1 1998/06/18 21:27:51 henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.4 1998/06/11 05:55:31 rgb
+ * Added transform version string pointer to xformsw structure definition.
+ * Added extern declarations for transform version strings.
+ *
+ * Revision 1.3 1998/05/18 22:02:54 rgb
+ * Modify the *_zeroize function prototypes to include one parameter.
+ *
+ * Revision 1.2 1998/04/21 21:29:08 rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space. Only kernel changes checked in at this time. radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1 1998/04/09 03:06:14 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:06 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5 1997/06/03 04:24:48 ji
+ * Added ESP-3DES-MD5-96
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * Added new transforms.
+ *
+ * Revision 0.3 1996/11/20 14:39:04 ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/ipsec_xmit.h b/src/libfreeswan/ipsec_xmit.h
new file mode 100644
index 000000000..033984886
--- /dev/null
+++ b/src/libfreeswan/ipsec_xmit.h
@@ -0,0 +1,140 @@
+/*
+ * IPSEC tunneling code
+ * Copyright (C) 1996, 1997 John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ipsec_xmit.h,v 1.3 2004/06/13 19:37:07 as Exp $
+ */
+
+#include "freeswan/ipsec_sa.h"
+
+enum ipsec_xmit_value
+{
+ IPSEC_XMIT_STOLEN=2,
+ IPSEC_XMIT_PASS=1,
+ IPSEC_XMIT_OK=0,
+ IPSEC_XMIT_ERRMEMALLOC=-1,
+ IPSEC_XMIT_ESP_BADALG=-2,
+ IPSEC_XMIT_BADPROTO=-3,
+ IPSEC_XMIT_ESP_PUSHPULLERR=-4,
+ IPSEC_XMIT_BADLEN=-5,
+ IPSEC_XMIT_AH_BADALG=-6,
+ IPSEC_XMIT_SAIDNOTFOUND=-7,
+ IPSEC_XMIT_SAIDNOTLIVE=-8,
+ IPSEC_XMIT_REPLAYROLLED=-9,
+ IPSEC_XMIT_LIFETIMEFAILED=-10,
+ IPSEC_XMIT_CANNOTFRAG=-11,
+ IPSEC_XMIT_MSSERR=-12,
+ IPSEC_XMIT_ERRSKBALLOC=-13,
+ IPSEC_XMIT_ENCAPFAIL=-14,
+ IPSEC_XMIT_NODEV=-15,
+ IPSEC_XMIT_NOPRIVDEV=-16,
+ IPSEC_XMIT_NOPHYSDEV=-17,
+ IPSEC_XMIT_NOSKB=-18,
+ IPSEC_XMIT_NOIPV6=-19,
+ IPSEC_XMIT_NOIPOPTIONS=-20,
+ IPSEC_XMIT_TTLEXPIRED=-21,
+ IPSEC_XMIT_BADHHLEN=-22,
+ IPSEC_XMIT_PUSHPULLERR=-23,
+ IPSEC_XMIT_ROUTEERR=-24,
+ IPSEC_XMIT_RECURSDETECT=-25,
+ IPSEC_XMIT_IPSENDFAILURE=-26,
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+ IPSEC_XMIT_ESPUDP=-27,
+#endif
+};
+
+struct ipsec_xmit_state
+{
+ struct sk_buff *skb; /* working skb pointer */
+ struct device *dev; /* working dev pointer */
+ struct ipsecpriv *prv; /* Our device' private space */
+ struct sk_buff *oskb; /* Original skb pointer */
+ struct net_device_stats *stats; /* This device's statistics */
+ struct iphdr *iph; /* Our new IP header */
+ __u32 newdst; /* The other SG's IP address */
+ __u32 orgdst; /* Original IP destination address */
+ __u32 orgedst; /* 1st SG's IP address */
+ __u32 newsrc; /* The new source SG's IP address */
+ __u32 orgsrc; /* Original IP source address */
+ __u32 innersrc; /* Innermost IP source address */
+ int iphlen; /* IP header length */
+ int pyldsz; /* upper protocol payload size */
+ int headroom;
+ int tailroom;
+ int max_headroom; /* The extra header space needed */
+ int max_tailroom; /* The extra stuffing needed */
+ int ll_headroom; /* The extra link layer hard_header space needed */
+ int tot_headroom; /* The total header space needed */
+ int tot_tailroom; /* The totalstuffing needed */
+ __u8 *saved_header; /* saved copy of the hard header */
+ unsigned short sport, dport;
+
+ struct sockaddr_encap matcher; /* eroute search key */
+ struct eroute *eroute;
+ struct ipsec_sa *ipsp, *ipsq; /* ipsec_sa pointers */
+ char sa_txt[SATOA_BUF];
+ size_t sa_len;
+ int hard_header_stripped; /* has the hard header been removed yet? */
+ int hard_header_len;
+ struct device *physdev;
+/* struct device *virtdev; */
+ short physmtu;
+ short mtudiff;
+#ifdef NET_21
+ struct rtable *route;
+#endif /* NET_21 */
+ struct sa_id outgoing_said;
+#ifdef NET_21
+ int pass;
+#endif /* NET_21 */
+ int error;
+ uint32_t eroute_pid;
+ struct ipsec_sa ips;
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+ uint8_t natt_type;
+ uint8_t natt_head;
+ uint16_t natt_sport;
+ uint16_t natt_dport;
+#endif
+};
+
+#if 0 /* save for alg refactorisation */
+struct xform_functions
+{
+ enum ipsec_xmit_value (*checks)(struct ipsec_xmit_state *ixs,
+ struct sk_buff *skb);
+ enum ipsec_xmit_value (*encrypt)(struct ipsec_xmit_state *ixs);
+
+ enum ipsec_xmit_value (*setup_auth)(struct ipsec_xmit_state *ixs,
+ struct sk_buff *skb,
+ __u32 *replay,
+ unsigned char **authenticator);
+ enum ipsec_xmit_value (*calc_auth)(struct ipsec_xmit_state *ixs,
+ struct sk_buff *skb);
+};
+#endif
+
+enum ipsec_xmit_value
+ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs);
+
+enum ipsec_xmit_value
+ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs);
+
+enum ipsec_xmit_value
+ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs);
+
+extern int ipsec_xmit_trap_count;
+extern int ipsec_xmit_trap_sendcount;
+
+extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er);
diff --git a/src/libfreeswan/keyblobtoid.3 b/src/libfreeswan/keyblobtoid.3
new file mode 100644
index 000000000..be381531a
--- /dev/null
+++ b/src/libfreeswan/keyblobtoid.3
@@ -0,0 +1,103 @@
+.TH IPSEC_KEYBLOBTOID 3 "25 March 2002"
+.\" RCSID $Id: keyblobtoid.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec keyblobtoid, splitkeytoid \- generate key IDs from RSA keys
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "size_t keyblobtoid(const unsigned char *blob,"
+.ti +1c
+.B "size_t bloblen, char *dst, size_t dstlen);"
+.br
+.B "size_t splitkeytoid(const unsigned char *e, size_t elen,"
+.ti +1c
+.B "const unsigned char *m, size_t mlen, char *dst,
+.ti +1c
+.B "size_t dstlen);"
+.SH DESCRIPTION
+.I Keyblobtoid
+and
+.I splitkeytoid
+generate
+key IDs
+from RSA keys,
+for use in messages and reporting,
+writing the result to
+.IR dst .
+A
+.I key ID
+is a short ASCII string identifying a key;
+currently it is just the first nine characters of the base64
+encoding of the RFC 2537/3110 ``byte blob'' representation of the key.
+(Beware that no finite key ID can be collision-proof:
+there is always some small chance of two random keys having the
+same ID.)
+.PP
+.I Keyblobtoid
+generates a key ID from a key which is already in the form of an
+RFC 2537/3110 binary key
+.I blob
+(encoded exponent length, exponent, modulus).
+.PP
+.I Splitkeytoid
+generates a key ID from a key given in the form of a separate
+(binary) exponent
+.I e
+and modulus
+.IR m .
+.PP
+The
+.I dstlen
+parameter of either
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines a constant
+.B KEYID_BUF
+which is the size of a buffer large enough for worst-case results.
+.PP
+Both functions return
+.B 0
+for a failure, and otherwise
+always return the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.P
+With keys generated by
+.IR ipsec_rsasigkey (3),
+the first two base64 digits are always the same,
+and the third carries only about one bit of information.
+It's worse with keys using longer fixed exponents,
+e.g. the 24-bit exponent that's common in X.509 certificates.
+However, being able to relate key IDs to the full
+base64 text form of keys by eye is sufficiently useful that this
+waste of space seems justifiable.
+The choice of nine digits is a compromise between bulk and
+probability of collision.
+.SH SEE ALSO
+RFC 3110,
+\fIRSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)\fR,
+Eastlake, 2001
+(superseding the older but better-known RFC 2537).
+.SH DIAGNOSTICS
+Fatal errors are:
+key too short to supply enough bits to construct a complete key ID
+(almost certainly indicating a garbage key);
+exponent too long for its length to be representable.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/keyblobtoid.c b/src/libfreeswan/keyblobtoid.c
new file mode 100644
index 000000000..7798601cf
--- /dev/null
+++ b/src/libfreeswan/keyblobtoid.c
@@ -0,0 +1,148 @@
+/*
+ * generate printable key IDs
+ * Copyright (C) 2002 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: keyblobtoid.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - keyblobtoid - generate a printable key ID from an RFC 2537/3110 key blob
+ * Current algorithm is just to use first nine base64 digits.
+ */
+size_t
+keyblobtoid(src, srclen, dst, dstlen)
+const unsigned char *src;
+size_t srclen;
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ char buf[KEYID_BUF];
+ size_t ret;
+# define NDIG 9
+
+ if (srclen < (NDIG*6 + 7)/8) {
+ strcpy(buf, "?len= ?");
+ buf[5] = '0' + srclen;
+ ret = 0;
+ } else {
+ (void) datatot(src, srclen, 64, buf, NDIG+1);
+ ret = NDIG+1;
+ }
+
+ if (dstlen > 0) {
+ if (strlen(buf)+1 > dstlen)
+ *(buf + dstlen - 1) = '\0';
+ strcpy(dst, buf);
+ }
+ return ret;
+}
+
+/*
+ - splitkeytoid - generate a printable key ID from exponent/modulus pair
+ * Just constructs the beginnings of a key blob and calls keyblobtoid().
+ */
+size_t
+splitkeytoid(e, elen, m, mlen, dst, dstlen)
+const unsigned char *e;
+size_t elen;
+const unsigned char *m;
+size_t mlen;
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ unsigned char buf[KEYID_BUF]; /* ample room */
+ unsigned char *bufend = buf + sizeof(buf);
+ unsigned char *p;
+ size_t n;
+
+ p = buf;
+ if (elen <= 255)
+ *p++ = elen;
+ else if ((elen &~ 0xffff) == 0) {
+ *p++ = 0;
+ *p++ = (elen>>8) & 0xff;
+ *p++ = elen & 0xff;
+ } else
+ return 0; /* unrepresentable exponent length */
+
+ n = bufend - p;
+ if (elen < n)
+ n = elen;
+ memcpy(p, e, n);
+ p += n;
+
+ n = bufend - p;
+ if (n > 0) {
+ if (mlen < n)
+ n = mlen;
+ memcpy(p, m, n);
+ p += n;
+ }
+
+ return keyblobtoid(buf, p - buf, dst, dstlen);
+}
+
+
+
+#ifdef KEYBLOBTOID_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ typedef unsigned char uc;
+ uc hexblob[] = "\x01\x03\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52";
+ uc hexe[] = "\x03";
+ uc hexm[] = "\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52\xef\x85";
+ char b64nine[] = "AQOF8tZ2m";
+ char b64six[] = "AQOF8t";
+ char buf[100];
+ size_t n;
+ char *b = b64nine;
+ size_t bl = strlen(b) + 1;
+ int st = 0;
+
+ n = keyblobtoid(hexblob, strlen(hexblob), buf, sizeof(buf));
+ if (n != bl) {
+ fprintf(stderr, "%s: keyblobtoid returned %d not %d\n",
+ argv[0], n, bl);
+ st = 1;
+ }
+ if (strcmp(buf, b) != 0) {
+ fprintf(stderr, "%s: keyblobtoid generated `%s' not `%s'\n",
+ argv[0], buf, b);
+ st = 1;
+ }
+ n = splitkeytoid(hexe, strlen(hexe), hexm, strlen(hexm), buf,
+ sizeof(buf));
+ if (n != bl) {
+ fprintf(stderr, "%s: splitkeytoid returned %d not %d\n",
+ argv[0], n, bl);
+ st = 1;
+ }
+ if (strcmp(buf, b) != 0) {
+ fprintf(stderr, "%s: splitkeytoid generated `%s' not `%s'\n",
+ argv[0], buf, b);
+ st = 1;
+ }
+ exit(st);
+}
+
+#endif /* KEYBLOBTOID_MAIN */
diff --git a/src/libfreeswan/optionsfrom.3 b/src/libfreeswan/optionsfrom.3
new file mode 100644
index 000000000..e270475bd
--- /dev/null
+++ b/src/libfreeswan/optionsfrom.3
@@ -0,0 +1,182 @@
+.TH IPSEC_OPTIONSFROM 3 "16 Oct 1998"
+.\" RCSID $Id: optionsfrom.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec optionsfrom \- read additional ``command-line'' options from file
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *optionsfrom(char *filename, int *argcp,"
+.ti +1c
+.B "char ***argvp, int optind, FILE *errsto);"
+.SH DESCRIPTION
+.I Optionsfrom
+is called from within a
+.IR getopt_long (3)
+scan,
+as the result of the appearance of an option (preferably
+.BR \-\-optionsfrom )
+to insert additional ``command-line'' arguments
+into the scan immediately after
+the option.
+Typically this would be done to pick up options which are
+security-sensitive and should not be visible to
+.IR ps (1)
+and similar commands,
+and hence cannot be supplied as part
+of the actual command line or the environment.
+.PP
+.I Optionsfrom
+reads the additional arguments from the specified
+.IR filename ,
+allocates a new argument vector to hold pointers to the existing
+arguments plus the new ones,
+and amends
+.I argc
+and
+.I argv
+(via the pointers
+.I argcp
+and
+.IR argvp ,
+which must point to the
+.I argc
+and
+.I argv
+being supplied to
+.IR getopt_long (3))
+accordingly.
+.I Optind
+must be the index, in the original argument vector,
+of the next argument.
+.PP
+If
+.I errsto
+is NULL,
+.I optionsfrom
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+If
+.I errsto
+is non-NULL and an error occurs,
+.I optionsfrom
+prints a suitable complaint onto the
+.I errsto
+descriptor and invokes
+.I exit
+with an exit status of 2;
+this is a convenience for cases where more sophisticated
+responses are not required.
+.PP
+The text of existing arguments is not disturbed by
+.IR optionsfrom ,
+so pointers to them and into them remain valid.
+.PP
+The file of additional arguments is an ASCII text file.
+Lines consisting solely of white space,
+and lines beginning with
+.BR # ,
+are comments and are ignored.
+Otherwise, a line which does not begin with
+.BR \-
+is taken to be a single argument;
+if it both begins and ends with double-quote ("),
+those quotes are stripped off (note, no other processing is done within
+the line!).
+A line beginning with
+.B \-
+is considered to contain multiple arguments separated by white space.
+.PP
+Because
+.I optionsfrom
+reads its entire file before the
+.IR getopt_long (3)
+scan is resumed, an
+.I optionsfrom
+file can contain another
+.B \-\-optionsfrom
+option.
+Obviously, infinite loops are possible here.
+If
+.I errsto
+is non-NULL,
+.I optionsfrom
+considers it an error to be called more than 100 times.
+If
+.I errsto
+is NULL,
+loop detection is up to the caller
+(and the internal loop counter is zeroed out).
+.SH EXAMPLE
+A reasonable way to invoke
+.I optionsfrom
+would be like so:
+.PP
+.nf
+.ft B
+#include <getopt.h>
+
+struct option opts[] = {
+ /* ... */
+ "optionsfrom", 1, NULL, '+',
+ /* ... */
+};
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
+ switch (opt) {
+ /* ... */
+ case '+': /* optionsfrom */
+ optionsfrom(optarg, &argc, &argv, optind, stderr);
+ /* does not return on error */
+ break;
+ /* ... */
+ }
+ /* ... */
+.ft
+.fi
+.SH SEE ALSO
+getopt_long(3)
+.SH DIAGNOSTICS
+Errors in
+.I optionsfrom
+are:
+unable to open file;
+attempt to allocate temporary storage for argument or
+argument vector failed;
+read error in file;
+line too long.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The double-quote convention is rather simplistic.
+.PP
+Line length is currently limited to 1023 bytes,
+and there is no continuation convention.
+.PP
+The restriction of error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+.PP
+There is a certain element of unwarranted chumminess with
+the insides of
+.IR getopt_long (3)
+here.
+No non-public interfaces are actually used, but
+.IR optionsfrom
+does rely on
+.IR getopt_long (3)
+being well-behaved in certain ways that are not actually
+promised by the specs.
diff --git a/src/libfreeswan/optionsfrom.c b/src/libfreeswan/optionsfrom.c
new file mode 100644
index 000000000..d96a3124d
--- /dev/null
+++ b/src/libfreeswan/optionsfrom.c
@@ -0,0 +1,301 @@
+/*
+ * pick up more options from a file, in the middle of an option scan
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: optionsfrom.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#include <stdio.h>
+
+#define MAX 100 /* loop-detection limit */
+
+/* internal work area */
+struct work {
+# define LOTS 1024
+ char buf[LOTS];
+ char *line;
+ char *pending;
+};
+
+static const char *dowork(const char *, int *, char ***, int);
+static const char *getanarg(FILE *, struct work *, char **);
+static char *getline(FILE *, char *, size_t);
+
+/*
+ - optionsfrom - add some options, taken from a file, to argc/argv
+ * If errsto is non-NULL, does not return in event of error.
+ */
+const char * /* NULL for success, else string literal */
+optionsfrom(filename, argcp, argvp, optind, errsto)
+const char *filename;
+int *argcp; /* pointer to argc */
+char ***argvp; /* pointer to argv */
+int optind; /* current optind, number of next argument */
+FILE *errsto; /* where to report errors (NULL means return) */
+{
+ const char *e;
+ static int nuses = 0;
+
+ if (errsto != NULL) {
+ nuses++;
+ if (nuses >= MAX) {
+ fprintf(errsto,
+ "%s: optionsfrom called %d times, looping?\n",
+ (*argvp)[0], nuses);
+ exit(2);
+ }
+ } else
+ nuses = 0;
+
+ e = dowork(filename, argcp, argvp, optind);
+ if (e != NULL && errsto != NULL) {
+ fprintf(errsto, "%s: optionsfrom failed: %s\n", (*argvp)[0], e);
+ exit(2);
+ }
+ return e;
+}
+
+/*
+ - dowork - do all the real work of optionsfrom
+ * Does not alter the existing arguments, but does relocate and alter
+ * the argv pointer vector.
+ */
+static const char * /* NULL for success, else string literal */
+dowork(filename, argcp, argvp, optind)
+const char *filename;
+int *argcp; /* pointer to argc */
+char ***argvp; /* pointer to argv */
+int optind; /* current optind, number of next argument */
+{
+ char **newargv;
+ char **tmp;
+ int newargc;
+ int next; /* place for next argument */
+ int room; /* how many more new arguments we can hold */
+# define SOME 10 /* first guess at how many we'll need */
+ FILE *f;
+ int i;
+ const char *p;
+ struct work wa; /* for getanarg() */
+
+ f = fopen(filename, "r");
+ if (f == NULL)
+ return "unable to open file";
+
+ newargc = *argcp + SOME;
+ newargv = malloc((newargc+1) * sizeof(char *));
+ if (newargv == NULL)
+ return "unable to allocate memory";
+ memcpy(newargv, *argvp, optind * sizeof(char *));
+ room = SOME;
+ next = optind;
+
+ newargv[next] = NULL;
+ wa.pending = NULL;
+ while ((p = getanarg(f, &wa, &newargv[next])) == NULL) {
+ if (room == 0) {
+ newargc += SOME;
+ tmp = realloc(newargv, (newargc+1) * sizeof(char *));
+ if (tmp == NULL) {
+ p = "out of space for new argv";
+ break; /* NOTE BREAK OUT */
+ }
+ newargv = tmp;
+ room += SOME;
+ }
+ next++;
+ room--;
+ }
+ if (p != NULL && !feof(f)) { /* error of some kind */
+ for (i = optind+1; i <= next; i++)
+ if (newargv[i] != NULL)
+ free(newargv[i]);
+ free(newargv);
+ fclose(f);
+ return p;
+ }
+
+ fclose(f);
+ memcpy(newargv + next, *argvp + optind,
+ (*argcp+1-optind) * sizeof(char *));
+ *argcp += next - optind;
+ *argvp = newargv;
+ return NULL;
+}
+
+/*
+ - getanarg - get a malloced argument from the file
+ */
+static const char * /* NULL for success, else string literal */
+getanarg(f, w, linep)
+FILE *f;
+struct work *w;
+char **linep; /* where to store pointer if successful */
+{
+ size_t len;
+ char *p;
+ char *endp;
+
+ while (w->pending == NULL) { /* no pending line */
+ if ((w->line = getline(f, w->buf, sizeof(w->buf))) == NULL)
+ return "error in line read"; /* caller checks EOF */
+ if (w->line[0] != '#' &&
+ *(w->line + strspn(w->line, " \t")) != '\0')
+ w->pending = w->line;
+ }
+
+ if (w->pending == w->line && w->line[0] != '-') {
+ /* fresh plain line */
+ w->pending = NULL;
+ p = w->line;
+ endp = p + strlen(p);
+ if (*p == '"' && endp > p+1 && *(endp-1) == '"') {
+ p++;
+ endp--;
+ *endp = '\0';
+ }
+ if (w->line == w->buf) {
+ *linep = malloc(endp - p + 1);
+ if (*linep == NULL)
+ return "out of memory for new line";
+ strcpy(*linep, p);
+ } else /* getline already malloced it */
+ *linep = p;
+ return NULL;
+ }
+
+ /* chip off a piece of a pending line */
+ p = w->pending;
+ p += strspn(p, " \t");
+ endp = p + strcspn(p, " \t");
+ len = endp - p;
+ if (*endp != '\0') {
+ *endp++ = '\0';
+ endp += strspn(endp, " \t");
+ }
+ /* endp now points to next real character, or to line-end NUL */
+ *linep = malloc(len + 1);
+ if (*linep == NULL) {
+ if (w->line != w->buf)
+ free(w->line);
+ return "out of memory for new argument";
+ }
+ strcpy(*linep, p);
+ if (*endp == '\0') {
+ w->pending = NULL;
+ if (w->line != w->buf)
+ free(w->line);
+ } else
+ w->pending = endp;
+ return NULL;
+}
+
+/*
+ - getline - read a line from the file, trim newline off
+ */
+static char * /* pointer to line, NULL for eof/error */
+getline(f, buf, bufsize)
+FILE *f;
+char *buf; /* buffer to use, if convenient */
+size_t bufsize; /* size of buf */
+{
+ size_t len;
+
+ if (fgets(buf, bufsize, f) == NULL)
+ return NULL;
+ len = strlen(buf);
+
+ if (len < bufsize-1 || buf[bufsize-1] == '\n') {
+ /* it fit */
+ buf[len-1] = '\0';
+ return buf;
+ }
+
+ /* oh crud, buffer overflow */
+ /* for now, to hell with it */
+ return NULL;
+}
+
+
+
+#ifdef TEST
+
+#include <getopt.h>
+
+char usage[] = "Usage: tester [--foo] [--bar] [--optionsfrom file] arg ...";
+struct option opts[] = {
+ "foo", 0, NULL, 'f',
+ "bar", 0, NULL, 'b',
+ "builtin", 0, NULL, 'B',
+ "optionsfrom", 1, NULL, '+',
+ "help", 0, NULL, 'h',
+ "version", 0, NULL, 'v',
+ 0, 0, NULL, 0,
+};
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int opt;
+ extern char *optarg;
+ extern int optind;
+ int errflg = 0;
+ const char *p;
+ int i;
+ FILE *errs = NULL;
+
+ while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
+ switch (opt) {
+ case 'f':
+ case 'b':
+ break;
+ case 'B':
+ errs = stderr;
+ break;
+ case '+': /* optionsfrom */
+ p = optionsfrom(optarg, &argc, &argv, optind, errs);
+ if (p != NULL) {
+ fprintf(stderr, "%s: optionsfrom error: %s\n",
+ argv[0], p);
+ exit(1);
+ }
+ break;
+ case 'h': /* help */
+ printf("%s\n", usage);
+ exit(0);
+ break;
+ case 'v': /* version */
+ printf("1\n");
+ exit(0);
+ break;
+ case '?':
+ default:
+ errflg = 1;
+ break;
+ }
+ if (errflg) {
+ fprintf(stderr, "%s\n", usage);
+ exit(2);
+ }
+
+ for (i = 1; i < argc; i++)
+ printf("%d: `%s'\n", i, argv[i]);
+ exit(0);
+}
+
+
+#endif /* TEST */
diff --git a/src/libfreeswan/pfkey.h b/src/libfreeswan/pfkey.h
new file mode 100644
index 000000000..afa5ce032
--- /dev/null
+++ b/src/libfreeswan/pfkey.h
@@ -0,0 +1,498 @@
+/*
+ * FreeS/WAN specific PF_KEY headers
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pfkey.h,v 1.2 2004/03/22 21:53:18 as Exp $
+ */
+
+#ifndef __NET_IPSEC_PF_KEY_H
+#define __NET_IPSEC_PF_KEY_H
+#ifdef __KERNEL__
+extern struct proto_ops pfkey_proto_ops;
+typedef struct sock pfkey_sock;
+extern int debug_pfkey;
+
+extern /* void */ int pfkey_init(void);
+extern /* void */ int pfkey_cleanup(void);
+
+extern struct sock *pfkey_sock_list;
+struct socket_list
+{
+ struct socket *socketp;
+ struct socket_list *next;
+};
+extern int pfkey_list_insert_socket(struct socket*, struct socket_list**);
+extern int pfkey_list_remove_socket(struct socket*, struct socket_list**);
+extern struct socket_list *pfkey_open_sockets;
+extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];
+
+/*
+ * There is a field-by-field copy in klips/net/ipsec/ipsec_alg.h
+ * please keep in sync until we migrate all support stuff
+ * to ipsec_alg objects
+ */
+struct supported
+{
+ uint16_t supported_alg_exttype;
+ uint8_t supported_alg_id;
+ uint8_t supported_alg_ivlen;
+ uint16_t supported_alg_minbits;
+ uint16_t supported_alg_maxbits;
+};
+extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];
+struct supported_list
+{
+ struct supported *supportedp;
+ struct supported_list *next;
+};
+extern int pfkey_list_insert_supported(struct supported*, struct supported_list**);
+extern int pfkey_list_remove_supported(struct supported*, struct supported_list**);
+
+struct sockaddr_key
+{
+ uint16_t key_family; /* PF_KEY */
+ uint16_t key_pad; /* not used */
+ uint32_t key_pid; /* process ID */
+};
+
+struct pfkey_extracted_data
+{
+ struct ipsec_sa* ips;
+ struct ipsec_sa* ips2;
+ struct eroute *eroute;
+};
+
+extern int
+pfkey_alloc_eroute(struct eroute** eroute);
+
+extern int
+pfkey_sa_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_lifetime_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_address_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_key_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_ident_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_sens_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_prop_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_supported_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_spirange_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_x_satype_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int
+pfkey_x_debug_process(struct sadb_ext *pfkey_ext,
+ struct pfkey_extracted_data* extr);
+
+extern int pfkey_register_reply(int satype, struct sadb_msg *);
+extern int pfkey_upmsg(struct socket *, struct sadb_msg *);
+extern int pfkey_expire(struct ipsec_sa *, int);
+extern int pfkey_acquire(struct ipsec_sa *);
+#else /* ! __KERNEL__ */
+
+extern void (*pfkey_debug_func)(const char *message, ...);
+
+#endif /* __KERNEL__ */
+
+extern uint8_t satype2proto(uint8_t satype);
+extern uint8_t proto2satype(uint8_t proto);
+extern char* satype2name(uint8_t satype);
+extern char* proto2name(uint8_t proto);
+
+struct key_opt
+{
+ uint32_t key_pid; /* process ID */
+ struct sock *sk;
+};
+
+#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid
+
+#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t))
+#define BITS_PER_OCTET 8
+#define OCTETBITS 8
+#define PFKEYBITS 64
+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
+#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */
+
+#define PFKEYv2_MAX_MSGSIZE 4096
+
+/*
+ * PF_KEYv2 permitted and required extensions in and out bitmaps
+ */
+struct pf_key_ext_parsers_def {
+ int (*parser)(struct sadb_ext*);
+ char *parser_name;
+};
+
+
+extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/];
+#define EXT_BITS_IN 0
+#define EXT_BITS_OUT 1
+#define EXT_BITS_PERM 0
+#define EXT_BITS_REQ 1
+
+extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
+extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
+extern void pfkey_msg_free(struct sadb_msg **pfkey_msg);
+
+extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg,
+ struct pf_key_ext_parsers_def *ext_parsers[],
+ struct sadb_ext **extensions,
+ int dir);
+
+/*
+ * PF_KEYv2 build function prototypes
+ */
+
+int
+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
+ uint8_t msg_type,
+ uint8_t satype,
+ uint8_t msg_errno,
+ uint32_t seq,
+ uint32_t pid);
+
+int
+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t spi, /* in network order */
+ uint8_t replay_window,
+ uint8_t sa_state,
+ uint8_t auth,
+ uint8_t encrypt,
+ uint32_t flags,
+ uint32_t/*IPsecSAref_t*/ ref);
+
+int
+pfkey_sa_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t spi, /* in network order */
+ uint8_t replay_window,
+ uint8_t sa_state,
+ uint8_t auth,
+ uint8_t encrypt,
+ uint32_t flags);
+
+int
+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t allocations,
+ uint64_t bytes,
+ uint64_t addtime,
+ uint64_t usetime,
+ uint32_t packets);
+
+int
+pfkey_address_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint8_t proto,
+ uint8_t prefixlen,
+ struct sockaddr* address);
+
+int
+pfkey_key_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t key_bits,
+ char* key);
+
+int
+pfkey_ident_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t ident_type,
+ uint64_t ident_id,
+ uint8_t ident_len,
+ char* ident_string);
+
+#ifdef __KERNEL__
+extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16);
+extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr);
+extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr);
+#endif /* __KERNEL__ */
+
+int
+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext,
+ uint8_t type);
+int
+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t port);
+
+int
+pfkey_sens_build(struct sadb_ext** pfkey_ext,
+ uint32_t dpd,
+ uint8_t sens_level,
+ uint8_t sens_len,
+ uint64_t* sens_bitmap,
+ uint8_t integ_level,
+ uint8_t integ_len,
+ uint64_t* integ_bitmap);
+
+int
+pfkey_x_protocol_build(struct sadb_ext **, uint8_t);
+
+
+int
+pfkey_prop_build(struct sadb_ext** pfkey_ext,
+ uint8_t replay,
+ unsigned int comb_num,
+ struct sadb_comb* comb);
+
+int
+pfkey_supported_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ unsigned int alg_num,
+ struct sadb_alg* alg);
+
+int
+pfkey_spirange_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint32_t min,
+ uint32_t max);
+
+int
+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext);
+
+int
+pfkey_x_satype_build(struct sadb_ext** pfkey_ext,
+ uint8_t satype);
+
+int
+pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
+ uint32_t tunnel,
+ uint32_t netlink,
+ uint32_t xform,
+ uint32_t eroute,
+ uint32_t spi,
+ uint32_t radij,
+ uint32_t esp,
+ uint32_t ah,
+ uint32_t rcv,
+ uint32_t pfkey,
+ uint32_t ipcomp,
+ uint32_t verbose);
+
+int
+pfkey_msg_build(struct sadb_msg** pfkey_msg,
+ struct sadb_ext* extensions[],
+ int dir);
+
+/* in pfkey_v2_debug.c - routines to decode numbers -> strings */
+const char *
+pfkey_v2_sadb_ext_string(int extnum);
+
+const char *
+pfkey_v2_sadb_type_string(int sadb_type);
+
+
+#endif /* __NET_IPSEC_PF_KEY_H */
+
+/*
+ * $Log: pfkey.h,v $
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.2.1.2.1 2004/03/16 09:48:18 as
+ * alg-0.8.1rc12 patch merged
+ *
+ * Revision 1.1.2.1 2004/03/15 22:30:06 as
+ * nat-0.6c patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.42 2003/08/25 22:08:19 mcr
+ * removed pfkey_proto_init() from pfkey.h for 2.6 support.
+ *
+ * Revision 1.41 2003/05/07 17:28:57 mcr
+ * new function pfkey_debug_func added for us in debugging from
+ * pfkey library.
+ *
+ * Revision 1.40 2003/01/30 02:31:34 rgb
+ *
+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
+ *
+ * Revision 1.39 2002/09/20 15:40:21 rgb
+ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc().
+ * Added ref parameter to pfkey_sa_build().
+ * Cleaned out unused cruft.
+ *
+ * Revision 1.38 2002/05/14 02:37:24 rgb
+ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
+ * ipsec_sa or ipsec_sa.
+ * Added function prototypes for the functions moved to
+ * pfkey_v2_ext_process.c.
+ *
+ * Revision 1.37 2002/04/24 07:36:49 mcr
+ * Moved from ./lib/pfkey.h,v
+ *
+ * Revision 1.36 2002/01/20 20:34:49 mcr
+ * added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.35 2001/11/27 05:27:47 mcr
+ * pfkey parses are now maintained by a structure
+ * that includes their name for debug purposes.
+ *
+ * Revision 1.34 2001/11/26 09:23:53 rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.33 2001/11/06 19:47:47 rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.32 2001/09/08 21:13:34 rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.31 2001/06/14 19:35:16 rgb
+ * Update copyright date.
+ *
+ * Revision 1.30 2001/02/27 07:04:52 rgb
+ * Added satype2name prototype.
+ *
+ * Revision 1.29 2001/02/26 19:59:33 rgb
+ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
+ *
+ * Revision 1.28 2000/10/10 20:10:19 rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.27 2000/09/21 04:20:45 rgb
+ * Fixed array size off-by-one error. (Thanks Svenning!)
+ *
+ * Revision 1.26 2000/09/12 03:26:05 rgb
+ * Added pfkey_acquire prototype.
+ *
+ * Revision 1.25 2000/09/08 19:21:28 rgb
+ * Fix pfkey_prop_build() parameter to be only single indirection.
+ *
+ * Revision 1.24 2000/09/01 18:46:42 rgb
+ * Added a supported algorithms array lists, one per satype and registered
+ * existing algorithms.
+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
+ * list.
+ *
+ * Revision 1.23 2000/08/27 01:55:26 rgb
+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
+ *
+ * Revision 1.22 2000/08/20 21:39:23 rgb
+ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and
+ * pfkey_expire().
+ *
+ * Revision 1.21 2000/08/15 17:29:23 rgb
+ * Fixes from SZI to untested pfkey_prop_build().
+ *
+ * Revision 1.20 2000/05/10 20:14:19 rgb
+ * Fleshed out sensitivity, proposal and supported extensions.
+ *
+ * Revision 1.19 2000/03/16 14:07:23 rgb
+ * Renamed ALIGN macro to avoid fighting with others in kernel.
+ *
+ * Revision 1.18 2000/01/22 23:24:06 rgb
+ * Added prototypes for proto2satype(), satype2proto() and proto2name().
+ *
+ * Revision 1.17 2000/01/21 06:26:59 rgb
+ * Converted from double tdb arguments to one structure (extr)
+ * containing pointers to all temporary information structures.
+ * Added klipsdebug switching capability.
+ * Dropped unused argument to pfkey_x_satype_build().
+ *
+ * Revision 1.16 1999/12/29 21:17:41 rgb
+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
+ * parameter for cleaner manipulation of extensions[] and to guard
+ * against potential memory leaks.
+ * Changed the I/F to pfkey_msg_free() for the same reason.
+ *
+ * Revision 1.15 1999/12/09 23:12:54 rgb
+ * Added macro for BITS_PER_OCTET.
+ * Added argument to pfkey_sa_build() to do eroutes.
+ *
+ * Revision 1.14 1999/12/08 20:33:25 rgb
+ * Changed sa_family_t to uint16_t for 2.0.xx compatibility.
+ *
+ * Revision 1.13 1999/12/07 19:53:40 rgb
+ * Removed unused first argument from extension parsers.
+ * Changed __u* types to uint* to avoid use of asm/types.h and
+ * sys/types.h in userspace code.
+ * Added function prototypes for pfkey message and extensions
+ * initialisation and cleanup.
+ *
+ * Revision 1.12 1999/12/01 22:19:38 rgb
+ * Change pfkey_sa_build to accept an SPI in network byte order.
+ *
+ * Revision 1.11 1999/11/27 11:55:26 rgb
+ * Added extern sadb_satype2proto to enable moving protocol lookup table
+ * to lib/pfkey_v2_parse.c.
+ * Delete unused, moved typedefs.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ *
+ * Revision 1.10 1999/11/23 22:29:21 rgb
+ * This file has been moved in the distribution from klips/net/ipsec to
+ * lib.
+ * Add macros for dealing with alignment and rounding up more opaquely.
+ * The uint<n>_t type defines have been moved to freeswan.h to avoid
+ * chicken-and-egg problems.
+ * Add macros for dealing with alignment and rounding up more opaque.
+ * Added prototypes for using extention header bitmaps.
+ * Added prototypes of all the build functions.
+ *
+ * Revision 1.9 1999/11/20 21:59:48 rgb
+ * Moved socketlist type declarations and prototypes for shared use.
+ * Slightly modified scope of sockaddr_key declaration.
+ *
+ * Revision 1.8 1999/11/17 14:34:25 rgb
+ * Protect sa_family_t from being used in userspace with GLIBC<2.
+ *
+ * Revision 1.7 1999/10/27 19:40:35 rgb
+ * Add a maximum PFKEY packet size macro.
+ *
+ * Revision 1.6 1999/10/26 16:58:58 rgb
+ * Created a sockaddr_key and key_opt socket extension structures.
+ *
+ * Revision 1.5 1999/06/10 05:24:41 rgb
+ * Renamed variables to reduce confusion.
+ *
+ * Revision 1.4 1999/04/29 15:21:11 rgb
+ * Add pfkey support to debugging.
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.3 1999/04/15 17:58:07 rgb
+ * Add RCSID labels.
+ *
+ */
diff --git a/src/libfreeswan/pfkey_v2_build.c b/src/libfreeswan/pfkey_v2_build.c
new file mode 100644
index 000000000..340c12cfe
--- /dev/null
+++ b/src/libfreeswan/pfkey_v2_build.c
@@ -0,0 +1,1435 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pfkey_v2_build.c,v 1.4 2005/04/07 19:43:52 as Exp $
+ */
+
+/*
+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c.
+ */
+
+char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.4 2005/04/07 19:43:52 as Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h> /* for printk */
+
+# include "freeswan/ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h> /* error codes */
+# include <linux/types.h> /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h> /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h> /* struct iphdr */
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+# include <linux/ipv6.h> /* struct ipv6hdr */
+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
+# define MALLOC(size) kmalloc(size, GFP_ATOMIC)
+# define FREE(obj) kfree(obj)
+# include <freeswan.h>
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+# include <malloc.h>
+# include <string.h> /* memset */
+
+# include <freeswan.h>
+unsigned int pfkey_lib_debug = 0;
+
+void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1);
+
+/* #define PLUTO */
+
+#define DEBUGGING(args...) if(pfkey_lib_debug) { \
+ if(pfkey_debug_func != NULL) { \
+ (*pfkey_debug_func)("pfkey_lib_debug:" args); \
+ } else { \
+ printf("pfkey_lib_debug:" args); \
+ } }
+# define MALLOC(size) malloc(size)
+# define FREE(obj) free(obj)
+#endif /* __KERNEL__ */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef __KERNEL__
+
+#include "freeswan/radij.h" /* rd_nodes */
+#include "freeswan/ipsec_encap.h" /* sockaddr_encap */
+
+# define DEBUGGING(args...) \
+ KLIPS_PRINT(debug_pfkey, "klips_debug:" args)
+#endif /* __KERNEL__ */
+
+#include "ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+void
+pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
+{
+ int i;
+
+ for (i = 0; i != SADB_EXT_MAX + 1; i++) {
+ extensions[i] = NULL;
+ }
+}
+
+void
+pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
+{
+ int i;
+
+ if (!extensions) {
+ return;
+ }
+
+ if (extensions[0]) {
+ memset(extensions[0], 0, sizeof(struct sadb_msg));
+ FREE(extensions[0]);
+ extensions[0] = NULL;
+ }
+
+ for (i = 1; i != SADB_EXT_MAX + 1; i++) {
+ if(extensions[i]) {
+ memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+ FREE(extensions[i]);
+ extensions[i] = NULL;
+ }
+ }
+}
+
+void
+pfkey_msg_free(struct sadb_msg **pfkey_msg)
+{
+ if (*pfkey_msg) {
+ memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+ FREE(*pfkey_msg);
+ *pfkey_msg = NULL;
+ }
+}
+
+/* Default extension builders taken from the KLIPS code */
+
+int
+pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
+ uint8_t msg_type,
+ uint8_t satype,
+ uint8_t msg_errno,
+ uint32_t seq,
+ uint32_t pid)
+{
+ int error = 0;
+ struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_msg_hdr_build:\n");
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
+ &pfkey_ext,
+ pfkey_ext,
+ *pfkey_ext);
+ /* sanity checks... */
+ if (pfkey_msg) {
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "why is pfkey_msg already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (!msg_type) {
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "msg type not set, must be non-zero..\n");
+ SENDERR(EINVAL);
+ }
+
+ if (msg_type > SADB_MAX) {
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "msg type too large:%d.\n",
+ msg_type);
+ SENDERR(EINVAL);
+ }
+
+ if (satype > SADB_SATYPE_MAX) {
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "satype %d > max %d\n",
+ satype, SADB_SATYPE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg));
+ *pfkey_ext = (struct sadb_ext*)pfkey_msg;
+
+ if (pfkey_msg == NULL) {
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_msg, 0, sizeof(struct sadb_msg));
+
+ pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_msg->sadb_msg_type = msg_type;
+ pfkey_msg->sadb_msg_satype = satype;
+
+ pfkey_msg->sadb_msg_version = PF_KEY_V2;
+ pfkey_msg->sadb_msg_errno = msg_errno;
+ pfkey_msg->sadb_msg_reserved = 0;
+ pfkey_msg->sadb_msg_seq = seq;
+ pfkey_msg->sadb_msg_pid = pid;
+ DEBUGGING(
+ "pfkey_msg_hdr_build: "
+ "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
+ &pfkey_ext,
+ pfkey_ext,
+ *pfkey_ext);
+errlab:
+ return error;
+}
+
+int
+pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t spi,
+ uint8_t replay_window,
+ uint8_t sa_state,
+ uint8_t auth,
+ uint8_t encrypt,
+ uint32_t flags,
+ uint32_t/*IPsecSAref_t*/ ref)
+{
+ int error = 0;
+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n",
+ ntohl(spi), /* in network order */
+ replay_window,
+ sa_state,
+ auth,
+ encrypt,
+ flags);
+ /* sanity checks... */
+ if (pfkey_sa) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "why is pfkey_sa already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (exttype != SADB_EXT_SA
+ && exttype != SADB_X_EXT_SA2) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "invalid exttype=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ if (replay_window > 64) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "replay window size: %d -- must be 0 <= size <= 64\n",
+ replay_window);
+ SENDERR(EINVAL);
+ }
+
+ if (auth > SADB_AALG_MAX) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "auth=%d > SADB_AALG_MAX=%d.\n",
+ auth,
+ SADB_AALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if (encrypt > SADB_EALG_MAX) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "encrypt=%d > SADB_EALG_MAX=%d.\n",
+ encrypt,
+ SADB_EALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if (sa_state > SADB_SASTATE_MAX) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "sa_state=%d exceeds MAX=%d.\n",
+ sa_state,
+ SADB_SASTATE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if (sa_state == SADB_SASTATE_DEAD) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "sa_state=%d is DEAD=%d is not allowed.\n",
+ sa_state,
+ SADB_SASTATE_DEAD);
+ SENDERR(EINVAL);
+ }
+
+ if ((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
+ ref,
+ IPSEC_SAREF_NULL,
+ IPSEC_SA_REF_TABLE_NUM_ENTRIES);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_sa = (struct sadb_sa*)MALLOC(sizeof(struct sadb_sa));
+ *pfkey_ext = (struct sadb_ext*)pfkey_sa;
+
+ if (pfkey_sa == NULL) {
+ DEBUGGING(
+ "pfkey_sa_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_sa, 0, sizeof(struct sadb_sa));
+
+ pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_sa->sadb_sa_exttype = exttype;
+ pfkey_sa->sadb_sa_spi = spi;
+ pfkey_sa->sadb_sa_replay = replay_window;
+ pfkey_sa->sadb_sa_state = sa_state;
+ pfkey_sa->sadb_sa_auth = auth;
+ pfkey_sa->sadb_sa_encrypt = encrypt;
+ pfkey_sa->sadb_sa_flags = flags;
+ pfkey_sa->sadb_x_sa_ref = ref;
+
+errlab:
+ return error;
+}
+
+int
+pfkey_sa_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t spi,
+ uint8_t replay_window,
+ uint8_t sa_state,
+ uint8_t auth,
+ uint8_t encrypt,
+ uint32_t flags)
+{
+ return pfkey_sa_ref_build(pfkey_ext,
+ exttype,
+ spi,
+ replay_window,
+ sa_state,
+ auth,
+ encrypt,
+ flags,
+ IPSEC_SAREF_NULL);
+}
+
+int
+pfkey_lifetime_build(struct sadb_ext ** pfkey_ext,
+ uint16_t exttype,
+ uint32_t allocations,
+ uint64_t bytes,
+ uint64_t addtime,
+ uint64_t usetime,
+ uint32_t packets)
+{
+ int error = 0;
+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_lifetime_build:\n");
+ /* sanity checks... */
+ if (pfkey_lifetime) {
+ DEBUGGING(
+ "pfkey_lifetime_build: "
+ "why is pfkey_lifetime already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (exttype != SADB_EXT_LIFETIME_CURRENT
+ && exttype != SADB_EXT_LIFETIME_HARD
+ && exttype != SADB_EXT_LIFETIME_SOFT) {
+ DEBUGGING(
+ "pfkey_lifetime_build: "
+ "invalid exttype=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime));
+ *pfkey_ext = (struct sadb_ext*)pfkey_lifetime;
+
+ if (pfkey_lifetime == NULL) {
+ DEBUGGING(
+ "pfkey_lifetime_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime));
+
+ pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_lifetime->sadb_lifetime_exttype = exttype;
+ pfkey_lifetime->sadb_lifetime_allocations = allocations;
+ pfkey_lifetime->sadb_lifetime_bytes = bytes;
+ pfkey_lifetime->sadb_lifetime_addtime = addtime;
+ pfkey_lifetime->sadb_lifetime_usetime = usetime;
+ pfkey_lifetime->sadb_x_lifetime_packets = packets;
+
+errlab:
+ return error;
+}
+
+int
+pfkey_address_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint8_t proto,
+ uint8_t prefixlen,
+ struct sockaddr* address)
+{
+ int error = 0;
+ int saddr_len = 0;
+ char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/];
+ struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_address_build: "
+ "exttype=%d proto=%d prefixlen=%d\n",
+ exttype,
+ proto,
+ prefixlen);
+ /* sanity checks... */
+ if (pfkey_address) {
+ DEBUGGING(
+ "pfkey_address_build: "
+ "why is pfkey_address already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (!address) {
+ DEBUGGING("pfkey_address_build: "
+ "address is NULL\n");
+ SENDERR(EINVAL);
+ }
+
+ switch(exttype) {
+ case SADB_EXT_ADDRESS_SRC:
+ case SADB_EXT_ADDRESS_DST:
+ case SADB_EXT_ADDRESS_PROXY:
+ case SADB_X_EXT_ADDRESS_DST2:
+ case SADB_X_EXT_ADDRESS_SRC_FLOW:
+ case SADB_X_EXT_ADDRESS_DST_FLOW:
+ case SADB_X_EXT_ADDRESS_SRC_MASK:
+ case SADB_X_EXT_ADDRESS_DST_MASK:
+ case SADB_X_EXT_NAT_T_OA:
+ break;
+ default:
+ DEBUGGING(
+ "pfkey_address_build: "
+ "unrecognised ext_type=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ switch (address->sa_family) {
+ case AF_INET:
+ DEBUGGING(
+ "pfkey_address_build: "
+ "found address family AF_INET.\n");
+ saddr_len = sizeof(struct sockaddr_in);
+ sprintf(ipaddr_txt, "%d.%d.%d.%d:%d"
+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF
+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF
+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF
+ , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF
+ , ntohs(((struct sockaddr_in*)address)->sin_port));
+ break;
+ case AF_INET6:
+ DEBUGGING(
+ "pfkey_address_build: "
+ "found address family AF_INET6.\n");
+ saddr_len = sizeof(struct sockaddr_in6);
+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x"
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7])
+ , ntohs(((struct sockaddr_in6*)address)->sin6_port));
+ break;
+ default:
+ DEBUGGING(
+ "pfkey_address_build: "
+ "address->sa_family=%d not supported.\n",
+ address->sa_family);
+ SENDERR(EPFNOSUPPORT);
+ }
+
+ DEBUGGING(
+ "pfkey_address_build: "
+ "found address=%s.\n",
+ ipaddr_txt);
+ if (prefixlen != 0) {
+ DEBUGGING(
+ "pfkey_address_build: "
+ "address prefixes not supported yet.\n");
+ SENDERR(EAFNOSUPPORT); /* not supported yet */
+ }
+
+ pfkey_address = (struct sadb_address*)
+ MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN));
+ *pfkey_ext = (struct sadb_ext*)pfkey_address;
+
+ if (pfkey_address == NULL) {
+ DEBUGGING(
+ "pfkey_lifetime_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_address,
+ 0,
+ ALIGN_N(sizeof(struct sadb_address) + saddr_len,
+ IPSEC_PFKEYv2_ALIGN));
+
+ pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len,
+ IPSEC_PFKEYv2_ALIGN);
+
+ pfkey_address->sadb_address_exttype = exttype;
+ pfkey_address->sadb_address_proto = proto;
+ pfkey_address->sadb_address_prefixlen = prefixlen;
+ pfkey_address->sadb_address_reserved = 0;
+
+ memcpy((char*)pfkey_address + sizeof(struct sadb_address),
+ address,
+ saddr_len);
+
+#if 0
+ for (i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) {
+ pfkey_address_s_ska.sin_zero[i] = 0;
+ }
+#endif
+ DEBUGGING(
+ "pfkey_address_build: "
+ "successful.\n");
+
+ errlab:
+ return error;
+}
+
+int
+pfkey_key_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t key_bits,
+ char* key)
+{
+ int error = 0;
+ struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_key_build:\n");
+ /* sanity checks... */
+ if (pfkey_key) {
+ DEBUGGING(
+ "pfkey_key_build: "
+ "why is pfkey_key already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (!key_bits) {
+ DEBUGGING(
+ "pfkey_key_build: "
+ "key_bits is zero, it must be non-zero.\n");
+ SENDERR(EINVAL);
+ }
+
+ if ( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) {
+ DEBUGGING(
+ "pfkey_key_build: "
+ "unsupported extension type=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_key = (struct sadb_key*)
+ MALLOC(sizeof(struct sadb_key) +
+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
+ *pfkey_ext = (struct sadb_ext*)pfkey_key;
+
+ if (pfkey_key == NULL) {
+ DEBUGGING(
+ "pfkey_key_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_key,
+ 0,
+ sizeof(struct sadb_key) +
+ DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
+
+ pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits,
+ 64);
+ pfkey_key->sadb_key_exttype = exttype;
+ pfkey_key->sadb_key_bits = key_bits;
+ pfkey_key->sadb_key_reserved = 0;
+ memcpy((char*)pfkey_key + sizeof(struct sadb_key),
+ key,
+ DIVUP(key_bits, 8));
+
+errlab:
+ return error;
+}
+
+int
+pfkey_ident_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t ident_type,
+ uint64_t ident_id,
+ uint8_t ident_len,
+ char* ident_string)
+{
+ int error = 0;
+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext;
+ int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+
+ DEBUGGING(
+ "pfkey_ident_build:\n");
+ /* sanity checks... */
+ if (pfkey_ident) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "why is pfkey_ident already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if ( !((exttype == SADB_EXT_IDENTITY_SRC) ||
+ (exttype == SADB_EXT_IDENTITY_DST))) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "unsupported extension type=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ if (ident_type == SADB_IDENTTYPE_RESERVED) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "ident_type must be non-zero.\n");
+ SENDERR(EINVAL);
+ }
+
+ if (ident_type > SADB_IDENTTYPE_MAX) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "identtype=%d out of range.\n",
+ ident_type);
+ SENDERR(EINVAL);
+ }
+
+ if ((ident_type == SADB_IDENTTYPE_PREFIX ||
+ ident_type == SADB_IDENTTYPE_FQDN) &&
+ !ident_string) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "string required to allocate size of extension.\n");
+ SENDERR(EINVAL);
+ }
+
+#if 0
+ if (ident_type == SADB_IDENTTYPE_USERFQDN) {
+ }
+#endif
+
+ pfkey_ident = (struct sadb_ident*)
+ MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN);
+ *pfkey_ext = (struct sadb_ext*)pfkey_ident;
+
+ if (pfkey_ident == NULL) {
+ DEBUGGING(
+ "pfkey_ident_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN);
+
+ pfkey_ident->sadb_ident_len = ident_len;
+ pfkey_ident->sadb_ident_exttype = exttype;
+ pfkey_ident->sadb_ident_type = ident_type;
+ pfkey_ident->sadb_ident_reserved = 0;
+ pfkey_ident->sadb_ident_id = ident_id;
+ memcpy((char*)pfkey_ident + sizeof(struct sadb_ident),
+ ident_string,
+ data_len);
+
+errlab:
+ return error;
+}
+
+int
+pfkey_sens_build(struct sadb_ext** pfkey_ext,
+ uint32_t dpd,
+ uint8_t sens_level,
+ uint8_t sens_len,
+ uint64_t* sens_bitmap,
+ uint8_t integ_level,
+ uint8_t integ_len,
+ uint64_t* integ_bitmap)
+{
+ int error = 0;
+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext;
+ int i;
+ uint64_t* bitmap;
+
+ DEBUGGING(
+ "pfkey_sens_build:\n");
+ /* sanity checks... */
+ if (pfkey_sens) {
+ DEBUGGING(
+ "pfkey_sens_build: "
+ "why is pfkey_sens already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(
+ "pfkey_sens_build: "
+ "Sorry, I can't build exttype=%d yet.\n",
+ (*pfkey_ext)->sadb_ext_type);
+ SENDERR(EINVAL); /* don't process these yet */
+
+ pfkey_sens = (struct sadb_sens*)
+ MALLOC(sizeof(struct sadb_sens) +
+ (sens_len + integ_len) * sizeof(uint64_t));
+ *pfkey_ext = (struct sadb_ext*)pfkey_sens;
+
+ if (pfkey_sens == NULL) {
+ DEBUGGING(
+ "pfkey_sens_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_sens,
+ 0,
+ sizeof(struct sadb_sens) +
+ (sens_len + integ_len) * sizeof(uint64_t));
+
+ pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) +
+ (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
+ pfkey_sens->sadb_sens_dpd = dpd;
+ pfkey_sens->sadb_sens_sens_level = sens_level;
+ pfkey_sens->sadb_sens_sens_len = sens_len;
+ pfkey_sens->sadb_sens_integ_level = integ_level;
+ pfkey_sens->sadb_sens_integ_len = integ_len;
+ pfkey_sens->sadb_sens_reserved = 0;
+
+ bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens));
+ for (i = 0; i < sens_len; i++) {
+ *bitmap = sens_bitmap[i];
+ bitmap++;
+ }
+ for (i = 0; i < integ_len; i++) {
+ *bitmap = integ_bitmap[i];
+ bitmap++;
+ }
+
+errlab:
+ return error;
+}
+
+int
+pfkey_prop_build(struct sadb_ext** pfkey_ext,
+ uint8_t replay,
+ unsigned int comb_num,
+ struct sadb_comb* comb)
+{
+ int error = 0;
+ int i;
+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext;
+ struct sadb_comb *combp;
+
+ DEBUGGING(
+ "pfkey_prop_build:\n");
+ /* sanity checks... */
+ if (pfkey_prop) {
+ DEBUGGING(
+ "pfkey_prop_build: "
+ "why is pfkey_prop already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ pfkey_prop = (struct sadb_prop*)
+ MALLOC(sizeof(struct sadb_prop) +
+ comb_num * sizeof(struct sadb_comb));
+
+ *pfkey_ext = (struct sadb_ext*)pfkey_prop;
+
+ if (pfkey_prop == NULL) {
+ DEBUGGING(
+ "pfkey_prop_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_prop,
+ 0,
+ sizeof(struct sadb_prop) +
+ comb_num * sizeof(struct sadb_comb));
+
+ pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
+ comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
+ pfkey_prop->sadb_prop_replay = replay;
+
+ for (i=0; i<3; i++) {
+ pfkey_prop->sadb_prop_reserved[i] = 0;
+ }
+
+ combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop));
+ for (i = 0; i < comb_num; i++) {
+ memcpy (combp, &(comb[i]), sizeof(struct sadb_comb));
+ combp++;
+ }
+
+#if 0
+ uint8_t sadb_comb_auth;
+ uint8_t sadb_comb_encrypt;
+ uint16_t sadb_comb_flags;
+ uint16_t sadb_comb_auth_minbits;
+ uint16_t sadb_comb_auth_maxbits;
+ uint16_t sadb_comb_encrypt_minbits;
+ uint16_t sadb_comb_encrypt_maxbits;
+ uint32_t sadb_comb_reserved;
+ uint32_t sadb_comb_soft_allocations;
+ uint32_t sadb_comb_hard_allocations;
+ uint64_t sadb_comb_soft_bytes;
+ uint64_t sadb_comb_hard_bytes;
+ uint64_t sadb_comb_soft_addtime;
+ uint64_t sadb_comb_hard_addtime;
+ uint64_t sadb_comb_soft_usetime;
+ uint64_t sadb_comb_hard_usetime;
+ uint32_t sadb_comb_soft_packets;
+ uint32_t sadb_comb_hard_packets;
+#endif
+errlab:
+ return error;
+}
+
+int
+pfkey_supported_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ unsigned int alg_num,
+ struct sadb_alg* alg)
+{
+ int error = 0;
+ unsigned int i;
+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext;
+ struct sadb_alg *pfkey_alg;
+
+ /* sanity checks... */
+ if (pfkey_supported) {
+ DEBUGGING(
+ "pfkey_supported_build: "
+ "why is pfkey_supported already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if ( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) {
+ DEBUGGING(
+ "pfkey_supported_build: "
+ "unsupported extension type=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_supported = (struct sadb_supported*)
+ MALLOC(sizeof(struct sadb_supported) +
+ alg_num * sizeof(struct sadb_alg));
+
+ *pfkey_ext = (struct sadb_ext*)pfkey_supported;
+
+ if (pfkey_supported == NULL) {
+ DEBUGGING(
+ "pfkey_supported_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_supported,
+ 0,
+ sizeof(struct sadb_supported) +
+ alg_num *
+ sizeof(struct sadb_alg));
+
+ pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) +
+ alg_num *
+ sizeof(struct sadb_alg)) /
+ IPSEC_PFKEYv2_ALIGN;
+ pfkey_supported->sadb_supported_exttype = exttype;
+ pfkey_supported->sadb_supported_reserved = 0;
+
+ pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported));
+ for(i = 0; i < alg_num; i++) {
+ memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg));
+ pfkey_alg->sadb_alg_reserved = 0;
+ pfkey_alg++;
+ }
+
+#if 0
+ DEBUGGING(
+ "pfkey_supported_build: "
+ "Sorry, I can't build exttype=%d yet.\n",
+ (*pfkey_ext)->sadb_ext_type);
+ SENDERR(EINVAL); /* don't process these yet */
+
+ uint8_t sadb_alg_id;
+ uint8_t sadb_alg_ivlen;
+ uint16_t sadb_alg_minbits;
+ uint16_t sadb_alg_maxbits;
+ uint16_t sadb_alg_reserved;
+#endif
+errlab:
+ return error;
+}
+
+int
+pfkey_spirange_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint32_t min, /* in network order */
+ uint32_t max) /* in network order */
+{
+ int error = 0;
+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext;
+
+ /* sanity checks... */
+ if (pfkey_spirange) {
+ DEBUGGING(
+ "pfkey_spirange_build: "
+ "why is pfkey_spirange already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (ntohl(max) < ntohl(min)) {
+ DEBUGGING(
+ "pfkey_spirange_build: "
+ "minspi=%08x must be < maxspi=%08x.\n",
+ ntohl(min),
+ ntohl(max));
+ SENDERR(EINVAL);
+ }
+
+ if (ntohl(min) <= 255) {
+ DEBUGGING(
+ "pfkey_spirange_build: "
+ "minspi=%08x must be > 255.\n",
+ ntohl(min));
+ SENDERR(EEXIST);
+ }
+
+ pfkey_spirange = (struct sadb_spirange*)
+ MALLOC(sizeof(struct sadb_spirange));
+ *pfkey_ext = (struct sadb_ext*)pfkey_spirange;
+
+ if (pfkey_spirange == NULL) {
+ DEBUGGING(
+ "pfkey_spirange_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_spirange,
+ 0,
+ sizeof(struct sadb_spirange));
+
+ pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+ pfkey_spirange->sadb_spirange_min = min;
+ pfkey_spirange->sadb_spirange_max = max;
+ pfkey_spirange->sadb_spirange_reserved = 0;
+ errlab:
+ return error;
+}
+
+int
+pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext)
+{
+ int error = 0;
+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext;
+
+ /* sanity checks... */
+ if (pfkey_x_kmprivate) {
+ DEBUGGING(
+ "pfkey_x_kmprivate_build: "
+ "why is pfkey_x_kmprivate already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
+
+ DEBUGGING(
+ "pfkey_x_kmprivate_build: "
+ "Sorry, I can't build exttype=%d yet.\n",
+ (*pfkey_ext)->sadb_ext_type);
+ SENDERR(EINVAL); /* don't process these yet */
+
+ pfkey_x_kmprivate = (struct sadb_x_kmprivate*)
+ MALLOC(sizeof(struct sadb_x_kmprivate));
+ *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate;
+
+ if (pfkey_x_kmprivate == NULL) {
+ DEBUGGING(
+ "pfkey_x_kmprivate_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_x_kmprivate,
+ 0,
+ sizeof(struct sadb_x_kmprivate));
+
+ pfkey_x_kmprivate->sadb_x_kmprivate_len =
+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE;
+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
+errlab:
+ return error;
+}
+
+int
+pfkey_x_satype_build(struct sadb_ext** pfkey_ext,
+ uint8_t satype)
+{
+ int error = 0;
+ int i;
+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_x_satype_build:\n");
+ /* sanity checks... */
+ if (pfkey_x_satype) {
+ DEBUGGING(
+ "pfkey_x_satype_build: "
+ "why is pfkey_x_satype already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ if (!satype) {
+ DEBUGGING(
+ "pfkey_x_satype_build: "
+ "SA type not set, must be non-zero.\n");
+ SENDERR(EINVAL);
+ }
+
+ if (satype > SADB_SATYPE_MAX) {
+ DEBUGGING(
+ "pfkey_x_satype_build: "
+ "satype %d > max %d\n",
+ satype, SADB_SATYPE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ pfkey_x_satype = (struct sadb_x_satype*)
+ MALLOC(sizeof(struct sadb_x_satype));
+
+ *pfkey_ext = (struct sadb_ext*)pfkey_x_satype;
+
+ if (pfkey_x_satype == NULL) {
+ DEBUGGING(
+ "pfkey_x_satype_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ memset(pfkey_x_satype,
+ 0,
+ sizeof(struct sadb_x_satype));
+
+ pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
+ pfkey_x_satype->sadb_x_satype_satype = satype;
+ for (i=0; i<3; i++) {
+ pfkey_x_satype->sadb_x_satype_reserved[i] = 0;
+ }
+
+errlab:
+ return error;
+}
+
+int
+pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
+ uint32_t tunnel,
+ uint32_t netlink,
+ uint32_t xform,
+ uint32_t eroute,
+ uint32_t spi,
+ uint32_t radij,
+ uint32_t esp,
+ uint32_t ah,
+ uint32_t rcv,
+ uint32_t pfkey,
+ uint32_t ipcomp,
+ uint32_t verbose)
+{
+ int error = 0;
+ int i;
+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_x_debug_build:\n");
+ /* sanity checks... */
+ if (pfkey_x_debug) {
+ DEBUGGING(
+ "pfkey_x_debug_build: "
+ "why is pfkey_x_debug already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(
+ "pfkey_x_debug_build: "
+ "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
+ tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose);
+
+ pfkey_x_debug = (struct sadb_x_debug*)
+ MALLOC(sizeof(struct sadb_x_debug));
+ *pfkey_ext = (struct sadb_ext*)pfkey_x_debug;
+
+ if (pfkey_x_debug == NULL) {
+ DEBUGGING(
+ "pfkey_x_debug_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+#if 0
+ memset(pfkey_x_debug,
+ 0,
+ sizeof(struct sadb_x_debug));
+#endif
+
+ pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG;
+
+ pfkey_x_debug->sadb_x_debug_tunnel = tunnel;
+ pfkey_x_debug->sadb_x_debug_netlink = netlink;
+ pfkey_x_debug->sadb_x_debug_xform = xform;
+ pfkey_x_debug->sadb_x_debug_eroute = eroute;
+ pfkey_x_debug->sadb_x_debug_spi = spi;
+ pfkey_x_debug->sadb_x_debug_radij = radij;
+ pfkey_x_debug->sadb_x_debug_esp = esp;
+ pfkey_x_debug->sadb_x_debug_ah = ah;
+ pfkey_x_debug->sadb_x_debug_rcv = rcv;
+ pfkey_x_debug->sadb_x_debug_pfkey = pfkey;
+ pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp;
+ pfkey_x_debug->sadb_x_debug_verbose = verbose;
+
+ for (i=0; i<4; i++) {
+ pfkey_x_debug->sadb_x_debug_reserved[i] = 0;
+ }
+
+errlab:
+ return error;
+}
+
+int
+pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext,
+ uint8_t type)
+{
+ int error = 0;
+ int i;
+ struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_x_nat_t_type_build:\n");
+ /* sanity checks... */
+ if (pfkey_x_nat_t_type) {
+ DEBUGGING(
+ "pfkey_x_nat_t_type_build: "
+ "why is pfkey_x_nat_t_type already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(
+ "pfkey_x_nat_t_type_build: "
+ "type=%d\n", type);
+
+ pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*)
+ MALLOC(sizeof(struct sadb_x_nat_t_type));
+
+ *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type;
+ if (pfkey_x_nat_t_type == NULL) {
+ DEBUGGING(
+ "pfkey_x_nat_t_type_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+
+ pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type;
+ for (i=0; i<3; i++) {
+ pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0;
+ }
+
+errlab:
+ return error;
+}
+
+int
+pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext,
+ uint16_t exttype,
+ uint16_t port)
+{
+ int error = 0;
+ struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext;
+
+ DEBUGGING(
+ "pfkey_x_nat_t_port_build:\n");
+ /* sanity checks... */
+ if (pfkey_x_nat_t_port) {
+ DEBUGGING(
+ "pfkey_x_nat_t_port_build: "
+ "why is pfkey_x_nat_t_port already pointing to something?\n");
+ SENDERR(EINVAL);
+ }
+
+ switch (exttype) {
+ case SADB_X_EXT_NAT_T_SPORT:
+ case SADB_X_EXT_NAT_T_DPORT:
+ break;
+ default:
+ DEBUGGING(
+ "pfkey_nat_t_port_build: "
+ "unrecognised ext_type=%d.\n",
+ exttype);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(
+ "pfkey_x_nat_t_port_build: "
+ "ext=%d, port=%d\n", exttype, port);
+
+ pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*)
+ MALLOC(sizeof(struct sadb_x_nat_t_port));
+ *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port;
+
+ if (pfkey_x_nat_t_port == NULL) {
+ DEBUGGING(
+ "pfkey_x_nat_t_port_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+
+ pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN;
+ pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype;
+ pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port;
+ pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0;
+
+errlab:
+ return error;
+}
+
+int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext,
+ uint8_t protocol)
+{
+ int error = 0;
+ struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext;
+ DEBUGGING("pfkey_x_protocol_build: protocol=%u\n", protocol);
+ /* sanity checks... */
+ if (p != 0) {
+ DEBUGGING("pfkey_x_protocol_build: bogus protocol pointer\n");
+ SENDERR(EINVAL);
+ }
+ if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) {
+ DEBUGGING("pfkey_build: memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+ *pfkey_ext = (struct sadb_ext *)p;
+ p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t);
+ p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
+ p->sadb_protocol_proto = protocol;
+ p->sadb_protocol_flags = 0;
+ p->sadb_protocol_reserved2 = 0;
+ errlab:
+ return error;
+}
+
+
+#if I_DONT_THINK_THIS_WILL_BE_USEFUL
+int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*)
+ =
+{
+ NULL, /* pfkey_msg_build, */
+ pfkey_sa_build,
+ pfkey_lifetime_build,
+ pfkey_lifetime_build,
+ pfkey_lifetime_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_key_build,
+ pfkey_key_build,
+ pfkey_ident_build,
+ pfkey_ident_build,
+ pfkey_sens_build,
+ pfkey_prop_build,
+ pfkey_supported_build,
+ pfkey_supported_build,
+ pfkey_spirange_build,
+ pfkey_x_kmprivate_build,
+ pfkey_x_satype_build,
+ pfkey_sa_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_address_build,
+ pfkey_x_ext_debug_build
+};
+#endif
+
+int
+pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir)
+{
+ int error = 0;
+ unsigned ext;
+ unsigned total_size;
+ struct sadb_ext *pfkey_ext;
+ int extensions_seen = 0;
+ struct sadb_ext *extensions_check[SADB_EXT_MAX + 1];
+
+ if (!extensions[0]) {
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "extensions[0] must be specified (struct sadb_msg).\n");
+ SENDERR(EINVAL);
+ }
+
+ total_size = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+ for (ext = 1; ext <= SADB_EXT_MAX; ext++) {
+ if(extensions[ext]) {
+ total_size += (extensions[ext])->sadb_ext_len;
+ }
+ }
+
+ if (!(*pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN))) {
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "memory allocation failed\n");
+ SENDERR(ENOMEM);
+ }
+
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n",
+ *pfkey_msg,
+ (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN),
+ &(extensions[0]));
+ memcpy(*pfkey_msg,
+ extensions[0],
+ sizeof(struct sadb_msg));
+ (*pfkey_msg)->sadb_msg_len = total_size;
+ (*pfkey_msg)->sadb_msg_reserved = 0;
+ extensions_seen = 1 ;
+
+ pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg));
+
+ for (ext = 1; ext <= SADB_EXT_MAX; ext++) {
+ /* copy from extension[ext] to buffer */
+ if (extensions[ext]) {
+ /* Is this type of extension permitted for this type of message? */
+ if (!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] &
+ 1<<ext)) {
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n",
+ ext,
+ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
+ 1<<ext);
+ SENDERR(EINVAL);
+ }
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "copying %lu bytes from extensions[%u]=0p%p to=0p%p\n",
+ (unsigned long)(extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN),
+ ext,
+ extensions[ext],
+ pfkey_ext);
+ memcpy(pfkey_ext,
+ extensions[ext],
+ (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+ {
+ char *pfkey_ext_c = (char *)pfkey_ext;
+
+ pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN;
+ pfkey_ext = (struct sadb_ext *)pfkey_ext_c;
+ }
+ /* Mark that we have seen this extension and remember the header location */
+ extensions_seen |= ( 1 << ext );
+ }
+ }
+
+ /* check required extensions */
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "extensions permitted=%08x, seen=%08x, required=%08x.\n",
+ extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
+ extensions_seen,
+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]);
+
+ if ((extensions_seen &
+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) !=
+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) {
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "required extensions missing:%08x.\n",
+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] -
+ (extensions_seen &
+ extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) );
+ SENDERR(EINVAL);
+ }
+
+ error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir);
+ if (error) {
+ DEBUGGING(
+ "pfkey_msg_build: "
+ "Trouble parsing newly built pfkey message, error=%d.\n",
+ error);
+ SENDERR(-error);
+ }
+
+errlab:
+
+ return error;
+}
diff --git a/src/libfreeswan/pfkey_v2_debug.c b/src/libfreeswan/pfkey_v2_debug.c
new file mode 100644
index 000000000..8430766aa
--- /dev/null
+++ b/src/libfreeswan/pfkey_v2_debug.c
@@ -0,0 +1,177 @@
+/*
+ * @(#) pfkey version 2 debugging messages
+ *
+ * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
+ * and Michael Richardson <mcr@freeswan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pfkey_v2_debug.c,v 1.2 2004/03/22 21:53:18 as Exp $
+ *
+ */
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h> /* for printk */
+
+# include "freeswan/ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h> /* error codes */
+# include <linux/types.h> /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h> /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+extern int debug_pfkey;
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+
+#endif /* __KERNEL__ */
+
+#include "freeswan.h"
+#include "pfkeyv2.h"
+#include "pfkey.h"
+
+/*
+ * This file provides ASCII translations of PF_KEY magic numbers.
+ *
+ */
+
+static char *pfkey_sadb_ext_strings[]={
+ "reserved", /* SADB_EXT_RESERVED 0 */
+ "security-association", /* SADB_EXT_SA 1 */
+ "lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */
+ "lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */
+ "lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */
+ "source-address", /* SADB_EXT_ADDRESS_SRC 5 */
+ "destination-address", /* SADB_EXT_ADDRESS_DST 6 */
+ "proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */
+ "authentication-key", /* SADB_EXT_KEY_AUTH 8 */
+ "cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */
+ "source-identity", /* SADB_EXT_IDENTITY_SRC 10 */
+ "destination-identity", /* SADB_EXT_IDENTITY_DST 11 */
+ "sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */
+ "proposal", /* SADB_EXT_PROPOSAL 13 */
+ "supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */
+ "supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */
+ "spi-range", /* SADB_EXT_SPIRANGE 16 */
+ "X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */
+ "X-satype2", /* SADB_X_EXT_SATYPE2 18 */
+ "X-security-association", /* SADB_X_EXT_SA2 19 */
+ "X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */
+ "X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */
+ "X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */
+ "X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */
+ "X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */
+ "X-set-debug", /* SADB_X_EXT_DEBUG 25 */
+ "X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 26 */
+ "X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 27 */
+ "X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 28 */
+ "X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 29 */
+};
+
+const char *
+pfkey_v2_sadb_ext_string(int ext)
+{
+ if(ext <= SADB_EXT_MAX) {
+ return pfkey_sadb_ext_strings[ext];
+ } else {
+ return "unknown-ext";
+ }
+}
+
+
+static char *pfkey_sadb_type_strings[]={
+ "reserved", /* SADB_RESERVED */
+ "getspi", /* SADB_GETSPI */
+ "update", /* SADB_UPDATE */
+ "add", /* SADB_ADD */
+ "delete", /* SADB_DELETE */
+ "get", /* SADB_GET */
+ "acquire", /* SADB_ACQUIRE */
+ "register", /* SADB_REGISTER */
+ "expire", /* SADB_EXPIRE */
+ "flush", /* SADB_FLUSH */
+ "dump", /* SADB_DUMP */
+ "x-promisc", /* SADB_X_PROMISC */
+ "x-pchange", /* SADB_X_PCHANGE */
+ "x-groupsa", /* SADB_X_GRPSA */
+ "x-addflow(eroute)", /* SADB_X_ADDFLOW */
+ "x-delflow(eroute)", /* SADB_X_DELFLOW */
+ "x-debug", /* SADB_X_DEBUG */
+};
+
+const char *
+pfkey_v2_sadb_type_string(int sadb_type)
+{
+ if(sadb_type <= SADB_MAX) {
+ return pfkey_sadb_type_strings[sadb_type];
+ } else {
+ return "unknown-sadb-type";
+ }
+}
+
+
+
+
+/*
+ * $Log: pfkey_v2_debug.c,v $
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.2.1 2004/03/15 22:30:06 as
+ * nat-0.6c patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:26 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.7 2002/09/20 05:01:26 rgb
+ * Fixed limit inclusion error in both type and ext string conversion.
+ *
+ * Revision 1.6 2002/04/24 07:55:32 mcr
+ * #include patches and Makefiles for post-reorg compilation.
+ *
+ * Revision 1.5 2002/04/24 07:36:40 mcr
+ * Moved from ./lib/pfkey_v2_debug.c,v
+ *
+ * Revision 1.4 2002/01/29 22:25:36 rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.3 2002/01/29 01:59:09 mcr
+ * removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * updating of IPv6 structures to match latest in6.h version.
+ * removed dead code from freeswan.h that also duplicated kversions.h
+ * code.
+ *
+ * Revision 1.2 2002/01/20 20:34:50 mcr
+ * added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.1 2001/11/27 05:30:06 mcr
+ * initial set of debug strings for pfkey debugging.
+ * this will eventually only be included for debug builds.
+ *
+ * Revision 1.1 2001/09/21 04:12:03 mcr
+ * first compilable version.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/pfkey_v2_ext_bits.c b/src/libfreeswan/pfkey_v2_ext_bits.c
new file mode 100644
index 000000000..b41941848
--- /dev/null
+++ b/src/libfreeswan/pfkey_v2_ext_bits.c
@@ -0,0 +1,789 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pfkey_v2_ext_bits.c,v 1.2 2004/03/22 21:53:18 as Exp $
+ */
+
+/*
+ * Template from klips/net/ipsec/ipsec/ipsec_parse.c.
+ */
+
+char pfkey_v2_ext_bits_c_version[] = "$Id: pfkey_v2_ext_bits.c,v 1.2 2004/03/22 21:53:18 as Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h> /* for printk */
+
+# include "freeswan/ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h> /* error codes */
+# include <linux/types.h> /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h> /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h> /* struct iphdr */
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+# include <linux/ipv6.h>
+# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+#endif
+
+#include <freeswan.h>
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = {
+
+/* INBOUND EXTENSIONS */
+{
+
+/* PERMITTED IN */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_SPIRANGE
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_X_EXT_NAT_T_TYPE
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+| 1<<SADB_X_EXT_NAT_T_OA
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_EXPIRE */
+0
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_X_EXT_PROTOCOL
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_X_EXT_PROTOCOL
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+},
+
+/* REQUIRED IN */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_SPIRANGE
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_EXT_KEY_AUTH*/
+/*| 1<<SADB_EXT_KEY_ENCRYPT*/
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_EXT_KEY_AUTH*/
+/*| 1<<SADB_EXT_KEY_ENCRYPT*/
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_EXPIRE */
+0
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_X_EXT_SATYPE2*/
+/*| 1<<SADB_X_EXT_SA2*/
+/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+/*| 1<<SADB_EXT_SA*/
+#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+#endif
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+}
+
+},
+
+/* OUTBOUND EXTENSIONS */
+{
+
+/* PERMITTED OUT */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_X_EXT_NAT_T_TYPE
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+| 1<<SADB_X_EXT_NAT_T_OA
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+,
+/* SADB_EXPIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_X_EXT_PROTOCOL
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_X_EXT_PROTOCOL
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+},
+
+/* REQUIRED OUT */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/* | 1<<SADB_EXT_KEY_AUTH */
+/* | 1<<SADB_EXT_KEY_ENCRYPT */
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+/* | 1<<SADB_EXT_SUPPORTED_AUTH
+ | 1<<SADB_EXT_SUPPORTED_ENCRYPT */
+,
+/* SADB_EXPIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+/* | 1<<SADB_EXT_LIFETIME_HARD
+ | 1<<SADB_EXT_LIFETIME_SOFT */
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+/*| 1<<SADB_EXT_SA*/
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+}
+}
+};
+
+/*
+ * $Log: pfkey_v2_ext_bits.c,v $
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.2.1 2004/03/15 22:30:06 as
+ * nat-0.6c patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:26 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.15 2002/04/24 07:55:32 mcr
+ * #include patches and Makefiles for post-reorg compilation.
+ *
+ * Revision 1.14 2002/04/24 07:36:40 mcr
+ * Moved from ./lib/pfkey_v2_ext_bits.c,v
+ *
+ * Revision 1.13 2002/01/29 22:25:36 rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.12 2002/01/29 01:59:10 mcr
+ * removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * updating of IPv6 structures to match latest in6.h version.
+ * removed dead code from freeswan.h that also duplicated kversions.h
+ * code.
+ *
+ * Revision 1.11 2001/10/18 04:45:24 rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.10 2001/09/08 21:13:35 rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.9 2001/06/14 19:35:16 rgb
+ * Update copyright date.
+ *
+ * Revision 1.8 2001/03/26 23:07:36 rgb
+ * Remove requirement for auth and enc key from UPDATE.
+ *
+ * Revision 1.7 2000/09/12 22:35:37 rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.6 2000/09/09 06:39:01 rgb
+ * Added comments for clarity.
+ *
+ * Revision 1.5 2000/06/02 22:54:14 rgb
+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
+ *
+ * Revision 1.4 2000/01/21 06:27:56 rgb
+ * Added address cases for eroute flows.
+ * Added comments for each message type.
+ * Added klipsdebug switching capability.
+ * Fixed GRPSA bitfields.
+ *
+ * Revision 1.3 1999/12/01 22:20:27 rgb
+ * Remove requirement for a proxy address in an incoming getspi message.
+ *
+ * Revision 1.2 1999/11/27 11:57:06 rgb
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ * Add CVS log entry to bottom of file.
+ * Cleaned out unused bits.
+ *
+ */
diff --git a/src/libfreeswan/pfkey_v2_parse.c b/src/libfreeswan/pfkey_v2_parse.c
new file mode 100644
index 000000000..440aa8c1d
--- /dev/null
+++ b/src/libfreeswan/pfkey_v2_parse.c
@@ -0,0 +1,1824 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pfkey_v2_parse.c,v 1.4 2004/06/13 20:35:07 as Exp $
+ */
+
+/*
+ * Template from klips/net/ipsec/ipsec/ipsec_parser.c.
+ */
+
+char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.4 2004/06/13 20:35:07 as Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h> /* for printk */
+
+#include "freeswan/ipsec_kversion.h" /* for malloc switch */
+
+# ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h> /* error codes */
+# include <linux/types.h> /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h> /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h> /* struct iphdr */
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+# include <linux/ipv6.h> /* struct ipv6hdr */
+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+extern int debug_pfkey;
+
+#include "freeswan.h"
+
+#include "ipsec_encap.h"
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+
+# include <freeswan.h>
+# include <constants.h>
+# include <defs.h> /* for PRINTF_LIKE */
+# include <log.h> /* for debugging and DBG_log */
+
+/* #define PLUTO */
+
+# ifdef PLUTO
+# define DEBUGGING(level, args...) { DBG_log("pfkey_lib_debug:" args); }
+# else
+# define DEBUGGING(level, args...) if(pfkey_lib_debug & level) { printf("pfkey_lib_debug:" args); } else { ; }
+# endif
+
+#endif /* __KERNEL__ */
+
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef __KERNEL__
+extern int sysctl_ipsec_debug_verbose;
+# define DEBUGGING(level, args...) \
+ KLIPS_PRINT( \
+ ((debug_pfkey & level & (PF_KEY_DEBUG_PARSE_STRUCT | PF_KEY_DEBUG_PARSE_PROBLEM)) \
+ || (sysctl_ipsec_debug_verbose && (debug_pfkey & level & PF_KEY_DEBUG_PARSE_FLOW))) \
+ , "klips_debug:" args)
+#endif /* __KERNEL__ */
+#include "ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */
+
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+struct satype_tbl {
+ uint8_t proto;
+ uint8_t satype;
+ char* name;
+} static satype_tbl[] = {
+#ifdef __KERNEL__
+ { IPPROTO_ESP, SADB_SATYPE_ESP, "ESP" },
+ { IPPROTO_AH, SADB_SATYPE_AH, "AH" },
+ { IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" },
+#ifdef CONFIG_IPSEC_IPCOMP
+ { IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" },
+#endif /* CONFIG_IPSEC_IPCOMP */
+ { IPPROTO_INT, SADB_X_SATYPE_INT, "INT" },
+#else /* __KERNEL__ */
+ { SA_ESP, SADB_SATYPE_ESP, "ESP" },
+ { SA_AH, SADB_SATYPE_AH, "AH" },
+ { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" },
+ { SA_COMP, SADB_X_SATYPE_COMP, "COMP" },
+ { SA_INT, SADB_X_SATYPE_INT, "INT" },
+#endif /* __KERNEL__ */
+ { 0, 0, "UNKNOWN" }
+};
+
+uint8_t
+satype2proto(uint8_t satype)
+{
+ int i =0;
+
+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
+ i++;
+ }
+ return satype_tbl[i].proto;
+}
+
+uint8_t
+proto2satype(uint8_t proto)
+{
+ int i = 0;
+
+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
+ i++;
+ }
+ return satype_tbl[i].satype;
+}
+
+char*
+satype2name(uint8_t satype)
+{
+ int i = 0;
+
+ while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
+ i++;
+ }
+ return satype_tbl[i].name;
+}
+
+char*
+proto2name(uint8_t proto)
+{
+ int i = 0;
+
+ while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
+ i++;
+ }
+ return satype_tbl[i].name;
+}
+
+/* Default extension parsers taken from the KLIPS code */
+
+DEBUG_NO_STATIC int
+pfkey_sa_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
+#if 0
+ struct sadb_sa sav2;
+#endif
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_sa_parse: entry\n");
+ /* sanity checks... */
+ if(!pfkey_sa) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "NULL pointer passed in.\n");
+ SENDERR(EINVAL);
+ }
+
+#if 0
+ /* check if this structure is short, and if so, fix it up.
+ * XXX this is NOT the way to do things.
+ */
+ if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) {
+
+ /* yes, so clear out a temporary structure, and copy first */
+ memset(&sav2, 0, sizeof(sav2));
+ memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1));
+ sav2.sadb_x_sa_ref=-1;
+ sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_sa = &sav2;
+ }
+#endif
+
+
+ if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
+ pfkey_sa->sadb_sa_len,
+ (int)sizeof(struct sadb_sa));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
+ pfkey_sa->sadb_sa_encrypt,
+ SADB_EALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
+ pfkey_sa->sadb_sa_auth,
+ SADB_AALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "state=%d exceeds MAX=%d.\n",
+ pfkey_sa->sadb_sa_state,
+ SADB_SASTATE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "state=%d is DEAD=%d.\n",
+ pfkey_sa->sadb_sa_state,
+ SADB_SASTATE_DEAD);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_sa->sadb_sa_replay > 64) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "replay window size: %d -- must be 0 <= size <= 64\n",
+ pfkey_sa->sadb_sa_replay);
+ SENDERR(EINVAL);
+ }
+
+ if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) ||
+ (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2)))
+ {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
+ pfkey_sa->sadb_sa_exttype,
+ SADB_EXT_SA,
+ SADB_X_EXT_SA2);
+ SENDERR(EINVAL);
+ }
+
+ if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sa_parse: "
+ "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
+ pfkey_sa->sadb_x_sa_ref,
+ IPSEC_SAREF_NULL,
+ IPSEC_SA_REF_TABLE_NUM_ENTRIES);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_sa_parse: "
+ "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n",
+ pfkey_sa->sadb_sa_len,
+ pfkey_sa->sadb_sa_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype),
+ (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi),
+ pfkey_sa->sadb_sa_replay,
+ pfkey_sa->sadb_sa_state,
+ pfkey_sa->sadb_sa_auth,
+ pfkey_sa->sadb_sa_encrypt,
+ pfkey_sa->sadb_sa_flags,
+ pfkey_sa->sadb_x_sa_ref);
+
+ errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_lifetime_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_lifetime_parse:enter\n");
+ /* sanity checks... */
+ if(!pfkey_lifetime) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_lifetime_parse: "
+ "NULL pointer passed in.\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_lifetime->sadb_lifetime_len !=
+ sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_lifetime_parse: "
+ "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
+ pfkey_lifetime->sadb_lifetime_len,
+ (int)sizeof(struct sadb_lifetime));
+ SENDERR(EINVAL);
+ }
+
+ if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) &&
+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) &&
+ (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_lifetime_parse: "
+ "unexpected ext_type=%d.\n",
+ pfkey_lifetime->sadb_lifetime_exttype);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_lifetime_parse: "
+ "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n",
+ pfkey_lifetime->sadb_lifetime_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype),
+ pfkey_lifetime->sadb_lifetime_allocations,
+ (unsigned)pfkey_lifetime->sadb_lifetime_bytes,
+ (unsigned)pfkey_lifetime->sadb_lifetime_addtime,
+ (unsigned)pfkey_lifetime->sadb_lifetime_usetime,
+ pfkey_lifetime->sadb_x_lifetime_packets);
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_address_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ int saddr_len = 0;
+ struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
+ struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
+ char ipaddr_txt[ADDRTOT_BUF];
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_address_parse:enter\n");
+ /* sanity checks... */
+ if(!pfkey_address) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "NULL pointer passed in.\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_address->sadb_address_len <
+ (sizeof(struct sadb_address) + sizeof(struct sockaddr))/
+ IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+ pfkey_address->sadb_address_len,
+ (int)sizeof(struct sadb_address),
+ (int)sizeof(struct sockaddr));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_address->sadb_address_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "res=%d, must be zero.\n",
+ pfkey_address->sadb_address_reserved);
+ SENDERR(EINVAL);
+ }
+
+ switch(pfkey_address->sadb_address_exttype) {
+ case SADB_EXT_ADDRESS_SRC:
+ case SADB_EXT_ADDRESS_DST:
+ case SADB_EXT_ADDRESS_PROXY:
+ case SADB_X_EXT_ADDRESS_DST2:
+ case SADB_X_EXT_ADDRESS_SRC_FLOW:
+ case SADB_X_EXT_ADDRESS_DST_FLOW:
+ case SADB_X_EXT_ADDRESS_SRC_MASK:
+ case SADB_X_EXT_ADDRESS_DST_MASK:
+ case SADB_X_EXT_NAT_T_OA:
+ break;
+ default:
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "unexpected ext_type=%d.\n",
+ pfkey_address->sadb_address_exttype);
+ SENDERR(EINVAL);
+ }
+
+ switch(s->sa_family) {
+ case AF_INET:
+ saddr_len = sizeof(struct sockaddr_in);
+ sprintf(ipaddr_txt, "%d.%d.%d.%d"
+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF
+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF
+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF
+ , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF);
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_address_parse: "
+ "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n",
+ pfkey_address->sadb_address_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
+ s->sa_family,
+ ipaddr_txt,
+ pfkey_address->sadb_address_proto,
+ ntohs(((struct sockaddr_in*)s)->sin_port));
+ break;
+ case AF_INET6:
+ saddr_len = sizeof(struct sockaddr_in6);
+ sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x"
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6])
+ , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7]));
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_address_parse: "
+ "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n",
+ pfkey_address->sadb_address_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
+ s->sa_family,
+ ipaddr_txt,
+ pfkey_address->sadb_address_proto,
+ ((struct sockaddr_in6*)s)->sin6_port);
+ break;
+ default:
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "s->sa_family=%d not supported.\n",
+ s->sa_family);
+ SENDERR(EPFNOSUPPORT);
+ }
+
+ if(pfkey_address->sadb_address_len !=
+ DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+ pfkey_address->sadb_address_len,
+ (int)sizeof(struct sadb_address),
+ saddr_len);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_address->sadb_address_prefixlen != 0) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_address_parse: "
+ "address prefixes not supported yet.\n");
+ SENDERR(EAFNOSUPPORT); /* not supported yet */
+ }
+
+ /* XXX check if port!=0 */
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_address_parse: successful.\n");
+ errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_key_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_key_parse:enter\n");
+ /* sanity checks... */
+
+ if(!pfkey_key) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "NULL pointer passed in.\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_key->sadb_key_len,
+ (int)sizeof(struct sadb_key));
+ SENDERR(EINVAL);
+ }
+
+ if(!pfkey_key->sadb_key_bits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "key length set to zero, must be non-zero.\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_key->sadb_key_len !=
+ DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits,
+ PFKEYBITS)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "key length=%d does not agree with extension length=%d.\n",
+ pfkey_key->sadb_key_bits,
+ pfkey_key->sadb_key_len);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_key->sadb_key_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "res=%d, must be zero.\n",
+ pfkey_key->sadb_key_reserved);
+ SENDERR(EINVAL);
+ }
+
+ if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ||
+ (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "expecting extension type AUTH or ENCRYPT, got %d.\n",
+ pfkey_key->sadb_key_exttype);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_key_parse: "
+ "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n",
+ pfkey_key->sadb_key_len,
+ pfkey_key->sadb_key_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype),
+ pfkey_key->sadb_key_bits,
+ pfkey_key->sadb_key_reserved);
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_ident_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
+
+ /* sanity checks... */
+ if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_ident_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_ident->sadb_ident_len,
+ (int)sizeof(struct sadb_ident));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_ident_parse: "
+ "ident_type=%d out of range, must be less than %d.\n",
+ pfkey_ident->sadb_ident_type,
+ SADB_IDENTTYPE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_ident->sadb_ident_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_ident_parse: "
+ "res=%d, must be zero.\n",
+ pfkey_ident->sadb_ident_reserved);
+ SENDERR(EINVAL);
+ }
+
+ /* string terminator/padding must be zero */
+ if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
+ if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_ident_parse: "
+ "string padding must be zero, last is 0x%02x.\n",
+ *((char*)pfkey_ident +
+ pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1));
+ SENDERR(EINVAL);
+ }
+ }
+
+ if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ||
+ (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_key_parse: "
+ "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
+ pfkey_ident->sadb_ident_exttype);
+ SENDERR(EINVAL);
+ }
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_sens_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext;
+
+ /* sanity checks... */
+ if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sens_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_sens->sadb_sens_len,
+ (int)sizeof(struct sadb_sens));
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_sens_parse: "
+ "Sorry, I can't parse exttype=%d yet.\n",
+ pfkey_ext->sadb_ext_type);
+#if 0
+ SENDERR(EINVAL); /* don't process these yet */
+#endif
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_prop_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ int i, num_comb;
+ struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext;
+ struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop));
+
+ /* sanity checks... */
+ if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) ||
+ (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
+ pfkey_prop->sadb_prop_len,
+ (int)sizeof(struct sadb_prop),
+ (int)sizeof(struct sadb_comb));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_prop->sadb_prop_replay > 64) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "replay window size: %d -- must be 0 <= size <= 64\n",
+ pfkey_prop->sadb_prop_replay);
+ SENDERR(EINVAL);
+ }
+
+ for(i=0; i<3; i++) {
+ if(pfkey_prop->sadb_prop_reserved[i]) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "res[%d]=%d, must be zero.\n",
+ i, pfkey_prop->sadb_prop_reserved[i]);
+ SENDERR(EINVAL);
+ }
+ }
+
+ num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb);
+
+ for(i = 0; i < num_comb; i++) {
+ if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
+ i,
+ pfkey_comb->sadb_comb_auth,
+ SADB_AALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_auth) {
+ if(!pfkey_comb->sadb_comb_auth_minbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
+ i);
+ SENDERR(EINVAL);
+ }
+ if(!pfkey_comb->sadb_comb_auth_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n",
+ i);
+ SENDERR(EINVAL);
+ }
+ if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_auth_minbits,
+ pfkey_comb->sadb_comb_auth_maxbits);
+ SENDERR(EINVAL);
+ }
+ } else {
+ if(pfkey_comb->sadb_comb_auth_minbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_auth_minbits);
+ SENDERR(EINVAL);
+ }
+ if(pfkey_comb->sadb_comb_auth_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_auth_maxbits);
+ SENDERR(EINVAL);
+ }
+ }
+
+ if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_comb_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
+ i,
+ pfkey_comb->sadb_comb_encrypt,
+ SADB_EALG_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_encrypt) {
+ if(!pfkey_comb->sadb_comb_encrypt_minbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
+ i);
+ SENDERR(EINVAL);
+ }
+ if(!pfkey_comb->sadb_comb_encrypt_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n",
+ i);
+ SENDERR(EINVAL);
+ }
+ if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_encrypt_minbits,
+ pfkey_comb->sadb_comb_encrypt_maxbits);
+ SENDERR(EINVAL);
+ }
+ } else {
+ if(pfkey_comb->sadb_comb_encrypt_minbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_encrypt_minbits);
+ SENDERR(EINVAL);
+ }
+ if(pfkey_comb->sadb_comb_encrypt_maxbits) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_encrypt_maxbits);
+ SENDERR(EINVAL);
+ }
+ }
+
+ /* XXX do sanity check on flags */
+
+ if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n",
+ i,
+ pfkey_comb->sadb_comb_soft_allocations,
+ pfkey_comb->sadb_comb_hard_allocations);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
+ i,
+ (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes,
+ (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
+ i,
+ (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime,
+ (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
+ i,
+ (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime,
+ (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n",
+ i,
+ pfkey_comb->sadb_x_comb_soft_packets,
+ pfkey_comb->sadb_x_comb_hard_packets);
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_comb->sadb_comb_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_prop_parse: "
+ "comb[%d].res=%d, must be zero.\n",
+ i,
+ pfkey_comb->sadb_comb_reserved);
+ SENDERR(EINVAL);
+ }
+ pfkey_comb++;
+ }
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_supported_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ unsigned int i, num_alg;
+ struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext;
+ struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported));
+
+ /* sanity checks... */
+ if((pfkey_supported->sadb_supported_len <
+ sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) ||
+ (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) -
+ sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) {
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
+ pfkey_supported->sadb_supported_len,
+ (int)sizeof(struct sadb_supported),
+ (int)sizeof(struct sadb_alg));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_supported->sadb_supported_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "res=%d, must be zero.\n",
+ pfkey_supported->sadb_supported_reserved);
+ SENDERR(EINVAL);
+ }
+
+ num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg);
+
+ for(i = 0; i < num_alg; i++) {
+ /* process algo description */
+ if(pfkey_alg->sadb_alg_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n",
+ i,
+ pfkey_alg->sadb_alg_id,
+ pfkey_alg->sadb_alg_ivlen,
+ pfkey_alg->sadb_alg_minbits,
+ pfkey_alg->sadb_alg_maxbits,
+ pfkey_alg->sadb_alg_reserved);
+ SENDERR(EINVAL);
+ }
+
+ /* XXX can alg_id auth/enc be determined from info given?
+ Yes, but OpenBSD's method does not iteroperate with rfc2367.
+ rgb, 2000-04-06 */
+
+ switch(pfkey_supported->sadb_supported_exttype) {
+ case SADB_EXT_SUPPORTED_AUTH:
+ if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
+ i,
+ pfkey_alg->sadb_alg_id,
+ SADB_AALG_MAX);
+ SENDERR(EINVAL);
+ }
+ break;
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+ i,
+ pfkey_alg->sadb_alg_id,
+ SADB_EALG_MAX);
+ SENDERR(EINVAL);
+ }
+ break;
+ default:
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_supported_parse: "
+ "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+ i,
+ pfkey_alg->sadb_alg_id,
+ SADB_EALG_MAX);
+ SENDERR(EINVAL);
+ }
+ pfkey_alg++;
+ }
+
+ errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_spirange_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext;
+
+ /* sanity checks... */
+ if(pfkey_spirange->sadb_spirange_len !=
+ sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_spirange_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_spirange->sadb_spirange_len,
+ (int)sizeof(struct sadb_spirange));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_spirange->sadb_spirange_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_spirange_parse: "
+ "reserved=%d must be set to zero.\n",
+ pfkey_spirange->sadb_spirange_reserved);
+ SENDERR(EINVAL);
+ }
+
+ if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_spirange_parse: "
+ "minspi=%08x must be < maxspi=%08x.\n",
+ ntohl(pfkey_spirange->sadb_spirange_min),
+ ntohl(pfkey_spirange->sadb_spirange_max));
+ SENDERR(EINVAL);
+ }
+
+ if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_spirange_parse: "
+ "minspi=%08x must be > 255.\n",
+ ntohl(pfkey_spirange->sadb_spirange_min));
+ SENDERR(EEXIST);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_spirange_parse: "
+ "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n",
+ pfkey_spirange->sadb_spirange_len,
+ pfkey_spirange->sadb_spirange_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype),
+ pfkey_spirange->sadb_spirange_min,
+ pfkey_spirange->sadb_spirange_max,
+ pfkey_spirange->sadb_spirange_reserved);
+ errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext;
+
+ /* sanity checks... */
+ if(pfkey_x_kmprivate->sadb_x_kmprivate_len <
+ sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_kmprivate_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_x_kmprivate->sadb_x_kmprivate_len,
+ (int)sizeof(struct sadb_x_kmprivate));
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_kmprivate_parse: "
+ "reserved=%d must be set to zero.\n",
+ pfkey_x_kmprivate->sadb_x_kmprivate_reserved);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_kmprivate_parse: "
+ "Sorry, I can't parse exttype=%d yet.\n",
+ pfkey_ext->sadb_ext_type);
+ SENDERR(EINVAL); /* don't process these yet */
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_satype_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ int i;
+ struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_x_satype_parse: enter\n");
+ /* sanity checks... */
+ if(pfkey_x_satype->sadb_x_satype_len !=
+ sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_satype_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_x_satype->sadb_x_satype_len,
+ (int)sizeof(struct sadb_x_satype));
+ SENDERR(EINVAL);
+ }
+
+ if(!pfkey_x_satype->sadb_x_satype_satype) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_satype_parse: "
+ "satype is zero, must be non-zero.\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_satype_parse: "
+ "satype %d > max %d, invalid.\n",
+ pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX);
+ SENDERR(EINVAL);
+ }
+
+ if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_satype_parse: "
+ "proto lookup from satype=%d failed.\n",
+ pfkey_x_satype->sadb_x_satype_satype);
+ SENDERR(EINVAL);
+ }
+
+ for(i = 0; i < 3; i++) {
+ if(pfkey_x_satype->sadb_x_satype_reserved[i]) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_satype_parse: "
+ "reserved[%d]=%d must be set to zero.\n",
+ i, pfkey_x_satype->sadb_x_satype_reserved[i]);
+ SENDERR(EINVAL);
+ }
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_x_satype_parse: "
+ "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n",
+ pfkey_x_satype->sadb_x_satype_len,
+ pfkey_x_satype->sadb_x_satype_exttype,
+ pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype),
+ pfkey_x_satype->sadb_x_satype_satype,
+ satype2name(pfkey_x_satype->sadb_x_satype_satype),
+ pfkey_x_satype->sadb_x_satype_reserved[0],
+ pfkey_x_satype->sadb_x_satype_reserved[1],
+ pfkey_x_satype->sadb_x_satype_reserved[2]);
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ int i;
+ struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_x_debug_parse: enter\n");
+ /* sanity checks... */
+ if(pfkey_x_debug->sadb_x_debug_len !=
+ sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_debug_parse: "
+ "size wrong ext_len=%d, key_ext_len=%d.\n",
+ pfkey_x_debug->sadb_x_debug_len,
+ (int)sizeof(struct sadb_x_debug));
+ SENDERR(EINVAL);
+ }
+
+ for(i = 0; i < 4; i++) {
+ if(pfkey_x_debug->sadb_x_debug_reserved[i]) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_debug_parse: "
+ "reserved[%d]=%d must be set to zero.\n",
+ i, pfkey_x_debug->sadb_x_debug_reserved[i]);
+ SENDERR(EINVAL);
+ }
+ }
+
+errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext)
+{
+ int error = 0;
+ struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n");
+ /* sanity checks... */
+
+ if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+ p->sadb_protocol_len, (int)sizeof(*p));
+ SENDERR(EINVAL);
+ }
+
+ if (p->sadb_protocol_reserved2 != 0) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_protocol_parse: res=%d, must be zero.\n",
+ p->sadb_protocol_reserved2);
+ SENDERR(EINVAL);
+ }
+
+ errlab:
+ return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext)
+{
+ return 0;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext)
+{
+ return 0;
+}
+
+#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME};
+
+DEFINEPARSER(pfkey_sa_parse);
+DEFINEPARSER(pfkey_lifetime_parse);
+DEFINEPARSER(pfkey_address_parse);
+DEFINEPARSER(pfkey_key_parse);
+DEFINEPARSER(pfkey_ident_parse);
+DEFINEPARSER(pfkey_sens_parse);
+DEFINEPARSER(pfkey_prop_parse);
+DEFINEPARSER(pfkey_supported_parse);
+DEFINEPARSER(pfkey_spirange_parse);
+DEFINEPARSER(pfkey_x_kmprivate_parse);
+DEFINEPARSER(pfkey_x_satype_parse);
+DEFINEPARSER(pfkey_x_ext_debug_parse);
+DEFINEPARSER(pfkey_x_ext_protocol_parse);
+DEFINEPARSER(pfkey_x_ext_nat_t_type_parse);
+DEFINEPARSER(pfkey_x_ext_nat_t_port_parse);
+
+struct pf_key_ext_parsers_def *ext_default_parsers[]=
+{
+ NULL, /* pfkey_msg_parse, */
+ &pfkey_sa_parse_def,
+ &pfkey_lifetime_parse_def,
+ &pfkey_lifetime_parse_def,
+ &pfkey_lifetime_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_key_parse_def,
+ &pfkey_key_parse_def,
+ &pfkey_ident_parse_def,
+ &pfkey_ident_parse_def,
+ &pfkey_sens_parse_def,
+ &pfkey_prop_parse_def,
+ &pfkey_supported_parse_def,
+ &pfkey_supported_parse_def,
+ &pfkey_spirange_parse_def,
+ &pfkey_x_kmprivate_parse_def,
+ &pfkey_x_satype_parse_def,
+ &pfkey_sa_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_address_parse_def,
+ &pfkey_x_ext_debug_parse_def,
+ &pfkey_x_ext_protocol_parse_def ,
+ &pfkey_x_ext_nat_t_type_parse_def,
+ &pfkey_x_ext_nat_t_port_parse_def,
+ &pfkey_x_ext_nat_t_port_parse_def,
+ &pfkey_address_parse_def
+};
+
+int
+pfkey_msg_parse(struct sadb_msg *pfkey_msg,
+ struct pf_key_ext_parsers_def *ext_parsers[],
+ struct sadb_ext *extensions[],
+ int dir)
+{
+ int error = 0;
+ int remain;
+ struct sadb_ext *pfkey_ext;
+ int extensions_seen = 0;
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_msg_parse: "
+ "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n",
+ pfkey_msg->sadb_msg_version,
+ pfkey_msg->sadb_msg_type,
+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
+ pfkey_msg->sadb_msg_errno,
+ pfkey_msg->sadb_msg_satype,
+ satype2name(pfkey_msg->sadb_msg_satype),
+ pfkey_msg->sadb_msg_len,
+ pfkey_msg->sadb_msg_reserved,
+ pfkey_msg->sadb_msg_seq,
+ pfkey_msg->sadb_msg_pid);
+
+ if(ext_parsers == NULL) ext_parsers = ext_default_parsers;
+
+ pfkey_extensions_init(extensions);
+
+ remain = pfkey_msg->sadb_msg_len;
+ remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+
+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg +
+ sizeof(struct sadb_msg));
+
+ extensions[0] = (struct sadb_ext *) pfkey_msg;
+
+
+ if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "not PF_KEY_V2 msg, found %d, should be %d.\n",
+ pfkey_msg->sadb_msg_version,
+ PF_KEY_V2);
+ SENDERR(EINVAL);
+ }
+
+ if(!pfkey_msg->sadb_msg_type) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "msg type not set, must be non-zero..\n");
+ SENDERR(EINVAL);
+ }
+
+ if(pfkey_msg->sadb_msg_type > SADB_MAX) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "msg type=%d > max=%d.\n",
+ pfkey_msg->sadb_msg_type,
+ SADB_MAX);
+ SENDERR(EINVAL);
+ }
+
+ switch(pfkey_msg->sadb_msg_type) {
+ case SADB_GETSPI:
+ case SADB_UPDATE:
+ case SADB_ADD:
+ case SADB_DELETE:
+ case SADB_GET:
+ case SADB_X_GRPSA:
+ case SADB_X_ADDFLOW:
+ if(!satype2proto(pfkey_msg->sadb_msg_satype)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "satype %d conversion to proto failed for msg_type %d (%s).\n",
+ pfkey_msg->sadb_msg_satype,
+ pfkey_msg->sadb_msg_type,
+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+ SENDERR(EINVAL);
+ } else {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n",
+ pfkey_msg->sadb_msg_satype,
+ satype2name(pfkey_msg->sadb_msg_satype),
+ satype2proto(pfkey_msg->sadb_msg_satype),
+ pfkey_msg->sadb_msg_type,
+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+ }
+ case SADB_ACQUIRE:
+ case SADB_REGISTER:
+ case SADB_EXPIRE:
+ if(!pfkey_msg->sadb_msg_satype) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "satype is zero, must be non-zero for msg_type %d(%s).\n",
+ pfkey_msg->sadb_msg_type,
+ pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+ SENDERR(EINVAL);
+ }
+ default:
+ break;
+ }
+
+ /* errno must not be set in downward messages */
+ /* this is not entirely true... a response to an ACQUIRE could return an error */
+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "errno set to %d.\n",
+ pfkey_msg->sadb_msg_errno);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_msg_parse: "
+ "remain=%d, ext_type=%d(%s), ext_len=%d.\n",
+ remain,
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ pfkey_ext->sadb_ext_len);
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_msg_parse: "
+ "extensions permitted=%08x, required=%08x.\n",
+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
+
+ extensions_seen = 1;
+
+ while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) {
+ /* Is there enough message left to support another extension header? */
+ if(remain < pfkey_ext->sadb_ext_len) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "remain %d less than ext len %d.\n",
+ remain, pfkey_ext->sadb_ext_len);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_msg_parse: "
+ "parsing ext type=%d(%s) remain=%d.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ remain);
+
+ /* Is the extension header type valid? */
+ if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ SADB_EXT_MAX);
+ SENDERR(EINVAL);
+ }
+
+ /* Have we already seen this type of extension? */
+ if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0)
+ {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "ext type %d(%s) already seen.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
+ SENDERR(EINVAL);
+ }
+
+ /* Do I even know about this type of extension? */
+ if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "ext type %d(%s) unknown, ignoring.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
+ goto next_ext;
+ }
+
+ /* Is this type of extension permitted for this type of message? */
+ if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] &
+ 1<<pfkey_ext->sadb_ext_type)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<<type=%08x\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+ 1<<pfkey_ext->sadb_ext_type);
+ SENDERR(EINVAL);
+ }
+
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_msg_parse: "
+ "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n",
+ remain,
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ pfkey_ext->sadb_ext_len,
+ pfkey_ext,
+ ext_parsers[pfkey_ext->sadb_ext_type]->parser_name);
+
+ /* Parse the extension */
+ if((error =
+ (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "extension parsing for type %d(%s) failed with error %d.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+ error);
+ SENDERR(-error);
+ }
+ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+ "pfkey_msg_parse: "
+ "Extension %d(%s) parsed.\n",
+ pfkey_ext->sadb_ext_type,
+ pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
+
+ /* Mark that we have seen this extension and remember the header location */
+ extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type );
+ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext;
+
+ next_ext:
+ /* Calculate how much message remains */
+ remain -= pfkey_ext->sadb_ext_len;
+
+ if(!remain) {
+ break;
+ }
+ /* Find the next extension header */
+ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext +
+ pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+ }
+
+ if(remain) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "unexpected remainder of %d.\n",
+ remain);
+ /* why is there still something remaining? */
+ SENDERR(EINVAL);
+ }
+
+ /* check required extensions */
+ DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+ "pfkey_msg_parse: "
+ "extensions permitted=%08x, seen=%08x, required=%08x.\n",
+ extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+ extensions_seen,
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
+
+ /* don't check further if it is an error return message since it
+ may not have a body */
+ if(pfkey_msg->sadb_msg_errno) {
+ SENDERR(-error);
+ }
+
+ if((extensions_seen &
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) !=
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "required extensions missing:%08x.\n",
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] -
+ (extensions_seen &
+ extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]));
+ SENDERR(EINVAL);
+ }
+
+ if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW)
+ && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW)
+ != SADB_X_EXT_ADDRESS_DELFLOW)
+ && (((extensions_seen & (1<<SADB_EXT_SA)) != (1<<SADB_EXT_SA))
+ || ((((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_flags
+ & SADB_X_SAFLAGS_CLEARFLOW)
+ != SADB_X_SAFLAGS_CLEARFLOW))) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n",
+ SADB_X_EXT_ADDRESS_DELFLOW
+ - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW),
+ (1<<SADB_EXT_SA) - (extensions_seen & (1<<SADB_EXT_SA)));
+ SENDERR(EINVAL);
+ }
+
+ switch(pfkey_msg->sadb_msg_type) {
+ case SADB_ADD:
+ case SADB_UPDATE:
+ /* check maturity */
+ if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state !=
+ SADB_SASTATE_MATURE) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "state=%d for add or update should be MATURE=%d.\n",
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
+ SADB_SASTATE_MATURE);
+ SENDERR(EINVAL);
+ }
+
+ /* check AH and ESP */
+ switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) {
+ case SADB_SATYPE_AH:
+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth !=
+ SADB_AALG_NONE)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "auth alg is zero, must be non-zero for AH SAs.\n");
+ SENDERR(EINVAL);
+ }
+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt !=
+ SADB_EALG_NONE) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "AH handed encalg=%d, must be zero.\n",
+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt);
+ SENDERR(EINVAL);
+ }
+ break;
+ case SADB_SATYPE_ESP:
+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
+ SADB_EALG_NONE)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n",
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
+ SENDERR(EINVAL);
+ }
+ if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt ==
+ SADB_EALG_NULL) &&
+ (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth ==
+ SADB_AALG_NONE) ) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "ESP handed encNULL+authNONE, illegal combination.\n");
+ SENDERR(EINVAL);
+ }
+ break;
+ case SADB_X_SATYPE_COMP:
+ if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
+ SADB_EALG_NONE)) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n",
+ ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
+ ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
+ SENDERR(EINVAL);
+ }
+ if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth !=
+ SADB_AALG_NONE) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "COMP handed auth=%d, must be zero.\n",
+ ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth);
+ SENDERR(EINVAL);
+ }
+ break;
+ default:
+ break;
+ }
+ if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) {
+ DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+ "pfkey_msg_parse: "
+ "spi=%08x must be > 255.\n",
+ ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi));
+ SENDERR(EINVAL);
+ }
+ default:
+ break;
+ }
+errlab:
+
+ return error;
+}
+
+/*
+ * $Log: pfkey_v2_parse.c,v $
+ * Revision 1.4 2004/06/13 20:35:07 as
+ * removed references to ipsec_netlink.h
+ *
+ * Revision 1.3 2004/03/30 10:00:17 as
+ * 64 bit issues
+ *
+ * Revision 1.2 2004/03/22 21:53:18 as
+ * merged alg-0.8.1 branch with HEAD
+ *
+ * Revision 1.1.2.1 2004/03/15 22:30:06 as
+ * nat-0.6c patch merged
+ *
+ * Revision 1.1 2004/03/15 20:35:26 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.53 2003/01/30 02:32:09 rgb
+ *
+ * Rename SAref table macro names for clarity.
+ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
+ *
+ * Revision 1.52 2002/12/30 06:53:07 mcr
+ * deal with short SA structures... #if 0 out for now. Probably
+ * not quite the right way.
+ *
+ * Revision 1.51 2002/12/13 18:16:02 mcr
+ * restored sa_ref code
+ *
+ * Revision 1.50 2002/12/13 18:06:52 mcr
+ * temporarily removed sadb_x_sa_ref reference for 2.xx
+ *
+ * Revision 1.49 2002/10/05 05:02:58 dhr
+ *
+ * C labels go on statements
+ *
+ * Revision 1.48 2002/09/20 15:40:45 rgb
+ * Added sadb_x_sa_ref to struct sadb_sa.
+ *
+ * Revision 1.47 2002/09/20 05:01:31 rgb
+ * Fixed usage of pfkey_lib_debug.
+ * Format for function declaration style consistency.
+ * Added text labels to elucidate numeric values presented.
+ * Re-organised debug output to reduce noise in output.
+ *
+ * Revision 1.46 2002/07/24 18:44:54 rgb
+ * Type fiddling to tame ia64 compiler.
+ *
+ * Revision 1.45 2002/05/23 07:14:11 rgb
+ * Cleaned up %p variants to 0p%p for test suite cleanup.
+ *
+ * Revision 1.44 2002/04/24 07:55:32 mcr
+ * #include patches and Makefiles for post-reorg compilation.
+ *
+ * Revision 1.43 2002/04/24 07:36:40 mcr
+ * Moved from ./lib/pfkey_v2_parse.c,v
+ *
+ * Revision 1.42 2002/01/29 22:25:36 rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.41 2002/01/29 01:59:10 mcr
+ * removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * updating of IPv6 structures to match latest in6.h version.
+ * removed dead code from freeswan.h that also duplicated kversions.h
+ * code.
+ *
+ * Revision 1.40 2002/01/20 20:34:50 mcr
+ * added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.39 2001/11/27 05:29:22 mcr
+ * pfkey parses are now maintained by a structure
+ * that includes their name for debug purposes.
+ * DEBUGGING() macro changed so that it takes a debug
+ * level so that pf_key() can use this to decode the
+ * structures without innundanting humans.
+ * Also uses pfkey_v2_sadb_ext_string() in messages.
+ *
+ * Revision 1.38 2001/11/06 19:47:47 rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.37 2001/10/18 04:45:24 rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.36 2001/06/14 19:35:16 rgb
+ * Update copyright date.
+ *
+ * Revision 1.35 2001/05/03 19:44:51 rgb
+ * Standardise on SENDERR() macro.
+ *
+ * Revision 1.34 2001/03/16 07:41:51 rgb
+ * Put freeswan.h include before pluto includes.
+ *
+ * Revision 1.33 2001/02/27 07:13:51 rgb
+ * Added satype2name() function.
+ * Added text to default satype_tbl entry.
+ * Added satype2name() conversions for most satype debug output.
+ *
+ * Revision 1.32 2001/02/26 20:01:09 rgb
+ * Added internal IP protocol 61 for magic SAs.
+ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
+ * Re-formatted debug output (split lines, consistent spacing).
+ * Removed acquire, register and expire requirements for a known satype.
+ * Changed message type checking to a switch structure.
+ * Verify expected NULL auth for IPCOMP.
+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for
+ * appropriate message types.
+ *
+ * Revision 1.31 2000/12/01 07:09:00 rgb
+ * Added ipcomp sanity check to require encalgo is set.
+ *
+ * Revision 1.30 2000/11/17 18:10:30 rgb
+ * Fixed bugs mostly relating to spirange, to treat all spi variables as
+ * network byte order since this is the way PF_KEYv2 stored spis.
+ *
+ * Revision 1.29 2000/10/12 00:02:39 rgb
+ * Removed 'format, ##' nonsense from debug macros for RH7.0.
+ *
+ * Revision 1.28 2000/09/20 16:23:04 rgb
+ * Remove over-paranoid extension check in the presence of sadb_msg_errno.
+ *
+ * Revision 1.27 2000/09/20 04:04:21 rgb
+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
+ * oopsen.
+ *
+ * Revision 1.26 2000/09/15 11:37:02 rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.25 2000/09/12 22:35:37 rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.24 2000/09/12 18:59:54 rgb
+ * Added Gerhard's IPv6 support to pfkey parts of libfreeswan.
+ *
+ * Revision 1.23 2000/09/12 03:27:00 rgb
+ * Moved DEBUGGING definition to compile kernel with debug off.
+ *
+ * Revision 1.22 2000/09/09 06:39:27 rgb
+ * Restrict pfkey errno check to downward messages only.
+ *
+ * Revision 1.21 2000/09/08 19:22:34 rgb
+ * Enabled pfkey_sens_parse().
+ * Added check for errno on downward acquire messages only.
+ *
+ * Revision 1.20 2000/09/01 18:48:23 rgb
+ * Fixed reserved check bug and added debug output in
+ * pfkey_supported_parse().
+ * Fixed debug output label bug in pfkey_ident_parse().
+ *
+ * Revision 1.19 2000/08/27 01:55:26 rgb
+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
+ *
+ * Revision 1.18 2000/08/24 17:00:36 rgb
+ * Ignore unknown extensions instead of failing.
+ *
+ * Revision 1.17 2000/06/02 22:54:14 rgb
+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
+ *
+ * Revision 1.16 2000/05/10 19:25:11 rgb
+ * Fleshed out proposal and supported extensions.
+ *
+ * Revision 1.15 2000/01/24 21:15:31 rgb
+ * Added disabled pluto pfkey lib debug flag.
+ * Added algo debugging reporting.
+ *
+ * Revision 1.14 2000/01/22 23:24:29 rgb
+ * Added new functions proto2satype() and satype2proto() and lookup
+ * table satype_tbl. Also added proto2name() since it was easy.
+ *
+ * Revision 1.13 2000/01/21 09:43:59 rgb
+ * Cast ntohl(spi) as (unsigned long int) to shut up compiler.
+ *
+ * Revision 1.12 2000/01/21 06:28:19 rgb
+ * Added address cases for eroute flows.
+ * Indented compiler directives for readability.
+ * Added klipsdebug switching capability.
+ *
+ * Revision 1.11 1999/12/29 21:14:59 rgb
+ * Fixed debug text cut and paste typo.
+ *
+ * Revision 1.10 1999/12/10 17:45:24 rgb
+ * Added address debugging.
+ *
+ * Revision 1.9 1999/12/09 23:11:42 rgb
+ * Ditched <string.h> include since we no longer use memset().
+ * Use new pfkey_extensions_init() instead of memset().
+ * Added check for SATYPE in pfkey_msg_build().
+ * Tidy up comments and debugging comments.
+ *
+ * Revision 1.8 1999/12/07 19:55:26 rgb
+ * Removed unused first argument from extension parsers.
+ * Removed static pluto debug flag.
+ * Moved message type and state checking to pfkey_msg_parse().
+ * Changed print[fk] type from lx to x to quiet compiler.
+ * Removed redundant remain check.
+ * Changed __u* types to uint* to avoid use of asm/types.h and
+ * sys/types.h in userspace code.
+ *
+ * Revision 1.7 1999/12/01 22:20:51 rgb
+ * Moved pfkey_lib_debug variable into the library.
+ * Added pfkey version check into header parsing.
+ * Added check for SATYPE only for those extensions that require a
+ * non-zero value.
+ *
+ * Revision 1.6 1999/11/27 11:58:05 rgb
+ * Added ipv6 headers.
+ * Moved sadb_satype2proto protocol lookup table from
+ * klips/net/ipsec/pfkey_v2_parser.c.
+ * Enable lifetime_current checking.
+ * Debugging error messages added.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ * Add CVS log entry to bottom of file.
+ * Moved auth and enc alg check to pfkey_msg_parse().
+ * Enable accidentally disabled spirange parsing.
+ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff --git a/src/libfreeswan/pfkeyv2.h b/src/libfreeswan/pfkeyv2.h
new file mode 100644
index 000000000..07126f1b8
--- /dev/null
+++ b/src/libfreeswan/pfkeyv2.h
@@ -0,0 +1,375 @@
+/*
+ * RCSID $Id: pfkeyv2.h,v 1.5 2004/10/04 22:43:56 as Exp $
+ */
+
+/*
+RFC 2367 PF_KEY Key Management API July 1998
+
+
+Appendix D: Sample Header File
+
+This file defines structures and symbols for the PF_KEY Version 2
+key management interface. It was written at the U.S. Naval Research
+Laboratory. This file is in the public domain. The authors ask that
+you leave this credit intact on any copies of this file.
+*/
+#ifndef __PFKEY_V2_H
+#define __PFKEY_V2_H 1
+
+#define PF_KEY_V2 2
+#define PFKEYV2_REVISION 199806L
+
+#define SADB_RESERVED 0
+#define SADB_GETSPI 1
+#define SADB_UPDATE 2
+#define SADB_ADD 3
+#define SADB_DELETE 4
+#define SADB_GET 5
+#define SADB_ACQUIRE 6
+#define SADB_REGISTER 7
+#define SADB_EXPIRE 8
+#define SADB_FLUSH 9
+#define SADB_DUMP 10
+#define SADB_X_PROMISC 11
+#define SADB_X_PCHANGE 12
+#define SADB_X_GRPSA 13
+#define SADB_X_ADDFLOW 14
+#define SADB_X_DELFLOW 15
+#define SADB_X_DEBUG 16
+#define SADB_X_NAT_T_NEW_MAPPING 17
+#define SADB_MAX 17
+
+struct sadb_msg {
+ uint8_t sadb_msg_version;
+ uint8_t sadb_msg_type;
+ uint8_t sadb_msg_errno;
+ uint8_t sadb_msg_satype;
+ uint16_t sadb_msg_len;
+ uint16_t sadb_msg_reserved;
+ uint32_t sadb_msg_seq;
+ uint32_t sadb_msg_pid;
+};
+
+struct sadb_ext {
+ uint16_t sadb_ext_len;
+ uint16_t sadb_ext_type;
+};
+
+struct sadb_sa {
+ uint16_t sadb_sa_len;
+ uint16_t sadb_sa_exttype;
+ uint32_t sadb_sa_spi;
+ uint8_t sadb_sa_replay;
+ uint8_t sadb_sa_state;
+ uint8_t sadb_sa_auth;
+ uint8_t sadb_sa_encrypt;
+ uint32_t sadb_sa_flags;
+ uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */
+ uint8_t sadb_x_reserved[4];
+};
+
+struct sadb_sa_v1 {
+ uint16_t sadb_sa_len;
+ uint16_t sadb_sa_exttype;
+ uint32_t sadb_sa_spi;
+ uint8_t sadb_sa_replay;
+ uint8_t sadb_sa_state;
+ uint8_t sadb_sa_auth;
+ uint8_t sadb_sa_encrypt;
+ uint32_t sadb_sa_flags;
+};
+
+struct sadb_lifetime {
+ uint16_t sadb_lifetime_len;
+ uint16_t sadb_lifetime_exttype;
+ uint32_t sadb_lifetime_allocations;
+ uint64_t sadb_lifetime_bytes;
+ uint64_t sadb_lifetime_addtime;
+ uint64_t sadb_lifetime_usetime;
+ uint32_t sadb_x_lifetime_packets;
+ uint32_t sadb_x_lifetime_reserved;
+};
+
+struct sadb_address {
+ uint16_t sadb_address_len;
+ uint16_t sadb_address_exttype;
+ uint8_t sadb_address_proto;
+ uint8_t sadb_address_prefixlen;
+ uint16_t sadb_address_reserved;
+};
+
+struct sadb_key {
+ uint16_t sadb_key_len;
+ uint16_t sadb_key_exttype;
+ uint16_t sadb_key_bits;
+ uint16_t sadb_key_reserved;
+};
+
+struct sadb_ident {
+ uint16_t sadb_ident_len;
+ uint16_t sadb_ident_exttype;
+ uint16_t sadb_ident_type;
+ uint16_t sadb_ident_reserved;
+ uint64_t sadb_ident_id;
+};
+
+struct sadb_sens {
+ uint16_t sadb_sens_len;
+ uint16_t sadb_sens_exttype;
+ uint32_t sadb_sens_dpd;
+ uint8_t sadb_sens_sens_level;
+ uint8_t sadb_sens_sens_len;
+ uint8_t sadb_sens_integ_level;
+ uint8_t sadb_sens_integ_len;
+ uint32_t sadb_sens_reserved;
+};
+
+struct sadb_prop {
+ uint16_t sadb_prop_len;
+ uint16_t sadb_prop_exttype;
+ uint8_t sadb_prop_replay;
+ uint8_t sadb_prop_reserved[3];
+};
+
+struct sadb_comb {
+ uint8_t sadb_comb_auth;
+ uint8_t sadb_comb_encrypt;
+ uint16_t sadb_comb_flags;
+ uint16_t sadb_comb_auth_minbits;
+ uint16_t sadb_comb_auth_maxbits;
+ uint16_t sadb_comb_encrypt_minbits;
+ uint16_t sadb_comb_encrypt_maxbits;
+ uint32_t sadb_comb_reserved;
+ uint32_t sadb_comb_soft_allocations;
+ uint32_t sadb_comb_hard_allocations;
+ uint64_t sadb_comb_soft_bytes;
+ uint64_t sadb_comb_hard_bytes;
+ uint64_t sadb_comb_soft_addtime;
+ uint64_t sadb_comb_hard_addtime;
+ uint64_t sadb_comb_soft_usetime;
+ uint64_t sadb_comb_hard_usetime;
+ uint32_t sadb_x_comb_soft_packets;
+ uint32_t sadb_x_comb_hard_packets;
+};
+
+struct sadb_supported {
+ uint16_t sadb_supported_len;
+ uint16_t sadb_supported_exttype;
+ uint32_t sadb_supported_reserved;
+};
+
+struct sadb_alg {
+ uint8_t sadb_alg_id;
+ uint8_t sadb_alg_ivlen;
+ uint16_t sadb_alg_minbits;
+ uint16_t sadb_alg_maxbits;
+ uint16_t sadb_alg_reserved;
+};
+
+struct sadb_spirange {
+ uint16_t sadb_spirange_len;
+ uint16_t sadb_spirange_exttype;
+ uint32_t sadb_spirange_min;
+ uint32_t sadb_spirange_max;
+ uint32_t sadb_spirange_reserved;
+};
+
+struct sadb_x_kmprivate {
+ uint16_t sadb_x_kmprivate_len;
+ uint16_t sadb_x_kmprivate_exttype;
+ uint32_t sadb_x_kmprivate_reserved;
+};
+
+struct sadb_x_satype {
+ uint16_t sadb_x_satype_len;
+ uint16_t sadb_x_satype_exttype;
+ uint8_t sadb_x_satype_satype;
+ uint8_t sadb_x_satype_reserved[3];
+};
+
+struct sadb_x_policy {
+ uint16_t sadb_x_policy_len;
+ uint16_t sadb_x_policy_exttype;
+ uint16_t sadb_x_policy_type;
+ uint8_t sadb_x_policy_dir;
+ uint8_t sadb_x_policy_reserved;
+ uint32_t sadb_x_policy_id;
+ uint32_t sadb_x_policy_reserved2;
+};
+
+struct sadb_x_debug {
+ uint16_t sadb_x_debug_len;
+ uint16_t sadb_x_debug_exttype;
+ uint32_t sadb_x_debug_tunnel;
+ uint32_t sadb_x_debug_netlink;
+ uint32_t sadb_x_debug_xform;
+ uint32_t sadb_x_debug_eroute;
+ uint32_t sadb_x_debug_spi;
+ uint32_t sadb_x_debug_radij;
+ uint32_t sadb_x_debug_esp;
+ uint32_t sadb_x_debug_ah;
+ uint32_t sadb_x_debug_rcv;
+ uint32_t sadb_x_debug_pfkey;
+ uint32_t sadb_x_debug_ipcomp;
+ uint32_t sadb_x_debug_verbose;
+ uint8_t sadb_x_debug_reserved[4];
+};
+
+struct sadb_x_nat_t_type {
+ uint16_t sadb_x_nat_t_type_len;
+ uint16_t sadb_x_nat_t_type_exttype;
+ uint8_t sadb_x_nat_t_type_type;
+ uint8_t sadb_x_nat_t_type_reserved[3];
+};
+struct sadb_x_nat_t_port {
+ uint16_t sadb_x_nat_t_port_len;
+ uint16_t sadb_x_nat_t_port_exttype;
+ uint16_t sadb_x_nat_t_port_port;
+ uint16_t sadb_x_nat_t_port_reserved;
+};
+
+/*
+ * A protocol structure for passing through the transport level
+ * protocol. It contains more fields than are actually used/needed
+ * but it is this way to be compatible with the structure used in
+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
+ */
+struct sadb_protocol {
+ uint16_t sadb_protocol_len;
+ uint16_t sadb_protocol_exttype;
+ uint8_t sadb_protocol_proto;
+ uint8_t sadb_protocol_direction;
+ uint8_t sadb_protocol_flags;
+ uint8_t sadb_protocol_reserved2;
+};
+
+#define SADB_EXT_RESERVED 0
+#define SADB_EXT_SA 1
+#define SADB_EXT_LIFETIME_CURRENT 2
+#define SADB_EXT_LIFETIME_HARD 3
+#define SADB_EXT_LIFETIME_SOFT 4
+#define SADB_EXT_ADDRESS_SRC 5
+#define SADB_EXT_ADDRESS_DST 6
+#define SADB_EXT_ADDRESS_PROXY 7
+#define SADB_EXT_KEY_AUTH 8
+#define SADB_EXT_KEY_ENCRYPT 9
+#define SADB_EXT_IDENTITY_SRC 10
+#define SADB_EXT_IDENTITY_DST 11
+#define SADB_EXT_SENSITIVITY 12
+#define SADB_EXT_PROPOSAL 13
+#define SADB_EXT_SUPPORTED_AUTH 14
+#define SADB_EXT_SUPPORTED_ENCRYPT 15
+#define SADB_EXT_SPIRANGE 16
+#define SADB_X_EXT_KMPRIVATE 17
+#define SADB_X_EXT_SATYPE2 18
+#ifdef KERNEL26_HAS_KAME_DUPLICATES
+#define SADB_X_EXT_POLICY 18
+#endif
+#define SADB_X_EXT_SA2 19
+#define SADB_X_EXT_ADDRESS_DST2 20
+#define SADB_X_EXT_ADDRESS_SRC_FLOW 21
+#define SADB_X_EXT_ADDRESS_DST_FLOW 22
+#define SADB_X_EXT_ADDRESS_SRC_MASK 23
+#define SADB_X_EXT_ADDRESS_DST_MASK 24
+#define SADB_X_EXT_DEBUG 25
+#define SADB_X_EXT_PROTOCOL 26
+#define SADB_X_EXT_NAT_T_TYPE 27
+#define SADB_X_EXT_NAT_T_SPORT 28
+#define SADB_X_EXT_NAT_T_DPORT 29
+#define SADB_X_EXT_NAT_T_OA 30
+#define SADB_EXT_MAX 30
+
+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
+#define SADB_X_EXT_ADDRESS_DELFLOW \
+ ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_MASK))
+
+#define SADB_SATYPE_UNSPEC 0
+#define SADB_SATYPE_AH 2
+#define SADB_SATYPE_ESP 3
+#define SADB_SATYPE_RSVP 5
+#define SADB_SATYPE_OSPFV2 6
+#define SADB_SATYPE_RIPV2 7
+#define SADB_SATYPE_MIP 8
+#define SADB_X_SATYPE_IPIP 9
+#ifdef KERNEL26_HAS_KAME_DUPLICATES
+#define SADB_X_SATYPE_IPCOMP 9 /* ICK! */
+#endif
+#define SADB_X_SATYPE_COMP 10
+#define SADB_X_SATYPE_INT 11
+#define SADB_SATYPE_MAX 11
+
+#define SADB_SASTATE_LARVAL 0
+#define SADB_SASTATE_MATURE 1
+#define SADB_SASTATE_DYING 2
+#define SADB_SASTATE_DEAD 3
+#define SADB_SASTATE_MAX 3
+
+#define SADB_SAFLAGS_PFS 1
+#define SADB_X_SAFLAGS_REPLACEFLOW 2
+#define SADB_X_SAFLAGS_CLEARFLOW 4
+#define SADB_X_SAFLAGS_INFLOW 8
+
+/* not obvious, but these are the same values as used in isakmp,
+ * and in freeswan/ipsec_policy.h. If you need to add any, they
+ * should be added as according to
+ * http://www.iana.org/assignments/isakmp-registry
+ *
+ * and if not, then please try to use a private-use value, and
+ * consider asking IANA to assign a value.
+ */
+#define SADB_AALG_NONE 0
+#define SADB_AALG_MD5_HMAC 2
+#define SADB_AALG_SHA1_HMAC 3
+#define SADB_AALG_DES_MAC 4
+#define SADB_AALG_SHA2_256_HMAC 5
+#define SADB_AALG_SHA2_384_HMAC 6
+#define SADB_AALG_SHA2_512_HMAC 7
+#define SADB_AALG_RIPEMD_160_HMAC 8
+#define SADB_AALG_AES_XCBC_MAC 9
+#define SADB_X_AALG_NULL 251 /* kame */
+#define SADB_AALG_MAX 251
+
+#define SADB_EALG_NONE 0
+#define SADB_EALG_DES_CBC 2
+#define SADB_EALG_3DES_CBC 3
+#define SADB_EALG_RC5_CBC 4
+#define SADB_EALG_IDEA_CBC 5
+#define SADB_EALG_CAST_CBC 6
+#define SADB_EALG_BLOWFISH_CBC 7
+#define SADB_EALG_NULL 11
+#define SADB_EALG_AES_CBC 12
+#define SADB_EALG_AES_CTR 13
+#define SADB_X_EALG_SERPENT_CBC 252
+#define SADB_X_EALG_TWOFISH_CBC 253
+#define SADB_EALG_MAX 253
+
+#define SADB_X_CALG_NONE 0
+#define SADB_X_CALG_OUI 1
+#define SADB_X_CALG_DEFLATE 2
+#define SADB_X_CALG_LZS 3
+#define SADB_X_CALG_V42BIS 4
+#ifdef KERNEL26_HAS_KAME_DUPLICATES
+#define SADB_X_CALG_LZJH 4
+#endif
+#define SADB_X_CALG_MAX 4
+
+#define SADB_X_TALG_NONE 0
+#define SADB_X_TALG_IPv4_in_IPv4 1
+#define SADB_X_TALG_IPv6_in_IPv4 2
+#define SADB_X_TALG_IPv4_in_IPv6 3
+#define SADB_X_TALG_IPv6_in_IPv6 4
+#define SADB_X_TALG_MAX 4
+
+
+#define SADB_IDENTTYPE_RESERVED 0
+#define SADB_IDENTTYPE_PREFIX 1
+#define SADB_IDENTTYPE_FQDN 2
+#define SADB_IDENTTYPE_USERFQDN 3
+#define SADB_X_IDENTTYPE_CONNECTION 4
+#define SADB_IDENTTYPE_MAX 4
+
+#define SADB_KEY_FLAGS_MAX 0
+#endif /* __PFKEY_V2_H */
diff --git a/src/libfreeswan/portof.3 b/src/libfreeswan/portof.3
new file mode 100644
index 000000000..fac0d8bc3
--- /dev/null
+++ b/src/libfreeswan/portof.3
@@ -0,0 +1,70 @@
+.TH IPSEC_PORTOF 3 "8 Sept 2000"
+.\" RCSID $Id: portof.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec portof \- get port field of an ip_address
+.br
+ipsec setportof \- set port field of an ip_address
+.br
+ipsec sockaddrof \- get pointer to internal sockaddr of an ip_address
+.br
+ipsec sockaddrlenof \- get length of internal sockaddr of an ip_address
+.SH SYNOPSIS
+.B "#include <freeswan.h>"
+.sp
+.B "int portof(const ip_address *src);"
+.br
+.B "void setportof(int port, ip_address *dst);"
+.br
+.B "struct sockaddr *sockaddrof(ip_address *src);"
+.br
+.B "size_t sockaddrlenof(const ip_address *src);"
+.SH DESCRIPTION
+The
+.B <freeswan.h>
+internal type
+.I ip_address
+contains one of the
+.I sockaddr
+types internally.
+\fIReliance on this feature is discouraged\fR,
+but it may occasionally be necessary.
+These functions provide low-level tools for this purpose.
+.PP
+.I Portof
+and
+.I setportof
+respectively read and write the port-number field of the internal
+.IR sockaddr .
+The values are in network byte order.
+.PP
+.I Sockaddrof
+returns a pointer to the internal
+.IR sockaddr ,
+for passing to other functions.
+.PP
+.I Sockaddrlenof
+reports the size of the internal
+.IR sockaddr ,
+for use in storage allocation.
+.SH SEE ALSO
+inet(3), ipsec_initaddr(3)
+.SH DIAGNOSTICS
+.I Portof
+returns
+.BR \-1 ,
+.I sockaddrof
+returns
+.BR NULL ,
+and
+.I sockaddrlenof
+returns
+.B 0
+if an unknown address family is found within the
+.IR ip_address .
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+These functions all depend on low-level details of the
+.I ip_address
+type, which are in principle subject to change.
+Avoid using them unless really necessary.
diff --git a/src/libfreeswan/portof.c b/src/libfreeswan/portof.c
new file mode 100644
index 000000000..d028ea034
--- /dev/null
+++ b/src/libfreeswan/portof.c
@@ -0,0 +1,96 @@
+/*
+ * low-level ip_address ugliness
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: portof.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - portof - get the port field of an ip_address
+ */
+int /* network order */
+portof(src)
+const ip_address *src;
+{
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ return src->u.v4.sin_port;
+ break;
+ case AF_INET6:
+ return src->u.v6.sin6_port;
+ break;
+ default:
+ return -1; /* "can't happen" */
+ break;
+ }
+}
+
+/*
+ - setportof - set the port field of an ip_address
+ */
+void
+setportof(port, dst)
+int port; /* network order */
+ip_address *dst;
+{
+ switch (dst->u.v4.sin_family) {
+ case AF_INET:
+ dst->u.v4.sin_port = port;
+ break;
+ case AF_INET6:
+ dst->u.v6.sin6_port = port;
+ break;
+ }
+}
+
+/*
+ - sockaddrof - get a pointer to the sockaddr hiding inside an ip_address
+ */
+struct sockaddr *
+sockaddrof(src)
+ip_address *src;
+{
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ return (struct sockaddr *)&src->u.v4;
+ break;
+ case AF_INET6:
+ return (struct sockaddr *)&src->u.v6;
+ break;
+ default:
+ return NULL; /* "can't happen" */
+ break;
+ }
+}
+
+/*
+ - sockaddrlenof - get length of the sockaddr hiding inside an ip_address
+ */
+size_t /* 0 for error */
+sockaddrlenof(src)
+const ip_address *src;
+{
+ switch (src->u.v4.sin_family) {
+ case AF_INET:
+ return sizeof(src->u.v4);
+ break;
+ case AF_INET6:
+ return sizeof(src->u.v6);
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
diff --git a/src/libfreeswan/prng.3 b/src/libfreeswan/prng.3
new file mode 100644
index 000000000..51f19364f
--- /dev/null
+++ b/src/libfreeswan/prng.3
@@ -0,0 +1,121 @@
+.TH IPSEC_PRNG 3 "1 April 2002"
+.\" RCSID $Id: prng.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec prng_init \- initialize IPsec pseudorandom-number generator
+.br
+ipsec prng_bytes \- get bytes from IPsec pseudorandom-number generator
+.br
+ipsec prng_final \- close down IPsec pseudorandom-number generator
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "void prng_init(struct prng *prng,"
+.ti +1c
+.B "const unsigned char *key, size_t keylen);"
+.br
+.B "void prng_bytes(struct prng *prng, char *dst,"
+.ti +1c
+.B "size_t dstlen);"
+.br
+.B "unsigned long prng_count(struct prng *prng);"
+.br
+.B "void prng_final(struct prng *prng);"
+.SH DESCRIPTION
+.I Prng_init
+initializes a crypto-quality pseudo-random-number generator from a key;
+.I prng_bytes
+obtains pseudo-random bytes from it;
+.I prng_count
+reports the number of bytes extracted from it to date;
+.I prng_final
+closes it down.
+It is the user's responsibility to initialize a PRNG before using it,
+and not to use it again after it is closed down.
+.PP
+.I Prng_init
+initializes,
+or re-initializes,
+the specified
+.I prng
+from the
+.IR key ,
+whose length is given by
+.IR keylen .
+The user must allocate the
+.B "struct prng"
+pointed to by
+.IR prng .
+There is no particular constraint on the length of the key,
+although a key longer than 256 bytes is unnecessary because
+only the first 256 would be used.
+Initialization requires on the order of 3000 integer operations,
+independent of key length.
+.PP
+.I Prng_bytes
+obtains
+.I dstlen
+pseudo-random bytes from the PRNG and puts them in
+.IR buf .
+This is quite fast,
+on the order of 10 integer operations per byte.
+.PP
+.I Prng_count
+reports the number of bytes obtained from the PRNG
+since it was (last) initialized.
+.PP
+.I Prng_final
+closes down a PRNG by
+zeroing its internal memory,
+obliterating all trace of the state used to generate its previous output.
+This requires on the order of 250 integer operations.
+.PP
+The
+.B <freeswan.h>
+header file supplies the definition of the
+.B prng
+structure.
+Examination of its innards is discouraged, as they may change.
+.PP
+The PRNG algorithm
+used by these functions is currently identical to that of RC4(TM).
+This algorithm is cryptographically strong,
+sufficiently unpredictable that even a hostile observer will
+have difficulty determining the next byte of output from past history,
+provided it is initialized from a reasonably large key composed of
+highly random bytes (see
+.IR random (4)).
+The usual run of software pseudo-random-number generators
+(e.g.
+.IR random (3))
+are
+.I not
+cryptographically strong.
+.PP
+The well-known attacks against RC4(TM),
+e.g. as found in 802.11b's WEP encryption system,
+apply only if multiple PRNGs are initialized with closely-related keys
+(e.g., using a counter appended to a base key).
+If such keys are used, the first few hundred pseudo-random bytes
+from each PRNG should be discarded,
+to give the PRNGs a chance to randomize their innards properly.
+No useful attacks are known if the key is well randomized to begin with.
+.SH SEE ALSO
+random(3), random(4)
+.br
+Bruce Schneier,
+\fIApplied Cryptography\fR, 2nd ed., 1996, ISBN 0-471-11709-9,
+pp. 397-8.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+If an attempt is made to obtain more than 4e9 bytes
+between initializations,
+the PRNG will continue to work but
+.IR prng_count 's
+output will stick at
+.BR 4000000000 .
+Fixing this would require a longer integer type and does
+not seem worth the trouble,
+since you should probably re-initialize before then anyway...
+.PP
+``RC4'' is a trademark of RSA Data Security, Inc.
diff --git a/src/libfreeswan/prng.c b/src/libfreeswan/prng.c
new file mode 100644
index 000000000..e31836783
--- /dev/null
+++ b/src/libfreeswan/prng.c
@@ -0,0 +1,202 @@
+/*
+ * crypto-class pseudorandom number generator
+ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397
+ * Copyright (C) 2002 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: prng.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - prng_init - initialize PRNG from a key
+ */
+void
+prng_init(prng, key, keylen)
+struct prng *prng;
+const unsigned char *key;
+size_t keylen;
+{
+ unsigned char k[256];
+ int i, j;
+ unsigned const char *p;
+ unsigned const char *keyend = key + keylen;
+ unsigned char t;
+
+ for (i = 0; i <= 255; i++)
+ prng->sbox[i] = i;
+ p = key;
+ for (i = 0; i <= 255; i++) {
+ k[i] = *p++;
+ if (p >= keyend)
+ p = key;
+ }
+ j = 0;
+ for (i = 0; i <= 255; i++) {
+ j = (j + prng->sbox[i] + k[i]) & 0xff;
+ t = prng->sbox[i];
+ prng->sbox[i] = prng->sbox[j];
+ prng->sbox[j] = t;
+ k[i] = 0; /* clear out key memory */
+ }
+ prng->i = 0;
+ prng->j = 0;
+ prng->count = 0;
+}
+
+/*
+ - prng_bytes - get some pseudorandom bytes from PRNG
+ */
+void
+prng_bytes(prng, dst, dstlen)
+struct prng *prng;
+unsigned char *dst;
+size_t dstlen;
+{
+ int i, j, t;
+ unsigned char *p = dst;
+ size_t remain = dstlen;
+# define MAX 4000000000ul
+
+ while (remain > 0) {
+ i = (prng->i + 1) & 0xff;
+ prng->i = i;
+ j = (prng->j + prng->sbox[i]) & 0xff;
+ prng->j = j;
+ t = prng->sbox[i];
+ prng->sbox[i] = prng->sbox[j];
+ prng->sbox[j] = t;
+ t = (t + prng->sbox[i]) & 0xff;
+ *p++ = prng->sbox[t];
+ remain--;
+ }
+ if (prng->count < MAX - dstlen)
+ prng->count += dstlen;
+ else
+ prng->count = MAX;
+}
+
+/*
+ - prnt_count - how many bytes have been extracted from PRNG so far?
+ */
+unsigned long
+prng_count(prng)
+struct prng *prng;
+{
+ return prng->count;
+}
+
+/*
+ - prng_final - clear out PRNG to ensure nothing left in memory
+ */
+void
+prng_final(prng)
+struct prng *prng;
+{
+ int i;
+
+ for (i = 0; i <= 255; i++)
+ prng->sbox[i] = 0;
+ prng->i = 0;
+ prng->j = 0;
+ prng->count = 0; /* just for good measure */
+}
+
+
+
+#ifdef PRNG_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ struct prng pr;
+ unsigned char buf[100];
+ unsigned char *p;
+ size_t n;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ prng_init(&pr, argv[1], strlen(argv[1]));
+ prng_bytes(&pr, buf, 32);
+ printf("0x");
+ for (p = buf, n = 32; n > 0; p++, n--)
+ printf("%02x", *p);
+ printf("\n%lu bytes\n", prng_count(&pr));
+ prng_final(&pr);
+ exit(0);
+}
+
+void
+regress()
+{
+ struct prng pr;
+ unsigned char buf[100];
+ unsigned char *p;
+ size_t n;
+ /* somewhat non-random sample key */
+ unsigned char key[] = "here we go gathering nuts in May";
+ /* first thirty bytes of output from that key */
+ unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c"
+ "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71"
+ "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28";
+ int nzero, none;
+ int show = 0;
+
+ prng_init(&pr, key, strlen(key));
+ prng_bytes(&pr, buf, sizeof(buf));
+ for (p = buf, n = sizeof(buf); n > 0; p++, n--) {
+ if (*p == 0)
+ nzero++;
+ if (*p == 255)
+ none++;
+ }
+ if (nzero > 3 || none > 3) {
+ fprintf(stderr, "suspiciously non-random output!\n");
+ show = 1;
+ }
+ if (memcmp(buf, good, strlen(good)) != 0) {
+ fprintf(stderr, "incorrect output!\n");
+ show = 1;
+ }
+ if (show) {
+ fprintf(stderr, "0x");
+ for (p = buf, n = sizeof(buf); n > 0; p++, n--)
+ fprintf(stderr, "%02x", *p);
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ if (prng_count(&pr) != sizeof(buf)) {
+ fprintf(stderr, "got %u bytes, but count is %lu\n",
+ sizeof(buf), prng_count(&pr));
+ exit(1);
+ }
+ prng_final(&pr);
+ exit(0);
+}
+
+#endif /* PRNG_MAIN */
diff --git a/src/libfreeswan/radij.h b/src/libfreeswan/radij.h
new file mode 100644
index 000000000..2a66093a0
--- /dev/null
+++ b/src/libfreeswan/radij.h
@@ -0,0 +1,280 @@
+/*
+ * RCSID $Id: radij.h,v 1.1 2004/03/15 20:35:25 as Exp $
+ */
+
+/*
+ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite
+ *
+ * Variable and procedure names have been modified so that they don't
+ * conflict with the original BSD code, as a small number of modifications
+ * have been introduced and we may want to reuse this code in BSD.
+ *
+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek
+ * chi or a German ch sound (as `doch', not as in `milch'), or even a
+ * spanish j as in Juan. It is not as far back in the throat like
+ * the corresponding Hebrew sound, nor is it a soft breath like the English h.
+ * It has nothing to do with the Dutch ij sound.
+ *
+ * Here is the appropriate copyright notice:
+ */
+
+/*
+ * Copyright (c) 1988, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)radix.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _RADIJ_H_
+#define _RADIJ_H_
+
+/*
+#define RJ_DEBUG
+*/
+
+#ifdef __KERNEL__
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+/*
+ * Radix search tree node layout.
+ */
+
+struct radij_node
+{
+ struct radij_mask *rj_mklist; /* list of masks contained in subtree */
+ struct radij_node *rj_p; /* parent */
+ short rj_b; /* bit offset; -1-index(netmask) */
+ char rj_bmask; /* node: mask for bit test*/
+ u_char rj_flags; /* enumerated next */
+#define RJF_NORMAL 1 /* leaf contains normal route */
+#define RJF_ROOT 2 /* leaf is root leaf for tree */
+#define RJF_ACTIVE 4 /* This node is alive (for rtfree) */
+ union {
+ struct { /* leaf only data: */
+ caddr_t rj_Key; /* object of search */
+ caddr_t rj_Mask; /* netmask, if present */
+ struct radij_node *rj_Dupedkey;
+ } rj_leaf;
+ struct { /* node only data: */
+ int rj_Off; /* where to start compare */
+ struct radij_node *rj_L;/* progeny */
+ struct radij_node *rj_R;/* progeny */
+ }rj_node;
+ } rj_u;
+#ifdef RJ_DEBUG
+ int rj_info;
+ struct radij_node *rj_twin;
+ struct radij_node *rj_ybro;
+#endif
+};
+
+#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey
+#define rj_key rj_u.rj_leaf.rj_Key
+#define rj_mask rj_u.rj_leaf.rj_Mask
+#define rj_off rj_u.rj_node.rj_Off
+#define rj_l rj_u.rj_node.rj_L
+#define rj_r rj_u.rj_node.rj_R
+
+/*
+ * Annotations to tree concerning potential routes applying to subtrees.
+ */
+
+extern struct radij_mask {
+ short rm_b; /* bit offset; -1-index(netmask) */
+ char rm_unused; /* cf. rj_bmask */
+ u_char rm_flags; /* cf. rj_flags */
+ struct radij_mask *rm_mklist; /* more masks to try */
+ caddr_t rm_mask; /* the mask */
+ int rm_refs; /* # of references to this struct */
+} *rj_mkfreelist;
+
+#define MKGet(m) {\
+ if (rj_mkfreelist) {\
+ m = rj_mkfreelist; \
+ rj_mkfreelist = (m)->rm_mklist; \
+ } else \
+ R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\
+
+#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);}
+
+struct radij_node_head {
+ struct radij_node *rnh_treetop;
+ int rnh_addrsize; /* permit, but not require fixed keys */
+ int rnh_pktsize; /* permit, but not require fixed keys */
+#if 0
+ struct radij_node *(*rnh_addaddr) /* add based on sockaddr */
+ __P((void *v, void *mask,
+ struct radij_node_head *head, struct radij_node nodes[]));
+#endif
+ int (*rnh_addaddr) /* add based on sockaddr */
+ __P((void *v, void *mask,
+ struct radij_node_head *head, struct radij_node nodes[]));
+ struct radij_node *(*rnh_addpkt) /* add based on packet hdr */
+ __P((void *v, void *mask,
+ struct radij_node_head *head, struct radij_node nodes[]));
+#if 0
+ struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */
+ __P((void *v, void *mask, struct radij_node_head *head));
+#endif
+ int (*rnh_deladdr) /* remove based on sockaddr */
+ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node));
+ struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */
+ __P((void *v, void *mask, struct radij_node_head *head));
+ struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */
+ __P((void *v, struct radij_node_head *head));
+ struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */
+ __P((void *v, struct radij_node_head *head));
+ int (*rnh_walktree) /* traverse tree */
+ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
+ struct radij_node rnh_nodes[3]; /* empty tree for common case */
+};
+
+
+#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
+#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
+#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n))
+#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n)))
+#define Free(p) kfree((caddr_t)p);
+
+void rj_init __P((void));
+int rj_inithead __P((void **, int));
+int rj_refines __P((void *, void *));
+int rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
+struct radij_node
+ *rj_addmask __P((void *, int, int)) /* , rgb */ ;
+int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *,
+ struct radij_node [2])) /* , rgb */ ;
+int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ;
+struct radij_node /* rgb */
+ *rj_insert __P((void *, struct radij_node_head *, int *,
+ struct radij_node [2])),
+ *rj_match __P((void *, struct radij_node_head *)),
+ *rj_newpair __P((void *, int, struct radij_node[2])),
+ *rj_search __P((void *, struct radij_node *)),
+ *rj_search_m __P((void *, struct radij_node *, void *));
+
+void rj_deltree(struct radij_node_head *);
+void rj_delnodes(struct radij_node *);
+void rj_free_mkfreelist(void);
+int radijcleartree(void);
+int radijcleanup(void);
+
+extern struct radij_node_head *mask_rjhead;
+extern int maj_keylen;
+#endif /* __KERNEL__ */
+
+#endif /* _RADIJ_H_ */
+
+
+/*
+ * $Log: radij.h,v $
+ * Revision 1.1 2004/03/15 20:35:25 as
+ * added files from freeswan-2.04-x509-1.5.3
+ *
+ * Revision 1.12 2002/04/24 07:36:48 mcr
+ * Moved from ./klips/net/ipsec/radij.h,v
+ *
+ * Revision 1.11 2001/09/20 15:33:00 rgb
+ * Min/max cleanup.
+ *
+ * Revision 1.10 1999/11/18 04:09:20 rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.9 1999/05/05 22:02:33 rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.8 1999/04/29 15:24:58 rgb
+ * Add check for existence of macros min/max.
+ *
+ * Revision 1.7 1999/04/11 00:29:02 henry
+ * GPL boilerplate
+ *
+ * Revision 1.6 1999/04/06 04:54:29 rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+ * patch shell fixes.
+ *
+ * Revision 1.5 1999/01/22 06:30:32 rgb
+ * 64-bit clean-up.
+ *
+ * Revision 1.4 1998/11/30 13:22:55 rgb
+ * Rationalised all the klips kernel file headers. They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.3 1998/10/25 02:43:27 rgb
+ * Change return type on rj_addroute and rj_delete and add and argument
+ * to the latter to be able to transmit more infomation about errors.
+ *
+ * Revision 1.2 1998/07/14 18:09:51 rgb
+ * Add a routine to clear eroute table.
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.1 1998/06/18 21:30:22 henry
+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel
+ * build scripts happier about symlinks
+ *
+ * Revision 1.4 1998/05/25 20:34:16 rgb
+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
+ *
+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
+ * add ipsec_rj_walker_delete.
+ *
+ * Recover memory for eroute table on unload of module.
+ *
+ * Revision 1.3 1998/04/22 16:51:37 rgb
+ * Tidy up radij debug code from recent rash of modifications to debug code.
+ *
+ * Revision 1.2 1998/04/14 17:30:38 rgb
+ * Fix up compiling errors for radij tree memory reclamation.
+ *
+ * Revision 1.1 1998/04/09 03:06:16 henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1 1998/04/08 05:35:04 henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4 1997/01/15 01:28:15 ji
+ * No changes.
+ *
+ * Revision 0.3 1996/11/20 14:44:45 ji
+ * Release update only.
+ *
+ * Revision 0.2 1996/11/02 00:18:33 ji
+ * First limited release.
+ *
+ *
+ */
diff --git a/src/libfreeswan/rangetoa.c b/src/libfreeswan/rangetoa.c
new file mode 100644
index 000000000..e63b432f8
--- /dev/null
+++ b/src/libfreeswan/rangetoa.c
@@ -0,0 +1,61 @@
+/*
+ * convert binary form of address range to ASCII
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: rangetoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - rangetoa - convert address range to ASCII
+ */
+size_t /* space needed for full conversion */
+rangetoa(addrs, format, dst, dstlen)
+struct in_addr addrs[2];
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t len;
+ size_t rest;
+ int n;
+ char *p;
+
+ switch (format) {
+ case 0:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ len = addrtoa(addrs[0], 0, dst, dstlen);
+ if (len < dstlen)
+ for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
+ p++, len++, n--)
+ *p = '.';
+ else
+ p = NULL;
+ if (len < dstlen)
+ rest = dstlen - len;
+ else {
+ if (dstlen > 0)
+ *(dst + dstlen - 1) = '\0';
+ rest = 0;
+ }
+
+ len += addrtoa(addrs[1], 0, p, rest);
+
+ return len;
+}
diff --git a/src/libfreeswan/rangetosubnet.3 b/src/libfreeswan/rangetosubnet.3
new file mode 100644
index 000000000..7d707545e
--- /dev/null
+++ b/src/libfreeswan/rangetosubnet.3
@@ -0,0 +1,59 @@
+.TH IPSEC_RANGETOSUBNET 3 "8 Sept 2000"
+.\" RCSID $Id: rangetosubnet.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec rangetosubnet \- convert address range to subnet
+.SH SYNOPSIS
+.B "#include <freeswan.h>"
+.sp
+.B "const char *rangetosubnet(const ip_address *start,"
+.ti +1c
+.B "const ip_address *stop, ip_subnet *dst);"
+.SH DESCRIPTION
+.I Rangetosubnet
+accepts two IP addresses which define an address range,
+from
+.I start
+to
+.I stop
+inclusive,
+and converts this to a subnet if possible.
+The addresses must both be IPv4 or both be IPv6,
+and the address family of the resulting subnet is the same.
+.PP
+.I Rangetosubnet
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.SH SEE ALSO
+ipsec_initsubnet(3), ipsec_ttosubnet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I rangetosubnet
+are:
+mixed address families;
+unknown address family;
+.I start
+and
+.I stop
+do not define a subnet.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The restriction of error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = rangetosubnet( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/rangetosubnet.c b/src/libfreeswan/rangetosubnet.c
new file mode 100644
index 000000000..048b10556
--- /dev/null
+++ b/src/libfreeswan/rangetosubnet.c
@@ -0,0 +1,226 @@
+/*
+ * express an address range as a subnet (if possible)
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: rangetosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - rangetosubnet - turn an address range into a subnet, if possible
+ *
+ * A range which is a valid subnet will have a network part which is the
+ * same in the from value and the to value, followed by a host part which
+ * is all 0 in the from value and all 1 in the to value.
+ */
+err_t
+rangetosubnet(from, to, dst)
+const ip_address *from;
+const ip_address *to;
+ip_subnet *dst;
+{
+ unsigned const char *fp;
+ unsigned const char *tp;
+ unsigned fb;
+ unsigned tb;
+ unsigned const char *f;
+ unsigned const char *t;
+ size_t n;
+ size_t n2;
+ int i;
+ int nnet;
+ unsigned m;
+
+ if (addrtypeof(from) != addrtypeof(to))
+ return "mismatched address types";
+ n = addrbytesptr(from, &fp);
+ if (n == 0)
+ return "unknown address type";
+ n2 = addrbytesptr(to, &tp);
+ if (n != n2)
+ return "internal size mismatch in rangetosubnet";
+
+ f = fp;
+ t = tp;
+ nnet = 0;
+ for (i = n; i > 0 && *f == *t; i--, f++, t++)
+ nnet += 8;
+ if (i > 0 && !(*f == 0x00 && *t == 0xff)) { /* mid-byte bdry. */
+ fb = *f++;
+ tb = *t++;
+ i--;
+ m = 0x80;
+ while ((fb&m) == (tb&m)) {
+ fb &= ~m;
+ tb |= m;
+ m >>= 1;
+ nnet++;
+ }
+ if (fb != 0x00 || tb != 0xff)
+ return "not a valid subnet";
+ }
+ for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++)
+ continue;
+
+ if (i != 0)
+ return "invalid subnet";
+
+ return initsubnet(from, nnet, 'x', dst);
+}
+
+
+
+#ifdef RANGETOSUBNET_MAIN
+
+#include <stdio.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ ip_address start;
+ ip_address stop;
+ ip_subnet sub;
+ char buf[100];
+ const char *oops;
+ size_t n;
+ int af;
+ int i;
+
+ if (argc == 2 && strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s [-6] start stop\n", argv[0]);
+ fprintf(stderr, " or: %s -r\n", argv[0]);
+ exit(2);
+ }
+
+ af = AF_INET;
+ i = 1;
+ if (strcmp(argv[i], "-6") == 0) {
+ af = AF_INET6;
+ i++;
+ }
+
+ oops = ttoaddr(argv[i], 0, af, &start);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: start conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ oops = ttoaddr(argv[i+1], 0, af, &stop);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: stop conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ oops = rangetosubnet(&start, &stop, &sub);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: rangetosubnet failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ n = subnettot(&sub, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conversion", argv[0]);
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ int family;
+ char *start;
+ char *stop;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {4, "1.2.3.0", "1.2.3.255", "1.2.3.0/24"},
+ {4, "1.2.3.0", "1.2.3.7", "1.2.3.0/29"},
+ {4, "1.2.3.240", "1.2.3.255", "1.2.3.240/28"},
+ {4, "0.0.0.0", "255.255.255.255", "0.0.0.0/0"},
+ {4, "1.2.3.4", "1.2.3.4", "1.2.3.4/32"},
+ {4, "1.2.3.0", "1.2.3.254", NULL},
+ {4, "1.2.3.0", "1.2.3.126", NULL},
+ {4, "1.2.3.0", "1.2.3.125", NULL},
+ {4, "1.2.0.0", "1.2.255.255", "1.2.0.0/16"},
+ {4, "1.2.0.0", "1.2.0.255", "1.2.0.0/24"},
+ {4, "1.2.255.0", "1.2.255.255", "1.2.255.0/24"},
+ {4, "1.2.255.0", "1.2.254.255", NULL},
+ {4, "1.2.255.1", "1.2.255.255", NULL},
+ {4, "1.2.0.1", "1.2.255.255", NULL},
+ {6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:ffff", "1:2:3:4:5:6:7:0/112"},
+ {6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:fff", "1:2:3:4:5:6:7:0/116"},
+ {6, "1:2:3:4:5:6:7:f0", "1:2:3:4:5:6:7:ff", "1:2:3:4:5:6:7:f0/124"},
+ {4, NULL, NULL, NULL},
+};
+
+void
+regress()
+{
+ struct rtab *r;
+ int status = 0;
+ ip_address start;
+ ip_address stop;
+ ip_subnet sub;
+ char buf[100];
+ const char *oops;
+ size_t n;
+ int af;
+
+ for (r = rtab; r->start != NULL; r++) {
+ af = (r->family == 4) ? AF_INET : AF_INET6;
+ oops = ttoaddr(r->start, 0, af, &start);
+ if (oops != NULL) {
+ printf("surprise failure converting `%s'\n", r->start);
+ exit(1);
+ }
+ oops = ttoaddr(r->stop, 0, af, &stop);
+ if (oops != NULL) {
+ printf("surprise failure converting `%s'\n", r->stop);
+ exit(1);
+ }
+ oops = rangetosubnet(&start, &stop, &sub);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s'-`%s' rangetosubnet failed: %s\n",
+ r->start, r->stop, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s'-`%s' rangetosubnet succeeded unexpectedly\n",
+ r->start, r->stop);
+ status = 1;
+ } else {
+ n = subnettot(&sub, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ printf("`%s'-`%s' subnettot failed: need %ld\n",
+ r->start, r->stop, (long)n);
+ status = 1;
+ } else if (strcmp(r->output, buf) != 0) {
+ printf("`%s'-`%s' gave `%s', expected `%s'\n",
+ r->start, r->stop, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* RANGETOSUBNET_MAIN */
diff --git a/src/libfreeswan/sameaddr.3 b/src/libfreeswan/sameaddr.3
new file mode 100644
index 000000000..71be10761
--- /dev/null
+++ b/src/libfreeswan/sameaddr.3
@@ -0,0 +1,165 @@
+.TH IPSEC_ANYADDR 3 "28 Nov 2000"
+.\" RCSID $Id: sameaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec sameaddr \- are two addresses the same?
+.br
+ipsec addrcmp \- ordered comparison of addresses
+.br
+ipsec samesubnet \- are two subnets the same?
+.br
+ipsec addrinsubnet \- is an address within a subnet?
+.br
+ipsec subnetinsubnet \- is a subnet within another subnet?
+.br
+ipsec subnetishost \- is a subnet a single host?
+.br
+ipsec samesaid \- are two SA IDs the same?
+.br
+ipsec sameaddrtype \- are two addresses of the same address family?
+.br
+ipsec samesubnettype \- are two subnets of the same address family?
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "int sameaddr(const ip_address *a, const ip_address *b);"
+.br
+.B "int addrcmp(const ip_address *a, const ip_address *b);"
+.br
+.B "int samesubnet(const ip_subnet *a, const ip_subnet *b);"
+.br
+.B "int addrinsubnet(const ip_address *a, const ip_subnet *s);"
+.br
+.B "int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);"
+.br
+.B "int subnetishost(const ip_subnet *s);"
+.br
+.B "int samesaid(const ip_said *a, const ip_said *b);"
+.br
+.B "int sameaddrtype(const ip_address *a, const ip_address *b);"
+.br
+.B "int samesubnettype(const ip_subnet *a, const ip_subnet *b);"
+.SH DESCRIPTION
+These functions do various comparisons and tests on the
+.I ip_address
+type and
+.I ip_subnet
+types.
+.PP
+.I Sameaddr
+returns
+non-zero
+if addresses
+.I a
+and
+.IR b
+are identical,
+and
+.B 0
+otherwise.
+Addresses of different families are never identical.
+.PP
+.I Addrcmp
+returns
+.BR \-1 ,
+.BR 0 ,
+or
+.BR 1
+respectively
+if address
+.I a
+is less than, equal to, or greater than
+.IR b .
+If they are not of the same address family,
+they are never equal;
+the ordering reported in this case is arbitrary
+(and probably not useful) but consistent.
+.PP
+.I Samesubnet
+returns
+non-zero
+if subnets
+.I a
+and
+.IR b
+are identical,
+and
+.B 0
+otherwise.
+Subnets of different address families are never identical.
+.PP
+.I Addrinsubnet
+returns
+non-zero
+if address
+.I a
+is within subnet
+.IR s
+and
+.B 0
+otherwise.
+An address is never within a
+subnet of a different address family.
+.PP
+.I Subnetinsubnet
+returns
+non-zero
+if subnet
+.I a
+is a subset of subnet
+.IR b
+and
+.B 0
+otherwise.
+A subnet is deemed to be a subset of itself.
+A subnet is never a subset of another
+subnet if their address families differ.
+.PP
+.I Subnetishost
+returns
+non-zero
+if subnet
+.I s
+is in fact only a single host,
+and
+.B 0
+otherwise.
+.PP
+.I Samesaid
+returns
+non-zero
+if SA IDs
+.I a
+and
+.IR b
+are identical,
+and
+.B 0
+otherwise.
+.PP
+.I Sameaddrtype
+returns
+non-zero
+if addresses
+.I a
+and
+.IR b
+are of the same address family,
+and
+.B 0
+otherwise.
+.PP
+.I Samesubnettype
+returns
+non-zero
+if subnets
+.I a
+and
+.IR b
+are of the same address family,
+and
+.B 0
+otherwise.
+.SH SEE ALSO
+inet(3), ipsec_initaddr(3)
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/sameaddr.c b/src/libfreeswan/sameaddr.c
new file mode 100644
index 000000000..efc40796e
--- /dev/null
+++ b/src/libfreeswan/sameaddr.c
@@ -0,0 +1,190 @@
+/*
+ * comparisons
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: sameaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static int samenbits(const ip_address *a, const ip_address *b, int n);
+
+/*
+ - addrcmp - compare two addresses
+ * Caution, the order of the tests is subtle: doing type test before
+ * size test can yield cases where a<b, b<c, but a>c.
+ */
+int /* like memcmp */
+addrcmp(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+ int at = addrtypeof(a);
+ int bt = addrtypeof(b);
+ const unsigned char *ap;
+ const unsigned char *bp;
+ size_t as = addrbytesptr(a, &ap);
+ size_t bs = addrbytesptr(b, &bp);
+ size_t n = (as < bs) ? as : bs; /* min(as, bs) */
+ int c = memcmp(ap, bp, n);
+
+ if (c != 0) /* bytes differ */
+ return (c < 0) ? -1 : 1;
+ if (as != bs) /* comparison incomplete: lexical order */
+ return (as < bs) ? -1 : 1;
+ if (at != bt) /* bytes same but not same type: break tie */
+ return (at < bt) ? -1 : 1;
+ return 0;
+}
+
+/*
+ - sameaddr - are two addresses the same?
+ */
+int
+sameaddr(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+ return (addrcmp(a, b) == 0) ? 1 : 0;
+}
+
+/*
+ - samesubnet - are two subnets the same?
+ */
+int
+samesubnet(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+ if (!sameaddr(&a->addr, &b->addr)) /* also does type check */
+ return 0;
+ if (a->maskbits != b->maskbits)
+ return 0;
+ return 1;
+}
+
+/*
+ - subnetishost - is a subnet in fact a single host?
+ */
+int
+subnetishost(a)
+const ip_subnet *a;
+{
+ return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
+}
+
+/*
+ - samesaid - are two SA IDs the same?
+ */
+int
+samesaid(a, b)
+const ip_said *a;
+const ip_said *b;
+{
+ if (a->spi != b->spi) /* test first, most likely to be different */
+ return 0;
+ if (!sameaddr(&a->dst, &b->dst))
+ return 0;
+ if (a->proto != b->proto)
+ return 0;
+ return 1;
+}
+
+/*
+ - sameaddrtype - do two addresses have the same type?
+ */
+int
+sameaddrtype(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+ return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
+}
+
+/*
+ - samesubnettype - do two subnets have the same type?
+ */
+int
+samesubnettype(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+ return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
+}
+
+/*
+ - addrinsubnet - is this address in this subnet?
+ */
+int
+addrinsubnet(a, s)
+const ip_address *a;
+const ip_subnet *s;
+{
+ if (addrtypeof(a) != subnettypeof(s))
+ return 0;
+ if (!samenbits(a, &s->addr, s->maskbits))
+ return 0;
+ return 1;
+}
+
+/*
+ - subnetinsubnet - is one subnet within another?
+ */
+int
+subnetinsubnet(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+ if (subnettypeof(a) != subnettypeof(b))
+ return 0;
+ if (a->maskbits < b->maskbits) /* a is bigger than b */
+ return 0;
+ if (!samenbits(&a->addr, &b->addr, b->maskbits))
+ return 0;
+ return 1;
+}
+
+/*
+ - samenbits - do two addresses have the same first n bits?
+ */
+static int
+samenbits(a, b, nbits)
+const ip_address *a;
+const ip_address *b;
+int nbits;
+{
+ const unsigned char *ap;
+ const unsigned char *bp;
+ size_t n;
+ int m;
+
+ if (addrtypeof(a) != addrtypeof(b))
+ return 0; /* arbitrary */
+ n = addrbytesptr(a, &ap);
+ if (n == 0)
+ return 0; /* arbitrary */
+ (void) addrbytesptr(b, &bp);
+ if (nbits > n*8)
+ return 0; /* "can't happen" */
+
+ for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
+ continue;
+ if (nbits >= 8)
+ return 0;
+ if (nbits > 0) { /* partial byte */
+ m = ~(0xff >> nbits);
+ if ((*ap & m) != (*bp & m))
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/libfreeswan/satoa.c b/src/libfreeswan/satoa.c
new file mode 100644
index 000000000..410fb8437
--- /dev/null
+++ b/src/libfreeswan/satoa.c
@@ -0,0 +1,102 @@
+/*
+ * convert from binary form of SA ID to ASCII
+ * Copyright (C) 1998, 1999, 2001 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: satoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct typename {
+ char type;
+ char *name;
+} typenames[] = {
+ { SA_AH, "ah" },
+ { SA_ESP, "esp" },
+ { SA_IPIP, "tun" },
+ { SA_COMP, "comp" },
+ { SA_INT, "int" },
+ { 0, NULL }
+};
+
+/*
+ - satoa - convert SA to ASCII "ah507@1.2.3.4"
+ */
+size_t /* space needed for full conversion */
+satoa(sa, format, dst, dstlen)
+struct sa_id sa;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t len = 0; /* 0 means not handled yet */
+ int base;
+ struct typename *tn;
+ char buf[30+ADDRTOA_BUF];
+
+ switch (format) {
+ case 0:
+ base = 16; /* temporarily at least */
+ break;
+ case 'd':
+ base = 10;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ for (tn = typenames; tn->name != NULL; tn++)
+ if (sa.proto == tn->type)
+ break;
+ if (tn->name == NULL)
+ return 0;
+
+ if (strcmp(tn->name, PASSTHROUGHTYPE) == 0 &&
+ sa.spi == PASSTHROUGHSPI &&
+ sa.dst.s_addr == PASSTHROUGHDST) {
+ strcpy(buf, PASSTHROUGHNAME);
+ len = strlen(buf);
+ } else if (sa.proto == SA_INT && sa.dst.s_addr == 0) {
+ char *p;
+
+ switch (ntohl(sa.spi)) {
+ case SPI_PASS: p = "%pass"; break;
+ case SPI_DROP: p = "%drop"; break;
+ case SPI_REJECT: p = "%reject"; break;
+ case SPI_HOLD: p = "%hold"; break;
+ case SPI_TRAP: p = "%trap"; break;
+ case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
+ default: p = NULL; break;
+ }
+ if (p != NULL) {
+ strcpy(buf, p);
+ len = strlen(buf);
+ }
+ }
+
+ if (len == 0) {
+ strcpy(buf, tn->name);
+ len = strlen(buf);
+ len += ultoa(ntohl(sa.spi), base, buf+len, sizeof(buf)-len);
+ *(buf+len-1) = '@';
+ len += addrtoa(sa.dst, 0, buf+len, sizeof(buf)-len);
+ }
+
+ if (dst != NULL) {
+ if (len > dstlen)
+ *(buf+dstlen-1) = '\0';
+ strcpy(dst, buf);
+ }
+ return len;
+}
diff --git a/src/libfreeswan/satot.c b/src/libfreeswan/satot.c
new file mode 100644
index 000000000..927f4ca1f
--- /dev/null
+++ b/src/libfreeswan/satot.c
@@ -0,0 +1,132 @@
+/*
+ * convert from binary form of SA ID to text
+ * Copyright (C) 2000, 2001 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: satot.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct typename {
+ char type;
+ char *name;
+} typenames[] = {
+ { SA_AH, "ah" },
+ { SA_ESP, "esp" },
+ { SA_IPIP, "tun" },
+ { SA_COMP, "comp" },
+ { SA_INT, "int" },
+ { 0, NULL }
+};
+
+/*
+ - satot - convert SA to text "ah507@1.2.3.4"
+ */
+size_t /* space needed for full conversion */
+satot(sa, format, dst, dstlen)
+const ip_said *sa;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t len = 0; /* 0 means "not recognized yet" */
+ int base;
+ int showversion; /* use delimiter to show IP version? */
+ struct typename *tn;
+ char *p;
+ char *pre;
+ char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
+ char unk[10];
+
+ switch (format) {
+ case 0:
+ base = 16;
+ showversion = 1;
+ break;
+ case 'f':
+ base = 17;
+ showversion = 1;
+ break;
+ case 'x':
+ base = 'x';
+ showversion = 0;
+ break;
+ case 'd':
+ base = 10;
+ showversion = 0;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ pre = NULL;
+ for (tn = typenames; tn->name != NULL; tn++)
+ if (sa->proto == tn->type) {
+ pre = tn->name;
+ break; /* NOTE BREAK OUT */
+ }
+ if (pre == NULL) { /* unknown protocol */
+ strcpy(unk, "unk");
+ (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
+ sizeof(unk)-strlen(unk));
+ pre = unk;
+ }
+
+ if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
+ sa->spi == PASSTHROUGHSPI &&
+ isunspecaddr(&sa->dst)) {
+ strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
+ PASSTHROUGH4NAME :
+ PASSTHROUGH6NAME);
+ len = strlen(buf);
+ }
+
+ if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
+ isunspecaddr(&sa->dst)) {
+ switch (ntohl(sa->spi)) {
+ case SPI_PASS: p = "%pass"; break;
+ case SPI_DROP: p = "%drop"; break;
+ case SPI_REJECT: p = "%reject"; break;
+ case SPI_HOLD: p = "%hold"; break;
+ case SPI_TRAP: p = "%trap"; break;
+ case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
+ default: p = NULL; break;
+ }
+ if (p != NULL) {
+ strcpy(buf, p);
+ len = strlen(buf);
+ }
+ }
+
+ if (len == 0) { /* general case needed */
+ strcpy(buf, pre);
+ len = strlen(buf);
+ if (showversion) {
+ *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
+ ':';
+ len++;
+ *(buf+len) = '\0';
+ }
+ len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
+ *(buf+len-1) = '@';
+ len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
+ }
+
+ if (dst != NULL) {
+ if (len > dstlen)
+ *(buf+dstlen-1) = '\0';
+ strcpy(dst, buf);
+ }
+ return len;
+}
diff --git a/src/libfreeswan/subnetof.3 b/src/libfreeswan/subnetof.3
new file mode 100644
index 000000000..1911e499f
--- /dev/null
+++ b/src/libfreeswan/subnetof.3
@@ -0,0 +1,47 @@
+.TH IPSEC_SUBNETOF 3 "11 June 2001"
+.\" RCSID $Id: subnetof.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec subnetof \- given Internet address and subnet mask, return subnet number
+.br
+ipsec hostof \- given Internet address and subnet mask, return host part
+.br
+ipsec broadcastof \- given Internet address and subnet mask, return broadcast address
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "struct in_addr subnetof(struct in_addr addr,"
+.ti +1c
+.B "struct in_addr mask);"
+.br
+.B "struct in_addr hostof(struct in_addr addr,"
+.ti +1c
+.B "struct in_addr mask);"
+.br
+.B "struct in_addr broadcastof(struct in_addr addr,"
+.ti +1c
+.B "struct in_addr mask);"
+.SH DESCRIPTION
+These functions are obsolete; see
+.IR ipsec_networkof (3)
+for their replacements.
+.PP
+.I Subnetof
+takes an Internet
+.I address
+and a subnet
+.I mask
+and returns the network part of the address
+(all in network byte order).
+.I Hostof
+similarly returns the host part, and
+.I broadcastof
+returns the broadcast address (all-1s convention) for the network.
+.PP
+These functions are provided to hide the Internet bit-munging inside
+an API, in hopes of easing the eventual transition to IPv6.
+.SH SEE ALSO
+inet(3), ipsec_atosubnet(3)
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+Calling functions for this is more costly than doing it yourself.
diff --git a/src/libfreeswan/subnetof.c b/src/libfreeswan/subnetof.c
new file mode 100644
index 000000000..1b288c591
--- /dev/null
+++ b/src/libfreeswan/subnetof.c
@@ -0,0 +1,60 @@
+/*
+ * minor network-address manipulation utilities
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: subnetof.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnetof - given address and mask, return subnet part
+ */
+struct in_addr
+subnetof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+ struct in_addr result;
+
+ result.s_addr = addr.s_addr & mask.s_addr;
+ return result;
+}
+
+/*
+ - hostof - given address and mask, return host part
+ */
+struct in_addr
+hostof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+ struct in_addr result;
+
+ result.s_addr = addr.s_addr & ~mask.s_addr;
+ return result;
+}
+
+/*
+ - broadcastof - given (network) address and mask, return broadcast address
+ */
+struct in_addr
+broadcastof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+ struct in_addr result;
+
+ result.s_addr = addr.s_addr | ~mask.s_addr;
+ return result;
+}
diff --git a/src/libfreeswan/subnettoa.c b/src/libfreeswan/subnettoa.c
new file mode 100644
index 000000000..36cad8b88
--- /dev/null
+++ b/src/libfreeswan/subnettoa.c
@@ -0,0 +1,62 @@
+/*
+ * convert binary form of subnet description to ASCII
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: subnettoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettoa - convert address and mask to ASCII "addr/mask"
+ * Output expresses the mask as a bit count if possible, else dotted decimal.
+ */
+size_t /* space needed for full conversion */
+subnettoa(addr, mask, format, dst, dstlen)
+struct in_addr addr;
+struct in_addr mask;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t len;
+ size_t rest;
+ int n;
+ char *p;
+
+ switch (format) {
+ case 0:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ len = addrtoa(addr, 0, dst, dstlen);
+ if (len < dstlen) {
+ dst[len - 1] = '/';
+ p = dst + len;
+ rest = dstlen - len;
+ } else {
+ p = NULL;
+ rest = 0;
+ }
+
+ n = masktobits(mask);
+ if (n >= 0)
+ len += ultoa((unsigned long)n, 10, p, rest);
+ else
+ len += addrtoa(mask, 0, p, rest);
+
+ return len;
+}
diff --git a/src/libfreeswan/subnettot.c b/src/libfreeswan/subnettot.c
new file mode 100644
index 000000000..0385d25e5
--- /dev/null
+++ b/src/libfreeswan/subnettot.c
@@ -0,0 +1,56 @@
+/*
+ * convert binary form of subnet description to text
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: subnettot.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettot - convert subnet to text "addr/bitcount"
+ */
+size_t /* space needed for full conversion */
+subnettot(sub, format, dst, dstlen)
+const ip_subnet *sub;
+int format; /* character */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ size_t len;
+ size_t rest;
+ char *p;
+
+ switch (format) {
+ case 0:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ len = addrtot(&sub->addr, format, dst, dstlen);
+ if (len < dstlen) {
+ dst[len - 1] = '/';
+ p = dst + len;
+ rest = dstlen - len;
+ } else {
+ p = NULL;
+ rest = 0;
+ }
+
+
+ len += ultoa((unsigned long)sub->maskbits, 10, p, rest);
+
+ return len;
+}
diff --git a/src/libfreeswan/subnettypeof.c b/src/libfreeswan/subnettypeof.c
new file mode 100644
index 000000000..6f44b2e4b
--- /dev/null
+++ b/src/libfreeswan/subnettypeof.c
@@ -0,0 +1,109 @@
+/*
+ * extract parts of an ip_subnet, and related
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: subnettypeof.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettypeof - get the address type of an ip_subnet
+ */
+int
+subnettypeof(src)
+const ip_subnet *src;
+{
+ return src->addr.u.v4.sin_family;
+}
+
+/*
+ - networkof - get the network address of a subnet
+ */
+void
+networkof(src, dst)
+const ip_subnet *src;
+ip_address *dst;
+{
+ *dst = src->addr;
+}
+
+/*
+ - maskof - get the mask of a subnet, as an address
+ */
+void
+maskof(src, dst)
+const ip_subnet *src;
+ip_address *dst;
+{
+ int b;
+ unsigned char buf[16];
+ size_t n = addrlenof(&src->addr);
+ unsigned char *p;
+
+ if (src->maskbits > n*8 || n > sizeof(buf))
+ return; /* "can't happen" */
+
+ p = buf;
+ for (b = src->maskbits; b >= 8; b -= 8)
+ *p++ = 0xff;
+ if (b != 0)
+ *p++ = (0xff << (8 - b)) & 0xff;
+ while (p - buf < n)
+ *p++ = 0;
+
+ (void) initaddr(buf, n, addrtypeof(&src->addr), dst);
+}
+
+/*
+ - masktocount - convert a mask, expressed as an address, to a bit count
+ */
+int /* -1 if not valid mask */
+masktocount(src)
+const ip_address *src;
+{
+ int b;
+ unsigned const char *bp;
+ size_t n;
+ unsigned const char *p;
+ unsigned const char *stop;
+
+ n = addrbytesptr(src, &bp);
+ if (n == 0)
+ return -1;
+
+ p = bp;
+ stop = bp + n;
+
+ n = 0;
+ while (p < stop && *p == 0xff) {
+ p++;
+ n += 8;
+ }
+ if (p < stop && *p != 0) { /* boundary in mid-byte */
+ b = *p++;
+ while (b&0x80) {
+ b <<= 1;
+ n++;
+ }
+ if ((b&0xff) != 0)
+ return -1; /* bits not contiguous */
+ }
+ while (p < stop && *p == 0)
+ p++;
+
+ if (p != stop)
+ return -1;
+
+ return n;
+}
diff --git a/src/libfreeswan/ttoaddr.3 b/src/libfreeswan/ttoaddr.3
new file mode 100644
index 000000000..5bf48d4b2
--- /dev/null
+++ b/src/libfreeswan/ttoaddr.3
@@ -0,0 +1,377 @@
+.TH IPSEC_TTOADDR 3 "28 Sept 2001"
+.\" RCSID $Id: ttoaddr.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec ttoaddr, tnatoaddr, addrtot \- convert Internet addresses to and from text
+.br
+ipsec ttosubnet, subnettot \- convert subnet/mask text form to and from addresses
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *ttoaddr(const char *src, size_t srclen,"
+.ti +1c
+.B "int af, ip_address *addr);"
+.br
+.B "const char *tnatoaddr(const char *src, size_t srclen,"
+.ti +1c
+.B "int af, ip_address *addr);"
+.br
+.B "size_t addrtot(const ip_address *addr, int format,"
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.sp
+.B "const char *ttosubnet(const char *src, size_t srclen,"
+.ti +1c
+.B "int af, ip_subnet *dst);"
+.br
+.B "size_t subnettot(const ip_subnet *sub, int format,"
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.SH DESCRIPTION
+.I Ttoaddr
+converts a text-string name or numeric address into a binary address
+(in network byte order).
+.I Tnatoaddr
+does the same conversion,
+but the only text forms it accepts are
+the ``official'' forms of
+numeric address (dotted-decimal for IPv4, colon-hex for IPv6).
+.I Addrtot
+does the reverse conversion, from binary address back to a text form.
+.I Ttosubnet
+and
+.I subnettot
+do likewise for the ``address/mask'' form used to write a
+specification of a subnet.
+.PP
+An IPv4 address is specified in text as a
+dotted-decimal address (e.g.
+.BR 1.2.3.4 ),
+an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
+.BR 0x01020304 ,
+which is synonymous with
+.BR 1.2.3.4 ),
+an eight-digit host-order hexadecimal number with a
+.B 0h
+prefix (e.g.
+.BR 0h01020304 ,
+which is synonymous with
+.B 1.2.3.4
+on a big-endian host and
+.B 4.3.2.1
+on a little-endian host),
+a DNS name to be looked up via
+.IR gethostbyname (3),
+or an old-style network name to be looked up via
+.IR getnetbyname (3).
+.PP
+A dotted-decimal address may be incomplete, in which case
+text-to-binary conversion implicitly appends
+as many instances of
+.B .0
+as necessary to bring it up to four components.
+The components of a dotted-decimal address are always taken as
+decimal, and leading zeros are ignored.
+For example,
+.B 10
+is synonymous with
+.BR 10.0.0.0 ,
+and
+.B 128.009.000.032
+is synonymous with
+.BR 128.9.0.32
+(the latter example is verbatim from RFC 1166).
+The result of applying
+.I addrtot
+to an IPv4 address is always complete and does not contain leading zeros.
+.PP
+Use of hexadecimal addresses is
+.B strongly
+.BR discouraged ;
+they are included only to save hassles when dealing with
+the handful of perverted programs which already print
+network addresses in hexadecimal.
+.PP
+An IPv6 address is specified in text with
+colon-hex notation (e.g.
+.BR 0:56:78ab:22:33:44:55:66 ),
+colon-hex with
+.B ::
+abbreviating at most one subsequence of multiple zeros (e.g.
+.BR 99:ab::54:068 ,
+which is synonymous with
+.BR 99:ab:0:0:0:0:54:68 ),
+or a DNS name to be looked up via
+.IR gethostbyname (3).
+The result of applying
+.I addrtot
+to an IPv6 address will use
+.B ::
+abbreviation if possible,
+and will not contain leading zeros.
+.PP
+The letters in hexadecimal
+may be uppercase or lowercase or any mixture thereof.
+.PP
+DNS names may be complete (optionally terminated with a ``.'')
+or incomplete, and are looked up as specified by local system configuration
+(see
+.IR resolver (5)).
+The
+.I h_addr
+value returned by
+.IR gethostbyname2 (3)
+is used,
+so with current DNS implementations,
+the result when the name corresponds to more than one address is
+difficult to predict.
+IPv4 name lookup resorts to
+.IR getnetbyname (3)
+only if
+.IR gethostbyname2 (3)
+fails.
+.PP
+A subnet specification is of the form \fInetwork\fB/\fImask\fR.
+The
+.I network
+and
+.I mask
+can be any form acceptable to
+.IR ttoaddr .
+In addition, and preferably, the
+.I mask
+can be a decimal integer (leading zeros ignored) giving a bit count,
+in which case
+it stands for a mask with that number of high bits on and all others off
+(e.g.,
+.B 24
+in IPv4 means
+.BR 255.255.255.0 ).
+In any case, the mask must be contiguous
+(a sequence of high bits on and all remaining low bits off).
+As a special case, the subnet specification
+.B %default
+is a synonym for
+.B 0.0.0.0/0
+or
+.B ::/0
+in IPv4 or IPv6 respectively.
+.PP
+.I Ttosubnet
+ANDs the mask with the address before returning,
+so that any non-network bits in the address are turned off
+(e.g.,
+.B 10.1.2.3/24
+is synonymous with
+.BR 10.1.2.0/24 ).
+.I Subnettot
+always generates the decimal-integer-bit-count
+form of the mask,
+with no leading zeros.
+.PP
+The
+.I srclen
+parameter of
+.I ttoaddr
+and
+.I ttosubnet
+specifies the length of the text string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I af
+parameter of
+.I ttoaddr
+and
+.I ttosubnet
+specifies the address family of interest.
+It should be either
+.B AF_INET
+or
+.BR AF_INET6 .
+.PP
+The
+.I dstlen
+parameter of
+.I addrtot
+and
+.I subnettot
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines constants,
+.B ADDRTOT_BUF
+and
+.BR SUBNETTOT_BUF ,
+which are the sizes of buffers just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I addrtot
+and
+.I subnettot
+specifies what format is to be used for the conversion.
+The value
+.B 0
+(not the character
+.BR '0' ,
+but a zero value)
+specifies a reasonable default,
+and is in fact the only format currently available in
+.IR subnettot .
+.I Addrtot
+also accepts format values
+.B 'r'
+(signifying a text form suitable for DNS reverse lookups,
+e.g.
+.B 4.3.2.1.IN-ADDR.ARPA.
+for IPv4 and
+RFC 2874 format for IPv6),
+and
+.B 'R'
+(signifying an alternate reverse-lookup form,
+an error for IPv4 and RFC 1886 format for IPv6).
+Reverse-lookup names always end with a ``.''.
+.PP
+The text-to-binary functions return NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+The binary-to-text functions return
+.B 0
+for a failure, and otherwise
+always return the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.SH SEE ALSO
+inet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I ttoaddr
+are:
+empty input;
+unknown address family;
+attempt to allocate temporary storage for a very long name failed;
+name lookup failed;
+syntax error in dotted-decimal or colon-hex form;
+dotted-decimal or colon-hex component too large.
+.PP
+Fatal errors in
+.I ttosubnet
+are:
+no
+.B /
+in
+.IR src ;
+.I ttoaddr
+error in conversion of
+.I network
+or
+.IR mask ;
+bit-count mask too big;
+mask non-contiguous.
+.PP
+Fatal errors in
+.I addrtot
+and
+.I subnettot
+are:
+unknown format.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The interpretation of incomplete dotted-decimal addresses
+(e.g.
+.B 10/24
+means
+.BR 10.0.0.0/24 )
+differs from that of some older conversion
+functions, e.g. those of
+.IR inet (3).
+The behavior of the older functions has never been
+particularly consistent or particularly useful.
+.PP
+Ignoring leading zeros in dotted-decimal components and bit counts
+is arguably the most useful behavior in this application,
+but it might occasionally cause confusion with the historical use of leading
+zeros to denote octal numbers.
+.PP
+.I Ttoaddr
+does not support the mixed colon-hex-dotted-decimal
+convention used to embed an IPv4 address in an IPv6 address.
+.PP
+.I Addrtot
+always uses the
+.B ::
+abbreviation (which can appear only once in an address) for the
+.I first
+sequence of multiple zeros in an IPv6 address.
+One can construct addresses (unlikely ones) in which this is suboptimal.
+.PP
+.I Addrtot
+.B 'r'
+conversion of an IPv6 address uses lowercase hexadecimal,
+not the uppercase used in RFC 2874's examples.
+It takes careful reading of RFCs 2874, 2673, and 2234 to realize
+that lowercase is technically legitimate here,
+and there may be software which botches this
+and hence would have trouble with lowercase hex.
+.PP
+Possibly
+.I subnettot
+ought to recognize the
+.B %default
+case and generate that string as its output.
+Currently it doesn't.
+.PP
+It is barely possible that somebody, somewhere,
+might have a legitimate use for non-contiguous subnet masks.
+.PP
+.IR Getnetbyname (3)
+is a historical dreg.
+.PP
+.I Tnatoaddr
+probably should enforce completeness of dotted-decimal addresses.
+.PP
+The restriction of text-to-binary error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The text-to-binary error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = ttoaddr( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/ttoaddr.c b/src/libfreeswan/ttoaddr.c
new file mode 100644
index 000000000..efcb33e9f
--- /dev/null
+++ b/src/libfreeswan/ttoaddr.c
@@ -0,0 +1,426 @@
+/*
+ * conversion from text forms of addresses to internal ones
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ttoaddr.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * Legal ASCII characters in a domain name. Underscore technically is not,
+ * but is a common misunderstanding. Non-ASCII characters are simply
+ * exempted from checking at the moment, to allow for UTF-8 encoded stuff;
+ * the purpose of this check is merely to catch blatant errors.
+ */
+static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
+#define ISASCII(c) (((c) & 0x80) == 0)
+
+static err_t tryname(const char *, size_t, int, int, ip_address *);
+static err_t tryhex(const char *, size_t, int, ip_address *);
+static err_t trydotted(const char *, size_t, ip_address *);
+static err_t getbyte(const char **, const char *, int *);
+static err_t colon(const char *, size_t, ip_address *);
+static err_t getpiece(const char **, const char *, unsigned *);
+
+/*
+ - ttoaddr - convert text name or dotted-decimal address to binary address
+ */
+err_t /* NULL for success, else string literal */
+ttoaddr(src, srclen, af, dst)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+int af; /* address family */
+ip_address *dst;
+{
+ err_t oops;
+# define HEXLEN 10 /* strlen("0x11223344") */
+ int nultermd;
+
+ if (srclen == 0) {
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+ nultermd = 1;
+ } else
+ nultermd = 0; /* at least, not *known* to be terminated */
+
+ switch (af) {
+ case AF_INET:
+ case AF_INET6:
+ case 0: /* guess */
+ break;
+
+ default:
+ return "invalid address family";
+ }
+
+ if (af == AF_INET && srclen == HEXLEN && *src == '0') {
+ if (*(src+1) == 'x' || *(src+1) == 'X')
+ return tryhex(src+2, srclen-2, 'x', dst);
+ if (*(src+1) == 'h' || *(src+1) == 'H')
+ return tryhex(src+2, srclen-2, 'h', dst);
+ }
+
+ if (memchr(src, ':', srclen) != NULL) {
+ if(af == 0)
+ {
+ af = AF_INET6;
+ }
+
+ if (af != AF_INET6)
+ return "non-ipv6 address may not contain `:'";
+ return colon(src, srclen, dst);
+ }
+
+ if (af == 0 || af == AF_INET) {
+ oops = trydotted(src, srclen, dst);
+ if (oops == NULL)
+ return NULL; /* it worked */
+ if (*oops != '?')
+ return oops; /* probably meant as d-d */
+ }
+
+ return tryname(src, srclen, nultermd, af, dst);
+}
+
+/*
+ - tnatoaddr - convert text numeric address (only) to binary address
+ */
+err_t /* NULL for success, else string literal */
+tnatoaddr(src, srclen, af, dst)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+int af; /* address family */
+ip_address *dst;
+{
+ err_t oops;
+
+ if (srclen == 0) {
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+ }
+
+ switch (af) {
+ case 0: /* guess */
+ oops = colon(src, srclen, dst);
+ if(oops == NULL)
+ {
+ return NULL;
+ }
+ oops = trydotted(src, srclen, dst);
+ if(oops == NULL)
+ {
+ return NULL;
+ }
+ return "does not appear to be either IPv4 or IPv6 numeric address";
+ break;
+
+ case AF_INET6:
+ return colon(src, srclen, dst);
+ break;
+ case AF_INET:
+ oops = trydotted(src, srclen, dst);
+ if (oops == NULL)
+ return NULL; /* it worked */
+ if (*oops != '?')
+ return oops; /* probably meant as d-d */
+ return "does not appear to be numeric address";
+ break;
+ default:
+ return "unknown address family in tnatoaddr";
+ break;
+ }
+}
+
+/*
+ - tryname - try it as a name
+ * Slightly complicated by lack of reliable NUL termination in source.
+ */
+static err_t
+tryname(src, srclen, nultermd, af, dst)
+const char *src;
+size_t srclen;
+int nultermd; /* is it known to be NUL-terminated? */
+int af;
+ip_address *dst;
+{
+ struct hostent *h;
+ struct netent *ne = NULL;
+ char namebuf[100]; /* enough for most DNS names */
+ const char *cp;
+ char *p = namebuf;
+ size_t n;
+
+ for (cp = src, n = srclen; n > 0; cp++, n--)
+ if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)
+ return "illegal (non-DNS-name) character in name";
+
+ if (nultermd)
+ cp = src;
+ else {
+ if (srclen+1 > sizeof(namebuf)) {
+ p = (char *) MALLOC(srclen+1);
+ if (p == NULL)
+ return "unable to get temporary space for name";
+ }
+ p[0] = '\0'; /* strncpy semantics are wrong */
+ strncat(p, src, srclen);
+ cp = (const char *)p;
+ }
+
+ h = gethostbyname2(cp, af);
+ if (h == NULL && af == AF_INET)
+ ne = getnetbyname(cp);
+ if (p != namebuf)
+ FREE(p);
+ if (h == NULL && ne == NULL)
+ return "does not look numeric and name lookup failed";
+
+ if (h != NULL) {
+ if (h->h_addrtype != af)
+ return "address-type mismatch from gethostbyname2!!!";
+ return initaddr((unsigned char *)h->h_addr, h->h_length, af, dst);
+ } else {
+ if (ne->n_addrtype != af)
+ return "address-type mismatch from getnetbyname!!!";
+ ne->n_net = htonl(ne->n_net);
+ return initaddr((unsigned char *)&ne->n_net, sizeof(ne->n_net),
+ af, dst);
+ }
+}
+
+/*
+ - tryhex - try conversion as an eight-digit hex number (AF_INET only)
+ */
+static err_t
+tryhex(src, srclen, flavor, dst)
+const char *src;
+size_t srclen; /* should be 8 */
+int flavor; /* 'x' for network order, 'h' for host order */
+ip_address *dst;
+{
+ err_t oops;
+ unsigned long ul;
+ union {
+ uint32_t addr;
+ unsigned char buf[4];
+ } u;
+
+ if (srclen != 8)
+ return "internal error, tryhex called with bad length";
+
+ oops = ttoul(src, srclen, 16, &ul);
+ if (oops != NULL)
+ return oops;
+
+ u.addr = (flavor == 'h') ? ul : htonl(ul);
+ return initaddr(u.buf, sizeof(u.buf), AF_INET, dst);
+}
+
+/*
+ - trydotted - try conversion as dotted decimal (AF_INET only)
+ *
+ * If the first char of a complaint is '?', that means "didn't look like
+ * dotted decimal at all".
+ */
+static err_t
+trydotted(src, srclen, dst)
+const char *src;
+size_t srclen;
+ip_address *dst;
+{
+ const char *stop = src + srclen; /* just past end */
+ int byte;
+ err_t oops;
+# define NBYTES 4
+ unsigned char buf[NBYTES];
+ int i;
+
+ memset(buf, 0, sizeof(buf));
+ for (i = 0; i < NBYTES && src < stop; i++) {
+ oops = getbyte(&src, stop, &byte);
+ if (oops != NULL) {
+ if (*oops != '?')
+ return oops; /* bad number */
+ if (i > 1)
+ return oops+1; /* failed number */
+ return oops; /* with leading '?' */
+ }
+ buf[i] = byte;
+ if (i < 3 && src < stop && *src++ != '.') {
+ if (i == 0)
+ return "?syntax error in dotted-decimal address";
+ else
+ return "syntax error in dotted-decimal address";
+ }
+ }
+ if (src != stop)
+ return "extra garbage on end of dotted-decimal address";
+
+ return initaddr(buf, sizeof(buf), AF_INET, dst);
+}
+
+/*
+ - getbyte - try to scan a byte in dotted decimal
+ * A subtlety here is that all this arithmetic on ASCII digits really is
+ * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
+ * It's easier to just do it ourselves than set up for a call to ttoul().
+ *
+ * If the first char of a complaint is '?', that means "didn't look like a
+ * number at all".
+ */
+err_t
+getbyte(srcp, stop, retp)
+const char **srcp; /* *srcp is updated */
+const char *stop; /* first untouchable char */
+int *retp; /* return-value pointer */
+{
+ char c;
+ const char *p;
+ int no;
+
+ if (*srcp >= stop)
+ return "?empty number in dotted-decimal address";
+
+ no = 0;
+ p = *srcp;
+ while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
+ no = no*10 + (c - '0');
+ p++;
+ }
+ if (p == *srcp)
+ return "?non-numeric component in dotted-decimal address";
+ *srcp = p;
+ if (no > 255)
+ return "byte overflow in dotted-decimal address";
+ *retp = no;
+ return NULL;
+}
+
+/*
+ - colon - convert IPv6 "numeric" address
+ */
+static err_t
+colon(src, srclen, dst)
+const char *src;
+size_t srclen; /* known to be >0 */
+ip_address *dst;
+{
+ const char *stop = src + srclen; /* just past end */
+ unsigned piece;
+ int gapat; /* where was empty piece seen */
+ err_t oops;
+# define NPIECES 8
+ unsigned char buf[NPIECES*2]; /* short may have wrong byte order */
+ int i;
+ int j;
+# define IT "IPv6 numeric address"
+ int naftergap;
+
+ /* leading or trailing :: becomes single empty field */
+ if (*src == ':') { /* legal only if leading :: */
+ if (srclen == 1 || *(src+1) != ':')
+ return "illegal leading `:' in " IT;
+ if (srclen == 2) {
+ unspecaddr(AF_INET6, dst);
+ return NULL;
+ }
+ src++; /* past first but not second */
+ srclen--;
+ }
+ if (*(stop-1) == ':') { /* legal only if trailing :: */
+ if (srclen == 1 || *(stop-2) != ':')
+ return "illegal trailing `:' in " IT;
+ srclen--; /* leave one */
+ }
+
+ gapat = -1;
+ for (i = 0; i < NPIECES && src < stop; i++) {
+ oops = getpiece(&src, stop, &piece);
+ if (oops != NULL && *oops == ':') { /* empty field */
+ if (gapat >= 0)
+ return "more than one :: in " IT;
+ gapat = i;
+ } else if (oops != NULL)
+ return oops;
+ buf[2*i] = piece >> 8;
+ buf[2*i + 1] = piece & 0xff;
+ if (i < NPIECES-1) { /* there should be more input */
+ if (src == stop && gapat < 0)
+ return IT " ends prematurely";
+ if (src != stop && *src++ != ':')
+ return "syntax error in " IT;
+ }
+ }
+ if (src != stop)
+ return "extra garbage on end of " IT;
+
+ if (gapat < 0 && i < NPIECES) /* should have been caught earlier */
+ return "incomplete " IT " (internal error)";
+ if (gapat >= 0 && i == NPIECES)
+ return "non-abbreviating empty field in " IT;
+ if (gapat >= 0) {
+ naftergap = i - (gapat + 1);
+ for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) {
+ buf[2*j] = buf[2*i];
+ buf[2*j + 1] = buf[2*i + 1];
+ }
+ for (; j >= gapat; j--)
+ buf[2*j] = buf[2*j + 1] = 0;
+ }
+
+ return initaddr(buf, sizeof(buf), AF_INET6, dst);
+}
+
+/*
+ - getpiece - try to scan one 16-bit piece of an IPv6 address
+ */
+err_t /* ":" means "empty field seen" */
+getpiece(srcp, stop, retp)
+const char **srcp; /* *srcp is updated */
+const char *stop; /* first untouchable char */
+unsigned *retp; /* return-value pointer */
+{
+ const char *p;
+# define NDIG 4
+ int d;
+ unsigned long ret;
+ err_t oops;
+
+ if (*srcp >= stop || **srcp == ':') { /* empty field */
+ *retp = 0;
+ return ":";
+ }
+
+ p = *srcp;
+ d = 0;
+ while (p < stop && d < NDIG && isxdigit(*p)) {
+ p++;
+ d++;
+ }
+ if (d == 0)
+ return "non-hex field in IPv6 numeric address";
+ if (p < stop && d == NDIG && isxdigit(*p))
+ return "field in IPv6 numeric address longer than 4 hex digits";
+
+ oops = ttoul(*srcp, d, 16, &ret);
+ if (oops != NULL) /* shouldn't happen, really... */
+ return oops;
+
+ *srcp = p;
+ *retp = ret;
+ return NULL;
+}
diff --git a/src/libfreeswan/ttodata.3 b/src/libfreeswan/ttodata.3
new file mode 100644
index 000000000..98bbe4ab3
--- /dev/null
+++ b/src/libfreeswan/ttodata.3
@@ -0,0 +1,281 @@
+.TH IPSEC_TTODATA 3 "16 August 2003"
+.\" RCSID $Id: ttodata.3,v 1.2 2005/07/18 20:13:42 as Exp $
+.SH NAME
+ipsec ttodata, datatot \- convert binary data bytes from and to text formats
+.SH SYNOPSIS
+.B "#include <freeswan.h>"
+.sp
+.B "const char *ttodata(const char *src, size_t srclen,"
+.ti +1c
+.B "int base, char *dst, size_t dstlen, size_t *lenp);"
+.br
+.B "const char *ttodatav(const char *src, size_t srclen,"
+.ti +1c
+.B "int base, char *dst, size_t dstlen, size_t *lenp,"
+.ti +1c
+.B "char *errp, size_t errlen, int flags);"
+.br
+.B "size_t datatot(const char *src, size_t srclen,"
+.ti +1c
+.B "int format, char *dst, size_t dstlen);"
+.SH DESCRIPTION
+.IR Ttodata ,
+.IR ttodatav ,
+and
+.I datatot
+convert arbitrary binary data (e.g. encryption or authentication keys)
+from and to more-or-less human-readable text formats.
+.PP
+Currently supported formats are hexadecimal, base64, and characters.
+.PP
+A hexadecimal text value begins with a
+.B 0x
+(or
+.BR 0X )
+prefix and continues with two-digit groups
+of hexadecimal digits (0-9, and a-f or A-F),
+each group encoding the value of one binary byte, high-order digit first.
+A single
+.B _
+(underscore)
+between consecutive groups is ignored, permitting punctuation to improve
+readability; doing this every eight digits seems about right.
+.PP
+A base64 text value begins with a
+.B 0s
+(or
+.BR 0S )
+prefix
+and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /),
+each group encoding the value of three binary bytes as described in
+section 6.8 of RFC 2045.
+If
+.B flags
+has the
+.B TTODATAV_IGNORESPACE
+bit on, blanks are ignore (after the prefix).
+Note that the last one or two digits of a base64 group can be
+.B =
+to indicate that fewer than three binary bytes are encoded.
+.PP
+A character text value begins with a
+.B 0t
+(or
+.BR 0T )
+prefix
+and continues with text characters, each being the value of one binary byte.
+.PP
+All these functions basically copy data from
+.I src
+(whose size is specified by
+.IR srclen )
+to
+.I dst
+(whose size is specified by
+.IR dstlen ),
+doing the conversion en route.
+If the result will not fit in
+.IR dst ,
+it is truncated;
+under no circumstances are more than
+.I dstlen
+bytes of result written to
+.IR dst .
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result bytes are written at all.
+.PP
+The
+.I base
+parameter of
+.I ttodata
+and
+.I ttodatav
+specifies what format the input is in;
+normally it should be
+.B 0
+to signify that this gets figured out from the prefix.
+Values of
+.BR 16 ,
+.BR 64 ,
+and
+.BR 256
+respectively signify hexadecimal, base64, and character-text formats
+without prefixes.
+.PP
+The
+.I format
+parameter of
+.IR datatot ,
+a single character used as a type code,
+specifies which text format is wanted.
+The value
+.B 0
+(not ASCII
+.BR '0' ,
+but a zero value) specifies a reasonable default.
+Other currently-supported values are:
+.RS 2
+.TP 4
+.B 'x'
+continuous lower-case hexadecimal with a
+.B 0x
+prefix
+.TP
+.B 'h'
+lower-case hexadecimal with a
+.B 0x
+prefix and a
+.B _
+every eight digits
+.TP
+.B ':'
+lower-case hexadecimal with no prefix and a
+.B :
+(colon) every two digits
+.TP
+.B 16
+lower-case hexadecimal with no prefix or
+.B _
+.TP
+.B 's'
+continuous base64 with a
+.B 0s
+prefix
+.TP
+.B 64
+continuous base64 with no prefix
+.RE
+.PP
+The default format is currently
+.BR 'h' .
+.PP
+.I Ttodata
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+On success,
+if and only if
+.I lenp
+is non-NULL,
+.B *lenp
+is set to the number of bytes required to contain the full untruncated result.
+It is the caller's responsibility to check this against
+.I dstlen
+to determine whether he has obtained a complete result.
+The
+.B *lenp
+value is correct even if
+.I dstlen
+is zero, which offers a way to determine how much space would be needed
+before having to allocate any.
+.PP
+.I Ttodatav
+is just like
+.I ttodata
+except that in certain cases,
+if
+.I errp
+is non-NULL,
+the buffer pointed to by
+.I errp
+(whose length is given by
+.IR errlen )
+is used to hold a more detailed error message.
+The return value is NULL for success,
+and is either
+.I errp
+or a pointer to a string literal for failure.
+If the size of the error-message buffer is
+inadequate for the desired message,
+.I ttodatav
+will fall back on returning a pointer to a literal string instead.
+The
+.I freeswan.h
+header file defines a constant
+.B TTODATAV_BUF
+which is the size of a buffer large enough for worst-case results.
+.PP
+The normal return value of
+.IR datatot
+is the number of bytes required
+to contain the full untruncated result.
+It is the caller's responsibility to check this against
+.I dstlen
+to determine whether he has obtained a complete result.
+The return value is correct even if
+.I dstlen
+is zero, which offers a way to determine how much space would be needed
+before having to allocate any.
+A return value of
+.B 0
+signals a fatal error of some kind
+(see DIAGNOSTICS).
+.PP
+A zero value for
+.I srclen
+in
+.I ttodata
+(but not
+.IR datatot !)
+is synonymous with
+.BR strlen(src) .
+A non-zero
+.I srclen
+in
+.I ttodata
+must not include the terminating NUL.
+.PP
+Unless
+.I dstlen
+is zero,
+the result supplied by
+.I datatot
+is always NUL-terminated,
+and its needed-size return value includes space for the terminating NUL.
+.PP
+Several obsolete variants of these functions
+.RI ( atodata ,
+.IR datatoa ,
+.IR atobytes ,
+and
+.IR bytestoa )
+are temporarily also supported.
+.SH SEE ALSO
+sprintf(3), ipsec_atoaddr(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I ttodata
+and
+.I ttodatav
+are:
+unknown characters in the input;
+unknown or missing prefix;
+unknown base;
+incomplete digit group;
+non-zero padding in a base64 less-than-three-bytes digit group;
+zero-length input.
+.PP
+Fatal errors in
+.I datatot
+are:
+unknown format code;
+zero-length input.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+.I Datatot
+should have a format code to produce character-text output.
+.PP
+The
+.B 0s
+and
+.B 0t
+prefixes are the author's inventions and are not a standard
+of any kind.
+They have been chosen to avoid collisions with existing practice
+(some C implementations use
+.B 0b
+for binary)
+and possible confusion with unprefixed hexadecimal.
diff --git a/src/libfreeswan/ttodata.c b/src/libfreeswan/ttodata.c
new file mode 100644
index 000000000..e1bf7606a
--- /dev/null
+++ b/src/libfreeswan/ttodata.c
@@ -0,0 +1,722 @@
+/*
+ * convert from text form of arbitrary data (e.g., keys) to binary
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ttodata.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/* converters and misc */
+static int unhex(const char *, char *, size_t);
+static int unb64(const char *, char *, size_t);
+static int untext(const char *, char *, size_t);
+static const char *badch(const char *, int, char *, size_t);
+
+/* internal error codes for converters */
+#define SHORT (-2) /* internal buffer too short */
+#define BADPAD (-3) /* bad base64 padding */
+#define BADCH0 (-4) /* invalid character 0 */
+#define BADCH1 (-5) /* invalid character 1 */
+#define BADCH2 (-6) /* invalid character 2 */
+#define BADCH3 (-7) /* invalid character 3 */
+#define BADOFF(code) (BADCH0-(code))
+
+/*
+ - ttodatav - convert text to data, with verbose error reports
+ * If some of this looks slightly odd, it's because it has changed
+ * repeatedly (from the original atodata()) without a major rewrite.
+ */
+const char * /* NULL on success, else literal or errp */
+ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
+const char *src;
+size_t srclen; /* 0 means apply strlen() */
+int base; /* 0 means figure it out */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+size_t *lenp; /* where to record length (NULL is nowhere) */
+char *errp; /* error buffer */
+size_t errlen;
+unsigned int flags;
+{
+ size_t ingroup; /* number of input bytes converted at once */
+ char buf[4]; /* output from conversion */
+ int nbytes; /* size of output */
+ int (*decode)(const char *, char *, size_t);
+ char *stop;
+ int ndone;
+ int i;
+ int underscoreok;
+ int skipSpace = 0;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (dstlen == 0)
+ dst = buf; /* point it somewhere valid */
+ stop = dst + dstlen;
+
+ if (base == 0) {
+ if (srclen < 2)
+ return "input too short to be valid";
+ if (*src++ != '0')
+ return "input does not begin with format prefix";
+ switch (*src++) {
+ case 'x':
+ case 'X':
+ base = 16;
+ break;
+ case 's':
+ case 'S':
+ base = 64;
+ break;
+ case 't':
+ case 'T':
+ base = 256;
+ break;
+ default:
+ return "unknown format prefix";
+ }
+ srclen -= 2;
+ }
+ switch (base) {
+ case 16:
+ decode = unhex;
+ underscoreok = 1;
+ ingroup = 2;
+ break;
+ case 64:
+ decode = unb64;
+ underscoreok = 0;
+ ingroup = 4;
+ if(flags & TTODATAV_IGNORESPACE) {
+ skipSpace = 1;
+ }
+ break;
+
+ case 256:
+ decode = untext;
+ ingroup = 1;
+ underscoreok = 0;
+ break;
+ default:
+ return "unknown base";
+ }
+
+ /* proceed */
+ ndone = 0;
+ while (srclen > 0) {
+ char stage[4]; /* staging area for group */
+ size_t sl = 0;
+
+ /* Grab ingroup characters into stage,
+ * squeezing out blanks if we are supposed to ignore them.
+ */
+ for (sl = 0; sl < ingroup; src++, srclen--) {
+ if (srclen == 0)
+ return "input ends in mid-byte, perhaps truncated";
+ else if (!(skipSpace && (*src == ' ' || *src == '\t')))
+ stage[sl++] = *src;
+ }
+
+ nbytes = (*decode)(stage, buf, sizeof(buf));
+ switch (nbytes) {
+ case BADCH0:
+ case BADCH1:
+ case BADCH2:
+ case BADCH3:
+ return badch(stage, nbytes, errp, errlen);
+ case SHORT:
+ return "internal buffer too short (\"can't happen\")";
+ case BADPAD:
+ return "bad (non-zero) padding at end of base64 input";
+ }
+ if (nbytes <= 0)
+ return "unknown internal error";
+ for (i = 0; i < nbytes; i++) {
+ if (dst < stop)
+ *dst++ = buf[i];
+ ndone++;
+ }
+ while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
+ src++;
+ srclen--;
+ }
+ if (underscoreok && srclen > 1 && *src == '_') {
+ /* srclen > 1 means not last character */
+ src++;
+ srclen--;
+ }
+ }
+
+ if (ndone == 0)
+ return "no data bytes specified by input";
+ if (lenp != NULL)
+ *lenp = ndone;
+ return NULL;
+}
+
+/*
+ - ttodata - convert text to data
+ */
+const char * /* NULL on success, else literal */
+ttodata(src, srclen, base, dst, dstlen, lenp)
+const char *src;
+size_t srclen; /* 0 means apply strlen() */
+int base; /* 0 means figure it out */
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+size_t *lenp; /* where to record length (NULL is nowhere) */
+{
+ return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
+ (size_t)0, TTODATAV_SPACECOUNTS);
+}
+
+/*
+ - atodata - convert ASCII to data
+ * backward-compatibility interface
+ */
+size_t /* 0 for failure, true length for success */
+atodata(src, srclen, dst, dstlen)
+const char *src;
+size_t srclen;
+char *dst;
+size_t dstlen;
+{
+ size_t len;
+ const char *err;
+
+ err = ttodata(src, srclen, 0, dst, dstlen, &len);
+ if (err != NULL)
+ return 0;
+ return len;
+}
+
+/*
+ - atobytes - convert ASCII to data bytes
+ * another backward-compatibility interface
+ */
+const char *
+atobytes(src, srclen, dst, dstlen, lenp)
+const char *src;
+size_t srclen;
+char *dst;
+size_t dstlen;
+size_t *lenp;
+{
+ return ttodata(src, srclen, 0, dst, dstlen, lenp);
+}
+
+/*
+ - unhex - convert two ASCII hex digits to byte
+ */
+static int /* number of result bytes, or error code */
+unhex(src, dst, dstlen)
+const char *src; /* known to be full length */
+char *dst;
+size_t dstlen; /* not large enough is a failure */
+{
+ char *p;
+ unsigned byte;
+ static char hex[] = "0123456789abcdef";
+
+ if (dstlen < 1)
+ return SHORT;
+
+ p = strchr(hex, *src);
+ if (p == NULL)
+ p = strchr(hex, tolower(*src));
+ if (p == NULL)
+ return BADCH0;
+ byte = (p - hex) << 4;
+ src++;
+
+ p = strchr(hex, *src);
+ if (p == NULL)
+ p = strchr(hex, tolower(*src));
+ if (p == NULL)
+ return BADCH1;
+ byte |= (p - hex);
+
+ *dst = byte;
+ return 1;
+}
+
+/*
+ - unb64 - convert four ASCII base64 digits to three bytes
+ * Note that a base64 digit group is padded out with '=' if it represents
+ * less than three bytes: one byte is dd==, two is ddd=, three is dddd.
+ */
+static int /* number of result bytes, or error code */
+unb64(src, dst, dstlen)
+const char *src; /* known to be full length */
+char *dst;
+size_t dstlen;
+{
+ char *p;
+ unsigned byte1;
+ unsigned byte2;
+ static char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ if (dstlen < 3)
+ return SHORT;
+
+ p = strchr(base64, *src++);
+
+ if (p == NULL)
+ return BADCH0;
+ byte1 = (p - base64) << 2; /* first six bits */
+
+ p = strchr(base64, *src++);
+ if (p == NULL) {
+ return BADCH1;
+ }
+
+ byte2 = p - base64; /* next six: two plus four */
+ *dst++ = byte1 | (byte2 >> 4);
+ byte1 = (byte2 & 0xf) << 4;
+
+ p = strchr(base64, *src++);
+ if (p == NULL) {
+ if (*(src-1) == '=' && *src == '=') {
+ if (byte1 != 0) /* bad padding */
+ return BADPAD;
+ return 1;
+ }
+ return BADCH2;
+ }
+
+ byte2 = p - base64; /* next six: four plus two */
+ *dst++ = byte1 | (byte2 >> 2);
+ byte1 = (byte2 & 0x3) << 6;
+
+ p = strchr(base64, *src++);
+ if (p == NULL) {
+ if (*(src-1) == '=') {
+ if (byte1 != 0) /* bad padding */
+ return BADPAD;
+ return 2;
+ }
+ return BADCH3;
+ }
+ byte2 = p - base64; /* last six */
+ *dst++ = byte1 | byte2;
+
+ return 3;
+}
+
+/*
+ - untext - convert one ASCII character to byte
+ */
+static int /* number of result bytes, or error code */
+untext(src, dst, dstlen)
+const char *src; /* known to be full length */
+char *dst;
+size_t dstlen; /* not large enough is a failure */
+{
+ if (dstlen < 1)
+ return SHORT;
+
+ *dst = *src;
+ return 1;
+}
+
+/*
+ - badch - produce a nice complaint about an unknown character
+ *
+ * If the compiler complains that the array bigenough[] has a negative
+ * size, that means the TTODATAV_BUF constant has been set too small.
+ */
+static const char * /* literal or errp */
+badch(src, errcode, errp, errlen)
+const char *src;
+int errcode;
+char *errp; /* might be NULL */
+size_t errlen;
+{
+ static const char pre[] = "unknown character (`";
+ static const char suf[] = "') in input";
+ char buf[5];
+# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
+ struct sizecheck {
+ char bigenough[TTODATAV_BUF - REQD]; /* see above */
+ };
+ char ch;
+
+ if (errp == NULL || errlen < REQD)
+ return "unknown character in input";
+ strcpy(errp, pre);
+ ch = *(src + BADOFF(errcode));
+ if (isprint(ch)) {
+ buf[0] = ch;
+ buf[1] = '\0';
+ } else {
+ buf[0] = '\\';
+ buf[1] = ((ch & 0700) >> 6) + '0';
+ buf[2] = ((ch & 0070) >> 3) + '0';
+ buf[3] = ((ch & 0007) >> 0) + '0';
+ buf[4] = '\0';
+ }
+ strcat(errp, buf);
+ strcat(errp, suf);
+ return (const char *)errp;
+}
+
+
+
+#ifdef TTODATA_MAIN
+
+#include <stdio.h>
+
+struct artab;
+static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
+static void regress(char *pgm);
+static void hexout(const char *s, size_t len, FILE *f);
+
+/*
+ - main - convert first argument to hex, or run regression
+ */
+int
+main(int argc, char *argv[])
+{
+ char buf[1024];
+ char buf2[1024];
+ char err[512];
+ size_t n;
+ size_t i;
+ char *p = buf;
+ char *p2 = buf2;
+ char *pgm = argv[0];
+ const char *oops;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress(pgm); /* should not return */
+ fprintf(stderr, "%s: regress() returned?!?\n", pgm);
+ exit(1);
+ }
+
+ oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
+ err, sizeof(err), TTODATAV_IGNORESPACE);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
+ oops, argv[1]);
+ exit(1);
+ }
+
+ if (n > sizeof(buf)) {
+ p = (char *)malloc((size_t)n);
+ if (p == NULL) {
+ fprintf(stderr,
+ "%s: unable to malloc %d bytes for result\n",
+ pgm, n);
+ exit(1);
+ }
+ oops = ttodata(argv[1], 0, 0, p, n, &n);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
+ pgm, oops);
+ exit(1);
+ }
+ }
+
+ hexout(p, n, stdout);
+ printf("\n");
+
+ i = datatot(buf, n, 'h', buf2, sizeof(buf2));
+ if (i == 0) {
+ fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
+ argv[1]);
+ exit(1);
+ }
+
+ if (i > sizeof(buf2)) {
+ p2 = (char *)malloc((size_t)i);
+ if (p == NULL) {
+ fprintf(stderr,
+ "%s: unable to malloc %d bytes for result\n",
+ pgm, i);
+ exit(1);
+ }
+ i = datatot(buf, n, 'h', p2, i);
+ if (i == 0) {
+ fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
+ exit(1);
+ }
+ }
+
+ printf("%s\n", p2);
+
+ exit(0);
+}
+
+/*
+ - hexout - output an arbitrary-length string in hex
+ */
+static void
+hexout(s, len, f)
+const char *s;
+size_t len;
+FILE *f;
+{
+ size_t i;
+
+ fprintf(f, "0x");
+ for (i = 0; i < len; i++)
+ fprintf(f, "%02x", (unsigned char)s[i]);
+}
+
+struct artab {
+ int base;
+# define IGNORESPACE_BIAS 1000
+ char *ascii; /* NULL for end */
+ char *data; /* NULL for error expected */
+} atodatatab[] = {
+ { 0, "", NULL, },
+ { 0, "0", NULL, },
+ { 0, "0x", NULL, },
+ { 0, "0xa", NULL, },
+ { 0, "0xab", "\xab", },
+ { 0, "0xabc", NULL, },
+ { 0, "0xabcd", "\xab\xcd", },
+ { 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
+ { 0, "0x01x", NULL, },
+ { 0, "0xabcdef", "\xab\xcd\xef", },
+ { 0, "0xABCDEF", "\xab\xcd\xef", },
+ { 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
+ { 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
+ { 0, "0XaBc0_", NULL, },
+ { 0, "0X_aBc0", NULL, },
+ { 0, "0Xa_Bc0", NULL, },
+ { 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
+ { 0, "0s", NULL, },
+ { 0, "0sA", NULL, },
+ { 0, "0sBA", NULL, },
+ { 0, "0sCBA", NULL, },
+ { 0, "0sDCBA", "\x0c\x20\x40", },
+ { 0, "0SDCBA", "\x0c\x20\x40", },
+ { 0, "0sDA==", "\x0c", },
+ { 0, "0sDC==", NULL, },
+ { 0, "0sDCA=", "\x0c\x20", },
+ { 0, "0sDCB=", NULL, },
+ { 0, "0sDCAZ", "\x0c\x20\x19", },
+ { 0, "0sDCAa", "\x0c\x20\x1a", },
+ { 0, "0sDCAz", "\x0c\x20\x33", },
+ { 0, "0sDCA0", "\x0c\x20\x34", },
+ { 0, "0sDCA9", "\x0c\x20\x3d", },
+ { 0, "0sDCA+", "\x0c\x20\x3e", },
+ { 0, "0sDCA/", "\x0c\x20\x3f", },
+ { 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
+ { 0, "0t", NULL, },
+ { 0, "0tabc_xyz", "abc_xyz", },
+ { 256, "abc_xyz", "abc_xyz", },
+ { 0, NULL, NULL, },
+};
+
+struct drtab {
+ char *data; /* input; NULL for end */
+ char format;
+ int buflen; /* -1 means big buffer */
+ int outlen; /* -1 means strlen(ascii)+1 */
+ char *ascii; /* NULL for error expected */
+} datatoatab[] = {
+ { "", 'x', -1, -1, NULL, },
+ { "", 'X', -1, -1, NULL, },
+ { "", 'n', -1, -1, NULL, },
+ { "0", 'x', -1, -1, "0x30", },
+ { "0", 'x', 0, 5, "---", },
+ { "0", 'x', 1, 5, "", },
+ { "0", 'x', 2, 5, "0", },
+ { "0", 'x', 3, 5, "0x", },
+ { "0", 'x', 4, 5, "0x3", },
+ { "0", 'x', 5, 5, "0x30", },
+ { "0", 'x', 6, 5, "0x30", },
+ { "\xab\xcd", 'x', -1, -1, "0xabcd", },
+ { "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
+ { "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
+ { "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
+ { "\x01\x02", 'h', -1, -1, "0x0102", },
+ { "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
+ { "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
+ { "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
+ { "\x0c\x20\x40", 's', 0, 7, "---", },
+ { "\x0c\x20\x40", 's', 1, 7, "", },
+ { "\x0c\x20\x40", 's', 2, 7, "0", },
+ { "\x0c\x20\x40", 's', 3, 7, "0s", },
+ { "\x0c\x20\x40", 's', 4, 7, "0sD", },
+ { "\x0c\x20\x40", 's', 5, 7, "0sDC", },
+ { "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
+ { "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
+ { "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
+ { "\x0c", 's', -1, -1, "0sDA==", },
+ { "\x0c\x20", 's', -1, -1, "0sDCA=", },
+ { "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
+ { "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
+ { "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
+ { "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
+ { "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
+ { "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
+ { "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
+ { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
+ { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
+ { NULL, 'x', -1, -1, NULL, },
+};
+
+/*
+ - regress - regression-test ttodata() and datatot()
+ */
+static void
+check(r, buf, n, oops, status)
+struct artab *r;
+char *buf;
+size_t n;
+err_t oops;
+int *status;
+{
+ if (oops != NULL && r->data == NULL)
+ {} /* error expected */
+ else if (oops != NULL) {
+ printf("`%s' gave error `%s', expecting %d `", r->ascii,
+ oops, strlen(r->data));
+ hexout(r->data, strlen(r->data), stdout);
+ printf("'\n");
+ *status = 1;
+ } else if (r->data == NULL) {
+ printf("`%s' gave %d `", r->ascii, n);
+ hexout(buf, n, stdout);
+ printf("', expecting error\n");
+ *status = 1;
+ } else if (n != strlen(r->data)) {
+ printf("length wrong in `%s': got %d `", r->ascii, n);
+ hexout(buf, n, stdout);
+ printf("', expecting %d `", strlen(r->data));
+ hexout(r->data, strlen(r->data), stdout);
+ printf("'\n");
+ *status = 1;
+ } else if (memcmp(buf, r->data, n) != 0) {
+ printf("`%s' gave %d `", r->ascii, n);
+ hexout(buf, n, stdout);
+ printf("', expecting %d `", strlen(r->data));
+ hexout(r->data, strlen(r->data), stdout);
+ printf("'\n");
+ *status = 1;
+ }
+ fflush(stdout);
+}
+
+static void /* should not return at all, in fact */
+regress(pgm)
+char *pgm;
+{
+ struct artab *r;
+ struct drtab *dr;
+ char buf[100];
+ size_t n;
+ int status = 0;
+
+ for (r = atodatatab; r->ascii != NULL; r++) {
+ int base = r->base;
+ int xbase = 0;
+
+ if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
+ switch (r->ascii[1]) {
+ case 'x':
+ case 'X':
+ xbase = 16;
+ break;
+ case 's':
+ case 'S':
+ xbase = 64;
+ break;
+ case 't':
+ case 'T':
+ xbase = 256;
+ break;
+ }
+ }
+
+ if (base >= IGNORESPACE_BIAS) {
+ base = base - IGNORESPACE_BIAS;
+ check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
+ if (xbase != 0)
+ check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
+ } else {
+ check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
+ if (base == 64 || xbase == 64)
+ check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
+ if (xbase != 0) {
+ check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
+ if (base == 64 || xbase == 64)
+ check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
+ }
+ }
+ }
+ for (dr = datatoatab; dr->data != NULL; dr++) {
+ size_t should;
+
+ strcpy(buf, "---");
+ n = datatot(dr->data, strlen(dr->data), dr->format, buf,
+ (dr->buflen == -1) ? sizeof(buf) : dr->buflen);
+ should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
+ if (dr->outlen != -1)
+ should = dr->outlen;
+ if (n == 0 && dr->ascii == NULL)
+ {} /* error expected */
+ else if (n == 0) {
+ printf("`");
+ hexout(dr->data, strlen(dr->data), stdout);
+ printf("' %c gave error, expecting %d `%s'\n",
+ dr->format, should, dr->ascii);
+ status = 1;
+ } else if (dr->ascii == NULL) {
+ printf("`");
+ hexout(dr->data, strlen(dr->data), stdout);
+ printf("' %c gave %d `%.*s', expecting error\n",
+ dr->format, n, (int)n, buf);
+ status = 1;
+ } else if (n != should) {
+ printf("length wrong in `");
+ hexout(dr->data, strlen(dr->data), stdout);
+ printf("': got %d `%s'", n, buf);
+ printf(", expecting %d `%s'\n", should, dr->ascii);
+ status = 1;
+ } else if (strcmp(buf, dr->ascii) != 0) {
+ printf("`");
+ hexout(dr->data, strlen(dr->data), stdout);
+ printf("' gave %d `%s'", n, buf);
+ printf(", expecting %d `%s'\n", should, dr->ascii);
+ status = 1;
+ }
+ fflush(stdout);
+ }
+ exit(status);
+}
+
+#endif /* TTODATA_MAIN */
diff --git a/src/libfreeswan/ttoprotoport.c b/src/libfreeswan/ttoprotoport.c
new file mode 100644
index 000000000..46321838c
--- /dev/null
+++ b/src/libfreeswan/ttoprotoport.c
@@ -0,0 +1,103 @@
+/*
+ * conversion from protocol/port string to protocol and port
+ * Copyright (C) 2002 Mario Strasser <mast@gmx.net>,
+ * Zuercher Hochschule Winterthur,
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: ttoprotoport.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * ttoprotoport - converts from protocol/port string to protocol and port
+ */
+err_t
+ttoprotoport(src, src_len, proto, port, has_port_wildcard)
+char *src; /* input string */
+size_t src_len; /* length of input string, use strlen() if 0 */
+u_int8_t *proto; /* extracted protocol number */
+u_int16_t *port; /* extracted port number if it exists */
+int *has_port_wildcard; /* set if port is %any */
+{
+ char *end, *service_name;
+ char proto_name[16];
+ int proto_len;
+ long int l;
+ struct protoent *protocol;
+ struct servent *service;
+
+ /* get the length of the string */
+ if (!src_len) src_len = strlen(src);
+
+ /* locate delimiter '/' between protocol and port */
+ end = strchr(src, '/');
+ if (end != NULL) {
+ proto_len = end - src;
+ service_name = end + 1;
+ } else {
+ proto_len = src_len;
+ service_name = src + src_len;
+ }
+
+ /* copy protocol name*/
+ memset(proto_name, '\0', sizeof(proto_name));
+ memcpy(proto_name, src, proto_len);
+
+ /* extract protocol by trying to resolve it by name */
+ protocol = getprotobyname(proto_name);
+ if (protocol != NULL) {
+ *proto = protocol->p_proto;
+ }
+ else /* failed, now try it by number */
+ {
+ l = strtol(proto_name, &end, 0);
+
+ if (*proto_name && *end)
+ return "<protocol> is neither a number nor a valid name";
+
+ if (l < 0 || l > 0xff)
+ return "<protocol> must be between 0 and 255";
+
+ *proto = (u_int8_t)l;
+ }
+
+ /* is there a port wildcard? */
+ *has_port_wildcard = (strcmp(service_name, "%any") == 0);
+
+ if (*has_port_wildcard)
+ {
+ *port = 0;
+ return NULL;
+ }
+
+ /* extract port by trying to resolve it by name */
+ service = getservbyname(service_name, NULL);
+ if (service != NULL) {
+ *port = ntohs(service->s_port);
+ }
+ else /* failed, now try it by number */
+ {
+ l = strtol(service_name, &end, 0);
+
+ if (*service_name && *end)
+ return "<port> is neither a number nor a valid name";
+
+ if (l < 0 || l > 0xffff)
+ return "<port> must be between 0 and 65535";
+
+ *port = (u_int16_t)l;
+ }
+ return NULL;
+}
+
diff --git a/src/libfreeswan/ttosa.3 b/src/libfreeswan/ttosa.3
new file mode 100644
index 000000000..bf918e108
--- /dev/null
+++ b/src/libfreeswan/ttosa.3
@@ -0,0 +1,288 @@
+.TH IPSEC_TTOSA 3 "26 Nov 2001"
+.\" RCSID $Id: ttosa.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec ttosa, satot \- convert IPsec Security Association IDs to and from text
+.br
+ipsec initsaid \- initialize an SA ID
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "typedef struct {"
+.ti +1c
+.B "ip_address dst;"
+.ti +1c
+.B "ipsec_spi_t spi;"
+.ti +1c
+.B "int proto;"
+.br
+.B "} ip_said;"
+.sp
+.B "const char *ttosa(const char *src, size_t srclen,"
+.ti +1c
+.B "ip_said *sa);
+.br
+.B "size_t satot(const ip_said *sa, int format,"
+.ti +1c
+.B "char *dst, size_t dstlen);"
+.br
+.B "void initsaid(const ip_address *addr, ipsec_spi_t spi,"
+.ti +1c
+.B "int proto, ip_said *dst);"
+.SH DESCRIPTION
+.I Ttosa
+converts an ASCII Security Association (SA) specifier into an
+.B ip_said
+structure (containing
+a destination-host address
+in network byte order,
+an SPI number in network byte order, and
+a protocol code).
+.I Satot
+does the reverse conversion, back to a text SA specifier.
+.I Initsaid
+initializes an
+.B ip_said
+from separate items of information.
+.PP
+An SA is specified in text with a mail-like syntax, e.g.
+.BR esp.5a7@1.2.3.4 .
+An SA specifier contains
+a protocol prefix (currently
+.BR ah ,
+.BR esp ,
+.BR tun ,
+.BR comp ,
+or
+.BR int ),
+a single character indicating the address family
+.RB ( .
+for IPv4,
+.B :
+for IPv6),
+an unsigned integer SPI number in hexadecimal (with no
+.B 0x
+prefix),
+and an IP address.
+The IP address can be any form accepted by
+.IR ipsec_ttoaddr (3),
+e.g. dotted-decimal IPv4 address,
+colon-hex IPv6 address,
+or DNS name.
+.PP
+As a special case, the SA specifier
+.B %passthrough4
+or
+.B %passthrough6
+signifies the special SA used to indicate that packets should be
+passed through unaltered.
+(At present, these are synonyms for
+.B tun.0@0.0.0.0
+and
+.B tun:0@::
+respectively,
+but that is subject to change without notice.)
+.B %passthrough
+is a historical synonym for
+.BR %passthrough4 .
+These forms are known to both
+.I ttosa
+and
+.IR satot ,
+so the internal representation is never visible.
+.PP
+Similarly, the SA specifiers
+.BR %pass ,
+.BR %drop ,
+.BR %reject ,
+.BR %hold ,
+.BR %trap ,
+and
+.BR %trapsubnet
+signify special ``magic'' SAs used to indicate that packets should be
+passed, dropped, rejected (dropped with ICMP notification),
+held,
+and trapped (sent up to
+.IR ipsec_pluto (8),
+with either of two forms of
+.B %hold
+automatically installed)
+respectively.
+These forms too are known to both routines,
+so the internal representation of the magic SAs should never be visible.
+.PP
+The
+.B <freeswan.h>
+header file supplies the
+.B ip_said
+structure, as well as a data type
+.B ipsec_spi_t
+which is an unsigned 32-bit integer.
+(There is no consistency between kernel and user on what such a type
+is called, hence the header hides the differences.)
+.PP
+The protocol code uses the same numbers that IP does.
+For user convenience, given the difficulty in acquiring the exact set of
+protocol names used by the kernel,
+.B <freeswan.h>
+defines the names
+.BR SA_ESP ,
+.BR SA_AH ,
+.BR SA_IPIP ,
+and
+.BR SA_COMP
+to have the same values as the kernel names
+.BR IPPROTO_ESP ,
+.BR IPPROTO_AH ,
+.BR IPPROTO_IPIP ,
+and
+.BR IPPROTO_COMP .
+.PP
+.B <freeswan.h>
+also defines
+.BR SA_INT
+to have the value
+.BR 61
+(reserved by IANA for ``any host internal protocol'')
+and
+.BR SPI_PASS ,
+.BR SPI_DROP ,
+.BR SPI_REJECT ,
+.BR SPI_HOLD ,
+and
+.B SPI_TRAP
+to have the values 256-260 (in \fIhost\fR byte order) respectively.
+These are used in constructing the magic SAs
+(which always have address
+.BR 0.0.0.0 ).
+.PP
+If
+.I satot
+encounters an unknown protocol code, e.g. 77,
+it yields output using a prefix
+showing the code numerically, e.g. ``unk77''.
+This form is
+.I not
+recognized by
+.IR ttosa .
+.PP
+The
+.I srclen
+parameter of
+.I ttosa
+specifies the length of the string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I dstlen
+parameter of
+.I satot
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.B <freeswan.h>
+header file defines a constant,
+.BR SATOT_BUF ,
+which is the size of a buffer just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I satot
+specifies what format is to be used for the conversion.
+The value
+.B 0
+(not the ASCII character
+.BR '0' ,
+but a zero value)
+specifies a reasonable default
+(currently
+lowercase protocol prefix, lowercase hexadecimal SPI,
+dotted-decimal or colon-hex address).
+The value
+.B 'f'
+is similar except that the SPI is padded with
+.BR 0 s
+to a fixed 32-bit width, to ease aligning displayed tables.
+.PP
+.I Ttosa
+returns
+.B NULL
+for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.I Satot
+returns
+.B 0
+for a failure, and otherwise
+always returns the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL;
+it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred.
+.PP
+There is also, temporarily, support for some obsolete
+forms of SA specifier which lack the address-family indicator.
+.SH SEE ALSO
+ipsec_ttoul(3), ipsec_ttoaddr(3), ipsec_samesaid(3), inet(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I ttosa
+are:
+empty input;
+input too small to be a legal SA specifier;
+no
+.B @
+in input;
+unknown protocol prefix;
+conversion error in
+.I ttoul
+or
+.IR ttoaddr .
+.PP
+Fatal errors in
+.I satot
+are:
+unknown format.
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+The restriction of text-to-binary error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The text-to-binary error-reporting convention lends itself
+to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = ttosa( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/ttosa.c b/src/libfreeswan/ttosa.c
new file mode 100644
index 000000000..aa2283694
--- /dev/null
+++ b/src/libfreeswan/ttosa.c
@@ -0,0 +1,280 @@
+/*
+ * convert from text form of SA ID to binary
+ * Copyright (C) 2000, 2001 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ttosa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct satype {
+ char *prefix;
+ size_t prelen; /* strlen(prefix) */
+ int proto;
+} satypes[] = {
+ { "ah", 2, SA_AH },
+ { "esp", 3, SA_ESP },
+ { "tun", 3, SA_IPIP },
+ { "comp", 4, SA_COMP },
+ { "int", 3, SA_INT },
+ { NULL, 0, 0, }
+};
+
+static struct magic {
+ char *name;
+ char *really;
+} magic[] = {
+ { PASSTHROUGHNAME, PASSTHROUGH4IS },
+ { PASSTHROUGH4NAME, PASSTHROUGH4IS },
+ { PASSTHROUGH6NAME, PASSTHROUGH6IS },
+ { "%pass", "int256@0.0.0.0" },
+ { "%drop", "int257@0.0.0.0" },
+ { "%reject", "int258@0.0.0.0" },
+ { "%hold", "int259@0.0.0.0" },
+ { "%trap", "int260@0.0.0.0" },
+ { "%trapsubnet", "int261@0.0.0.0" },
+ { NULL, NULL }
+};
+
+/*
+ - ttosa - convert text "ah507@10.0.0.1" to SA identifier
+ */
+err_t /* NULL for success, else string literal */
+ttosa(src, srclen, sa)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+ip_said *sa;
+{
+ const char *at;
+ const char *addr;
+ size_t alen;
+ const char *spi = NULL;
+ struct satype *sat;
+ unsigned long ul;
+ const char *oops;
+ struct magic *mp;
+ size_t nlen;
+# define MINLEN 5 /* ah0@0 is as short as it can get */
+ int af;
+ int base;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+ if (srclen < MINLEN)
+ return "string too short to be SA identifier";
+ if (*src == '%') {
+ for (mp = magic; mp->name != NULL; mp++) {
+ nlen = strlen(mp->name);
+ if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
+ break;
+ }
+ if (mp->name == NULL)
+ return "unknown % keyword";
+ src = mp->really;
+ srclen = strlen(src);
+ }
+
+ at = memchr(src, '@', srclen);
+ if (at == NULL)
+ return "no @ in SA specifier";
+
+ for (sat = satypes; sat->prefix != NULL; sat++)
+ if (sat->prelen < srclen &&
+ strncmp(src, sat->prefix, sat->prelen) == 0) {
+ sa->proto = sat->proto;
+ spi = src + sat->prelen;
+ break; /* NOTE BREAK OUT */
+ }
+ if (sat->prefix == NULL)
+ return "SA specifier lacks valid protocol prefix";
+
+ if (spi >= at)
+ return "no SPI in SA specifier";
+ switch (*spi) {
+ case '.':
+ af = AF_INET;
+ spi++;
+ base = 16;
+ break;
+ case ':':
+ af = AF_INET6;
+ spi++;
+ base = 16;
+ break;
+ default:
+ af = AF_UNSPEC; /* not known yet */
+ base = 0;
+ break;
+ }
+ if (spi >= at)
+ return "no SPI found in SA specifier";
+ oops = ttoul(spi, at - spi, base, &ul);
+ if (oops != NULL)
+ return oops;
+ sa->spi = htonl(ul);
+
+ addr = at + 1;
+ alen = srclen - (addr - src);
+ if (af == AF_UNSPEC)
+ af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET;
+ oops = ttoaddr(addr, alen, af, &sa->dst);
+ if (oops != NULL)
+ return oops;
+
+ return NULL;
+}
+
+
+
+#ifdef TTOSA_MAIN
+
+#include <stdio.h>
+
+void regress(void);
+
+int
+main(int argc, char *argv[])
+{
+ ip_said sa;
+ char buf[100];
+ char buf2[100];
+ const char *oops;
+ size_t n;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ oops = ttosa(argv[1], 0, &sa);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ n = satot(&sa, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
+ fprintf(stderr, "%lx@", (long unsigned int)sa.spi);
+ (void) addrtot(&sa.dst, 0, buf2, sizeof(buf2));
+ fprintf(stderr, "%s", buf2);
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ int format;
+# define FUDGE 0x1000
+ char *input;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {0, "esp257@1.2.3.0", "esp.101@1.2.3.0"},
+ {0, "ah0x20@1.2.3.4", "ah.20@1.2.3.4"},
+ {0, "tun20@1.2.3.4", "tun.14@1.2.3.4"},
+ {0, "comp20@1.2.3.4", "comp.14@1.2.3.4"},
+ {0, "esp257@::1", "esp:101@::1"},
+ {0, "esp257@0bc:12de::1", "esp:101@bc:12de::1"},
+ {0, "esp78@1049:1::8007:2040", "esp:4e@1049:1::8007:2040"},
+ {0, "esp0x78@1049:1::8007:2040", "esp:78@1049:1::8007:2040"},
+ {0, "ah78@1049:1::8007:2040", "ah:4e@1049:1::8007:2040"},
+ {0, "ah0x78@1049:1::8007:2040", "ah:78@1049:1::8007:2040"},
+ {0, "tun78@1049:1::8007:2040", "tun:4e@1049:1::8007:2040"},
+ {0, "tun0x78@1049:1::8007:2040", "tun:78@1049:1::8007:2040"},
+ {0, "duk99@3ffe:370:400:ff::9001:3001", NULL},
+ {0, "esp78x@1049:1::8007:2040", NULL},
+ {0, "esp0x78@1049:1:0xfff::8007:2040", NULL},
+ {0, "es78@1049:1::8007:2040", NULL},
+ {0, "", NULL},
+ {0, "_", NULL},
+ {0, "ah2.2", NULL},
+ {0, "goo2@1.2.3.4", NULL},
+ {0, "esp9@1.2.3.4", "esp.9@1.2.3.4"},
+ {'f', "esp0xa9@1.2.3.4", "esp.000000a9@1.2.3.4"},
+ {0, "espp9@1.2.3.4", NULL},
+ {0, "es9@1.2.3.4", NULL},
+ {0, "ah@1.2.3.4", NULL},
+ {0, "esp7x7@1.2.3.4", NULL},
+ {0, "esp77@1.0x2.3.4", NULL},
+ {0, PASSTHROUGHNAME, PASSTHROUGH4NAME},
+ {0, PASSTHROUGH6NAME, PASSTHROUGH6NAME},
+ {0, "%pass", "%pass"},
+ {0, "int256@0.0.0.0", "%pass"},
+ {0, "%drop", "%drop"},
+ {0, "int257@0.0.0.0", "%drop"},
+ {0, "%reject", "%reject"},
+ {0, "int258@0.0.0.0", "%reject"},
+ {0, "%hold", "%hold"},
+ {0, "int259@0.0.0.0", "%hold"},
+ {0, "%trap", "%trap"},
+ {0, "int260@0.0.0.0", "%trap"},
+ {0, "%trapsubnet", "%trapsubnet"},
+ {0, "int261@0.0.0.0", "%trapsubnet"},
+ {0, "int262@0.0.0.0", "int.106@0.0.0.0"},
+ {FUDGE, "esp9@1.2.3.4", "unk77.9@1.2.3.4"},
+ {0, NULL, NULL}
+};
+
+void
+regress(void)
+{
+ struct rtab *r;
+ int status = 0;
+ ip_said sa;
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+
+ for (r = rtab; r->input != NULL; r++) {
+ strcpy(in, r->input);
+ oops = ttosa(in, 0, &sa);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s' ttosa failed: %s\n", r->input, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s' ttosa succeeded unexpectedly\n",
+ r->input);
+ status = 1;
+ } else {
+ if (r->format&FUDGE)
+ sa.proto = 77;
+ n = satot(&sa, (char)r->format, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ printf("`%s' satot failed: need %ld\n",
+ r->input, (long)n);
+ status = 1;
+ } else if (strcmp(r->output, buf) != 0) {
+ printf("`%s' gave `%s', expected `%s'\n",
+ r->input, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* TTOSA_MAIN */
diff --git a/src/libfreeswan/ttosubnet.c b/src/libfreeswan/ttosubnet.c
new file mode 100644
index 000000000..7f5cddb82
--- /dev/null
+++ b/src/libfreeswan/ttosubnet.c
@@ -0,0 +1,296 @@
+/*
+ * convert from text form of subnet specification to binary
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ttosubnet.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#ifndef DEFAULTSUBNET
+#define DEFAULTSUBNET "%default"
+#endif
+
+/*
+ - ttosubnet - convert text "addr/mask" to address and mask
+ * Mask can be integer bit count.
+ */
+err_t
+ttosubnet(src, srclen, af, dst)
+const char *src;
+size_t srclen; /* 0 means "apply strlen" */
+int af; /* AF_INET or AF_INET6 */
+ip_subnet *dst;
+{
+ const char *slash;
+ const char *colon;
+ const char *mask;
+ size_t mlen;
+ const char *oops;
+ unsigned long bc;
+ static char def[] = DEFAULTSUBNET;
+# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
+ static char defis4[] = "0/0";
+# define DEFIS4LEN (sizeof(defis4) - 1)
+ static char defis6[] = "::/0";
+# define DEFIS6LEN (sizeof(defis6) - 1)
+ ip_address addrtmp;
+ ip_address masktmp;
+ int nbits;
+ int i;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ switch (af) {
+ case AF_INET:
+ nbits = 32;
+ break;
+ case AF_INET6:
+ nbits = 128;
+ break;
+ default:
+ return "unknown address family in ttosubnet";
+ break;
+ }
+
+ if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
+ src = (af == AF_INET) ? defis4 : defis6;
+ srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
+ }
+
+ slash = memchr(src, '/', srclen);
+ if (slash == NULL)
+ return "no / in subnet specification";
+ mask = slash + 1;
+ mlen = srclen - (mask - src);
+
+ oops = ttoaddr(src, slash-src, af, &addrtmp);
+ if (oops != NULL)
+ return oops;
+
+ /* extract port */
+ colon = memchr(mask, ':', mlen);
+ if (colon == 0)
+ {
+ setportof(0, &addrtmp);
+ }
+ else
+ {
+ long port;
+
+ oops = ttoul(colon+1, mlen-(colon-mask+1), 10, &port);
+ if (oops != NULL)
+ return oops;
+ setportof(htons(port), &addrtmp);
+ mlen = colon - mask;
+ }
+
+ /*extract mask */
+ oops = ttoul(mask, mlen, 10, &bc);
+ if (oops == NULL) {
+ /* ttoul succeeded, it's a bit-count mask */
+ if (bc > nbits)
+ return "subnet mask bit count too large";
+ i = bc;
+ } else {
+ oops = ttoaddr(mask, mlen, af, &masktmp);
+ if (oops != NULL)
+ return oops;
+ i = masktocount(&masktmp);
+ if (i < 0)
+ return "non-contiguous or otherwise erroneous mask";
+ }
+
+ return initsubnet(&addrtmp, i, '0', dst);
+}
+
+
+
+#ifdef TTOSUBNET_MAIN
+
+#include <stdio.h>
+
+void regress(void);
+
+int main(int argc, char *argv[])
+{
+ ip_subnet s;
+ char buf[100];
+ char buf2[100];
+ const char *oops;
+ size_t n;
+ int af;
+ char *p;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
+ fprintf(stderr, " or: %s -r\n", argv[0]);
+ exit(2);
+ }
+
+ if (strcmp(argv[1], "-r") == 0) {
+ regress();
+ fprintf(stderr, "regress() returned?!?\n");
+ exit(1);
+ }
+
+ af = AF_INET;
+ p = argv[1];
+ if (strcmp(argv[1], "-6") == 0) {
+ af = AF_INET6;
+ p = argv[2];
+ } else if (strchr(argv[1], ':') != NULL)
+ af = AF_INET6;
+
+ oops = ttosubnet(p, 0, af, &s);
+ if (oops != NULL) {
+ fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+ exit(1);
+ }
+ n = subnettot(&s, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+ (void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
+ fprintf(stderr, "%s/", buf2);
+ fprintf(stderr, "%d", s.maskbits);
+ fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+ (long)n, (long)sizeof(buf));
+ exit(1);
+ }
+ printf("%s\n", buf);
+
+ exit(0);
+}
+
+struct rtab {
+ int family;
+ char *input;
+ char *output; /* NULL means error expected */
+} rtab[] = {
+ {4, "1.2.3.0/255.255.255.0", "1.2.3.0/24"},
+ {4, "1.2.3.0/24", "1.2.3.0/24"},
+ {4, "1.2.3.0/24:10", "1.2.3.0/24:10"},
+ {4, "1.2.3.0/24:-1", NULL},
+ {4, "1.2.3.0/24:none", NULL},
+ {4, "1.2.3.0/24:", NULL},
+ {4, "1.2.3.0/24:0x10", "1.2.3.0/24:16"},
+ {4, "1.2.3.0/24:0X10", "1.2.3.0/24:16"},
+ {4, "1.2.3.0/24:010", "1.2.3.0/24:8"},
+ {4, "1.2.3.1/255.255.255.240", "1.2.3.0/28"},
+ {4, "1.2.3.1/32", "1.2.3.1/32"},
+ {4, "1.2.3.1/0", "0.0.0.0/0"},
+/* {4, "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0"}, */
+ {4, "1.2.3.1/255.255.127.0", NULL},
+ {4, "128.009.000.032/32", "128.9.0.32/32"},
+ {4, "128.0x9.0.32/32", NULL},
+ {4, "0x80090020/32", "128.9.0.32/32"},
+ {4, "0x800x0020/32", NULL},
+ {4, "128.9.0.32/0xffFF0000", "128.9.0.0/16"},
+ {4, "128.9.0.32/0xff0000FF", NULL},
+ {4, "128.9.0.32/0x0000ffFF", NULL},
+ {4, "128.9.0.32/0x00ffFF0000", NULL},
+ {4, "128.9.0.32/0xffFF", NULL},
+ {4, "128.9.0.32.27/32", NULL},
+ {4, "128.9.0k32/32", NULL},
+ {4, "328.9.0.32/32", NULL},
+ {4, "128.9..32/32", NULL},
+ {4, "10/8", "10.0.0.0/8"},
+ {4, "10.0/8", "10.0.0.0/8"},
+ {4, "10.0.0/8", "10.0.0.0/8"},
+ {4, "10.0.1/24", "10.0.1.0/24"},
+ {4, "_", NULL},
+ {4, "_/_", NULL},
+ {4, "1.2.3.1", NULL},
+ {4, "1.2.3.1/_", NULL},
+ {4, "1.2.3.1/24._", NULL},
+ {4, "1.2.3.1/99", NULL},
+ {4, "localhost/32", "127.0.0.1/32"},
+ {4, "%default", "0.0.0.0/0"},
+ {6, "3049:1::8007:2040/0", "::/0"},
+ {6, "3049:1::8007:2040/128", "3049:1::8007:2040/128"},
+ {6, "3049:1::192.168.0.1/128", NULL}, /*"3049:1::c0a8:1/128",*/
+ {6, "3049:1::8007::2040/128", NULL},
+ {6, "3049:1::8007:2040/ffff::0", "3049::/16"},
+ {6, "3049:1::8007:2040/64", "3049:1::/64"},
+ {6, "3049:1::8007:2040/ffff::", "3049::/16"},
+ {6, "3049:1::8007:2040/0000:ffff::0", NULL},
+ {6, "3049:1::8007:2040/ff1f::0", NULL},
+ {6, "3049:1::8007:x:2040/128", NULL},
+ {6, "3049:1t::8007:2040/128", NULL},
+ {6, "3049:1::80071:2040/128", NULL},
+ {6, "::/21", "::/21"},
+ {6, "::1/128", "::1/128"},
+ {6, "1::/21", "1::/21"},
+ {6, "1::2/128", "1::2/128"},
+ {6, "1:0:0:0:0:0:0:2/128", "1::2/128"},
+ {6, "1:0:0:0:3:0:0:2/128", "1::3:0:0:2/128"},
+ {6, "1:0:0:3:0:0:0:2/128", "1::3:0:0:0:2/128"},
+ {6, "1:0:3:0:0:0:0:2/128", "1:0:3::2/128"},
+ {6, "abcd:ef01:2345:6789:0:00a:000:20/128", "abcd:ef01:2345:6789:0:a:0:20/128"},
+ {6, "3049:1::8007:2040/ffff:ffff:", NULL},
+ {6, "3049:1::8007:2040/ffff:88::", NULL},
+ {6, "3049:12::9000:3200/ffff:fff0::", "3049:10::/28"},
+ {6, "3049:12::9000:3200/28", "3049:10::/28"},
+ {6, "3049:12::9000:3200/ff00:::", NULL},
+ {6, "3049:12::9000:3200/ffff:::", NULL},
+ {6, "3049:12::9000:3200/128_", NULL},
+ {6, "3049:12::9000:3200/", NULL},
+ {6, "%default", "::/0"},
+ {4, NULL, NULL}
+};
+
+void
+regress(void)
+{
+ struct rtab *r;
+ int status = 0;
+ ip_subnet s;
+ char in[100];
+ char buf[100];
+ const char *oops;
+ size_t n;
+ int af;
+
+ for (r = rtab; r->input != NULL; r++) {
+ af = (r->family == 4) ? AF_INET : AF_INET6;
+ strcpy(in, r->input);
+ oops = ttosubnet(in, 0, af, &s);
+ if (oops != NULL && r->output == NULL)
+ {} /* okay, error expected */
+ else if (oops != NULL) {
+ printf("`%s' ttosubnet failed: %s\n", r->input, oops);
+ status = 1;
+ } else if (r->output == NULL) {
+ printf("`%s' ttosubnet succeeded unexpectedly\n",
+ r->input);
+ status = 1;
+ } else {
+ n = subnettot(&s, 0, buf, sizeof(buf));
+ if (n > sizeof(buf)) {
+ printf("`%s' subnettot failed: need %ld\n",
+ r->input, (long)n);
+ status = 1;
+ } else if (strcmp(r->output, buf) != 0) {
+ printf("`%s' gave `%s', expected `%s'\n",
+ r->input, buf, r->output);
+ status = 1;
+ }
+ }
+ }
+ exit(status);
+}
+
+#endif /* TTOSUBNET_MAIN */
diff --git a/src/libfreeswan/ttoul.3 b/src/libfreeswan/ttoul.3
new file mode 100644
index 000000000..67d4bd34f
--- /dev/null
+++ b/src/libfreeswan/ttoul.3
@@ -0,0 +1,192 @@
+.TH IPSEC_TTOUL 3 "16 Aug 2000"
+.\" RCSID $Id: ttoul.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec ttoul, ultot \- convert unsigned-long numbers to and from text
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *ttoul(const char *src, size_t srclen,"
+.ti +1c
+.B "int base, unsigned long *n);"
+.br
+.B "size_t ultot(unsigned long n, int format, char *dst,"
+.ti +1c
+.B "size_t dstlen);"
+.SH DESCRIPTION
+.I Ttoul
+converts a text-string number into a binary
+.B "unsigned long"
+value.
+.I Ultot
+does the reverse conversion, back to a text version.
+.PP
+Numbers are specified in text as
+decimal (e.g.
+.BR 123 ),
+octal with a leading zero (e.g.
+.BR 012 ,
+which has value 10),
+or hexadecimal with a leading
+.B 0x
+(e.g.
+.BR 0x1f ,
+which has value 31)
+in either upper or lower case.
+.PP
+The
+.I srclen
+parameter of
+.I ttoul
+specifies the length of the string pointed to by
+.IR src ;
+it is an error for there to be anything else
+(e.g., a terminating NUL) within that length.
+As a convenience for cases where an entire NUL-terminated string is
+to be converted,
+a
+.I srclen
+value of
+.B 0
+is taken to mean
+.BR strlen(src) .
+.PP
+The
+.I base
+parameter of
+.I ttoul
+can be
+.BR 8 ,
+.BR 10 ,
+or
+.BR 16 ,
+in which case the number supplied is assumed to be of that form
+(and in the case of
+.BR 16 ,
+to lack any
+.B 0x
+prefix).
+It can also be
+.BR 0 ,
+in which case the number is examined for a leading zero
+or a leading
+.B 0x
+to determine its base.
+.PP
+The
+.I dstlen
+parameter of
+.I ultot
+specifies the size of the
+.I dst
+parameter;
+under no circumstances are more than
+.I dstlen
+bytes written to
+.IR dst .
+A result which will not fit is truncated.
+.I Dstlen
+can be zero, in which case
+.I dst
+need not be valid and no result is written,
+but the return value is unaffected;
+in all other cases, the (possibly truncated) result is NUL-terminated.
+The
+.I freeswan.h
+header file defines a constant,
+.BR ULTOT_BUF ,
+which is the size of a buffer just large enough for worst-case results.
+.PP
+The
+.I format
+parameter of
+.I ultot
+must be one of:
+.RS
+.IP \fB'o'\fR 4
+octal conversion with leading
+.B 0
+.IP \fB\ 8\fR
+octal conversion with no leading
+.B 0
+.IP \fB'd'\fR
+decimal conversion
+.IP \fB10\fR
+same as
+.B d
+.IP \fB'x'\fR
+hexadecimal conversion, including leading
+.B 0x
+.IP \fB16\fR
+hexadecimal conversion with no leading
+.B 0x
+.IP \fB17\fR
+like
+.B 16
+except padded on left with
+.BR 0 s
+to eight digits (full width of a 32-bit number)
+.RE
+.PP
+.I Ttoul
+returns NULL for success and
+a pointer to a string-literal error message for failure;
+see DIAGNOSTICS.
+.I Ultot
+returns
+.B 0
+for a failure, and otherwise
+returns the size of buffer which would
+be needed to
+accommodate the full conversion result, including terminating NUL
+(it is the caller's responsibility to check this against the size of
+the provided buffer to determine whether truncation has occurred).
+.SH SEE ALSO
+atol(3), strtoul(3)
+.SH DIAGNOSTICS
+Fatal errors in
+.I ttoul
+are:
+empty input;
+unknown
+.IR base ;
+non-digit character found;
+number too large for an
+.BR "unsigned long" .
+.PP
+Fatal errors in
+.I ultot
+are:
+unknown
+.IR format .
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
+.SH BUGS
+Conversion of
+.B 0
+with format
+.B o
+yields
+.BR 00 .
+.PP
+.I Ultot
+format
+.B 17
+is a bit of a kludge.
+.PP
+The restriction of error reports to literal strings
+(so that callers don't need to worry about freeing them or copying them)
+does limit the precision of error reporting.
+.PP
+The error-reporting convention lends itself to slightly obscure code,
+because many readers will not think of NULL as signifying success.
+A good way to make it clearer is to write something like:
+.PP
+.RS
+.nf
+.B "const char *error;"
+.sp
+.B "error = ttoul( /* ... */ );"
+.B "if (error != NULL) {"
+.B " /* something went wrong */"
+.fi
+.RE
diff --git a/src/libfreeswan/ttoul.c b/src/libfreeswan/ttoul.c
new file mode 100644
index 000000000..9c6193c68
--- /dev/null
+++ b/src/libfreeswan/ttoul.c
@@ -0,0 +1,91 @@
+/*
+ * convert from text form of unsigned long to binary
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ttoul.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ttoul - convert text substring to unsigned long number
+ */
+const char * /* NULL for success, else string literal */
+ttoul(src, srclen, base, resultp)
+const char *src;
+size_t srclen; /* 0 means strlen(src) */
+int base; /* 0 means figure it out */
+unsigned long *resultp;
+{
+ const char *stop;
+ static char hex[] = "0123456789abcdef";
+ static char uchex[] = "0123456789ABCDEF";
+ int d;
+ char c;
+ char *p;
+ unsigned long r;
+ unsigned long rlimit;
+ int dlimit;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ if (srclen == 0)
+ return "empty string";
+
+ if (base == 0) {
+ if (srclen > 2 && *src == '0' &&
+ (*(src+1) == 'x' || *(src+1) == 'X'))
+ return ttoul(src+2, srclen-2, 16, resultp);
+ if (srclen > 1 && *src == '0')
+ return ttoul(src+1, srclen-1, 8, resultp);
+ return ttoul(src, srclen, 10, resultp);
+ }
+ if (base != 8 && base != 10 && base != 16)
+ return "unsupported number base";
+
+ r = 0;
+ stop = src + srclen;
+ if (base == 16) {
+ while (src < stop) {
+ c = *src++;
+ p = strchr(hex, c);
+ if (p != NULL)
+ d = p - hex;
+ else {
+ p = strchr(uchex, c);
+ if (p == NULL)
+ return "non-hex digit in hex number";
+ d = p - uchex;
+ }
+ r = (r << 4) | d;
+ }
+ /* defer length check to catch invalid digits first */
+ if (srclen > sizeof(unsigned long) * 2)
+ return "hex number too long";
+ } else {
+ rlimit = ULONG_MAX / base;
+ dlimit = (int)(ULONG_MAX - rlimit*base);
+ while (src < stop) {
+ c = *src++;
+ d = c - '0';
+ if (d < 0 || d >= base)
+ return "non-digit in number";
+ if (r > rlimit || (r == rlimit && d > dlimit))
+ return "unsigned-long overflow";
+ r = r*base + d;
+ }
+ }
+
+ *resultp = r;
+ return NULL;
+}
diff --git a/src/libfreeswan/ultoa.c b/src/libfreeswan/ultoa.c
new file mode 100644
index 000000000..2c2644826
--- /dev/null
+++ b/src/libfreeswan/ultoa.c
@@ -0,0 +1,67 @@
+/*
+ * convert unsigned long to ASCII
+ * Copyright (C) 1998, 1999 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ultoa.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ultoa - convert unsigned long to decimal ASCII
+ */
+size_t /* length required for full conversion */
+ultoa(n, base, dst, dstlen)
+unsigned long n;
+int base;
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ char buf[3*sizeof(unsigned long) + 1];
+ char *bufend = buf + sizeof(buf);
+ size_t len;
+ char *p;
+ static char hex[] = "0123456789abcdef";
+
+ p = bufend;
+ *--p = '\0';
+ if (base == 10) {
+ do {
+ *--p = n%10 + '0';
+ n /= 10;
+ } while (n != 0);
+ } else if (base == 16) {
+ do {
+ *--p = hex[n&0xf];
+ n >>= 4;
+ } while (n != 0);
+ *--p = 'x';
+ *--p = '0';
+ } else if (base == 8) {
+ do {
+ *--p = (n&07) + '0';
+ n >>= 3;
+ } while (n != 0);
+ *--p = '0';
+ } else
+ *--p = '?';
+
+ len = bufend - p;
+
+ if (dstlen > 0) {
+ if (len > dstlen)
+ *(p + dstlen - 1) = '\0';
+ strcpy(dst, p);
+ }
+ return len;
+}
diff --git a/src/libfreeswan/ultot.c b/src/libfreeswan/ultot.c
new file mode 100644
index 000000000..edffa4a2d
--- /dev/null
+++ b/src/libfreeswan/ultot.c
@@ -0,0 +1,83 @@
+/*
+ * convert unsigned long to text
+ * Copyright (C) 2000 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: ultot.c,v 1.1 2004/03/15 20:35:26 as Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ultot - convert unsigned long to text
+ */
+size_t /* length required for full conversion */
+ultot(n, base, dst, dstlen)
+unsigned long n;
+int base;
+char *dst; /* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+ char buf[3*sizeof(unsigned long) + 1];
+ char *bufend = buf + sizeof(buf);
+ size_t len;
+ char *p;
+ static char hex[] = "0123456789abcdef";
+# define HEX32 (32/4)
+
+ p = bufend;
+ *--p = '\0';
+ switch (base) {
+ case 10:
+ case 'd':
+ do {
+ *--p = n%10 + '0';
+ n /= 10;
+ } while (n != 0);
+ break;
+ case 16:
+ case 17:
+ case 'x':
+ do {
+ *--p = hex[n&0xf];
+ n >>= 4;
+ } while (n != 0);
+ if (base == 17)
+ while (bufend - p < HEX32 + 1)
+ *--p = '0';
+ if (base == 'x') {
+ *--p = 'x';
+ *--p = '0';
+ }
+ break;
+ case 8:
+ case 'o':
+ do {
+ *--p = (n&07) + '0';
+ n >>= 3;
+ } while (n != 0);
+ if (base == 'o')
+ *--p = '0';
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ len = bufend - p;
+ if (dstlen > 0) {
+ if (len > dstlen)
+ *(p + dstlen - 1) = '\0';
+ strcpy(dst, p);
+ }
+ return len;
+}
diff --git a/src/libfreeswan/version.3 b/src/libfreeswan/version.3
new file mode 100644
index 000000000..06c5f01e3
--- /dev/null
+++ b/src/libfreeswan/version.3
@@ -0,0 +1,44 @@
+.TH IPSEC_VERSION 3 "21 Nov 2001"
+.\" RCSID $Id: version.3,v 1.1 2004/03/15 20:35:26 as Exp $
+.SH NAME
+ipsec ipsec_version_code \- get IPsec version code
+.br
+ipsec ipsec_version_string \- get full IPsec version string
+.br
+ipsec ipsec_copyright_notice \- get IPsec copyright notice
+.SH SYNOPSIS
+.B "#include <freeswan.h>
+.sp
+.B "const char *ipsec_version_code(void);"
+.br
+.B "const char *ipsec_version_string(void);"
+.br
+.B "const char **ipsec_copyright_notice(void);"
+.SH DESCRIPTION
+These functions provide information on version numbering and copyright
+of the Linux FreeS/WAN IPsec implementation.
+.PP
+.I Ipsec_version_code
+returns a pointer to a string constant
+containing the current IPsec version code,
+such as ``1.92'' or ``snap2001Nov19b''.
+.PP
+.I Ipsec_version_string
+returns a pointer to a string constant giving a full version identification,
+consisting of the version code preceded by a prefix identifying the software,
+e.g. ``Linux FreeS/WAN 1.92''.
+.PP
+.I Ipsec_copyright_notice
+returns a pointer to a vector of pointers,
+terminated by a
+.BR NULL ,
+which is the text of a suitable copyright notice.
+Each pointer points to a string constant (possibly empty) which is one line
+of the somewhat-verbose copyright notice.
+The strings are NUL-terminated and do not contain a newline;
+supplying suitable line termination for the output device is
+the caller's responsibility.
+.SH SEE ALSO
+ipsec(8)
+.SH HISTORY
+Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/version.c b/src/libfreeswan/version.c
new file mode 100644
index 000000000..3a947b1b9
--- /dev/null
+++ b/src/libfreeswan/version.c
@@ -0,0 +1,43 @@
+/*
+ * return IPsec version information
+ * Copyright (C) 2001 Henry Spencer.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: version.in.c,v 1.2 2004/03/16 12:26:32 as Exp $
+ */
+
+#ifdef __KERNEL__
+#include <linux/netdevice.h>
+#endif
+
+#include "freeswan.h"
+
+static const char strongswan_number[] = VERSION;
+static const char strongswan_string[] = "Linux strongSwan " VERSION;
+
+/*
+ - ipsec_version_code - return IPsec version number/code, as string
+ */
+const char *
+ipsec_version_code()
+{
+ return strongswan_number;
+}
+
+/*
+ - ipsec_version_string - return full version string
+ */
+const char *
+ipsec_version_string()
+{
+ return strongswan_string;
+}