summaryrefslogtreecommitdiff
path: root/src/libtnccs/plugins
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-11-01 13:32:07 +0100
committerYves-Alexis Perez <corsac@debian.org>2013-11-01 13:32:07 +0100
commit5313d2d78ca150515f7f5eb39801c100690b6b29 (patch)
treec78e420367283bb1b16f14210b12687cdfbd26eb /src/libtnccs/plugins
parent6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (diff)
downloadvyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.tar.gz
vyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.zip
Imported Upstream version 5.1.1
Diffstat (limited to 'src/libtnccs/plugins')
-rw-r--r--src/libtnccs/plugins/tnc_imc/Makefile.am23
-rw-r--r--src/libtnccs/plugins/tnc_imc/Makefile.in765
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc.c427
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc.h60
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_bind_function.c222
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_manager.c441
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_manager.h32
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c79
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h42
-rw-r--r--src/libtnccs/plugins/tnc_imv/Makefile.am24
-rw-r--r--src/libtnccs/plugins/tnc_imv/Makefile.in768
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv.c424
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv.h60
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_bind_function.c246
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c470
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_manager.h32
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.c83
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h42
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.c406
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.h33
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/Makefile.am23
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/Makefile.in763
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c866
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.h31
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.c98
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h42
-rw-r--r--src/libtnccs/plugins/tnccs_11/Makefile.am33
-rw-r--r--src/libtnccs/plugins/tnccs_11/Makefile.in824
-rw-r--r--src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.c325
-rw-r--r--src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.h100
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.c243
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.h71
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c190
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.h80
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c140
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.h102
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c137
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h64
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c196
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h64
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.c186
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.h64
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c118
-rw-r--r--src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h54
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11.c670
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11.h42
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.c61
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h42
-rw-r--r--src/libtnccs/plugins/tnccs_20/Makefile.am34
-rw-r--r--src/libtnccs/plugins/tnccs_20/Makefile.in880
-rw-r--r--src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c612
-rw-r--r--src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h130
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.c181
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.h76
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.c174
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.h60
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.c352
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.h127
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.c102
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.h53
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.c179
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.h60
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c274
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h98
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.c217
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.h69
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.c311
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.h118
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c95
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h147
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.c314
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.h106
-rw-r--r--src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c316
-rw-r--r--src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h102
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20.c1073
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20.h42
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.c61
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h42
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/Makefile.am22
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/Makefile.in762
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c267
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h42
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c62
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h42
84 files changed, 17910 insertions, 0 deletions
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.am b/src/libtnccs/plugins/tnc_imc/Makefile.am
new file mode 100644
index 000000000..b2c26cbff
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.am
@@ -0,0 +1,23 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
+libstrongswan_tnc_imc_la_LIBADD = \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnc_imc_la_SOURCES = \
+ tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \
+ tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c
+
+libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.in b/src/libtnccs/plugins/tnc_imc/Makefile.in
new file mode 100644
index 000000000..79f91f72f
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.in
@@ -0,0 +1,765 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libtnccs/plugins/tnc_imc
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_tnc_imc_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo tnc_imc.lo \
+ tnc_imc_manager.lo tnc_imc_bind_function.lo
+libstrongswan_tnc_imc_la_OBJECTS = \
+ $(am_libstrongswan_tnc_imc_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnc_imc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnc_imc_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnc_imc_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnc_imc_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnc_imc_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnc_imc_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = \
+ -rdynamic
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
+@MONOLITHIC_FALSE@libstrongswan_tnc_imc_la_LIBADD = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+libstrongswan_tnc_imc_la_SOURCES = \
+ tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \
+ tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c
+
+libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_imc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_imc/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-tnc-imc.la: $(libstrongswan_tnc_imc_la_OBJECTS) $(libstrongswan_tnc_imc_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnc_imc_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnc_imc_la_LINK) $(am_libstrongswan_tnc_imc_la_rpath) $(libstrongswan_tnc_imc_la_OBJECTS) $(libstrongswan_tnc_imc_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_bind_function.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnc_imc/tnc_imc.c b/src/libtnccs/plugins/tnc_imc/tnc_imc.c
new file mode 100644
index 000000000..7c52ab384
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen,
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc.h"
+
+#include <dlfcn.h>
+
+#include <tncif_pa_subtypes.h>
+
+#include <utils/debug.h>
+#include <library.h>
+#include <collections/linked_list.h>
+#include <threading/mutex.h>
+
+typedef struct private_tnc_imc_t private_tnc_imc_t;
+
+/**
+ * Private data of an imc_t object.
+ */
+struct private_tnc_imc_t {
+
+ /**
+ * Public members of imc_t.
+ */
+ imc_t public;
+
+ /**
+ * Name of loaded IMC
+ */
+ char *name;
+
+ /**
+ * Handle of loaded IMC
+ */
+ void *handle;
+
+ /**
+ * ID of loaded IMC
+ */
+ TNC_IMCID id;
+
+ /**
+ * list of additional IMC IDs
+ */
+ linked_list_t *additional_ids;
+
+ /**
+ * List of message types supported by IMC - Vendor ID part
+ */
+ TNC_VendorIDList supported_vids;
+
+ /**
+ * List of message types supported by IMC - Subtype part
+ */
+ TNC_MessageSubtypeList supported_subtypes;
+
+ /**
+ * Number of supported message types
+ */
+ TNC_UInt32 type_count;
+
+ /**
+ * mutex to lock the imc_t object
+ */
+ mutex_t *mutex;
+};
+
+METHOD(imc_t, set_id, void,
+ private_tnc_imc_t *this, TNC_IMCID id)
+{
+ this->id = id;
+}
+
+METHOD(imc_t, get_id, TNC_IMCID,
+ private_tnc_imc_t *this)
+{
+ return this->id;
+}
+
+METHOD(imc_t, add_id, void,
+ private_tnc_imc_t *this, TNC_IMCID id)
+{
+ void *pointer;
+
+ /* store the scalar value in the pointer */
+ pointer = (void*)id;
+ this->additional_ids->insert_last(this->additional_ids, pointer);
+}
+
+METHOD(imc_t, has_id, bool,
+ private_tnc_imc_t *this, TNC_IMCID id)
+{
+ enumerator_t *enumerator;
+ TNC_IMCID additional_id;
+ void *pointer;
+ bool found = FALSE;
+
+ /* check primary IMC ID */
+ if (id == this->id)
+ {
+ return TRUE;
+ }
+
+ /* return if there are no additional IMC IDs */
+ if (this->additional_ids->get_count(this->additional_ids) == 0)
+ {
+ return FALSE;
+ }
+
+ /* check additional IMC IDs */
+ enumerator = this->additional_ids->create_enumerator(this->additional_ids);
+ while (enumerator->enumerate(enumerator, &pointer))
+ {
+ /* interpret pointer as scalar value */
+ additional_id = (TNC_UInt32)pointer;
+
+ if (id == additional_id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(imc_t, get_name, char*,
+ private_tnc_imc_t *this)
+{
+ return this->name;
+}
+
+METHOD(imc_t, set_message_types, void,
+ private_tnc_imc_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ char buf[BUF_LEN];
+ char *pos = buf;
+ int len = sizeof(buf);
+ int i, written;
+ size_t size;
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ enum_name_t *pa_subtype_names;
+
+ /* lock the imc_t instance */
+ this->mutex->lock(this->mutex);
+
+ /* Free existing VendorID and MessageSubtype lists */
+ free(this->supported_vids);
+ this->supported_vids = NULL;
+ free(this->supported_subtypes);
+ this->supported_subtypes = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_types)
+ {
+ size = type_count * sizeof(TNC_VendorID);
+ this->supported_vids = malloc(size);
+ size = type_count * sizeof(TNC_MessageSubtype);
+ this->supported_subtypes = malloc(size);
+
+ for (i = 0; i < type_count; i++)
+ {
+ vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY;
+ subtype = supported_types[i] & TNC_SUBTYPE_ANY;
+
+ pa_subtype_names = get_pa_subtype_names(vid);
+ if (pa_subtype_names)
+ {
+ written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x",
+ pen_names, vid, pa_subtype_names, subtype,
+ vid, subtype);
+ }
+ else
+ {
+ written = snprintf(pos, len," '%N' 0x%06x/0x%02x",
+ pen_names, vid, vid, subtype);
+ }
+ if (written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+
+ this->supported_vids[i] = vid;
+ this->supported_subtypes[i] = subtype;
+ }
+ }
+ *pos = '\0';
+ DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
+ this->id, type_count, (type_count == 1) ? "":"s", buf);
+
+ /* unlock the imc_t instance */
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(imc_t, set_message_types_long, void,
+ private_tnc_imc_t *this, TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count)
+{
+ char buf[BUF_LEN];
+ char *pos = buf;
+ int len = sizeof(buf);
+ int i, written;
+ size_t size;
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ enum_name_t *pa_subtype_names;
+
+ /* lock the imc_t instance */
+ this->mutex->lock(this->mutex);
+
+ /* Free existing VendorID and MessageSubtype lists */
+ free(this->supported_vids);
+ this->supported_vids = NULL;
+ free(this->supported_subtypes);
+ this->supported_subtypes = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_vids && supported_subtypes)
+ {
+ size = type_count * sizeof(TNC_VendorID);
+ this->supported_vids = malloc(size);
+ memcpy(this->supported_vids, supported_vids, size);
+ size = type_count * sizeof(TNC_MessageSubtype);
+ this->supported_subtypes = malloc(size);
+ memcpy(this->supported_subtypes, supported_subtypes, size);
+
+ for (i = 0; i < type_count; i++)
+ {
+ vid = supported_vids[i];
+ subtype = supported_subtypes[i];
+
+ pa_subtype_names = get_pa_subtype_names(vid);
+ if (pa_subtype_names)
+ {
+ written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x",
+ pen_names, vid, pa_subtype_names, subtype,
+ vid, subtype);
+ }
+ else
+ {
+ written = snprintf(pos, len," '%N' 0x%06x/0x%08x",
+ pen_names, vid, vid, subtype);
+ }
+ if (written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ }
+ *pos = '\0';
+ DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
+ this->id, type_count, (type_count == 1) ? "":"s", buf);
+
+ /* unlock the imc_t instance */
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(imc_t, type_supported, bool,
+ private_tnc_imc_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype)
+{
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ int i;
+
+ for (i = 0; i < this->type_count; i++)
+ {
+ vid = this->supported_vids[i];
+ subtype = this->supported_subtypes[i];
+
+ if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) ||
+ (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY ||
+ subtype == msg_subtype)))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(imc_t, destroy, void,
+ private_tnc_imc_t *this)
+{
+ if (this->handle && lib->settings->get_bool(lib->settings,
+ "libtnccs.plugins.tnc-imc.dlclose", TRUE))
+ {
+ dlclose(this->handle);
+ }
+ this->mutex->destroy(this->mutex);
+ this->additional_ids->destroy(this->additional_ids);
+ free(this->supported_vids);
+ free(this->supported_subtypes);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_tnc_imc_t* tnc_imc_create_empty(char *name)
+{
+ private_tnc_imc_t *this;
+
+ INIT(this,
+ .public = {
+ .set_id = _set_id,
+ .get_id = _get_id,
+ .add_id = _add_id,
+ .has_id = _has_id,
+ .get_name = _get_name,
+ .set_message_types = _set_message_types,
+ .set_message_types_long = _set_message_types_long,
+ .type_supported = _type_supported,
+ .destroy = _destroy,
+ },
+ .name = strdup(name),
+ .additional_ids = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ return this;
+}
+
+/**
+ * See header
+ */
+imc_t* tnc_imc_create(char *name, char *path)
+{
+ private_tnc_imc_t *this;
+
+ this = tnc_imc_create_empty(name);
+
+ this->handle = dlopen(path, RTLD_LAZY);
+ if (!this->handle)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
+ destroy(this);
+ return NULL;
+ }
+
+ this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
+ if (!this->public.initialize)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+ this->public.notify_connection_change =
+ dlsym(this->handle, "TNC_IMC_NotifyConnectionChange");
+ this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake");
+ if (!this->public.begin_handshake)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+ this->public.receive_message =
+ dlsym(this->handle, "TNC_IMC_ReceiveMessage");
+ this->public.receive_message_long =
+ dlsym(this->handle, "TNC_IMC_ReceiveMessageLong");
+ this->public.batch_ending =
+ dlsym(this->handle, "TNC_IMC_BatchEnding");
+ this->public.terminate =
+ dlsym(this->handle, "TNC_IMC_Terminate");
+ this->public.provide_bind_function =
+ dlsym(this->handle, "TNC_IMC_ProvideBindFunction");
+ if (!this->public.provide_bind_function)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+imc_t* tnc_imc_create_from_functions(char *name,
+ TNC_IMC_InitializePointer initialize,
+ TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMC_BeginHandshakePointer begin_handshake,
+ TNC_IMC_ReceiveMessagePointer receive_message,
+ TNC_IMC_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMC_BatchEndingPointer batch_ending,
+ TNC_IMC_TerminatePointer terminate,
+ TNC_IMC_ProvideBindFunctionPointer provide_bind_function)
+{
+ private_tnc_imc_t *this;
+
+ this = tnc_imc_create_empty(name);
+
+ this->public.initialize = initialize;
+ this->public.notify_connection_change = notify_connection_change;
+ this->public.begin_handshake = begin_handshake;
+ this->public.receive_message = receive_message;
+ this->public.receive_message_long = receive_message_long;
+ this->public.batch_ending = batch_ending;
+ this->public.terminate = terminate;
+ this->public.provide_bind_function = provide_bind_function;
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc.h b/src/libtnccs/plugins/tnc_imc/tnc_imc.h
new file mode 100644
index 000000000..2d4607e77
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ *
+ * @defgroup tnc_imc_t tnc_imc
+ * @{ @ingroup tnc_imc
+ */
+
+#ifndef TNC_IMC_H_
+#define TNC_IMC_H_
+
+#include <tnc/imc/imc.h>
+
+/**
+ * Create an Integrity Measurement Collector loaded from a library.
+ *
+ * @param name name of the IMC
+ * @param filename path to the dynamic IMC library
+ * @return instance of the imc_t interface
+ */
+imc_t* tnc_imc_create(char *name, char *filename);
+
+/**
+ * Create an Integrity Measurement Collector from a set of IMC functions.
+ *
+ * @param name name of the IMC
+ * @param initialize TNC_IMC_InitializePointer
+ * @param notify_connection_change TNC_IMC_NotifyConnectionChangePointer
+ * @param begin_handshake TNC_IMC_BeginHandshakePointer
+ * @param receive_message TNC_IMC_ReceiveMessagePointer
+ * @param receive_message_long TNC_IMC_ReceiveMessageLongPointer
+ * @param batch_ending TNC_IMC_BatchEndingPointer
+ * @param terminate TNC_IMC_TerminatePointer
+ * @param provide_bind_function TNC_IMC_ProvideBindFunctionPointer
+ * @return instance of the imc_t interface
+ */
+imc_t* tnc_imc_create_from_functions(char *name,
+ TNC_IMC_InitializePointer initialize,
+ TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMC_BeginHandshakePointer begin_handshake,
+ TNC_IMC_ReceiveMessagePointer receive_message,
+ TNC_IMC_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMC_BatchEndingPointer batch_ending,
+ TNC_IMC_TerminatePointer terminate,
+ TNC_IMC_ProvideBindFunctionPointer provide_bind_function);
+
+#endif /** TNC_IMC_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_bind_function.c b/src/libtnccs/plugins/tnc_imc/tnc_imc_bind_function.c
new file mode 100644
index 000000000..26a5ed2b4
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_bind_function.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <tnc/tnc.h>
+#include <tnc/imc/imc_manager.h>
+#include <tnc/tnccs/tnccs_manager.h>
+
+#include <utils/debug.h>
+
+/**
+ * Called by the IMC to inform a TNCC about the set of message types the IMC
+ * is able to receive
+ */
+TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->imcs->set_message_types(tnc->imcs, imc_id, supported_types,
+ type_count);
+}
+
+/**
+ * Called by the IMC to inform a TNCC about the set of message types the IMC
+ * is able to receive. This function supports long message types.
+ */
+TNC_Result TNC_TNCC_ReportMessageTypesLong(TNC_IMCID imc_id,
+ TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes,
+ TNC_UInt32 type_count)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring ReportMessageTypesLong() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->imcs->set_message_types_long(tnc->imcs, imc_id, supported_vids,
+ supported_subtypes, type_count);
+}
+
+/**
+ * Called by the IMC to ask a TNCC to retry an Integrity Check Handshake
+ */
+TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_RetryReason reason)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->request_handshake_retry(tnc->tnccs, TRUE, imc_id,
+ connection_id, reason);
+}
+
+/**
+ * Called by the IMC when an IMC-IMV message is to be sent
+ */
+TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ TNC_VendorID msg_vid;
+ TNC_MessageSubtype msg_subtype;
+
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY;
+ msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+
+ return tnc->tnccs->send_message(tnc->tnccs, imc_id, TNC_IMVID_ANY,
+ connection_id, 0, msg, msg_len, msg_vid, msg_subtype);
+}
+
+/**
+ * Called by the IMC when an IMC-IMV message is to be sent over IF-TNCCS 2.0
+ */
+TNC_Result TNC_TNCC_SendMessageLong(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 imv_id)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->send_message(tnc->tnccs, imc_id, imv_id, connection_id,
+ msg_flags, msg, msg_len, msg_vid, msg_subtype);
+}
+
+/**
+ * Called by the IMC to get the value of an attribute associated with a
+ * connection or with the TNCC as a whole.
+ */
+TNC_Result TNC_TNCC_GetAttribute(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *out_value_len)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->get_attribute(tnc->tnccs, TRUE, imc_id, connection_id,
+ attribute_id, buffer_len, buffer, out_value_len);
+}
+
+/**
+ * Called by the IMC to set the value of an attribute associated with a
+ * connection or with the TNCC as a whole.
+ */
+TNC_Result TNC_TNCC_SetAttribute(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer)
+{
+ if (!tnc->imcs->is_registered(tnc->imcs, imc_id))
+ {
+ DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->set_attribute(tnc->tnccs, TRUE, imc_id, connection_id,
+ attribute_id, buffer_len, buffer);
+}
+
+/**
+ * Called by the IMC when it wants to reserve an additional IMC ID for itself
+ */
+TNC_Result TNC_TNCC_ReserveAdditionalIMCID(TNC_IMCID imc_id, TNC_UInt32 *new_id)
+{
+ if (tnc->imcs->reserve_id(tnc->imcs, imc_id, new_id))
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+ DBG1(DBG_TNC, "ignoring ReserveAdditionalIMCID() from unregistered IMC %u",
+ imc_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+}
+
+/**
+ * Called by the IMC when it needs a function pointer
+ */
+TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id,
+ char *function_name,
+ void **function_pointer)
+{
+ if (streq(function_name, "TNC_TNCC_ReportMessageTypes"))
+ {
+ *function_pointer = (void*)TNC_TNCC_ReportMessageTypes;
+ }
+ else if (streq(function_name, "TNC_TNCC_ReportMessageTypesLong"))
+ {
+ *function_pointer = (void*)TNC_TNCC_ReportMessageTypesLong;
+ }
+ else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry"))
+ {
+ *function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry;
+ }
+ else if (streq(function_name, "TNC_TNCC_SendMessage"))
+ {
+ *function_pointer = (void*)TNC_TNCC_SendMessage;
+ }
+ else if (streq(function_name, "TNC_TNCC_SendMessageLong"))
+ {
+ *function_pointer = (void*)TNC_TNCC_SendMessageLong;
+ }
+ else if (streq(function_name, "TNC_TNCC_GetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCC_GetAttribute;
+ }
+ else if (streq(function_name, "TNC_TNCC_SetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCC_SetAttribute;
+ }
+ else if (streq(function_name, "TNC_TNCC_ReserveAdditionalIMCID"))
+ {
+ *function_pointer = (void*)TNC_TNCC_ReserveAdditionalIMCID;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return TNC_RESULT_SUCCESS;
+}
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.c b/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.c
new file mode 100644
index 000000000..311598fa9
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010-2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc_manager.h"
+#include "tnc_imc.h"
+
+#include <tncifimc.h>
+
+#include <utils/debug.h>
+#include <threading/rwlock.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+
+typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t;
+
+/**
+ * Private data of an imc_manager_t object.
+ */
+struct private_tnc_imc_manager_t {
+
+ /**
+ * Public members of imc_manager_t.
+ */
+ imc_manager_t public;
+
+ /**
+ * Linked list of IMCs
+ */
+ linked_list_t *imcs;
+
+ /**
+ * Lock to access IMC list
+ */
+ rwlock_t *lock;
+
+ /**
+ * Next IMC ID to be assigned
+ */
+ TNC_IMCID next_imc_id;
+
+ /**
+ * Mutex to access next IMC ID
+ */
+ mutex_t *id_mutex;
+};
+
+METHOD(imc_manager_t, add, bool,
+ private_tnc_imc_manager_t *this, imc_t *imc)
+{
+ TNC_Version version;
+ TNC_IMCID imc_id;
+
+ this->id_mutex->lock(this->id_mutex);
+ imc_id = this->next_imc_id++;
+ this->id_mutex->unlock(this->id_mutex);
+
+ imc->set_id(imc, imc_id);
+ if (imc->initialize(imc_id, TNC_IFIMC_VERSION_1,
+ TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc));
+ return FALSE;
+ }
+ this->lock->write_lock(this->lock);
+ this->imcs->insert_last(this->imcs, imc);
+ this->lock->unlock(this->lock);
+
+ if (imc->provide_bind_function(imc->get_id(imc),
+ TNC_TNCC_BindFunction) != TNC_RESULT_SUCCESS)
+ {
+ if (imc->terminate)
+ {
+ imc->terminate(imc->get_id(imc));
+ }
+ DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function",
+ imc->get_name(imc));
+ this->lock->write_lock(this->lock);
+ this->imcs->remove_last(this->imcs, (void**)&imc);
+ this->lock->unlock(this->lock);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(imc_manager_t, remove_, imc_t*,
+ private_tnc_imc_manager_t *this, TNC_IMCID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc, *removed_imc = NULL;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ this->imcs->remove_at(this->imcs, enumerator);
+ removed_imc = imc;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return removed_imc;
+}
+
+METHOD(imc_manager_t, load, bool,
+ private_tnc_imc_manager_t *this, char *name, char *path)
+{
+ imc_t *imc;
+
+ imc = tnc_imc_create(name, path);
+ if (!imc)
+ {
+ return FALSE;
+ }
+ if (!add(this, imc))
+ {
+ imc->destroy(imc);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), name, path);
+ return TRUE;
+}
+
+METHOD(imc_manager_t, load_from_functions, bool,
+ private_tnc_imc_manager_t *this, char *name,
+ TNC_IMC_InitializePointer initialize,
+ TNC_IMC_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMC_BeginHandshakePointer begin_handshake,
+ TNC_IMC_ReceiveMessagePointer receive_message,
+ TNC_IMC_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMC_BatchEndingPointer batch_ending,
+ TNC_IMC_TerminatePointer terminate,
+ TNC_IMC_ProvideBindFunctionPointer provide_bind_function)
+{
+ imc_t *imc;
+
+ imc = tnc_imc_create_from_functions(name,
+ initialize, notify_connection_change,
+ begin_handshake, receive_message,
+ receive_message_long, batch_ending,
+ terminate, provide_bind_function);
+ if (!imc)
+ {
+ return FALSE;
+ }
+ if (!add(this, imc))
+ {
+ imc->destroy(imc);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMC %u \"%s\" loaded", imc->get_id(imc), name);
+ return TRUE;
+}
+
+METHOD(imc_manager_t, is_registered, bool,
+ private_tnc_imc_manager_t *this, TNC_IMCID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->has_id(imc, id))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+METHOD(imc_manager_t, reserve_id, bool,
+ private_tnc_imc_manager_t *this, TNC_IMCID id, TNC_UInt32 *new_id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ found = TRUE;
+ this->id_mutex->lock(this->id_mutex);
+ *new_id = this->next_imc_id++;
+ this->id_mutex->unlock(this->id_mutex);
+ imc->add_id(imc, *new_id);
+ DBG2(DBG_TNC, "additional ID %u reserved for IMC with primary ID %u",
+ *new_id, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+METHOD(imc_manager_t, get_preferred_language, char*,
+ private_tnc_imc_manager_t *this)
+{
+ return lib->settings->get_str(lib->settings,
+ "libtnccs.plugins.tnc-imc.preferred_language", "en");
+}
+
+METHOD(imc_manager_t, notify_connection_change, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState state)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->notify_connection_change)
+ {
+ imc->notify_connection_change(imc->get_id(imc), id, state);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imc_manager_t, begin_handshake, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ imc->begin_handshake(imc->get_id(imc), id);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imc_manager_t, set_message_types, TNC_Result,
+ private_tnc_imc_manager_t *this, TNC_IMCID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ imc->set_message_types(imc, supported_types, type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return result;
+}
+
+METHOD(imc_manager_t, set_message_types_long, TNC_Result,
+ private_tnc_imc_manager_t *this, TNC_IMCID id,
+ TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ imc->set_message_types_long(imc, supported_vids, supported_subtypes,
+ type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return result;
+}
+
+METHOD(imc_manager_t, receive_message, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id,
+ bool excl,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imv_id,
+ TNC_UInt32 dst_imc_id)
+{
+ bool type_supported = FALSE;
+ TNC_MessageType msg_type;
+ TNC_UInt32 msg_flags;
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->type_supported(imc, msg_vid, msg_subtype) &&
+ (!excl || (excl && imc->has_id(imc, dst_imc_id))))
+ {
+ if (imc->receive_message_long && src_imv_id)
+ {
+ type_supported = TRUE;
+ msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+ imc->receive_message_long(imc->get_id(imc), connection_id,
+ msg_flags, msg, msg_len, msg_vid, msg_subtype,
+ src_imv_id, dst_imc_id);
+
+ }
+ else if (imc->receive_message && msg_vid <= TNC_VENDORID_ANY &&
+ msg_subtype <= TNC_SUBTYPE_ANY)
+ {
+ type_supported = TRUE;
+ msg_type = (msg_vid << 8) | msg_subtype;
+ imc->receive_message(imc->get_id(imc), connection_id,
+ msg, msg_len, msg_type);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!type_supported)
+ {
+ DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMC",
+ msg_vid, msg_subtype);
+ }
+}
+
+METHOD(imc_manager_t, batch_ending, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->batch_ending)
+ {
+ imc->batch_ending(imc->get_id(imc), id);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imc_manager_t, destroy, void,
+ private_tnc_imc_manager_t *this)
+{
+ imc_t *imc;
+
+ while (this->imcs->remove_last(this->imcs, (void**)&imc) == SUCCESS)
+ {
+ if (imc->terminate &&
+ imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
+ imc->get_name(imc));
+ }
+ imc->destroy(imc);
+ }
+ this->imcs->destroy(this->imcs);
+ this->lock->destroy(this->lock);
+ this->id_mutex->destroy(this->id_mutex);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imc_manager_t* tnc_imc_manager_create(void)
+{
+ private_tnc_imc_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add = _add,
+ .remove = _remove_, /* avoid name conflict with stdio.h */
+ .load = _load,
+ .load_from_functions = _load_from_functions,
+ .is_registered = _is_registered,
+ .reserve_id = _reserve_id,
+ .get_preferred_language = _get_preferred_language,
+ .notify_connection_change = _notify_connection_change,
+ .begin_handshake = _begin_handshake,
+ .set_message_types = _set_message_types,
+ .set_message_types_long = _set_message_types_long,
+ .receive_message = _receive_message,
+ .batch_ending = _batch_ending,
+ .destroy = _destroy,
+ },
+ .imcs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .id_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .next_imc_id = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.h b/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.h
new file mode 100644
index 000000000..ed490293b
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_manager.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ *
+ * @defgroup tnc_imc_manager tnc_imc_manager
+ * @{ @ingroup tnc_imc
+ */
+
+#ifndef TNC_IMC_MANAGER_H_
+#define TNC_IMC_MANAGER_H_
+
+#include <tnc/imc/imc_manager.h>
+
+/**
+ * Create an IMC manager instance.
+ */
+imc_manager_t *tnc_imc_manager_create();
+
+#endif /** TNC_IMC_MANAGER_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
new file mode 100644
index 000000000..859dded79
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010-2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc_plugin.h"
+#include "tnc_imc_manager.h"
+
+#include <tnc/tnc.h>
+
+typedef struct private_tnc_imc_plugin_t private_tnc_imc_plugin_t;
+
+/**
+ * Private data of a tnc_imc_plugin_t object.
+ */
+struct private_tnc_imc_plugin_t {
+
+ /**
+ * Public interface.
+ */
+ tnc_imc_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_tnc_imc_plugin_t *this)
+{
+ return "tnc-imc";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_tnc_imc_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
+ PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_tnc_imc_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnc_imc_plugin_create(void)
+{
+ private_tnc_imc_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h
new file mode 100644
index 000000000..8c5521cb2
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnc_imc tnc_imc
+ * @ingroup cplugins
+ *
+ * @defgroup tnc_imc_plugin tnc_imc_plugin
+ * @{ @ingroup tnc_imc
+ */
+
+#ifndef TNC_IMC_PLUGIN_H_
+#define TNC_IMC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnc_imc_plugin_t tnc_imc_plugin_t;
+
+/**
+ * TNC IMC plugin
+ */
+struct tnc_imc_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNC_IMC_PLUGIN_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.am b/src/libtnccs/plugins/tnc_imv/Makefile.am
new file mode 100644
index 000000000..0541d4c86
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.am
@@ -0,0 +1,24 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnc-imv.la
+libstrongswan_tnc_imv_la_LIBADD = \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnc_imv_la_SOURCES = \
+ tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \
+ tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \
+ tnc_imv_recommendations.h tnc_imv_recommendations.c
+
+libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.in b/src/libtnccs/plugins/tnc_imv/Makefile.in
new file mode 100644
index 000000000..20087a7a2
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.in
@@ -0,0 +1,768 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libtnccs/plugins/tnc_imv
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_tnc_imv_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo tnc_imv.lo \
+ tnc_imv_manager.lo tnc_imv_bind_function.lo \
+ tnc_imv_recommendations.lo
+libstrongswan_tnc_imv_la_OBJECTS = \
+ $(am_libstrongswan_tnc_imv_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnc_imv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnc_imv_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnc_imv_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnc_imv_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnc_imv_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnc_imv_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs \
+ -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = \
+ -rdynamic
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imv.la
+@MONOLITHIC_FALSE@libstrongswan_tnc_imv_la_LIBADD = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+libstrongswan_tnc_imv_la_SOURCES = \
+ tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \
+ tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \
+ tnc_imv_recommendations.h tnc_imv_recommendations.c
+
+libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_imv/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_imv/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-tnc-imv.la: $(libstrongswan_tnc_imv_la_OBJECTS) $(libstrongswan_tnc_imv_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnc_imv_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnc_imv_la_LINK) $(am_libstrongswan_tnc_imv_la_rpath) $(libstrongswan_tnc_imv_la_OBJECTS) $(libstrongswan_tnc_imv_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_bind_function.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_recommendations.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnc_imv/tnc_imv.c b/src/libtnccs/plugins/tnc_imv/tnc_imv.c
new file mode 100644
index 000000000..ebf904513
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen,
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv.h"
+
+#include <dlfcn.h>
+
+#include <tncif_pa_subtypes.h>
+
+#include <utils/debug.h>
+#include <library.h>
+#include <collections/linked_list.h>
+#include <threading/mutex.h>
+
+typedef struct private_tnc_imv_t private_tnc_imv_t;
+
+/**
+ * Private data of an imv_t object.
+ */
+struct private_tnc_imv_t {
+
+ /**
+ * Public members of imv_t.
+ */
+ imv_t public;
+
+ /**
+ * Name of loaded IMV
+ */
+ char *name;
+
+ /**
+ * Handle of loaded IMV
+ */
+ void *handle;
+
+ /**
+ * ID of loaded IMV
+ */
+ TNC_IMVID id;
+
+ /**
+ * List of additional IMV IDs
+ */
+ linked_list_t *additional_ids;
+
+ /**
+ * List of message types supported by IMV - Vendor ID part
+ */
+ TNC_VendorIDList supported_vids;
+
+ /**
+ * List of message types supported by IMV - Subtype part
+ */
+ TNC_MessageSubtypeList supported_subtypes;
+
+ /**
+ * Number of supported message types
+ */
+ TNC_UInt32 type_count;
+
+ /**
+ * mutex to lock the imv_t object
+ */
+ mutex_t *mutex;
+};
+
+METHOD(imv_t, set_id, void,
+ private_tnc_imv_t *this, TNC_IMVID id)
+{
+ this->id = id;
+}
+
+METHOD(imv_t, get_id, TNC_IMVID,
+ private_tnc_imv_t *this)
+{
+ return this->id;
+}
+
+METHOD(imv_t, add_id, void,
+ private_tnc_imv_t *this, TNC_IMVID id)
+{
+ TNC_IMVID *new_id;
+
+ new_id = malloc_thing(TNC_IMVID);
+ *new_id = id;
+ this->additional_ids->insert_last(this->additional_ids, new_id);
+}
+
+METHOD(imv_t, has_id, bool,
+ private_tnc_imv_t *this, TNC_IMVID id)
+{
+ enumerator_t *enumerator;
+ TNC_IMVID *additional_id;
+ bool found = FALSE;
+
+ /* check primary IMV ID */
+ if (id == this->id)
+ {
+ return TRUE;
+ }
+
+ /* return if there are no additional IMV IDs */
+ if (this->additional_ids->get_count(this->additional_ids) == 0)
+ {
+ return FALSE;
+ }
+
+ /* check additional IMV IDs */
+ enumerator = this->additional_ids->create_enumerator(this->additional_ids);
+ while (enumerator->enumerate(enumerator, &additional_id))
+ {
+ if (id == *additional_id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(imv_t, get_name, char*,
+ private_tnc_imv_t *this)
+{
+ return this->name;
+}
+
+METHOD(imv_t, set_message_types, void,
+ private_tnc_imv_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ char buf[BUF_LEN];
+ char *pos = buf;
+ int len = sizeof(buf);
+ int i, written;
+ size_t size;
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ enum_name_t *pa_subtype_names;
+
+ /* lock the imv_t instance */
+ this->mutex->lock(this->mutex);
+
+ /* Free existing VendorID and MessageSubtype lists */
+ free(this->supported_vids);
+ this->supported_vids = NULL;
+ free(this->supported_subtypes);
+ this->supported_subtypes = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_types)
+ {
+ size = type_count * sizeof(TNC_VendorID);
+ this->supported_vids = malloc(size);
+ size = type_count * sizeof(TNC_MessageSubtype);
+ this->supported_subtypes = malloc(size);
+
+ for (i = 0; i < type_count; i++)
+ {
+ vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY;
+ subtype = supported_types[i] & TNC_SUBTYPE_ANY;
+
+ pa_subtype_names = get_pa_subtype_names(vid);
+ if (pa_subtype_names)
+ {
+ written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x",
+ pen_names, vid, pa_subtype_names, subtype,
+ vid, subtype);
+ }
+ else
+ {
+ written = snprintf(pos, len," '%N' 0x%06x/0x%02x",
+ pen_names, vid, vid, subtype);
+ }
+ if (written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+
+ this->supported_vids[i] = vid;
+ this->supported_subtypes[i] = subtype;
+ }
+ }
+ *pos = '\0';
+ DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s",
+ this->id, type_count, (type_count == 1) ? "":"s", buf);
+
+ /* unlock the imv_t instance */
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(imv_t, set_message_types_long, void,
+ private_tnc_imv_t *this, TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count)
+{
+ char buf[BUF_LEN];
+ char *pos = buf;
+ int len = sizeof(buf);
+ int i, written;
+ size_t size;
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ enum_name_t *pa_subtype_names;
+
+ /* lock the imv_t instance */
+ this->mutex->lock(this->mutex);
+
+ /* Free existing VendorID and MessageSubtype lists */
+ free(this->supported_vids);
+ this->supported_vids = NULL;
+ free(this->supported_subtypes);
+ this->supported_subtypes = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_vids && supported_subtypes)
+ {
+ size = type_count * sizeof(TNC_VendorID);
+ this->supported_vids = malloc(size);
+ memcpy(this->supported_vids, supported_vids, size);
+ size = type_count * sizeof(TNC_MessageSubtype);
+ this->supported_subtypes = malloc(size);
+ memcpy(this->supported_subtypes, supported_subtypes, size);
+
+ for (i = 0; i < type_count; i++)
+ {
+ vid = supported_vids[i];
+ subtype = supported_subtypes[i];
+
+ pa_subtype_names = get_pa_subtype_names(vid);
+ if (pa_subtype_names)
+ {
+ written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x",
+ pen_names, vid, pa_subtype_names, subtype,
+ vid, subtype);
+ }
+ else
+ {
+ written = snprintf(pos, len," '%N' 0x%06x/0x%08x",
+ pen_names, vid, vid, subtype);
+ }
+ if (written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ }
+ *pos = '\0';
+ DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s",
+ this->id, type_count, (type_count == 1) ? "":"s", buf);
+
+ /* unlock the imv_t instance */
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(imv_t, type_supported, bool,
+ private_tnc_imv_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype)
+{
+ TNC_VendorID vid;
+ TNC_MessageSubtype subtype;
+ int i;
+
+ for (i = 0; i < this->type_count; i++)
+ {
+ vid = this->supported_vids[i];
+ subtype = this->supported_subtypes[i];
+
+ if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) ||
+ (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY ||
+ subtype == msg_subtype)))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(imv_t, destroy, void,
+ private_tnc_imv_t *this)
+{
+ if (this->handle && lib->settings->get_bool(lib->settings,
+ "libtnccs.plugins.tnc-imv.dlclose", TRUE))
+ {
+ dlclose(this->handle);
+ }
+ this->mutex->destroy(this->mutex);
+ this->additional_ids->destroy_function(this->additional_ids, free);
+ free(this->supported_vids);
+ free(this->supported_subtypes);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Generic constructor.
+ */
+static private_tnc_imv_t* tnc_imv_create_empty(char *name)
+{
+ private_tnc_imv_t *this;
+
+ INIT(this,
+ .public = {
+ .set_id = _set_id,
+ .get_id = _get_id,
+ .add_id = _add_id,
+ .has_id = _has_id,
+ .get_name = _get_name,
+ .set_message_types = _set_message_types,
+ .set_message_types_long = _set_message_types_long,
+ .type_supported = _type_supported,
+ .destroy = _destroy,
+ },
+ .name = strdup(name),
+ .additional_ids = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ return this;
+}
+
+/**
+ * Described in header.
+ */
+imv_t* tnc_imv_create(char *name, char *path)
+{
+ private_tnc_imv_t *this;
+
+ this = tnc_imv_create_empty(name);
+
+ this->handle = dlopen(path, RTLD_LAZY);
+ if (!this->handle)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror());
+ destroy(this);
+ return NULL;
+ }
+
+ this->public.initialize = dlsym(this->handle, "TNC_IMV_Initialize");
+ if (!this->public.initialize)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+ this->public.notify_connection_change =
+ dlsym(this->handle, "TNC_IMV_NotifyConnectionChange");
+ this->public.solicit_recommendation =
+ dlsym(this->handle, "TNC_IMV_SolicitRecommendation");
+ if (!this->public.solicit_recommendation)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+ this->public.receive_message =
+ dlsym(this->handle, "TNC_IMV_ReceiveMessage");
+ this->public.receive_message_long =
+ dlsym(this->handle, "TNC_IMV_ReceiveMessageLong");
+ this->public.batch_ending =
+ dlsym(this->handle, "TNC_IMV_BatchEnding");
+ this->public.terminate =
+ dlsym(this->handle, "TNC_IMV_Terminate");
+ this->public.provide_bind_function =
+ dlsym(this->handle, "TNC_IMV_ProvideBindFunction");
+ if (!this->public.provide_bind_function)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n",
+ path, dlerror());
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
+/**
+ * Described in header.
+ */
+imv_t* tnc_imv_create_from_functions(char *name,
+ TNC_IMV_InitializePointer initialize,
+ TNC_IMV_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMV_ReceiveMessagePointer receive_message,
+ TNC_IMV_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMV_SolicitRecommendationPointer solicit_recommendation,
+ TNC_IMV_BatchEndingPointer batch_ending,
+ TNC_IMV_TerminatePointer terminate,
+ TNC_IMV_ProvideBindFunctionPointer provide_bind_function)
+{
+ private_tnc_imv_t *this;
+
+ this = tnc_imv_create_empty(name);
+
+ this->public.initialize = initialize;
+ this->public.notify_connection_change = notify_connection_change;
+ this->public.receive_message = receive_message;
+ this->public.receive_message_long = receive_message_long;
+ this->public.solicit_recommendation = solicit_recommendation;
+ this->public.batch_ending = batch_ending;
+ this->public.terminate = terminate;
+ this->public.provide_bind_function = provide_bind_function;
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv.h b/src/libtnccs/plugins/tnc_imv/tnc_imv.h
new file mode 100644
index 000000000..e7c7b8b4f
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_t tnc_imv
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_H_
+#define TNC_IMV_H_
+
+#include <tnc/imv/imv.h>
+
+/**
+ * Create an Integrity Measurement Verifier loaded from a library.
+ *
+ * @param name name of the IMV
+ * @param filename path to the dynamic IMV library
+ * @return instance of the imv_t interface
+ */
+imv_t* tnc_imv_create(char *name, char *filename);
+
+/**
+ * Create an Integrity Measurement Verifier from a set of IMV functions.
+ *
+ * @param name name of the IMV
+ * @param initialize TNC_IMV_InitializePointer
+ * @param notify_connection_change TNC_IMV_NotifyConnectionChangePointer
+ * @param receive_message TNC_IMV_ReceiveMessagePointer
+ * @param receive_message_long TNC_IMV_ReceiveMessageLongPointer
+ * @param solicit_recommendation TNC_IMV_SolicitRecommendationPointer
+ * @param batch_ending TNC_IMV_BatchEndingPointer
+ * @param terminate TNC_IMV_TerminatePointer
+ * @param provide_bind_function TNC_IMV_ProvideBindFunctionPointer
+ * @return instance of the imv_t interface
+ */
+imv_t* tnc_imv_create_from_functions(char *name,
+ TNC_IMV_InitializePointer initialize,
+ TNC_IMV_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMV_ReceiveMessagePointer receive_message,
+ TNC_IMV_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMV_SolicitRecommendationPointer solicit_recommendation,
+ TNC_IMV_BatchEndingPointer batch_ending,
+ TNC_IMV_TerminatePointer terminate,
+ TNC_IMV_ProvideBindFunctionPointer provide_bind_function);
+
+#endif /** TNC_IMV_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_bind_function.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_bind_function.c
new file mode 100644
index 000000000..36cdb7fbb
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_bind_function.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010-2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <tnc/tnc.h>
+#include <tnc/imv/imv_manager.h>
+#include <tnc/tnccs/tnccs_manager.h>
+
+#include <utils/debug.h>
+
+/**
+ * Called by the IMV to inform a TNCS about the set of message types the IMV
+ * is able to receive
+ */
+TNC_Result TNC_TNCS_ReportMessageTypes(TNC_IMVID imv_id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->imvs->set_message_types(tnc->imvs, imv_id, supported_types,
+ type_count);
+}
+
+/**
+ * Called by the IMV to inform a TNCS about the set of message types the IMV
+ * is able to receive. This function supports long message types.
+ */
+TNC_Result TNC_TNCS_ReportMessageTypesLong(TNC_IMVID imv_id,
+ TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes,
+ TNC_UInt32 type_count)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring ReportMessageTypesLong() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->imvs->set_message_types_long(tnc->imvs, imv_id, supported_vids,
+ supported_subtypes, type_count);
+}
+
+/**
+ * Called by the IMV to ask a TNCS to retry an Integrity Check Handshake
+ */
+TNC_Result TNC_TNCS_RequestHandshakeRetry(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_RetryReason reason)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->request_handshake_retry(tnc->tnccs, FALSE, imv_id,
+ connection_id, reason);
+}
+
+/**
+ * Called by the IMV when an IMV-IMC message is to be sent
+ */
+TNC_Result TNC_TNCS_SendMessage(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ TNC_VendorID msg_vid;
+ TNC_MessageSubtype msg_subtype;
+
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY;
+ msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+
+ return tnc->tnccs->send_message(tnc->tnccs, TNC_IMCID_ANY, imv_id,
+ connection_id, 0, msg, msg_len, msg_vid, msg_subtype);
+}
+
+/**
+ * Called by the IMV when an IMV-IMC message is to be sent over IF-TNCCS 2.0
+ */
+TNC_Result TNC_TNCS_SendMessageLong(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 imc_id)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring SendMessageLong() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->send_message(tnc->tnccs, imc_id, imv_id, connection_id,
+ msg_flags, msg, msg_len, msg_vid, msg_subtype);
+}
+
+/**
+ * Called by the IMV to deliver its IMV Action Recommendation and IMV Evaluation
+ * Result to the TNCS
+ */
+TNC_Result TNC_TNCS_ProvideRecommendation(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_IMV_Action_Recommendation recommendation,
+ TNC_IMV_Evaluation_Result evaluation)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring ProvideRecommendation() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->provide_recommendation(tnc->tnccs, imv_id, connection_id,
+ recommendation, evaluation);
+}
+
+/**
+ * Called by the IMV to get the value of an attribute associated with a
+ * connection or with the TNCS as a whole.
+ */
+TNC_Result TNC_TNCS_GetAttribute(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *out_value_len)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->get_attribute(tnc->tnccs, FALSE, imv_id, connection_id,
+ attribute_id, buffer_len, buffer, out_value_len);
+}
+
+/**
+ * Called by the IMV to set the value of an attribute associated with a
+ * connection or with the TNCS as a whole.
+ */
+TNC_Result TNC_TNCS_SetAttribute(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer)
+{
+ if (!tnc->imvs->is_registered(tnc->imvs, imv_id))
+ {
+ DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return tnc->tnccs->set_attribute(tnc->tnccs, FALSE, imv_id, connection_id,
+ attribute_id, buffer_len, buffer);
+}
+
+/**
+ * Called by the IMV when it wants to reserve an additional IMV ID for itself
+ */
+TNC_Result TNC_TNCS_ReserveAdditionalIMVID(TNC_IMVID imv_id, TNC_UInt32 *new_id)
+{
+ if (tnc->imvs->reserve_id(tnc->imvs, imv_id, new_id))
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+ DBG1(DBG_TNC, "ignoring ReserveAdditionalIMVID() from unregistered IMV %u",
+ imv_id);
+ return TNC_RESULT_INVALID_PARAMETER;
+}
+
+/**
+ * Called by the IMV when it needs a function pointer
+ */
+TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id,
+ char *function_name,
+ void **function_pointer)
+{
+ if (streq(function_name, "TNC_TNCS_ReportMessageTypes"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ReportMessageTypes;
+ }
+ else if (streq(function_name, "TNC_TNCS_ReportMessageTypesLong"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ReportMessageTypesLong;
+ }
+ else if (streq(function_name, "TNC_TNCS_RequestHandshakeRetry"))
+ {
+ *function_pointer = (void*)TNC_TNCS_RequestHandshakeRetry;
+ }
+ else if (streq(function_name, "TNC_TNCS_SendMessage"))
+ {
+ *function_pointer = (void*)TNC_TNCS_SendMessage;
+ }
+ else if (streq(function_name, "TNC_TNCS_SendMessageLong"))
+ {
+ *function_pointer = (void*)TNC_TNCS_SendMessageLong;
+ }
+ else if (streq(function_name, "TNC_TNCS_ProvideRecommendation"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ProvideRecommendation;
+ }
+ else if (streq(function_name, "TNC_TNCS_GetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCS_GetAttribute;
+ }
+ else if (streq(function_name, "TNC_TNCS_SetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCS_SetAttribute;
+ }
+ else if (streq(function_name, "TNC_TNCS_ReserveAdditionalIMVID"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ReserveAdditionalIMVID;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return TNC_RESULT_SUCCESS;
+}
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
new file mode 100644
index 000000000..b4f131b5d
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv_manager.h"
+#include "tnc_imv.h"
+#include "tnc_imv_recommendations.h"
+
+#include <tncifimv.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <utils/debug.h>
+#include <threading/rwlock.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+
+typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t;
+
+/**
+ * Private data of an imv_manager_t object.
+ */
+struct private_tnc_imv_manager_t {
+
+ /**
+ * Public members of imv_manager_t.
+ */
+ imv_manager_t public;
+
+ /**
+ * Linked list of IMVs
+ */
+ linked_list_t *imvs;
+
+ /**
+ * Lock for IMV list
+ */
+ rwlock_t *lock;
+
+ /**
+ * Next IMV ID to be assigned
+ */
+ TNC_IMVID next_imv_id;
+
+ /**
+ * Mutex to access next IMV ID
+ */
+ mutex_t *id_mutex;
+
+ /**
+ * Policy defining how to derive final recommendation from individual ones
+ */
+ recommendation_policy_t policy;
+};
+
+METHOD(imv_manager_t, add, bool,
+ private_tnc_imv_manager_t *this, imv_t *imv)
+{
+ TNC_Version version;
+ TNC_IMVID imv_id;
+
+ this->id_mutex->lock(this->id_mutex);
+ imv_id = this->next_imv_id++;
+ this->id_mutex->unlock(this->id_mutex);
+
+ imv->set_id(imv, imv_id);
+ if (imv->initialize(imv_id, TNC_IFIMV_VERSION_1,
+ TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv));
+ return FALSE;
+ }
+ this->lock->write_lock(this->lock);
+ this->imvs->insert_last(this->imvs, imv);
+ this->lock->unlock(this->lock);
+
+ if (imv->provide_bind_function(imv->get_id(imv),
+ TNC_TNCS_BindFunction) != TNC_RESULT_SUCCESS)
+ {
+ if (imv->terminate)
+ {
+ imv->terminate(imv->get_id(imv));
+ }
+ DBG1(DBG_TNC, "IMV \"%s\" failed to obtain bind function",
+ imv->get_name(imv));
+ this->lock->write_lock(this->lock);
+ this->imvs->remove_last(this->imvs, (void**)&imv);
+ this->lock->unlock(this->lock);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(imv_manager_t, remove_, imv_t*,
+ private_tnc_imv_manager_t *this, TNC_IMVID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv, *removed_imv = NULL;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ this->imvs->remove_at(this->imvs, enumerator);
+ removed_imv = imv;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return removed_imv;
+}
+
+METHOD(imv_manager_t, load, bool,
+ private_tnc_imv_manager_t *this, char *name, char *path)
+{
+ imv_t *imv;
+
+ imv = tnc_imv_create(name, path);
+ if (!imv)
+ {
+ return FALSE;
+ }
+ if (!add(this, imv))
+ {
+ imv->destroy(imv);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), name, path);
+ return TRUE;
+}
+
+METHOD(imv_manager_t, load_from_functions, bool,
+ private_tnc_imv_manager_t *this, char *name,
+ TNC_IMV_InitializePointer initialize,
+ TNC_IMV_NotifyConnectionChangePointer notify_connection_change,
+ TNC_IMV_ReceiveMessagePointer receive_message,
+ TNC_IMV_ReceiveMessageLongPointer receive_message_long,
+ TNC_IMV_SolicitRecommendationPointer solicit_recommendation,
+ TNC_IMV_BatchEndingPointer batch_ending,
+ TNC_IMV_TerminatePointer terminate,
+ TNC_IMV_ProvideBindFunctionPointer provide_bind_function)
+{
+ imv_t *imv;
+
+ imv = tnc_imv_create_from_functions(name,
+ initialize,notify_connection_change,
+ receive_message, receive_message_long,
+ solicit_recommendation, batch_ending,
+ terminate, provide_bind_function);
+ if (!imv)
+ {
+ return FALSE;
+ }
+ if (!add(this, imv))
+ {
+ imv->destroy(imv);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMV %u \"%s\" loaded", imv->get_id(imv), name);
+ return TRUE;
+}
+
+METHOD(imv_manager_t, is_registered, bool,
+ private_tnc_imv_manager_t *this, TNC_IMVID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->has_id(imv, id))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+METHOD(imv_manager_t, reserve_id, bool,
+ private_tnc_imv_manager_t *this, TNC_IMVID id, TNC_UInt32 *new_id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ found = TRUE;
+ this->id_mutex->lock(this->id_mutex);
+ *new_id = this->next_imv_id++;
+ this->id_mutex->unlock(this->id_mutex);
+ imv->add_id(imv, *new_id);
+ DBG2(DBG_TNC, "additional ID %u reserved for IMV with primary ID %u",
+ *new_id, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t,
+ private_tnc_imv_manager_t *this)
+{
+ return this->policy;
+}
+
+METHOD(imv_manager_t, create_recommendations, recommendations_t*,
+ private_tnc_imv_manager_t *this)
+{
+ return tnc_imv_recommendations_create(this->imvs);
+}
+
+
+METHOD(imv_manager_t, notify_connection_change, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState state)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->notify_connection_change)
+ {
+ imv->notify_connection_change(imv->get_id(imv), id, state);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imv_manager_t, set_message_types, TNC_Result,
+ private_tnc_imv_manager_t *this, TNC_IMVID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ imv->set_message_types(imv, supported_types, type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return result;
+}
+
+METHOD(imv_manager_t, set_message_types_long, TNC_Result,
+ private_tnc_imv_manager_t *this, TNC_IMVID id,
+ TNC_VendorIDList supported_vids,
+ TNC_MessageSubtypeList supported_subtypes,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ imv->set_message_types_long(imv, supported_vids, supported_subtypes,
+ type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return result;
+}
+
+METHOD(imv_manager_t, solicit_recommendation, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ imv->solicit_recommendation(imv->get_id(imv), id);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imv_manager_t, receive_message, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
+ bool excl,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imc_id,
+ TNC_UInt32 dst_imv_id)
+{
+ bool type_supported = FALSE;
+ TNC_MessageType msg_type;
+ TNC_UInt32 msg_flags;
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ msg_type = (msg_vid << 8) | msg_subtype;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->type_supported(imv, msg_vid, msg_subtype) &&
+ (!excl || (excl && imv->has_id(imv, dst_imv_id))))
+ {
+ if (imv->receive_message_long && src_imc_id)
+ {
+ type_supported = TRUE;
+ msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+ imv->receive_message_long(imv->get_id(imv), connection_id,
+ msg_flags, msg, msg_len, msg_vid, msg_subtype,
+ src_imc_id, dst_imv_id);
+
+ }
+ else if (imv->receive_message && msg_vid <= TNC_VENDORID_ANY &&
+ msg_subtype <= TNC_SUBTYPE_ANY)
+ {
+ type_supported = TRUE;
+ msg_type = (msg_vid << 8) | msg_subtype;
+ imv->receive_message(imv->get_id(imv), connection_id,
+ msg, msg_len, msg_type);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!type_supported)
+ {
+ DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMV",
+ msg_vid, msg_subtype);
+ }
+}
+
+METHOD(imv_manager_t, batch_ending, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->batch_ending)
+ {
+ imv->batch_ending(imv->get_id(imv), id);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(imv_manager_t, destroy, void,
+ private_tnc_imv_manager_t *this)
+{
+ imv_t *imv;
+
+ while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
+ {
+ if (imv->terminate &&
+ imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
+ imv->get_name(imv));
+ }
+ imv->destroy(imv);
+ }
+ this->imvs->destroy(this->imvs);
+ this->lock->destroy(this->lock);
+ this->id_mutex->destroy(this->id_mutex);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_manager_t* tnc_imv_manager_create(void)
+{
+ private_tnc_imv_manager_t *this;
+ recommendation_policy_t policy;
+
+ INIT(this,
+ .public = {
+ .add = _add,
+ .remove = _remove_, /* avoid name conflict with stdio.h */
+ .load = _load,
+ .load_from_functions = _load_from_functions,
+ .is_registered = _is_registered,
+ .reserve_id = _reserve_id,
+ .get_recommendation_policy = _get_recommendation_policy,
+ .create_recommendations = _create_recommendations,
+ .notify_connection_change = _notify_connection_change,
+ .set_message_types = _set_message_types,
+ .set_message_types_long = _set_message_types_long,
+ .solicit_recommendation = _solicit_recommendation,
+ .receive_message = _receive_message,
+ .batch_ending = _batch_ending,
+ .destroy = _destroy,
+ },
+ .imvs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .id_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .next_imv_id = 1,
+ );
+
+ policy = enum_from_name(recommendation_policy_names,
+ lib->settings->get_str(lib->settings,
+ "libtnccs.plugins.tnc-imv.recommendation_policy", "default"));
+ this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT;
+ DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
+ recommendation_policy_names, this->policy);
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.h b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.h
new file mode 100644
index 000000000..2fe9e7ae3
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_manager tnc_imv_manager
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_MANAGER_H_
+#define TNC_IMV_MANAGER_H_
+
+#include <tnc/imv/imv_manager.h>
+
+/**
+ * Create an IMV manager instance.
+ */
+imv_manager_t *tnc_imv_manager_create();
+
+#endif /** TNC_IMV_MANAGER_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.c
new file mode 100644
index 000000000..d06c2fcaf
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010-2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv_plugin.h"
+#include "tnc_imv_manager.h"
+
+#include <tnc/tnc.h>
+
+
+typedef struct private_tnc_imv_plugin_t private_tnc_imv_plugin_t;
+
+/**
+ * Private data of a tnc_imv_plugin_t object.
+ */
+struct private_tnc_imv_plugin_t {
+
+ /**
+ * Public interface.
+ */
+ tnc_imv_plugin_t public;
+
+};
+
+
+METHOD(plugin_t, get_name, char*,
+ tnc_imv_plugin_t *this)
+{
+ return "tnc-imv";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_tnc_imv_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnc_manager_register, tnc_imv_manager_create),
+ PLUGIN_PROVIDE(CUSTOM, "imv-manager"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
+ PLUGIN_SDEPEND(DATABASE, DB_ANY),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_tnc_imv_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnc_imv_plugin_create()
+{
+ private_tnc_imv_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h
new file mode 100644
index 000000000..afeee2ea2
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnc_imv tnc_imv
+ * @ingroup cplugins
+ *
+ * @defgroup tnc_imv_plugin tnc_imv_plugin
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_PLUGIN_H_
+#define TNC_IMV_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnc_imv_plugin_t tnc_imv_plugin_t;
+
+/**
+ * TNC IMV plugin
+ */
+struct tnc_imv_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNC_IMV_PLUGIN_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.c
new file mode 100644
index 000000000..a9dbb2b9f
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2010-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <tncifimv.h>
+#include <tncif_names.h>
+#include <tncif_policy.h>
+
+#include <tnc/tnc.h>
+#include <tnc/imv/imv.h>
+#include <tnc/imv/imv_manager.h>
+#include <tnc/imv/imv_recommendations.h>
+
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+
+typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
+typedef struct recommendation_entry_t recommendation_entry_t;
+
+/**
+ * Recommendation entry
+ */
+struct recommendation_entry_t {
+
+ /**
+ * IMV ID
+ */
+ TNC_IMVID id;
+
+ /**
+ * Received a recommendation message from this IMV?
+ */
+ bool have_recommendation;
+
+ /**
+ * Action Recommendation provided by IMV instance
+ */
+ TNC_IMV_Action_Recommendation rec;
+
+ /**
+ * Evaluation Result provided by IMV instance
+ */
+ TNC_IMV_Evaluation_Result eval;
+
+ /**
+ * Reason string provided by IMV instance
+ */
+ chunk_t reason;
+
+ /**
+ * Reason language provided by IMV instance
+ */
+ chunk_t reason_language;
+};
+
+/**
+ * Private data of a recommendations_t object.
+ */
+struct private_tnc_imv_recommendations_t {
+
+ /**
+ * Public members of recommendations_t.
+ */
+ recommendations_t public;
+
+ /**
+ * list of recommendations and evaluations provided by IMVs
+ */
+ linked_list_t *recs;
+
+ /**
+ * Preferred language for remediation messages
+ */
+ chunk_t preferred_language;
+};
+
+METHOD(recommendations_t, provide_recommendation, TNC_Result,
+ private_tnc_imv_recommendations_t* this, TNC_IMVID id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'", id,
+ TNC_IMV_Action_Recommendation_names, rec,
+ TNC_IMV_Evaluation_Result_names, eval);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ entry->have_recommendation = TRUE;
+ entry->rec = rec;
+ entry->eval = eval;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL;
+}
+
+METHOD(recommendations_t, have_recommendation, bool,
+ private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ recommendation_policy_t policy;
+ TNC_IMV_Action_Recommendation final_rec;
+ TNC_IMV_Evaluation_Result final_eval;
+ bool first = TRUE, incomplete = FALSE;
+
+ final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ if (rec && eval)
+ {
+ *rec = final_rec;
+ *eval = final_eval;
+ }
+
+ if (this->recs->get_count(this->recs) == 0)
+ {
+ DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
+ return TRUE;
+ }
+ policy = tnc->imvs->get_recommendation_policy(tnc->imvs);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!entry->have_recommendation)
+ {
+ incomplete = TRUE;
+ break;
+ }
+ if (first)
+ {
+ final_rec = entry->rec;
+ final_eval = entry->eval;
+ first = FALSE;
+ continue;
+ }
+ switch (policy)
+ {
+ case RECOMMENDATION_POLICY_DEFAULT:
+ final_rec = tncif_policy_update_recommendation(final_rec,
+ entry->rec);
+ final_eval = tncif_policy_update_evaluation(final_eval,
+ entry->eval);
+ break;
+
+ case RECOMMENDATION_POLICY_ALL:
+ if (entry->rec != final_rec)
+ {
+ final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ }
+ if (entry->eval != final_eval)
+ {
+ final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ }
+ break;
+
+ case RECOMMENDATION_POLICY_ANY:
+ switch (entry->rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ final_rec = entry->rec;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ break;
+ }
+ switch (entry->eval)
+ {
+ case TNC_IMV_EVALUATION_RESULT_COMPLIANT:
+ final_eval = entry->eval;
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
+ final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_ERROR:
+ if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_DONT_KNOW:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (incomplete)
+ {
+ return FALSE;
+ }
+ if (rec && eval)
+ {
+ *rec = final_rec;
+ *eval = final_eval;
+ }
+ return TRUE;
+}
+
+METHOD(recommendations_t, clear_recommendation, void,
+ private_tnc_imv_recommendations_t *this)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ entry->have_recommendation = FALSE;
+ entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ chunk_clear(&entry->reason);
+ chunk_clear(&entry->reason_language);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(recommendations_t, get_preferred_language, chunk_t,
+ private_tnc_imv_recommendations_t *this)
+{
+ return this->preferred_language;
+}
+
+METHOD(recommendations_t, set_preferred_language, void,
+ private_tnc_imv_recommendations_t *this, chunk_t pref_lang)
+{
+ free(this->preferred_language.ptr);
+ this->preferred_language = chunk_clone(pref_lang);
+}
+
+METHOD(recommendations_t, set_reason_string, TNC_Result,
+ private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u is setting reason string to '%.*s'",
+ id, (int)reason.len, reason.ptr);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ free(entry->reason.ptr);
+ entry->reason = chunk_clone(reason);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
+}
+
+METHOD(recommendations_t, set_reason_language, TNC_Result,
+ private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason_lang)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u is setting reason language to '%.*s'",
+ id, (int)reason_lang.len, reason_lang.ptr);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ free(entry->reason_language.ptr);
+ entry->reason_language = chunk_clone(reason_lang);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
+}
+
+/**
+ * Enumerate reason and reason_language, not recommendation entries
+ */
+static bool reason_filter(void *null, recommendation_entry_t **entry,
+ TNC_IMVID *id, void *i2, chunk_t *reason, void *i3,
+ chunk_t *reason_language)
+{
+ if ((*entry)->reason.len)
+ {
+ *id = (*entry)->id;
+ *reason = (*entry)->reason;
+ *reason_language = (*entry)->reason_language;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+METHOD(recommendations_t, create_reason_enumerator, enumerator_t*,
+ private_tnc_imv_recommendations_t *this)
+{
+ return enumerator_create_filter(this->recs->create_enumerator(this->recs),
+ (void*)reason_filter, NULL, NULL);
+}
+
+METHOD(recommendations_t, destroy, void,
+ private_tnc_imv_recommendations_t *this)
+{
+ recommendation_entry_t *entry;
+
+ while (this->recs->remove_last(this->recs, (void**)&entry) == SUCCESS)
+ {
+ free(entry->reason.ptr);
+ free(entry->reason_language.ptr);
+ free(entry);
+ }
+ this->recs->destroy(this->recs);
+ free(this->preferred_language.ptr);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
+{
+ private_tnc_imv_recommendations_t *this;
+ recommendation_entry_t *entry;
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ INIT(this,
+ .public = {
+ .provide_recommendation = _provide_recommendation,
+ .have_recommendation = _have_recommendation,
+ .clear_recommendation = _clear_recommendation,
+ .get_preferred_language = _get_preferred_language,
+ .set_preferred_language = _set_preferred_language,
+ .set_reason_string = _set_reason_string,
+ .set_reason_language = _set_reason_language,
+ .create_reason_enumerator = _create_reason_enumerator,
+ .destroy = _destroy,
+ },
+ .recs = linked_list_create(),
+ );
+
+ enumerator = imv_list->create_enumerator(imv_list);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ entry = malloc_thing(recommendation_entry_t);
+ entry->id = imv->get_id(imv);
+ entry->have_recommendation = FALSE;
+ entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ entry->reason = chunk_empty;
+ entry->reason_language = chunk_empty;
+ this->recs->insert_last(this->recs, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.h b/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.h
new file mode 100644
index 000000000..66d03b2f8
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_recommendations.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_manager tnc_imv_manager
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_RECOMMENDATIONS_H_
+#define TNC_IMV_RECOMMENDATIONS_H_
+
+#include <tnc/imv/imv_recommendations.h>
+#include <collections/linked_list.h>
+
+/**
+ * Create an IMV empty recommendations instance
+ */
+recommendations_t *tnc_imv_recommendations_create();
+
+#endif /** TNC_IMV_RECOMMENDATIONS_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.am b/src/libtnccs/plugins/tnc_tnccs/Makefile.am
new file mode 100644
index 000000000..f16bf8e1b
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.am
@@ -0,0 +1,23 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la
+libstrongswan_tnc_tnccs_la_LIBADD = \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnc_tnccs_la_SOURCES = \
+ tnc_tnccs_plugin.h tnc_tnccs_plugin.c \
+ tnc_tnccs_manager.h tnc_tnccs_manager.c
+
+libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.in b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
new file mode 100644
index 000000000..776469098
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
@@ -0,0 +1,763 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libtnccs/plugins/tnc_tnccs
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_tnc_tnccs_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+am_libstrongswan_tnc_tnccs_la_OBJECTS = tnc_tnccs_plugin.lo \
+ tnc_tnccs_manager.lo
+libstrongswan_tnc_tnccs_la_OBJECTS = \
+ $(am_libstrongswan_tnc_tnccs_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnc_tnccs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnc_tnccs_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnc_tnccs_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnc_tnccs_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnc_tnccs_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnc_tnccs_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la
+@MONOLITHIC_FALSE@libstrongswan_tnc_tnccs_la_LIBADD = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+libstrongswan_tnc_tnccs_la_SOURCES = \
+ tnc_tnccs_plugin.h tnc_tnccs_plugin.c \
+ tnc_tnccs_manager.h tnc_tnccs_manager.c
+
+libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_tnccs/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnc_tnccs/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-tnc-tnccs.la: $(libstrongswan_tnc_tnccs_la_OBJECTS) $(libstrongswan_tnc_tnccs_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnc_tnccs_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnc_tnccs_la_LINK) $(am_libstrongswan_tnc_tnccs_la_rpath) $(libstrongswan_tnc_tnccs_la_OBJECTS) $(libstrongswan_tnc_tnccs_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_tnccs_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_tnccs_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
new file mode 100644
index 000000000..b8683f78c
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
@@ -0,0 +1,866 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+
+#include "tnc_tnccs_manager.h"
+
+#include <tnc/tnc.h>
+#include <tnc/imv/imv_manager.h>
+#include <tnc/imc/imc_manager.h>
+#include <tnc/imv/imv_manager.h>
+
+#include <tncif_identity.h>
+
+#include <tls.h>
+
+#include <utils/debug.h>
+#include <pen/pen.h>
+#include <bio/bio_writer.h>
+#include <collections/linked_list.h>
+#include <threading/rwlock.h>
+
+#include <stdio.h>
+
+typedef struct private_tnc_tnccs_manager_t private_tnc_tnccs_manager_t;
+typedef struct tnccs_entry_t tnccs_entry_t;
+typedef struct tnccs_connection_entry_t tnccs_connection_entry_t;
+
+/**
+ * TNCCS constructor entry
+ */
+struct tnccs_entry_t {
+
+ /**
+ * TNCCS protocol type
+ */
+ tnccs_type_t type;
+
+ /**
+ * constructor function to create instance
+ */
+ tnccs_constructor_t constructor;
+};
+
+/**
+ * TNCCS connection entry
+ */
+struct tnccs_connection_entry_t {
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID id;
+
+ /**
+ * TNCCS protocol type
+ */
+ tnccs_type_t type;
+
+ /**
+ * TNCCS instance
+ */
+ tnccs_t *tnccs;
+
+ /**
+ * TNCCS send message function
+ */
+ tnccs_send_message_t send_message;
+
+ /**
+ * TNCCS request handshake retry flag
+ */
+ bool *request_handshake_retry;
+
+ /**
+ * Maximum size of a PA-TNC message
+ */
+ u_int32_t max_msg_len;
+
+ /**
+ * collection of IMV recommendations
+ */
+ recommendations_t *recs;
+};
+
+/**
+ * private data of tnc_tnccs_manager
+ */
+struct private_tnc_tnccs_manager_t {
+
+ /**
+ * public functions
+ */
+ tnccs_manager_t public;
+
+ /**
+ * list of TNCCS protocol entries
+ */
+ linked_list_t *protocols;
+
+ /**
+ * rwlock to lock the TNCCS protocol entries
+ */
+ rwlock_t *protocol_lock;
+
+ /**
+ * connection ID counter
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * list of TNCCS connection entries
+ */
+ linked_list_t *connections;
+
+ /**
+ * rwlock to lock TNCCS connection entries
+ */
+ rwlock_t *connection_lock;
+
+};
+
+METHOD(tnccs_manager_t, add_method, void,
+ private_tnc_tnccs_manager_t *this, tnccs_type_t type,
+ tnccs_constructor_t constructor)
+{
+ tnccs_entry_t *entry;
+
+ entry = malloc_thing(tnccs_entry_t);
+ entry->type = type;
+ entry->constructor = constructor;
+
+ this->protocol_lock->write_lock(this->protocol_lock);
+ this->protocols->insert_last(this->protocols, entry);
+ this->protocol_lock->unlock(this->protocol_lock);
+}
+
+METHOD(tnccs_manager_t, remove_method, void,
+ private_tnc_tnccs_manager_t *this, tnccs_constructor_t constructor)
+{
+ enumerator_t *enumerator;
+ tnccs_entry_t *entry;
+
+ this->protocol_lock->write_lock(this->protocol_lock);
+ enumerator = this->protocols->create_enumerator(this->protocols);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (constructor == entry->constructor)
+ {
+ this->protocols->remove_at(this->protocols, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->protocol_lock->unlock(this->protocol_lock);
+}
+
+METHOD(tnccs_manager_t, create_instance, tnccs_t*,
+ private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server,
+ identification_t *server, identification_t *peer, tnc_ift_type_t transport,
+ tnccs_cb_t cb)
+{
+ enumerator_t *enumerator;
+ tnccs_entry_t *entry;
+ tnccs_t *protocol = NULL;
+
+ this->protocol_lock->read_lock(this->protocol_lock);
+ enumerator = this->protocols->create_enumerator(this->protocols);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (type == entry->type)
+ {
+ protocol = entry->constructor(is_server, server, peer, transport, cb);
+ if (protocol)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->protocol_lock->unlock(this->protocol_lock);
+
+ return protocol;
+}
+
+METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
+ private_tnc_tnccs_manager_t *this, tnccs_type_t type, tnccs_t *tnccs,
+ tnccs_send_message_t send_message, bool* request_handshake_retry,
+ u_int32_t max_msg_len, recommendations_t **recs)
+{
+ tnccs_connection_entry_t *entry;
+
+ entry = malloc_thing(tnccs_connection_entry_t);
+ entry->type = type;
+ entry->tnccs = tnccs;
+ entry->send_message = send_message;
+ entry->request_handshake_retry = request_handshake_retry;
+ entry->max_msg_len = max_msg_len;
+ if (recs)
+ {
+ /* we assume a TNC Server needing recommendations from IMVs */
+ if (!tnc->imvs)
+ {
+ DBG1(DBG_TNC, "no IMV manager available!");
+ free(entry);
+ return 0;
+ }
+ entry->recs = tnc->imvs->create_recommendations(tnc->imvs);
+ *recs = entry->recs;
+ }
+ else
+ {
+ /* we assume a TNC Client */
+ if (!tnc->imcs)
+ {
+ DBG1(DBG_TNC, "no IMC manager available!");
+ free(entry);
+ return 0;
+ }
+ entry->recs = NULL;
+ }
+ this->connection_lock->write_lock(this->connection_lock);
+ entry->id = ++this->connection_id;
+ this->connections->insert_last(this->connections, entry);
+ this->connection_lock->unlock(this->connection_lock);
+
+ DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
+ return entry->id;
+}
+
+METHOD(tnccs_manager_t, remove_connection, void,
+ private_tnc_tnccs_manager_t *this, TNC_ConnectionID id, bool is_server)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+
+ if (is_server)
+ {
+ if (tnc->imvs)
+ {
+ tnc->imvs->notify_connection_change(tnc->imvs, id,
+ TNC_CONNECTION_STATE_DELETE);
+ }
+ }
+ else
+ {
+ if (tnc->imcs)
+ {
+ tnc->imcs->notify_connection_change(tnc->imcs, id,
+ TNC_CONNECTION_STATE_DELETE);
+ }
+ }
+
+ this->connection_lock->write_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ this->connections->remove_at(this->connections, enumerator);
+ if (entry->recs)
+ {
+ entry->recs->destroy(entry->recs);
+ }
+ free(entry);
+ DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+}
+
+METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result,
+ private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id,
+ TNC_ConnectionID id,
+ TNC_RetryReason reason)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+
+ if (id == TNC_CONNECTIONID_ANY)
+ {
+ DBG2(DBG_TNC, "%s %u requests handshake retry for all connections "
+ "(reason: %u)", is_imc ? "IMC":"IMV", reason);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "%s %u requests handshake retry for Connection ID %u "
+ "(reason: %u)", is_imc ? "IMC":"IMV", imcv_id, id, reason);
+ }
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == TNC_CONNECTIONID_ANY || id == entry->id)
+ {
+ *entry->request_handshake_retry = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ return TNC_RESULT_SUCCESS;
+}
+
+METHOD(tnccs_manager_t, send_message, TNC_Result,
+ private_tnc_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype)
+
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ tnccs_send_message_t send_message = NULL;
+ tnccs_t *tnccs = NULL;
+
+ if (msg_vid == TNC_VENDORID_ANY || msg_subtype == TNC_SUBTYPE_ANY)
+ {
+ DBG1(DBG_TNC, "not sending message of invalid type 0x%02x/0x%08x",
+ msg_vid, msg_subtype);
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ tnccs = entry->tnccs;
+ send_message = entry->send_message;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (tnccs && send_message)
+ {
+ return send_message(tnccs, imc_id, imv_id, msg_flags, msg, msg_len,
+ msg_vid, msg_subtype);
+ }
+ return TNC_RESULT_FATAL;
+}
+
+METHOD(tnccs_manager_t, provide_recommendation, TNC_Result,
+ private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ recommendations_t *recs = NULL;
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ recs = entry->recs;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (recs)
+ {
+ recs->provide_recommendation(recs, imv_id, rec, eval);
+ return TNC_RESULT_SUCCESS;
+ }
+ return TNC_RESULT_FATAL;
+}
+
+/**
+ * Write the value of a boolean attribute into the buffer
+ */
+static TNC_Result bool_attribute(TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len,
+ bool value)
+{
+ *value_len = 1;
+
+ if (buffer && buffer_len > 0)
+ {
+ *buffer = value ? 0x01 : 0x00;
+ return TNC_RESULT_SUCCESS;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+}
+
+/**
+ * Write the value of an u_int32_t attribute into the buffer
+ */
+static TNC_Result uint_attribute(TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len,
+ u_int32_t value)
+{
+ *value_len = sizeof(u_int32_t);
+
+ if (buffer && buffer_len >= *value_len)
+ {
+ htoun32(buffer, value);
+ return TNC_RESULT_SUCCESS;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+}
+
+/**
+ * Write the value of string attribute into the buffer
+ */
+static TNC_Result str_attribute(TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len,
+ char *value)
+{
+ *value_len = 1 + strlen(value);
+
+ if (buffer && buffer_len >= *value_len)
+ {
+ snprintf(buffer, buffer_len, "%s", value);
+ return TNC_RESULT_SUCCESS;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+}
+
+/**
+ * Write the value of a TNC identity list into the buffer
+ */
+static TNC_Result identity_attribute(TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len,
+ linked_list_t *list)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ u_int32_t count;
+ chunk_t value;
+ tncif_identity_t *tnc_id;
+ TNC_Result result = TNC_RESULT_INVALID_PARAMETER;
+
+ count = list->get_count(list);
+ writer = bio_writer_create(4 + TNCIF_IDENTITY_MIN_SIZE * count);
+ writer->write_uint32(writer, count);
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &tnc_id))
+ {
+ tnc_id->build(tnc_id, writer);
+ }
+ enumerator->destroy(enumerator);
+
+ value = writer->get_buf(writer);
+ *value_len = value.len;
+ if (buffer && buffer_len >= value.len)
+ {
+ memcpy(buffer, value.ptr, value.len);
+ result = TNC_RESULT_SUCCESS;
+ }
+ writer->destroy(writer);
+
+ return result;
+}
+
+METHOD(tnccs_manager_t, get_attribute, TNC_Result,
+ private_tnc_tnccs_manager_t *this, bool is_imc,
+ TNC_UInt32 imcv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *value_len)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ bool attribute_match = FALSE, entry_found = FALSE;
+
+ if (is_imc)
+ {
+ switch (attribute_id)
+ {
+ /* these attributes are unsupported */
+ case TNC_ATTRIBUTEID_SOHR:
+ case TNC_ATTRIBUTEID_SSOHR:
+ return TNC_RESULT_INVALID_PARAMETER;
+
+ /* these attributes are supported */
+ case TNC_ATTRIBUTEID_PRIMARY_IMC_ID:
+ attribute_match = TRUE;
+ break;
+
+ /* these attributes are yet to be matched */
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (attribute_id)
+ {
+ /* these attributes are unsupported or invalid */
+ case TNC_ATTRIBUTEID_REASON_STRING:
+ case TNC_ATTRIBUTEID_REASON_LANGUAGE:
+ case TNC_ATTRIBUTEID_SOH:
+ case TNC_ATTRIBUTEID_SSOH:
+ return TNC_RESULT_INVALID_PARAMETER;
+
+ /* these attributes are supported */
+ case TNC_ATTRIBUTEID_PRIMARY_IMV_ID:
+ case TNC_ATTRIBUTEID_AR_IDENTITIES:
+ attribute_match = TRUE;
+ break;
+
+ /* these attributes are yet to be matched */
+ default:
+ break;
+ }
+ }
+
+ if (!attribute_match)
+ {
+ switch (attribute_id)
+ {
+ /* these attributes are supported */
+ case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE:
+ case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS:
+ case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE:
+ case TNC_ATTRIBUTEID_HAS_LONG_TYPES:
+ case TNC_ATTRIBUTEID_HAS_EXCLUSIVE:
+ case TNC_ATTRIBUTEID_HAS_SOH:
+ case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL:
+ case TNC_ATTRIBUTEID_IFTNCCS_VERSION:
+ case TNC_ATTRIBUTEID_IFT_PROTOCOL:
+ case TNC_ATTRIBUTEID_IFT_VERSION:
+ break;
+
+ /* these attributes are unsupported or unknown */
+ case TNC_ATTRIBUTEID_DHPN:
+ case TNC_ATTRIBUTEID_TLS_UNIQUE:
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ }
+
+ /* attributes specific to the TNCC or TNCS are unsupported */
+ if (id == TNC_CONNECTIONID_ANY)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ entry_found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (!entry_found)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ switch (attribute_id)
+ {
+ case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE:
+ {
+ recommendations_t *recs;
+ chunk_t pref_lang;
+
+ recs = entry->recs;
+ if (!recs)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ pref_lang = recs->get_preferred_language(recs);
+ if (pref_lang.len == 0)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ *value_len = pref_lang.len;
+ if (buffer && buffer_len >= pref_lang.len)
+ {
+ memcpy(buffer, pref_lang.ptr, pref_lang.len);
+ }
+ return TNC_RESULT_SUCCESS;
+ }
+ case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS:
+ return uint_attribute(buffer_len, buffer, value_len,
+ 0xffffffff);
+ case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE:
+ return uint_attribute(buffer_len, buffer, value_len,
+ entry->max_msg_len);
+ case TNC_ATTRIBUTEID_HAS_LONG_TYPES:
+ case TNC_ATTRIBUTEID_HAS_EXCLUSIVE:
+ return bool_attribute(buffer_len, buffer, value_len,
+ entry->type == TNCCS_2_0);
+ case TNC_ATTRIBUTEID_HAS_SOH:
+ return bool_attribute(buffer_len, buffer, value_len,
+ entry->type == TNCCS_SOH);
+ case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL:
+ {
+ char *protocol;
+
+ switch (entry->type)
+ {
+ case TNCCS_1_1:
+ case TNCCS_2_0:
+ protocol = "IF-TNCCS";
+ break;
+ case TNCCS_SOH:
+ protocol = "IF-TNCCS-SOH";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, protocol);
+ }
+ case TNC_ATTRIBUTEID_IFTNCCS_VERSION:
+ {
+ char *version;
+
+ switch (entry->type)
+ {
+ case TNCCS_1_1:
+ version = "1.1";
+ break;
+ case TNCCS_2_0:
+ version = "2.0";
+ break;
+ case TNCCS_SOH:
+ version = "1.0";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, version);
+ }
+ case TNC_ATTRIBUTEID_IFT_PROTOCOL:
+ {
+ char *protocol;
+
+ switch (entry->tnccs->get_transport(entry->tnccs))
+ {
+ case TNC_IFT_EAP_1_0:
+ case TNC_IFT_EAP_1_1:
+ case TNC_IFT_EAP_2_0:
+ protocol = "IF-T for Tunneled EAP";
+ break;
+ case TNC_IFT_TLS_1_0:
+ case TNC_IFT_TLS_2_0:
+ protocol = "IF-T for TLS";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, protocol);
+ }
+ case TNC_ATTRIBUTEID_IFT_VERSION:
+ {
+ char *version;
+
+ switch (entry->tnccs->get_transport(entry->tnccs))
+ {
+ case TNC_IFT_EAP_1_0:
+ case TNC_IFT_TLS_1_0:
+ version = "1.0";
+ break;
+ case TNC_IFT_EAP_1_1:
+ version = "1.1";
+ break;
+ case TNC_IFT_EAP_2_0:
+ case TNC_IFT_TLS_2_0:
+ version = "2.0";
+ break;
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return str_attribute(buffer_len, buffer, value_len, version);
+ }
+ case TNC_ATTRIBUTEID_AR_IDENTITIES:
+ {
+ linked_list_t *list;
+ identification_t *peer;
+ tnccs_t *tnccs;
+ tncif_identity_t *tnc_id;
+ u_int32_t id_type, subject_type;
+ chunk_t id_value;
+ char *id_str;
+ TNC_Result result;
+
+ list = linked_list_create();
+ tnccs = entry->tnccs;
+ peer = tnccs->tls.get_peer_id(&tnccs->tls);
+ if (peer)
+ {
+ switch (peer->get_type(peer))
+ {
+ case ID_IPV4_ADDR:
+ id_type = TNC_ID_IPV4_ADDR;
+ subject_type = TNC_SUBJECT_MACHINE;
+ break;
+ case ID_IPV6_ADDR:
+ id_type = TNC_ID_IPV6_ADDR;
+ subject_type = TNC_SUBJECT_MACHINE;
+ break;
+ case ID_FQDN:
+ id_type = TNC_ID_USERNAME;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ case ID_RFC822_ADDR:
+ id_type = TNC_ID_EMAIL_ADDR;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ case ID_DER_ASN1_DN:
+ id_type = TNC_ID_X500_DN;
+ subject_type = TNC_SUBJECT_USER;
+ break;
+ default:
+ id_type = TNC_ID_UNKNOWN;
+ subject_type = TNC_SUBJECT_UNKNOWN;
+ }
+ if (id_type != TNC_ID_UNKNOWN &&
+ asprintf(&id_str, "%Y", peer) >= 0)
+ {
+ id_value = chunk_from_str(id_str);
+ tnc_id = tncif_identity_create(
+ pen_type_create(PEN_TCG, id_type), id_value,
+ pen_type_create(PEN_TCG, subject_type),
+ pen_type_create(PEN_TCG,
+ tnccs->get_auth_type(tnccs)));
+ list->insert_last(list, tnc_id);
+ }
+ }
+ result = identity_attribute(buffer_len, buffer, value_len, list);
+ list->destroy_offset(list, offsetof(tncif_identity_t, destroy));
+ return result;
+ }
+ default:
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+}
+
+METHOD(tnccs_manager_t, set_attribute, TNC_Result,
+ private_tnc_tnccs_manager_t *this, bool is_imc,
+ TNC_UInt32 imcv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ recommendations_t *recs = NULL;
+
+ if (is_imc || id == TNC_CONNECTIONID_ANY ||
+ (attribute_id != TNC_ATTRIBUTEID_REASON_STRING &&
+ attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE))
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ recs = entry->recs;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (recs)
+ {
+ chunk_t attribute = { buffer, buffer_len };
+
+ if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING)
+ {
+ return recs->set_reason_string(recs, imcv_id, attribute);
+ }
+ else
+ {
+ return recs->set_reason_language(recs, imcv_id, attribute);
+ }
+ }
+ return TNC_RESULT_INVALID_PARAMETER;
+}
+
+METHOD(tnccs_manager_t, destroy, void,
+ private_tnc_tnccs_manager_t *this)
+{
+ this->protocols->destroy_function(this->protocols, free);
+ this->protocol_lock->destroy(this->protocol_lock);
+ this->connections->destroy_function(this->connections, free);
+ this->connection_lock->destroy(this->connection_lock);
+ free(this);
+}
+
+/*
+ * See header
+ */
+tnccs_manager_t *tnc_tnccs_manager_create()
+{
+ private_tnc_tnccs_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_method = _add_method,
+ .remove_method = _remove_method,
+ .create_instance = _create_instance,
+ .create_connection = _create_connection,
+ .remove_connection = _remove_connection,
+ .request_handshake_retry = _request_handshake_retry,
+ .send_message = _send_message,
+ .provide_recommendation = _provide_recommendation,
+ .get_attribute = _get_attribute,
+ .set_attribute = _set_attribute,
+ .destroy = _destroy,
+ },
+ .protocols = linked_list_create(),
+ .connections = linked_list_create(),
+ .protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.h b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.h
new file mode 100644
index 000000000..dd5149846
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnc_tnccs_manager tnc_tnccs_manager
+ * @{ @ingroup tnc_tnccs
+ */
+
+#ifndef TNC_TNCCS_MANAGER_H_
+#define TNC_TNCCS_MANAGER_H_
+
+#include <tnc/tnccs/tnccs_manager.h>
+
+/**
+ * Create a TNCCS manager instance.
+ */
+tnccs_manager_t *tnc_tnccs_manager_create();
+
+#endif /** TNC_TNCCS_MANAGER_H_ @}*/
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.c b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.c
new file mode 100644
index 000000000..1e4ddc195
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_tnccs_plugin.h"
+#include "tnc_tnccs_manager.h"
+
+#include <tnc/tnc.h>
+
+#include <utils/debug.h>
+
+typedef struct private_tnc_tnccs_plugin_t private_tnc_tnccs_plugin_t;
+
+/**
+ * Private data of a tnc_tnccs_plugin_t object.
+ */
+struct private_tnc_tnccs_plugin_t {
+
+ /**
+ * Public interface.
+ */
+ tnc_tnccs_plugin_t public;
+
+};
+
+
+METHOD(plugin_t, get_name, char*,
+ private_tnc_tnccs_plugin_t *this)
+{
+ return "tnc-tnccs";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_tnc_tnccs_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnc_manager_register, tnc_tnccs_manager_create),
+ PLUGIN_PROVIDE(CUSTOM, "tnccs-manager"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_tnc_tnccs_plugin_t *this)
+{
+ libtnccs_deinit();
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnc_tnccs_plugin_create(void)
+{
+ private_tnc_tnccs_plugin_t *this;
+
+ if (lib->integrity)
+ {
+ if (lib->integrity->check(lib->integrity, "libtnccs", libtnccs_init))
+ {
+ DBG1(DBG_LIB,
+ "lib 'libtnccs': passed file and segment integrity tests");
+ }
+ else
+ {
+ DBG1(DBG_LIB,
+ "lib 'libtnccs': failed integrity tests");
+ return NULL;
+ }
+ }
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ libtnccs_init();
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h
new file mode 100644
index 000000000..f935fa462
--- /dev/null
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnc_tnccs tnc_tnccs
+ * @ingroup cplugins
+ *
+ * @defgroup tnc_tnccs_plugin tnc_tnccs_plugin
+ * @{ @ingroup tnc_tnccs
+ */
+
+#ifndef TNC_TNCCS_PLUGIN_H_
+#define TNC_TNCCS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnc_tnccs_plugin_t tnc_tnccs_plugin_t;
+
+/**
+ * TNCCS manager plugin
+ */
+struct tnc_tnccs_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNC_TNCCS_PLUGIN_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.am b/src/libtnccs/plugins/tnccs_11/Makefile.am
new file mode 100644
index 000000000..cbe0b8e19
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.am
@@ -0,0 +1,33 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ ${xml_CFLAGS} \
+ -rdynamic
+
+libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS}
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnccs-11.la
+libstrongswan_tnccs_11_la_LIBADD += \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnccs_11_la_SOURCES = \
+ tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \
+ batch/tnccs_batch.h batch/tnccs_batch.c \
+ messages/tnccs_msg.h messages/tnccs_msg.c \
+ messages/imc_imv_msg.h messages/imc_imv_msg.c \
+ messages/tnccs_error_msg.h messages/tnccs_error_msg.c \
+ messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \
+ messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \
+ messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \
+ messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c
+
+libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.in b/src/libtnccs/plugins/tnccs_11/Makefile.in
new file mode 100644
index 000000000..76b453a0a
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.in
@@ -0,0 +1,824 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@MONOLITHIC_FALSE@am__append_1 = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+subdir = src/libtnccs/plugins/tnccs_11
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__append_1)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo \
+ batch/tnccs_batch.lo messages/tnccs_msg.lo \
+ messages/imc_imv_msg.lo messages/tnccs_error_msg.lo \
+ messages/tnccs_preferred_language_msg.lo \
+ messages/tnccs_reason_strings_msg.lo \
+ messages/tnccs_recommendation_msg.lo \
+ messages/tnccs_tncs_contact_info_msg.lo
+libstrongswan_tnccs_11_la_OBJECTS = \
+ $(am_libstrongswan_tnccs_11_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnccs_11_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnccs_11_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnccs_11_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnccs_11_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnccs_11_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnccs_11_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ ${xml_CFLAGS} \
+ -rdynamic
+
+libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} $(am__append_1)
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-11.la
+libstrongswan_tnccs_11_la_SOURCES = \
+ tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \
+ batch/tnccs_batch.h batch/tnccs_batch.c \
+ messages/tnccs_msg.h messages/tnccs_msg.c \
+ messages/imc_imv_msg.h messages/imc_imv_msg.c \
+ messages/tnccs_error_msg.h messages/tnccs_error_msg.c \
+ messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \
+ messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \
+ messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \
+ messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c
+
+libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_11/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_11/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+batch/$(am__dirstamp):
+ @$(MKDIR_P) batch
+ @: > batch/$(am__dirstamp)
+batch/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) batch/$(DEPDIR)
+ @: > batch/$(DEPDIR)/$(am__dirstamp)
+batch/tnccs_batch.lo: batch/$(am__dirstamp) \
+ batch/$(DEPDIR)/$(am__dirstamp)
+messages/$(am__dirstamp):
+ @$(MKDIR_P) messages
+ @: > messages/$(am__dirstamp)
+messages/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) messages/$(DEPDIR)
+ @: > messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/imc_imv_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_error_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_preferred_language_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_reason_strings_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_recommendation_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/tnccs_tncs_contact_info_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+
+libstrongswan-tnccs-11.la: $(libstrongswan_tnccs_11_la_OBJECTS) $(libstrongswan_tnccs_11_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnccs_11_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnccs_11_la_LINK) $(am_libstrongswan_tnccs_11_la_rpath) $(libstrongswan_tnccs_11_la_OBJECTS) $(libstrongswan_tnccs_11_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f batch/*.$(OBJEXT)
+ -rm -f batch/*.lo
+ -rm -f messages/*.$(OBJEXT)
+ -rm -f messages/*.lo
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@batch/$(DEPDIR)/tnccs_batch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/imc_imv_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_error_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_preferred_language_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_reason_strings_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_recommendation_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/tnccs_tncs_contact_info_msg.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf batch/.libs batch/_libs
+ -rm -rf messages/.libs messages/_libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f batch/$(DEPDIR)/$(am__dirstamp)
+ -rm -f batch/$(am__dirstamp)
+ -rm -f messages/$(DEPDIR)/$(am__dirstamp)
+ -rm -f messages/$(am__dirstamp)
+
+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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(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-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnccs_11/batch/tnccs_batch.c b/src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.c
new file mode 100644
index 000000000..660ba179d
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_batch.h"
+#include "messages/tnccs_error_msg.h"
+
+#include <tnc/tnccs/tnccs.h>
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+#include <libxml/parser.h>
+
+#define TNCCS_NS "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#"
+#define SCHEMA_NS "http://www.w3.org/2001/XMLSchema-instance"
+#define TNCCS_XSD "https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd"
+
+typedef struct private_tnccs_batch_t private_tnccs_batch_t;
+
+/**
+ * Private data of a tnccs_batch_t object.
+ *
+ */
+struct private_tnccs_batch_t {
+ /**
+ * Public tnccs_batch_t interface.
+ */
+ tnccs_batch_t public;
+
+ /**
+ * Batch ID
+ */
+ int batch_id;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * linked list of TNCCS messages
+ */
+ linked_list_t *messages;
+
+ /**
+ * linked list of TNCCS error messages
+ */
+ linked_list_t *errors;
+
+ /**
+ * XML document
+ */
+ xmlDocPtr doc;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(tnccs_batch_t, get_encoding, chunk_t,
+ private_tnccs_batch_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(tnccs_batch_t, add_msg, void,
+ private_tnccs_batch_t *this, tnccs_msg_t* msg)
+{
+ xmlNodePtr root;
+
+ DBG2(DBG_TNC, "adding %N message", tnccs_msg_type_names,
+ msg->get_type(msg));
+ this->messages->insert_last(this->messages, msg);
+ root = xmlDocGetRootElement(this->doc);
+ xmlAddChild(root, msg->get_node(msg));
+}
+
+METHOD(tnccs_batch_t, build, void,
+ private_tnccs_batch_t *this)
+{
+ xmlChar *xmlbuf;
+ int buf_size;
+
+ xmlDocDumpFormatMemory(this->doc, &xmlbuf, &buf_size, 1);
+ this->encoding = chunk_create(xmlbuf, buf_size);
+ this->encoding = chunk_clone(this->encoding);
+ xmlFree(xmlbuf);
+}
+
+METHOD(tnccs_batch_t, process, status_t,
+ private_tnccs_batch_t *this)
+{
+ tnccs_msg_t *tnccs_msg, *msg;
+ tnccs_error_type_t error_type = TNCCS_ERROR_OTHER;
+ char *error_msg, buf[BUF_LEN];
+ xmlNodePtr cur;
+ xmlNsPtr ns;
+ xmlChar *batchid, *recipient;
+ int batch_id;
+
+ this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len);
+ if (!this->doc)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "failed to parse XML message";
+ goto fatal;
+ }
+
+ /* check out the XML document */
+ cur = xmlDocGetRootElement(this->doc);
+ if (!cur)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "empty XML document";
+ goto fatal;
+ }
+
+ /* check TNCCS namespace */
+ ns = xmlSearchNsByHref(this->doc, cur, TNCCS_NS);
+ if (!ns)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "TNCCS namespace not found";
+ goto fatal;
+ }
+
+ /* check XML document type */
+ if (xmlStrcmp(cur->name, "TNCCS-Batch"))
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "wrong XML document type '%s', expected TNCCS-Batch",
+ cur->name);
+ goto fatal;
+ }
+
+ /* check presence of BatchID property */
+ batchid = xmlGetProp(cur, "BatchId");
+ if (!batchid)
+ {
+ error_type = TNCCS_ERROR_INVALID_BATCH_ID;
+ error_msg = "BatchId is missing";
+ goto fatal;
+ }
+
+ /* check BatchID */
+ batch_id = atoi((char*)batchid);
+ xmlFree(batchid);
+ if (batch_id != this->batch_id)
+ {
+ error_type = TNCCS_ERROR_INVALID_BATCH_ID;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "BatchId %d expected, got %d", this->batch_id,
+ batch_id);
+ goto fatal;
+ }
+
+ /* check presence of Recipient property */
+ recipient = xmlGetProp(cur, "Recipient");
+ if (!recipient)
+ {
+ error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
+ error_msg = "Recipient is missing";
+ goto fatal;
+ }
+
+ /* check recipient */
+ if (!streq(recipient, this->is_server ? "TNCS" : "TNCC"))
+ {
+ error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "message recipient expected '%s', got '%s'",
+ this->is_server ? "TNCS" : "TNCC", recipient);
+ xmlFree(recipient);
+ goto fatal;
+ }
+ xmlFree(recipient);
+
+ DBG2(DBG_TNC, "processing TNCCS Batch #%d", batch_id);
+
+ /* Now walk the tree, handling message nodes as we go */
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
+ {
+ /* ignore empty or blank nodes */
+ if (xmlIsBlankNode(cur))
+ {
+ continue;
+ }
+
+ /* ignore nodes with wrong namespace */
+ if (cur->ns != ns)
+ {
+ DBG1(DBG_TNC, "ignoring message node '%s' having wrong namespace",
+ cur->name);
+ continue;
+ }
+
+ tnccs_msg = tnccs_msg_create_from_node(cur, this->errors);
+
+ /* exit if a message parsing error occurred */
+ if (this->errors->get_count(this->errors) > 0)
+ {
+ return FAILED;
+ }
+
+ /* ignore unrecognized messages */
+ if (!tnccs_msg)
+ {
+ continue;
+ }
+
+ this->messages->insert_last(this->messages, tnccs_msg);
+ }
+ return SUCCESS;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*,
+ private_tnccs_batch_t *this)
+{
+ return this->messages->create_enumerator(this->messages);
+}
+
+METHOD(tnccs_batch_t, create_error_enumerator, enumerator_t*,
+ private_tnccs_batch_t *this)
+{
+ return this->errors->create_enumerator(this->errors);
+}
+
+METHOD(tnccs_batch_t, destroy, void,
+ private_tnccs_batch_t *this)
+{
+ this->messages->destroy_offset(this->messages,
+ offsetof(tnccs_msg_t, destroy));
+ this->errors->destroy_offset(this->errors,
+ offsetof(tnccs_msg_t, destroy));
+ xmlFreeDoc(this->doc);
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id)
+{
+ private_tnccs_batch_t *this;
+ xmlNodePtr n;
+ xmlNsPtr ns_xsi;
+ char buf[12];
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .batch_id = batch_id,
+ .doc = xmlNewDoc("1.0"),
+ );
+
+ DBG2(DBG_TNC, "creating TNCCS Batch #%d", this->batch_id);
+ n = xmlNewNode(NULL, "TNCCS-Batch");
+ xmlNewNs(n, TNCCS_NS, NULL);
+ ns_xsi = xmlNewNs(n, SCHEMA_NS, "xsi");
+ snprintf(buf, sizeof(buf), "%d", batch_id);
+ xmlNewProp(n, "BatchId", buf);
+ xmlNewProp(n, "Recipient", this->is_server ? "TNCC" : "TNCS");
+ xmlNewNsProp(n, ns_xsi, "schemaLocation", TNCCS_NS " " TNCCS_XSD);
+ xmlDocSetRootElement(this->doc, n);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, chunk_t data)
+{
+ private_tnccs_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .batch_id = batch_id,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.h b/src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.h
new file mode 100644
index 000000000..25301f763
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/batch/tnccs_batch.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_batch tnccs_batch
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_BATCH_H_
+#define TNCCS_BATCH_H_
+
+typedef enum tnccs_batch_type_t tnccs_batch_type_t;
+typedef struct tnccs_batch_t tnccs_batch_t;
+
+#include "messages/tnccs_msg.h"
+
+#include <library.h>
+
+/**
+ * Interface for a TNCCS 1.x Batch.
+ */
+struct tnccs_batch_t {
+
+ /**
+ * Get the encoding of the TNCCS 1.x Batch
+ *
+ * @return encoded TNCCS 1.x batch
+ */
+ chunk_t (*get_encoding)(tnccs_batch_t *this);
+
+ /**
+ * Add TNCCS message
+ *
+ * @param msg TNCCS message to be addedd
+ */
+ void (*add_msg)(tnccs_batch_t *this, tnccs_msg_t* msg);
+
+ /**
+ * Build the TNCCS 1.x Batch
+ */
+ void (*build)(tnccs_batch_t *this);
+
+ /**
+ * Process the TNCCS 1.x Batch
+ *
+ * @return return processing status
+ */
+ status_t (*process)(tnccs_batch_t *this);
+
+ /**
+ * Enumerates over all TNCCS Messages
+ *
+ * @return return message enumerator
+ */
+ enumerator_t* (*create_msg_enumerator)(tnccs_batch_t *this);
+
+ /**
+ * Enumerates over all parsing errors
+ *
+ * @return return error enumerator
+ */
+ enumerator_t* (*create_error_enumerator)(tnccs_batch_t *this);
+
+ /**
+ * Destroys a tnccs_batch_t object.
+ */
+ void (*destroy)(tnccs_batch_t *this);
+};
+
+/**
+ * Create an empty TNCCS 1.x Batch
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param batch_id number of the batch to be sent
+ */
+tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id);
+
+/**
+ * Create an unprocessed TNCCS 1.x Batch from data
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param batch_id current Batch ID
+ * @param data encoded PB-TNC batch
+ */
+tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id,
+ chunk_t data);
+
+#endif /** TNCCS_BATCH_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.c b/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.c
new file mode 100644
index 000000000..f0e821c8c
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_imv_msg.h"
+
+#include <tnc/tnccs/tnccs.h>
+
+#include <utils/lexparser.h>
+#include <utils/debug.h>
+
+typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
+
+#define BYTES_PER_LINE 57
+
+/**
+ * Private data of a imc_imv_msg_t object.
+ *
+ */
+struct private_imc_imv_msg_t {
+ /**
+ * Public imc_imv_msg_t interface.
+ */
+ imc_imv_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * IMC-IMV message type
+ */
+ TNC_MessageType msg_type;
+
+ /**
+ * IMC-IMV message body
+ */
+ chunk_t msg_body;
+
+};
+
+/**
+ * Encodes message data into multiple base64-encoded lines
+ */
+static chunk_t encode_base64(chunk_t data)
+{
+ chunk_t encoding;
+ u_char *pos;
+ size_t b64_chars, b64_lines;
+
+ /* handle empty message data object */
+ if (data.len == 0)
+ {
+ encoding = chunk_alloc(1);
+ *encoding.ptr = '\0';
+ return encoding;
+ }
+
+ /* compute and allocate maximum size of base64 object */
+ b64_chars = 4 * ((data.len + 2) / 3);
+ b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
+ encoding = chunk_alloc(b64_chars + b64_lines);
+ pos = encoding.ptr;
+
+ /* encode lines */
+ while (b64_lines--)
+ {
+ chunk_t data_line, b64_line;
+
+ data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE));
+ data.ptr += data_line.len;
+ data.len -= data_line.len;
+ b64_line = chunk_to_base64(data_line, pos);
+ pos += b64_line.len;
+ *pos = '\n';
+ pos++;
+ }
+ /* terminate last line with NULL character instead of newline */
+ *(pos-1) = '\0';
+
+ return encoding;
+}
+
+/**
+ * Decodes message data from multiple base64-encoded lines
+ */
+static chunk_t decode_base64(chunk_t data)
+{
+ chunk_t decoding, data_line, b64_line;
+ u_char *pos;
+
+ /* compute and allocate maximum size of decoded message data */
+ decoding = chunk_alloc(3 * ((data.len + 3) / 4));
+ pos = decoding.ptr;
+ decoding.len = 0;
+
+ while (fetchline(&data, &b64_line))
+ {
+ data_line = chunk_from_base64(b64_line, pos);
+ pos += data_line.len;
+ decoding.len += data_line.len;
+ }
+
+ return decoding;
+}
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_imc_imv_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_imc_imv_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_imc_imv_msg_t *this)
+{
+ free(this->msg_body.ptr);
+ free(this);
+}
+
+METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType,
+ private_imc_imv_msg_t *this)
+{
+ return this->msg_type;
+}
+
+METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
+ private_imc_imv_msg_t *this)
+{
+ return this->msg_body;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
+{
+ private_imc_imv_msg_t *this;
+ xmlNsPtr ns;
+ xmlNodePtr cur;
+ xmlChar *content;
+ chunk_t b64_body;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_msg_type = _get_msg_type,
+ .get_msg_body = _get_msg_body,
+ },
+ .type = IMC_IMV_MSG,
+ .node = node,
+ );
+
+ ns = node->ns;
+ cur = node->xmlChildrenNode;
+ while (cur)
+ {
+ if (streq(cur->name, "Type") && cur->ns == ns)
+ {
+ content = xmlNodeGetContent(cur);
+ this->msg_type = strtoul(content, NULL, 16);
+ xmlFree(content);
+ }
+ else if (streq(cur->name, "Base64") && cur->ns == ns)
+ {
+ content = xmlNodeGetContent(cur);
+ b64_body = chunk_create(content, strlen(content));
+ this->msg_body = decode_base64(b64_body);
+ xmlFree(content);
+ }
+ cur = cur->next;
+ }
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
+{
+ private_imc_imv_msg_t *this;
+ chunk_t b64_body;
+ char buf[10]; /* big enough for hex-encoded message type */
+ xmlNodePtr n;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_msg_type = _get_msg_type,
+ .get_msg_body = _get_msg_body,
+ },
+ .type = IMC_IMV_MSG,
+ .node = xmlNewNode(NULL, "IMC-IMV-Message"),
+ .msg_type = msg_type,
+ .msg_body = chunk_clone(msg_body),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, "Type");
+ snprintf(buf, 10, "%08x", this->msg_type);
+ xmlNodeSetContent(n, buf);
+ xmlAddChild(this->node, n);
+
+ /* encode the message as a Base64 node */
+ n = xmlNewNode(NULL, "Base64");
+ b64_body = encode_base64(this->msg_body);
+ xmlNodeSetContent(n, b64_body.ptr);
+ xmlAddChild(this->node, n);
+ free(b64_body.ptr);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.h b/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.h
new file mode 100644
index 000000000..3477fa74e
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/imc_imv_msg.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup imc_imv_msg imc_imv_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef IMC_IMV_MSG_H_
+#define IMC_IMV_MSG_H_
+
+typedef struct imc_imv_msg_t imc_imv_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tncif.h>
+
+/**
+ * Classs representing the PB-PA message type.
+ */
+struct imc_imv_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get IMC-IMV message type
+ *
+ * @return IMC-IMV message type
+ */
+ TNC_MessageType (*get_msg_type)(imc_imv_msg_t *this);
+
+ /**
+ * Get IMC-IMV message body
+ *
+ * @return IMC-IMV message body
+ */
+ chunk_t (*get_msg_body)(imc_imv_msg_t *this);
+};
+
+/**
+ * Create an IMC-IMV message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+*/
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
+
+/**
+ * Create an IMC-IMV message from parameters
+ *
+ * @param msg_type IMC-IMV message type
+ * @param msg_body IMC-IMV message body
+ */
+tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body);
+
+#endif /** IMC_IMV_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
new file mode 100644
index 000000000..86b7c6aa5
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_error_msg.h"
+
+#include <utils/debug.h>
+
+ENUM(tnccs_error_type_names, TNCCS_ERROR_BATCH_TOO_LONG, TNCCS_ERROR_OTHER,
+ "batch-too-long",
+ "malformed-batch",
+ "invalid-batch-id",
+ "invalid-recipient-type",
+ "internal-error",
+ "other"
+);
+
+typedef struct private_tnccs_error_msg_t private_tnccs_error_msg_t;
+
+/**
+ * Private data of a tnccs_error_msg_t object.
+ *
+ */
+struct private_tnccs_error_msg_t {
+ /**
+ * Public tnccs_error_msg_t interface.
+ */
+ tnccs_error_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Error type
+ */
+ tnccs_error_type_t error_type;
+
+ /**
+ * Error message
+ */
+ char *error_msg;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_error_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_error_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, get_ref, tnccs_msg_t*,
+ private_tnccs_error_msg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.tnccs_msg_interface;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_error_msg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->error_msg);
+ free(this);
+ }
+}
+
+METHOD(tnccs_error_msg_t, get_message, char*,
+ private_tnccs_error_msg_t *this, tnccs_error_type_t *type)
+{
+ *type = this->error_type;
+
+ return this->error_msg;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
+{
+ private_tnccs_error_msg_t *this;
+ xmlChar *error_type_name, *error_msg;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_message = _get_message,
+ },
+ .type = TNCCS_MSG_ERROR,
+ .ref = 1,
+ .node = node,
+ .error_type = TNCCS_ERROR_OTHER,
+ );
+
+ error_type_name = xmlGetProp(node, "type");
+ if (error_type_name)
+ {
+ this->error_type = enum_from_name(tnccs_error_type_names,
+ error_type_name);
+ if (this->error_type == -1)
+ {
+ this->error_type = TNCCS_ERROR_OTHER;
+ }
+ xmlFree(error_type_name);
+ }
+
+ error_msg = xmlNodeGetContent(node);
+ if (error_msg)
+ {
+ this->error_msg = strdup(error_msg);
+ xmlFree(error_msg);
+ }
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg)
+{
+ private_tnccs_error_msg_t *this;
+ xmlNodePtr n, n2;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_message = _get_message,
+ },
+ .type = TNCCS_MSG_ERROR,
+ .ref = 1,
+ .node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
+ .error_type = type,
+ .error_msg = strdup(msg),
+ );
+
+ DBG1(DBG_TNC, "%s", msg);
+
+ n = xmlNewNode(NULL, "Type");
+ xmlNodeSetContent(n, "00000002");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNewProp(n2, "type", enum_to_name(tnccs_error_type_names, type));
+ xmlNodeSetContent(n2, msg);
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.h
new file mode 100644
index 000000000..ce2ce9755
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_error_msg tnccs_error_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_ERROR_MSG_H_
+#define TNCCS_ERROR_MSG_H_
+
+typedef enum tnccs_error_type_t tnccs_error_type_t;
+typedef struct tnccs_error_msg_t tnccs_error_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * TNCCS error types as defined in section 8.1.4 of TCG TNC IF-TNCCS v1.2
+ */
+enum tnccs_error_type_t {
+ TNCCS_ERROR_BATCH_TOO_LONG,
+ TNCCS_ERROR_MALFORMED_BATCH,
+ TNCCS_ERROR_INVALID_BATCH_ID,
+ TNCCS_ERROR_INVALID_RECIPIENT_TYPE,
+ TNCCS_ERROR_INTERNAL_ERROR,
+ TNCCS_ERROR_OTHER
+};
+
+/**
+ * enum name for tnccs_error_type_t.
+ */
+extern enum_name_t *tnccs_error_type_names;
+
+/**
+ * Class representing the TNCCS-Error message type
+ */
+struct tnccs_error_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get error message and type
+ *
+ * @param type TNCCS error type
+ * @return arbitrary error message
+ */
+ char* (*get_message)(tnccs_error_msg_t *this, tnccs_error_type_t *type);
+};
+
+/**
+ * Create a TNCCS-Error message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ */
+tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node);
+
+/**
+ * Create a TNCCS-Error message from parameters
+ *
+ * @param type TNCCS error type
+ * @param msg arbitrary error message
+ */
+tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg);
+
+#endif /** TNCCS_ERROR_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
new file mode 100644
index 000000000..fa5ce8239
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_msg.h"
+#include "imc_imv_msg.h"
+#include "tnccs_error_msg.h"
+#include "tnccs_preferred_language_msg.h"
+#include "tnccs_reason_strings_msg.h"
+#include "tnccs_recommendation_msg.h"
+#include "tnccs_tncs_contact_info_msg.h"
+
+#include <library.h>
+#include <utils/debug.h>
+
+ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF,
+ "IMC-IMV",
+ "TNCCS-Recommendation",
+ "TNCCS-Error",
+ "TNCCS-PreferredLanguage",
+ "TNCCS-ReasonStrings",
+ "TNCCS-TNCSContactInfo"
+);
+
+/**
+ * See header
+ */
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
+{
+ char *error_msg, buf[BUF_LEN];
+ tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ tnccs_msg_t *msg;
+ tnccs_msg_type_t type = IMC_IMV_MSG;
+
+ if (streq((char*)node->name, "IMC-IMV-Message"))
+ {
+ DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+ return imc_imv_msg_create_from_node(node, errors);
+ }
+ else if (streq((char*)node->name, "TNCC-TNCS-Message"))
+ {
+ bool found = FALSE;
+ xmlNsPtr ns = node->ns;
+ xmlNodePtr cur = node->xmlChildrenNode;
+ xmlNodePtr xml_msg_node = NULL;
+
+ while (cur)
+ {
+ if (streq(cur->name, "Type") && cur->ns == ns)
+ {
+ xmlChar *content = xmlNodeGetContent(cur);
+
+ type = strtol(content, NULL, 16);
+ xmlFree(content);
+ found = TRUE;
+ }
+ else if (streq(cur->name, "XML") && cur->ns == ns)
+ {
+ xml_msg_node = cur->xmlChildrenNode;
+ }
+ cur = cur->next;
+ }
+ if (!found)
+ {
+ error_msg = "Type is missing in TNCC-TNCS-Message";
+ goto fatal;
+ }
+ if (!xml_msg_node)
+ {
+ error_msg = "XML node is missing in TNCC-TNCS-Message";
+ goto fatal;
+ }
+ cur = xml_msg_node;
+
+ /* skip empty and blank nodes */
+ while (cur && xmlIsBlankNode(cur))
+ {
+ cur = cur->next;
+ }
+ if (!cur)
+ {
+ error_msg = "XML node is empty";
+ goto fatal;
+ }
+
+ /* check if TNCCS message type and node name agree */
+ if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF)
+ {
+ DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+ if (cur->ns != ns)
+ {
+ error_msg = "node is not in the TNCCS message namespace";
+ goto fatal;
+ }
+ if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
+ {
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
+ tnccs_msg_type_names, type, (char*)cur->name);
+ goto fatal;
+ }
+ }
+
+ switch (type)
+ {
+ case TNCCS_MSG_RECOMMENDATION:
+ return tnccs_recommendation_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_ERROR:
+ return tnccs_error_msg_create_from_node(cur);
+ case TNCCS_MSG_PREFERRED_LANGUAGE:
+ return tnccs_preferred_language_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_REASON_STRINGS:
+ return tnccs_reason_strings_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_TNCS_CONTACT_INFO:
+ return tnccs_tncs_contact_info_msg_create_from_node(cur, errors);
+ default:
+ DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type);
+ return NULL;
+ }
+ }
+ DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name);
+ return NULL;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ errors->insert_last(errors, msg);
+ return NULL;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.h
new file mode 100644
index 000000000..88d6f07aa
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_msg tnccs_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_MSG_H_
+#define TNCCS_MSG_H_
+
+typedef enum tnccs_msg_type_t tnccs_msg_type_t;
+typedef struct tnccs_msg_t tnccs_msg_t;
+
+#include <library.h>
+#include <collections/linked_list.h>
+#include <libxml/parser.h>
+
+/**
+ * TNCC-TNCS messages as defined in section 2.8.5 of TCG TNC IF-TNCCS v1.2
+ */
+enum tnccs_msg_type_t {
+ IMC_IMV_MSG = 0,
+ TNCCS_MSG_RECOMMENDATION = 1,
+ TNCCS_MSG_ERROR = 2,
+ TNCCS_MSG_PREFERRED_LANGUAGE = 3,
+ TNCCS_MSG_REASON_STRINGS = 4,
+ TNCCS_MSG_TNCS_CONTACT_INFO = 5,
+ TNCCS_MSG_ROOF = 5
+};
+
+/**
+ * enum name for tnccs_msg_type_t.
+ */
+extern enum_name_t *tnccs_msg_type_names;
+
+/**
+ * Generic interface for all TNCCS message types.
+ *
+ * To handle all messages in a generic way, this interface
+ * must be implemented by each message type.
+ */
+struct tnccs_msg_t {
+
+ /**
+ * Get the TNCCS Message Type
+ *
+ * @return TNCCS Message Type
+ */
+ tnccs_msg_type_t (*get_type)(tnccs_msg_t *this);
+
+ /**
+ * Get the XML-encoded Message Node
+ *
+ * @return Message Node
+ */
+ xmlNodePtr (*get_node)(tnccs_msg_t *this);
+
+ /**
+ * Process the TNCCS Message
+ *
+ * @return return processing status
+ */
+ status_t (*process)(tnccs_msg_t *this);
+
+ /**
+ * Get a new reference to the message.
+ *
+ * @return this, with an increased refcount
+ */
+ tnccs_msg_t* (*get_ref)(tnccs_msg_t *this);
+
+ /**
+ * Destroys a tnccs_msg_t object.
+ */
+ void (*destroy)(tnccs_msg_t *this);
+};
+
+/**
+ * Create a pre-processed TNCCS message
+ *
+ * Useful for the parser which wants a generic constructor for all
+ * tnccs_msg_t types.
+ *
+ * @param node TNCCS message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
+
+#endif /** TNCCS_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
new file mode 100644
index 000000000..710269ba9
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_preferred_language_msg.h"
+
+#include <utils/debug.h>
+
+typedef struct private_tnccs_preferred_language_msg_t private_tnccs_preferred_language_msg_t;
+
+/**
+ * Private data of a tnccs_preferred_language_msg_t object.
+ *
+ */
+struct private_tnccs_preferred_language_msg_t {
+ /**
+ * Public tnccs_preferred_language_msg_t interface.
+ */
+ tnccs_preferred_language_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Preferred language
+ */
+ char *preferred_language;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ free(this->preferred_language);
+ free(this);
+}
+
+METHOD(tnccs_preferred_language_msg_t, get_preferred_language, char*,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->preferred_language;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_preferred_language_msg_t *this;
+ xmlChar *language;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_preferred_language = _get_preferred_language,
+ },
+ .type = TNCCS_MSG_PREFERRED_LANGUAGE,
+ .node = node,
+ );
+
+ language = xmlNodeGetContent(node);
+ this->preferred_language = strdup(language);
+ xmlFree(language);
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create(char *language)
+{
+ private_tnccs_preferred_language_msg_t *this;
+ xmlNodePtr n, n2;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_preferred_language = _get_preferred_language,
+ },
+ .type = TNCCS_MSG_PREFERRED_LANGUAGE,
+ .node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
+ .preferred_language = strdup(language),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, "Type");
+ xmlNodeSetContent(n, "00000003");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNodeSetContent(n2, language);
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
new file mode 100644
index 000000000..c2de7fe4d
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_preferred_language_msg tnccs_preferred_language_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_PREFERRED_LANGUAGE_MSG_H_
+#define TNCCS_PREFERRED_LANGUAGE_MSG_H_
+
+typedef struct tnccs_preferred_language_msg_t tnccs_preferred_language_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tncif.h>
+
+/**
+ * Class representing the TNCCS-PreferredLanguage message type
+ */
+struct tnccs_preferred_language_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get preferred language string
+ *
+ * @return preferred language string
+ */
+ char* (*get_preferred_language)(tnccs_preferred_language_msg_t *this);
+};
+
+/**
+ * Create a TNCCS-PreferredLanguage message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-PreferredLanguage message from parameters
+ *
+ * @param language preferred language string
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create(char *language);
+
+#endif /** TNCCS_PREFERRED_LANGUAGE_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
new file mode 100644
index 000000000..7c2f9b3f9
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_reason_strings_msg.h"
+#include "tnccs_error_msg.h"
+
+#include <utils/debug.h>
+
+typedef struct private_tnccs_reason_strings_msg_t private_tnccs_reason_strings_msg_t;
+
+/**
+ * Private data of a tnccs_reason_strings_msg_t object.
+ *
+ */
+struct private_tnccs_reason_strings_msg_t {
+ /**
+ * Public tnccs_reason_strings_msg_t interface.
+ */
+ tnccs_reason_strings_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Reason String
+ */
+ chunk_t reason;
+
+ /**
+ * Reason Language
+ */
+ chunk_t language;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ free(this->reason.ptr);
+ free(this->language.ptr);
+ free(this);
+}
+
+METHOD(tnccs_reason_strings_msg_t, get_reason, chunk_t,
+ private_tnccs_reason_strings_msg_t *this, chunk_t *language)
+{
+ *language = this->language;
+
+ return this->reason;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_reason_strings_msg_t *this;
+ char *error_msg, *lang_string, *reason_string;
+ tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ tnccs_msg_t *msg;
+ xmlNodePtr child;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_reason = _get_reason,
+ },
+ .type = TNCCS_MSG_REASON_STRINGS,
+ .node = node,
+ );
+
+ if (xmlStrcmp(node->name, "TNCCS-ReasonStrings"))
+ {
+ error_msg = "TNCCS-ReasonStrings tag expected";
+ goto fatal;
+ }
+
+ child = node->xmlChildrenNode;
+ while (child)
+ {
+ if (xmlIsBlankNode(child))
+ {
+ child = child->next;
+ continue;
+ }
+ if (xmlStrcmp(child->name, "ReasonString"))
+ {
+ error_msg = "ReasonString tag expected";
+ goto fatal;
+ }
+ break;
+ }
+
+ lang_string = xmlGetProp(child, "lang");
+ if (!lang_string)
+ {
+ lang_string = strdup("");
+ }
+ this->language = chunk_clone(chunk_from_str(lang_string));
+ xmlFree(lang_string);
+
+ reason_string = xmlNodeGetContent(child);
+ this->reason = chunk_clone(chunk_from_str(reason_string));
+ xmlFree(reason_string);
+
+ return &this->public.tnccs_msg_interface;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ errors->insert_last(errors, msg);
+ destroy(this);
+ return NULL;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language)
+{
+ private_tnccs_reason_strings_msg_t *this;
+ xmlNodePtr n, n2, n3;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_reason = _get_reason,
+ },
+ .type = TNCCS_MSG_REASON_STRINGS,
+ .node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
+ .reason = chunk_create_clone(malloc(reason.len + 1), reason),
+ .language = chunk_create_clone(malloc(language.len + 1), language),
+ );
+
+ /* add NULL termination for XML string representation */
+ this->reason.ptr[this->reason.len] = '\0';
+ this->language.ptr[this->language.len] = '\0';
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, "Type");
+ xmlNodeSetContent(n, "00000004");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
+
+ /* could add multiple reasons here, if we had them */
+
+ n3 = xmlNewNode(NULL, "ReasonString");
+ xmlNewProp(n3, "xml:lang", this->language.ptr);
+ xmlNodeSetContent(n3, this->reason.ptr);
+ xmlAddChild(n2, n3);
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
new file mode 100644
index 000000000..0046a5789
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_reason_strings_msg tnccs_reason_strings_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_REASON_STRINGS_MSG_H_
+#define TNCCS_REASON_STRINGS_MSG_H_
+
+typedef struct tnccs_reason_strings_msg_t tnccs_reason_strings_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * Class representing the TNCCS-ReasonStrings message type
+ */
+struct tnccs_reason_strings_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get reason string and language
+ *
+ * @param language reason language
+ * @return reason string
+ */
+ chunk_t (*get_reason)(tnccs_reason_strings_msg_t *this, chunk_t *language);
+};
+
+/**
+ * Create a TNCCS-ReasonStrings message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-ReasonStrings message from parameters
+ *
+ * @param reason reason string
+ * @param language reason language
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language);
+
+#endif /** TNCCS_REASON_STRINGS_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
new file mode 100644
index 000000000..013e0c7ed
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_recommendation_msg.h"
+#include "tnccs_error_msg.h"
+
+#include <utils/debug.h>
+
+typedef struct private_tnccs_recommendation_msg_t private_tnccs_recommendation_msg_t;
+
+/**
+ * Private data of a tnccs_recommendation_msg_t object.
+ *
+ */
+struct private_tnccs_recommendation_msg_t {
+ /**
+ * Public tnccs_recommendation_msg_t interface.
+ */
+ tnccs_recommendation_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Action Recommendation
+ */
+ TNC_IMV_Action_Recommendation rec;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_recommendation_msg_t *this)
+{
+ free(this);
+}
+
+METHOD(tnccs_recommendation_msg_t, get_recommendation, TNC_IMV_Action_Recommendation,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->rec;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_recommendation_msg_t *this;
+ xmlChar *rec_string;
+ char *error_msg, buf[BUF_LEN];
+ tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ tnccs_msg_t *msg;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_recommendation = _get_recommendation,
+ },
+ .type = TNCCS_MSG_RECOMMENDATION,
+ .node = node,
+ );
+
+ rec_string = xmlGetProp(node, "type");
+ if (!rec_string)
+ {
+ error_msg = "type property in TNCCS-Recommendation is missing";
+ goto fatal;
+ }
+ else if (streq(rec_string, "allow"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+ }
+ else if (streq(rec_string, "isolate"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+ }
+ else if (streq(rec_string, "none"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+ }
+ else
+ {
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "unsupported type property value '%s' "
+ "in TNCCS-Recommendation", rec_string);
+ xmlFree(rec_string);
+ goto fatal;
+ }
+ xmlFree(rec_string);
+
+ return &this->public.tnccs_msg_interface;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ errors->insert_last(errors, msg);
+ destroy(this);
+ return NULL;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec)
+{
+ private_tnccs_recommendation_msg_t *this;
+ xmlNodePtr n, n2;
+ char *rec_string;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_recommendation = _get_recommendation,
+ },
+ .type = TNCCS_MSG_RECOMMENDATION,
+ .node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
+ .rec = rec,
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, "Type");
+ xmlNodeSetContent(n, "00000001");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, "XML");
+ xmlAddChild(this->node, n);
+
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ rec_string = "allow";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ rec_string = "isolate";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ default:
+ rec_string = "none";
+ }
+
+ n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNewProp(n2, BAD_CAST "type", rec_string);
+ xmlNodeSetContent(n2, "");
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
new file mode 100644
index 000000000..3a67a3b32
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_recommendation_msg tnccs_recommendation_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_RECOMMENDATION_MSG_H_
+#define TNCCS_RECOMMENDATION_MSG_H_
+
+typedef struct tnccs_recommendation_msg_t tnccs_recommendation_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tncifimv.h>
+
+/**
+ * Class representing the TNCCS-Recommendation message type
+ */
+struct tnccs_recommendation_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get Action Recommendation
+ *
+ * @return Action Recommendation
+ */
+ TNC_IMV_Action_Recommendation (*get_recommendation)(tnccs_recommendation_msg_t *this);
+};
+
+/**
+ * Create a TNCCS-Recommendation message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-Recommendation message from parameters
+ *
+ * @param rec Action Recommendation
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec);
+
+#endif /** TNCCS_RECOMMENDATION_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
new file mode 100644
index 000000000..0d3e1c2a0
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_tncs_contact_info_msg.h"
+
+#include <utils/debug.h>
+
+typedef struct private_tnccs_tncs_contact_info_msg_t private_tnccs_tncs_contact_info_msg_t;
+
+/**
+ * Private data of a tnccs_tncs_contact_info_msg_t object.
+ *
+ */
+struct private_tnccs_tncs_contact_info_msg_t {
+ /**
+ * Public tnccs_tncs_contact_info_msg_t interface.
+ */
+ tnccs_tncs_contact_info_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_tncs_contact_info_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ },
+ .type = TNCCS_MSG_TNCS_CONTACT_INFO,
+ .node = node,
+ );
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void)
+{
+ private_tnccs_tncs_contact_info_msg_t *this;
+ xmlNodePtr n /*, n2 */;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ },
+ .type = TNCCS_MSG_TNCS_CONTACT_INFO,
+ .node = xmlNewNode(NULL, "TNCC-TNCS-Message"),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, "Type");
+ xmlNodeSetContent(n, "00000005");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, "XML");
+ xmlAddChild(this->node, n);
+
+/* TODO
+ n2 = xmlNewNode(NULL, enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNodeSetContent(n2, language);
+ xmlAddChild(n, n2);
+*/
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h b/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
new file mode 100644
index 000000000..8ed210a57
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_tncs_contact_info_msg tnccs_tncs_contact_info_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_TNCS_CONTACT_INFO_MSG_H_
+#define TNCCS_TNCS_CONTACT_INFO_MSG_H_
+
+typedef struct tnccs_tncs_contact_info_msg_t tnccs_tncs_contact_info_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * Class representing the TNCCS-TNCSContactInfo message type
+ */
+struct tnccs_tncs_contact_info_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+};
+
+/**
+ * Create a TNCCS-TNCSContactInfo message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-TNCSContactInfo message from parameters
+ *
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void);
+
+#endif /** TNCCS_TNCS_CONTACT_INFO_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11.c b/src/libtnccs/plugins/tnccs_11/tnccs_11.c
new file mode 100644
index 000000000..91854b587
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_11.h"
+#include "batch/tnccs_batch.h"
+#include "messages/tnccs_msg.h"
+#include "messages/imc_imv_msg.h"
+#include "messages/tnccs_error_msg.h"
+#include "messages/tnccs_preferred_language_msg.h"
+#include "messages/tnccs_reason_strings_msg.h"
+#include "messages/tnccs_recommendation_msg.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <tnc/tnc.h>
+#include <tnc/imc/imc_manager.h>
+#include <tnc/imv/imv_manager.h>
+#include <tnc/tnccs/tnccs.h>
+#include <tnc/tnccs/tnccs_manager.h>
+
+#include <utils/debug.h>
+#include <threading/mutex.h>
+
+typedef struct private_tnccs_11_t private_tnccs_11_t;
+
+/**
+ * Private data of a tnccs_11_t object.
+ */
+struct private_tnccs_11_t {
+
+ /**
+ * Public tnccs_t interface.
+ */
+ tnccs_t public;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * Server identity
+ */
+ identification_t *server;
+
+ /**
+ * Client identity
+ */
+ identification_t *peer;
+
+ /**
+ * Underlying TNC IF-T transport protocol
+ */
+ tnc_ift_type_t transport;
+
+ /**
+ * Type of TNC client authentication
+ */
+ u_int32_t auth_type;
+
+ /**
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * Last TNCCS batch ID
+ */
+ int batch_id;
+
+ /**
+ * TNCCS batch being constructed
+ */
+ tnccs_batch_t *batch;
+
+ /**
+ * Maximum PA-TNC message size
+ */
+ size_t max_msg_len;
+
+ /**
+ * Mutex locking the batch in construction
+ */
+ mutex_t *mutex;
+
+ /**
+ * Flag set while processing
+ */
+ bool fatal_error;
+
+ /**
+ * Flag set by TNCCS-Recommendation message
+ */
+ bool delete_state;
+
+ /**
+ * SendMessage() by IMC/IMV only allowed if flag is set
+ */
+ bool send_msg;
+
+ /**
+ * Flag set by IMC/IMV RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * Set of IMV recommendations (TNC Server only)
+ */
+ recommendations_t *recs;
+
+ /**
+ * Callback function to communicate recommendation (TNC Server only)
+ */
+ tnccs_cb_t callback;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+
+};
+
+METHOD(tnccs_t, send_msg, TNC_Result,
+ private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype)
+{
+ tnccs_msg_t *tnccs_msg;
+ TNC_MessageType msg_type;
+ enum_name_t *pa_subtype_names;
+
+ if (!this->send_msg)
+ {
+ DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
+ this->is_server ? "IMV" : "IMC",
+ this->is_server ? imv_id : imc_id);
+ return TNC_RESULT_ILLEGAL_OPERATION;
+ }
+ if (msg_vid > TNC_VENDORID_ANY || msg_subtype > TNC_SUBTYPE_ANY)
+ {
+ return TNC_RESULT_NO_LONG_MESSAGE_TYPES;
+ }
+ msg_type = (msg_vid << 8) | msg_subtype;
+
+ pa_subtype_names = get_pa_subtype_names(msg_vid);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "creating IMC-IMV message type '%N/%N' 0x%06x/0x%02x",
+ pen_names, msg_vid, pa_subtype_names, msg_subtype,
+ msg_vid, msg_subtype);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "creating IMC-IMV message type '%N' 0x%06x/0x%02x",
+ pen_names, msg_vid, msg_vid, msg_subtype);
+ }
+ tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len));
+
+ /* adding an IMC-IMV Message to TNCCS batch */
+ this->mutex->lock(this->mutex);
+ if (!this->batch)
+ {
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+ }
+ this->batch->add_msg(this->batch, tnccs_msg);
+ this->mutex->unlock(this->mutex);
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * Handle a single TNCCS message according to its type
+ */
+static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg)
+{
+ switch (msg->get_type(msg))
+ {
+ case IMC_IMV_MSG:
+ {
+ imc_imv_msg_t *imc_imv_msg;
+ TNC_MessageType msg_type;
+ chunk_t msg_body;
+ u_int32_t msg_vid, msg_subtype;
+ enum_name_t *pa_subtype_names;
+
+ imc_imv_msg = (imc_imv_msg_t*)msg;
+ msg_type = imc_imv_msg->get_msg_type(imc_imv_msg);
+ msg_body = imc_imv_msg->get_msg_body(imc_imv_msg);
+ msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY;
+ msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+
+ pa_subtype_names = get_pa_subtype_names(msg_vid);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "handling IMC-IMV message type '%N/%N' 0x%06x/0x%02x",
+ pen_names, msg_vid, pa_subtype_names, msg_subtype,
+ msg_vid, msg_subtype);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "handling IMC-IMV message type '%N' 0x%06x/0x%02x",
+ pen_names, msg_vid, msg_vid, msg_subtype);
+ }
+
+ this->send_msg = TRUE;
+ if (this->is_server)
+ {
+ tnc->imvs->receive_message(tnc->imvs, this->connection_id,
+ FALSE, msg_body.ptr, msg_body.len,
+ msg_vid, msg_subtype, 0, TNC_IMVID_ANY);
+ }
+ else
+ {
+ tnc->imcs->receive_message(tnc->imcs, this->connection_id,
+ FALSE, msg_body.ptr, msg_body.len,
+ msg_vid, msg_subtype, 0, TNC_IMCID_ANY);
+ }
+ this->send_msg = FALSE;
+ break;
+ }
+ case TNCCS_MSG_RECOMMENDATION:
+ {
+ tnccs_recommendation_msg_t *rec_msg;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+ rec_msg = (tnccs_recommendation_msg_t*)msg;
+ rec = rec_msg->get_recommendation(rec_msg);
+ if (this->is_server)
+ {
+ DBG1(DBG_TNC, "ignoring NCCS-Recommendation message from "
+ " TNC client");
+ break;
+ }
+ DBG1(DBG_TNC, "TNC recommendation is '%N'",
+ TNC_IMV_Action_Recommendation_names, rec);
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ default:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ }
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ state);
+ this->delete_state = TRUE;
+ break;
+ }
+ case TNCCS_MSG_ERROR:
+ {
+ tnccs_error_msg_t *err_msg;
+ tnccs_error_type_t error_type;
+ char *error_msg;
+
+ err_msg = (tnccs_error_msg_t*)msg;
+ error_msg = err_msg->get_message(err_msg, &error_type);
+ DBG1(DBG_TNC, "received '%N' TNCCS-Error: %s",
+ tnccs_error_type_names, error_type, error_msg);
+
+ /* we assume that all errors are fatal */
+ this->fatal_error = TRUE;
+ break;
+ }
+ case TNCCS_MSG_PREFERRED_LANGUAGE:
+ {
+ tnccs_preferred_language_msg_t *lang_msg;
+ char *lang;
+
+ lang_msg = (tnccs_preferred_language_msg_t*)msg;
+ lang = lang_msg->get_preferred_language(lang_msg);
+
+ DBG2(DBG_TNC, "setting preferred language to '%s'", lang);
+ this->recs->set_preferred_language(this->recs,
+ chunk_create(lang, strlen(lang)));
+ break;
+ }
+ case TNCCS_MSG_REASON_STRINGS:
+ {
+ tnccs_reason_strings_msg_t *reason_msg;
+ chunk_t reason_string, reason_lang;
+
+ reason_msg = (tnccs_reason_strings_msg_t*)msg;
+ reason_string = reason_msg->get_reason(reason_msg, &reason_lang);
+ DBG2(DBG_TNC, "reason string is '%.*s'", (int)reason_string.len,
+ reason_string.ptr);
+ DBG2(DBG_TNC, "language code is '%.*s'", (int)reason_lang.len,
+ reason_lang.ptr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+METHOD(tls_t, process, status_t,
+ private_tnccs_11_t *this, void *buf, size_t buflen)
+{
+ chunk_t data;
+ tnccs_batch_t *batch;
+ tnccs_msg_t *msg;
+ enumerator_t *enumerator;
+ status_t status;
+
+ if (this->is_server && !this->connection_id)
+ {
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_1_1, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, &this->recs);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+ }
+
+ data = chunk_create(buf, buflen);
+ DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
+ data.len, this->connection_id);
+ DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
+ batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data);
+ status = batch->process(batch);
+
+ if (status == FAILED)
+ {
+ this->fatal_error = TRUE;
+ this->mutex->lock(this->mutex);
+ if (this->batch)
+ {
+ DBG1(DBG_TNC, "cancelling TNCCS batch");
+ this->batch->destroy(this->batch);
+ this->batch_id--;
+ }
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+
+ /* add error messages to outbound batch */
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->batch->add_msg(this->batch, msg->get_ref(msg));
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+ }
+ else
+ {
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ handle_message(this, msg);
+ }
+ enumerator->destroy(enumerator);
+
+ /* received any TNCCS-Error messages */
+ if (this->fatal_error)
+ {
+ DBG1(DBG_TNC, "a fatal TNCCS-Error occurred, terminating connection");
+ batch->destroy(batch);
+ return FAILED;
+ }
+
+ this->send_msg = TRUE;
+ if (this->is_server)
+ {
+ tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
+ }
+ else
+ {
+ tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
+ }
+ this->send_msg = FALSE;
+ }
+ batch->destroy(batch);
+
+ return NEED_MORE;
+}
+
+/**
+ * Add a recommendation message if a final recommendation is available
+ */
+static void check_and_build_recommendation(private_tnccs_11_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMVID id;
+ chunk_t reason, language;
+ enumerator_t *enumerator;
+ tnccs_msg_t *msg;
+
+ if (!this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
+ }
+ if (this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ if (!this->batch)
+ {
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+ }
+
+ msg = tnccs_recommendation_msg_create(rec);
+ this->batch->add_msg(this->batch, msg);
+
+ /* currently we just send the first Reason String */
+ enumerator = this->recs->create_reason_enumerator(this->recs);
+ if (enumerator->enumerate(enumerator, &id, &reason, &language))
+ {
+ msg = tnccs_reason_strings_msg_create(reason, language);
+ this->batch->add_msg(this->batch, msg);
+ }
+ enumerator->destroy(enumerator);
+
+ /* we have reache the final state */
+ this->delete_state = TRUE;
+ }
+}
+
+METHOD(tls_t, build, status_t,
+ private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ status_t status;
+
+ /* Initialize the connection */
+ if (!this->is_server && !this->connection_id)
+ {
+ tnccs_msg_t *msg;
+ char *pref_lang;
+
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_1_1, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, NULL);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+
+ /* Create TNCCS-PreferredLanguage message */
+ pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
+ msg = tnccs_preferred_language_msg_create(pref_lang);
+ this->mutex->lock(this->mutex);
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+ this->batch->add_msg(this->batch, msg);
+ this->mutex->unlock(this->mutex);
+
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
+ tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ /* Do not allow any asynchronous IMCs or IMVs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->recs && !this->delete_state &&
+ (!this->batch || this->fatal_error))
+ {
+ check_and_build_recommendation(this);
+ }
+
+ if (this->batch)
+ {
+ chunk_t data;
+
+ this->batch->build(this->batch);
+ data = this->batch->get_encoding(this->batch);
+ DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
+ data.len, this->connection_id);
+ DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
+ *msglen = 0;
+
+ if (data.len > *buflen)
+ {
+ DBG1(DBG_TNC, "fragmentation of TNCCS batch not supported yet");
+ }
+ else
+ {
+ *buflen = data.len;
+ }
+ memcpy(buf, data.ptr, *buflen);
+ this->batch->destroy(this->batch);
+ this->batch = NULL;
+ status = ALREADY_DONE;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "no TNCCS Batch to send");
+ status = INVALID_STATE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
+}
+
+METHOD(tls_t, is_server, bool,
+ private_tnccs_11_t *this)
+{
+ return this->is_server;
+}
+
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_11_t *this)
+{
+ return this->server;
+}
+
+METHOD(tls_t, set_peer_id, void,
+ private_tnccs_11_t *this, identification_t *id)
+{
+ DESTROY_IF(this->peer);
+ this->peer = id->clone(id);
+}
+
+METHOD(tls_t, get_peer_id, identification_t*,
+ private_tnccs_11_t *this)
+{
+ return this->peer;
+}
+
+METHOD(tls_t, get_purpose, tls_purpose_t,
+ private_tnccs_11_t *this)
+{
+ return TLS_PURPOSE_EAP_TNC;
+}
+
+METHOD(tls_t, is_complete, bool,
+ private_tnccs_11_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+
+ if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ return this->callback ? this->callback(rec, eval) : TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+METHOD(tls_t, get_eap_msk, chunk_t,
+ private_tnccs_11_t *this)
+{
+ return chunk_empty;
+}
+
+METHOD(tls_t, destroy, void,
+ private_tnccs_11_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
+ this->is_server);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->batch);
+ free(this);
+ }
+}
+
+METHOD(tnccs_t, get_transport, tnc_ift_type_t,
+ private_tnccs_11_t *this)
+{
+ return this->transport;
+}
+
+METHOD(tnccs_t, set_transport, void,
+ private_tnccs_11_t *this, tnc_ift_type_t transport)
+{
+ this->transport = transport;
+}
+
+METHOD(tnccs_t, get_auth_type, u_int32_t,
+ private_tnccs_11_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(tnccs_t, set_auth_type, void,
+ private_tnccs_11_t *this, u_int32_t auth_type)
+{
+ this->auth_type = auth_type;
+}
+
+METHOD(tnccs_t, get_pdp_server, chunk_t,
+ private_tnccs_11_t *this, u_int16_t *port)
+{
+ *port = 0;
+
+ return chunk_empty;
+}
+
+METHOD(tnccs_t, get_ref, tnccs_t*,
+ private_tnccs_11_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+tnccs_t* tnccs_11_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb)
+{
+ private_tnccs_11_t *this;
+
+ INIT(this,
+ .public = {
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_id,
+ .set_peer_id = _set_peer_id,
+ .get_peer_id = _get_peer_id,
+ .get_purpose = _get_purpose,
+ .is_complete = _is_complete,
+ .get_eap_msk = _get_eap_msk,
+ .destroy = _destroy,
+ },
+ .get_transport = _get_transport,
+ .set_transport = _set_transport,
+ .get_auth_type = _get_auth_type,
+ .set_auth_type = _set_auth_type,
+ .get_pdp_server = _get_pdp_server,
+ .get_ref = _get_ref,
+ },
+ .is_server = is_server,
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
+ .callback = cb,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .max_msg_len = lib->settings->get_int(lib->settings,
+ "libtnccs.plugins.tnccs-11.max_message_size", 45000),
+ .ref = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11.h b/src/libtnccs/plugins/tnccs_11/tnccs_11.h
new file mode 100644
index 000000000..e805df8bb
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_11_h tnccs_11
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_11_H_
+#define TNCCS_11_H_
+
+#include <library.h>
+
+#include <tnc/tnccs/tnccs.h>
+
+/**
+ * Create an instance of the TNC IF-TNCCS 1.1 protocol handler.
+ *
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @param cb Callback function if TNC Server, NULL if TNC Client
+ * @return TNC_IF_TNCCS 1.1 protocol stack
+ */
+tnccs_t* tnccs_11_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb);
+
+#endif /** TNCCS_11_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.c b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.c
new file mode 100644
index 000000000..f534af008
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_11_plugin.h"
+#include "tnccs_11.h"
+
+#include <tnc/tnccs/tnccs_manager.h>
+
+METHOD(plugin_t, get_name, char*,
+ tnccs_11_plugin_t *this)
+{
+ return "tnccs-11";
+}
+
+METHOD(plugin_t, get_features, int,
+ tnccs_11_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnccs_method_register, tnccs_11_create),
+ PLUGIN_PROVIDE(CUSTOM, "tnccs-1.1"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ tnccs_11_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnccs_11_plugin_create()
+{
+ tnccs_11_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->plugin;
+}
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h
new file mode 100644
index 000000000..619a073ad
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_11 tnccs_11
+ * @ingroup cplugins
+ *
+ * @defgroup tnccs_11_plugin tnccs_11_plugin
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_11_PLUGIN_H_
+#define TNCCS_11_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnccs_11_plugin_t tnccs_11_plugin_t;
+
+/**
+ * EAP-TNC plugin
+ */
+struct tnccs_11_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNCCS_11_PLUGIN_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.am b/src/libtnccs/plugins/tnccs_20/Makefile.am
new file mode 100644
index 000000000..f64526eda
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.am
@@ -0,0 +1,34 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
+libstrongswan_tnccs_20_la_LIBADD = \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnccs_20_la_SOURCES = \
+ tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
+ messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
+ messages/ietf/pb_experimental_msg.h messages/ietf/pb_experimental_msg.c \
+ messages/ietf/pb_pa_msg.h messages/ietf/pb_pa_msg.c \
+ messages/ietf/pb_assessment_result_msg.h messages/ietf/pb_assessment_result_msg.c \
+ messages/ietf/pb_access_recommendation_msg.h messages/ietf/pb_access_recommendation_msg.c \
+ messages/ietf/pb_error_msg.h messages/ietf/pb_error_msg.c \
+ messages/ietf/pb_language_preference_msg.h messages/ietf/pb_language_preference_msg.c \
+ messages/ietf/pb_reason_string_msg.h messages/ietf/pb_reason_string_msg.c \
+ messages/ietf/pb_remediation_parameters_msg.h messages/ietf/pb_remediation_parameters_msg.c \
+ messages/tcg/pb_pdp_referral_msg.h messages/tcg/pb_pdp_referral_msg.c \
+ state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
+
+libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.in b/src/libtnccs/plugins/tnccs_20/Makefile.in
new file mode 100644
index 000000000..0bb3c7314
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.in
@@ -0,0 +1,880 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libtnccs/plugins/tnccs_20
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \
+ batch/pb_tnc_batch.lo messages/pb_tnc_msg.lo \
+ messages/ietf/pb_experimental_msg.lo \
+ messages/ietf/pb_pa_msg.lo \
+ messages/ietf/pb_assessment_result_msg.lo \
+ messages/ietf/pb_access_recommendation_msg.lo \
+ messages/ietf/pb_error_msg.lo \
+ messages/ietf/pb_language_preference_msg.lo \
+ messages/ietf/pb_reason_string_msg.lo \
+ messages/ietf/pb_remediation_parameters_msg.lo \
+ messages/tcg/pb_pdp_referral_msg.lo \
+ state_machine/pb_tnc_state_machine.lo
+libstrongswan_tnccs_20_la_OBJECTS = \
+ $(am_libstrongswan_tnccs_20_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnccs_20_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnccs_20_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnccs_20_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnccs_20_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnccs_20_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnccs_20_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
+@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+libstrongswan_tnccs_20_la_SOURCES = \
+ tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
+ messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
+ messages/ietf/pb_experimental_msg.h messages/ietf/pb_experimental_msg.c \
+ messages/ietf/pb_pa_msg.h messages/ietf/pb_pa_msg.c \
+ messages/ietf/pb_assessment_result_msg.h messages/ietf/pb_assessment_result_msg.c \
+ messages/ietf/pb_access_recommendation_msg.h messages/ietf/pb_access_recommendation_msg.c \
+ messages/ietf/pb_error_msg.h messages/ietf/pb_error_msg.c \
+ messages/ietf/pb_language_preference_msg.h messages/ietf/pb_language_preference_msg.c \
+ messages/ietf/pb_reason_string_msg.h messages/ietf/pb_reason_string_msg.c \
+ messages/ietf/pb_remediation_parameters_msg.h messages/ietf/pb_remediation_parameters_msg.c \
+ messages/tcg/pb_pdp_referral_msg.h messages/tcg/pb_pdp_referral_msg.c \
+ state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
+
+libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_20/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_20/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+batch/$(am__dirstamp):
+ @$(MKDIR_P) batch
+ @: > batch/$(am__dirstamp)
+batch/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) batch/$(DEPDIR)
+ @: > batch/$(DEPDIR)/$(am__dirstamp)
+batch/pb_tnc_batch.lo: batch/$(am__dirstamp) \
+ batch/$(DEPDIR)/$(am__dirstamp)
+messages/$(am__dirstamp):
+ @$(MKDIR_P) messages
+ @: > messages/$(am__dirstamp)
+messages/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) messages/$(DEPDIR)
+ @: > messages/$(DEPDIR)/$(am__dirstamp)
+messages/pb_tnc_msg.lo: messages/$(am__dirstamp) \
+ messages/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/$(am__dirstamp):
+ @$(MKDIR_P) messages/ietf
+ @: > messages/ietf/$(am__dirstamp)
+messages/ietf/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) messages/ietf/$(DEPDIR)
+ @: > messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_experimental_msg.lo: messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_pa_msg.lo: messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_assessment_result_msg.lo: \
+ messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_access_recommendation_msg.lo: \
+ messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_error_msg.lo: messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_language_preference_msg.lo: \
+ messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_reason_string_msg.lo: messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ietf/pb_remediation_parameters_msg.lo: \
+ messages/ietf/$(am__dirstamp) \
+ messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/tcg/$(am__dirstamp):
+ @$(MKDIR_P) messages/tcg
+ @: > messages/tcg/$(am__dirstamp)
+messages/tcg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) messages/tcg/$(DEPDIR)
+ @: > messages/tcg/$(DEPDIR)/$(am__dirstamp)
+messages/tcg/pb_pdp_referral_msg.lo: messages/tcg/$(am__dirstamp) \
+ messages/tcg/$(DEPDIR)/$(am__dirstamp)
+state_machine/$(am__dirstamp):
+ @$(MKDIR_P) state_machine
+ @: > state_machine/$(am__dirstamp)
+state_machine/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) state_machine/$(DEPDIR)
+ @: > state_machine/$(DEPDIR)/$(am__dirstamp)
+state_machine/pb_tnc_state_machine.lo: state_machine/$(am__dirstamp) \
+ state_machine/$(DEPDIR)/$(am__dirstamp)
+
+libstrongswan-tnccs-20.la: $(libstrongswan_tnccs_20_la_OBJECTS) $(libstrongswan_tnccs_20_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnccs_20_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnccs_20_la_LINK) $(am_libstrongswan_tnccs_20_la_rpath) $(libstrongswan_tnccs_20_la_OBJECTS) $(libstrongswan_tnccs_20_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f batch/*.$(OBJEXT)
+ -rm -f batch/*.lo
+ -rm -f messages/*.$(OBJEXT)
+ -rm -f messages/*.lo
+ -rm -f messages/ietf/*.$(OBJEXT)
+ -rm -f messages/ietf/*.lo
+ -rm -f messages/tcg/*.$(OBJEXT)
+ -rm -f messages/tcg/*.lo
+ -rm -f state_machine/*.$(OBJEXT)
+ -rm -f state_machine/*.lo
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@batch/$(DEPDIR)/pb_tnc_batch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/pb_tnc_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_access_recommendation_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_assessment_result_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_error_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_experimental_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_language_preference_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_pa_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_reason_string_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_remediation_parameters_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/tcg/$(DEPDIR)/pb_pdp_referral_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@state_machine/$(DEPDIR)/pb_tnc_state_machine.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf batch/.libs batch/_libs
+ -rm -rf messages/.libs messages/_libs
+ -rm -rf messages/ietf/.libs messages/ietf/_libs
+ -rm -rf messages/tcg/.libs messages/tcg/_libs
+ -rm -rf state_machine/.libs state_machine/_libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f batch/$(DEPDIR)/$(am__dirstamp)
+ -rm -f batch/$(am__dirstamp)
+ -rm -f messages/$(DEPDIR)/$(am__dirstamp)
+ -rm -f messages/$(am__dirstamp)
+ -rm -f messages/ietf/$(DEPDIR)/$(am__dirstamp)
+ -rm -f messages/ietf/$(am__dirstamp)
+ -rm -f messages/tcg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f messages/tcg/$(am__dirstamp)
+ -rm -f state_machine/$(DEPDIR)/$(am__dirstamp)
+ -rm -f state_machine/$(am__dirstamp)
+
+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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(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-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
new file mode 100644
index 000000000..ef0faf2c1
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
+ * Copyright (C) 2010-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_batch.h"
+#include "messages/ietf/pb_error_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <tnc/tnccs/tnccs.h>
+
+#include <collections/linked_list.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE,
+ "CDATA",
+ "SDATA",
+ "RESULT",
+ "CRETRY",
+ "SRETRY",
+ "CLOSE"
+);
+
+typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
+
+/**
+ * PB-Batch Header (see section 4.1 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version |D| Reserved | B-Type|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Batch Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_TNC_BATCH_FLAG_NONE 0x00
+#define PB_TNC_BATCH_FLAG_D (1<<7)
+#define PB_TNC_BATCH_HEADER_SIZE 8
+
+/**
+ * PB-TNC Message (see section 4.2 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PB-TNC Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_TNC_FLAG_NONE 0x00
+#define PB_TNC_FLAG_NOSKIP (1<<7)
+#define PB_TNC_HEADER_SIZE 12
+
+#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff
+
+/**
+ * Private data of a pb_tnc_batch_t object.
+ *
+ */
+struct private_pb_tnc_batch_t {
+ /**
+ * Public pb_pa_msg_t interface.
+ */
+ pb_tnc_batch_t public;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * PB-TNC Batch type
+ */
+ pb_tnc_batch_type_t type;
+
+ /**
+ * Current PB-TNC Batch size
+ */
+ size_t batch_len;
+
+ /**
+ * Maximum PB-TNC Batch size
+ */
+ size_t max_batch_len;
+
+ /**
+ * linked list of PB-TNC messages
+ */
+ linked_list_t *messages;
+
+ /**
+ * linked list of PB-TNC error messages
+ */
+ linked_list_t *errors;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+
+ /**
+ * Offset into encoding (used for error reporting)
+ */
+ u_int32_t offset;
+};
+
+METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t,
+ private_pb_tnc_batch_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_batch_t, get_encoding, chunk_t,
+ private_pb_tnc_batch_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_batch_t, add_msg, bool,
+ private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg)
+{
+ enum_name_t *msg_type_names;
+ chunk_t msg_value;
+ pen_type_t msg_type;
+ size_t msg_len;
+
+ msg->build(msg);
+ msg_value = msg->get_encoding(msg);
+ msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+
+ if (this->batch_len + msg_len > this->max_batch_len)
+ {
+ /* message just does not fit into this batch */
+ return FALSE;
+ }
+ this->batch_len += msg_len;
+
+ msg_type = msg->get_type(msg);
+ switch (msg_type.vendor_id)
+ {
+ default:
+ case PEN_IETF:
+ msg_type_names = pb_tnc_msg_type_names;
+ break;
+ case PEN_TCG:
+ msg_type_names = pb_tnc_tcg_msg_type_names;
+ break;
+ }
+ DBG2(DBG_TNC, "adding %N/%N message", pen_names, msg_type.vendor_id,
+ msg_type_names, msg_type.type);
+ this->messages->insert_last(this->messages, msg);
+ return TRUE;
+}
+
+METHOD(pb_tnc_batch_t, build, void,
+ private_pb_tnc_batch_t *this)
+{
+ u_int32_t msg_len;
+ chunk_t msg_value;
+ enumerator_t *enumerator;
+ pen_type_t msg_type;
+ pb_tnc_msg_t *msg;
+ pb_tnc_msg_info_t *msg_infos;
+ bio_writer_t *writer;
+
+ /* build PB-TNC batch header */
+ writer = bio_writer_create(this->batch_len);
+ writer->write_uint8 (writer, PB_TNC_VERSION);
+ writer->write_uint8 (writer, this->is_server ?
+ PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
+ writer->write_uint16(writer, this->type);
+ writer->write_uint32(writer, this->batch_len);
+
+ /* build PB-TNC messages */
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ u_int8_t flags = PB_TNC_FLAG_NONE;
+
+ /* build PB-TNC message */
+ msg_value = msg->get_encoding(msg);
+ msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+ msg_type = msg->get_type(msg);
+ switch (msg_type.vendor_id)
+ {
+ default:
+ case PEN_IETF:
+ msg_infos = pb_tnc_msg_infos;
+ break;
+ case PEN_TCG:
+ msg_infos = pb_tnc_tcg_msg_infos;
+ break;
+ }
+ if (msg_infos[msg_type.type].has_noskip_flag)
+ {
+ flags |= PB_TNC_FLAG_NOSKIP;
+ }
+ writer->write_uint8 (writer, flags);
+ writer->write_uint24(writer, msg_type.vendor_id);
+ writer->write_uint32(writer, msg_type.type);
+ writer->write_uint32(writer, msg_len);
+ writer->write_data (writer, msg_value);
+ }
+ enumerator->destroy(enumerator);
+
+ this->encoding = writer->extract_buf(writer);
+ writer->destroy(writer);
+}
+
+static status_t process_batch_header(private_pb_tnc_batch_t *this,
+ pb_tnc_state_machine_t *state_machine)
+{
+ bio_reader_t *reader;
+ pb_tnc_msg_t *msg;
+ pb_error_msg_t *err_msg;
+ u_int8_t version, flags, reserved, type;
+ u_int32_t batch_len;
+ bool directionality;
+
+ if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header",
+ this->encoding.len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, 0);
+ goto fatal;
+ }
+
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint8 (reader, &version);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint8 (reader, &type);
+ reader->read_uint32(reader, &batch_len);
+ reader->destroy(reader);
+
+ /* Version */
+ if (version != PB_TNC_VERSION)
+ {
+ DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%02x", version);
+ msg = pb_error_msg_create(TRUE, PEN_IETF,
+ PB_ERROR_VERSION_NOT_SUPPORTED);
+ err_msg = (pb_error_msg_t*)msg;
+ err_msg->set_bad_version(err_msg, version);
+ goto fatal;
+ }
+
+ /* Directionality */
+ directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
+ if (directionality == this->is_server)
+ {
+ DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
+ directionality ? "server" : "client");
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, 1);
+ goto fatal;
+ }
+
+ /* Batch Type */
+ this->type = type & 0x0F;
+ if (this->type > PB_BATCH_ROOF)
+ {
+ DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, 3);
+ goto fatal;
+ }
+
+ if (!state_machine->receive_batch(state_machine, this->type))
+ {
+ DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
+ pb_tnc_batch_type_names, this->type);
+ msg = pb_error_msg_create(TRUE, PEN_IETF,
+ PB_ERROR_UNEXPECTED_BATCH_TYPE);
+ goto fatal;
+ }
+ DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
+ this->type);
+
+ /* Batch Length */
+ if (this->encoding.len != batch_len)
+ {
+ DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes",
+ this->encoding.len, batch_len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, 4);
+ goto fatal;
+ }
+
+ this->offset = PB_TNC_BATCH_HEADER_SIZE;
+
+ /* Register an empty CDATA batch with the state machine */
+ if (this->type == PB_BATCH_CDATA)
+ {
+ state_machine->set_empty_cdata(state_machine,
+ this->offset == this->encoding.len);
+ }
+ return SUCCESS;
+
+fatal:
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
+{
+ bio_reader_t *reader;
+ pb_tnc_msg_t *pb_tnc_msg, *msg;
+ pb_tnc_msg_info_t *msg_infos;
+ u_int8_t flags;
+ u_int32_t vendor_id, msg_type, msg_len, offset;
+ chunk_t data, msg_value;
+ bool noskip_flag;
+ enum_name_t *msg_type_names;
+ pen_type_t msg_pen_type;
+ status_t status;
+
+ data = chunk_skip(this->encoding, this->offset);
+
+ if (data.len < PB_TNC_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header",
+ data.len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+
+ reader = bio_reader_create(data);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &msg_type);
+ reader->read_uint32(reader, &msg_len);
+ reader->destroy(reader);
+
+ noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE;
+
+ if (msg_len > data.len)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 8);
+ goto fatal;
+ }
+
+ if (vendor_id == PEN_RESERVED)
+ {
+ DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 1);
+ goto fatal;
+
+ }
+
+ if (msg_type == PB_TNC_RESERVED_MSG_TYPE)
+ {
+ DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved",
+ PB_TNC_RESERVED_MSG_TYPE);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 4);
+ goto fatal;
+ }
+
+ if (vendor_id == PEN_IETF && msg_type <= PB_MSG_ROOF)
+ {
+ if (msg_type == PB_MSG_EXPERIMENTAL && noskip_flag)
+ {
+ DBG1(DBG_TNC, "reject IETF/PB-Experimental message with "
+ "NOSKIP flag set");
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
+ goto fatal;
+ }
+ msg_type_names = pb_tnc_msg_type_names;
+ msg_infos = pb_tnc_msg_infos;
+ }
+ else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF)
+ {
+ msg_type_names = pb_tnc_tcg_msg_type_names;
+ msg_infos = pb_tnc_tcg_msg_infos;
+ }
+ else
+ {
+ if (msg_len < PB_TNC_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length",
+ msg_len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 8);
+ goto fatal;
+ }
+
+ if (noskip_flag)
+ {
+ DBG1(DBG_TNC, "reject PB-TNC message 0x%06x/0x%08x)",
+ vendor_id, msg_type);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
+ goto fatal;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "ignore PB-TNC message 0x%06x/0x%08x)",
+ vendor_id, msg_type);
+ this->offset += msg_len;
+ return SUCCESS;
+ }
+ }
+
+ if (msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE &&
+ msg_infos[msg_type].has_noskip_flag != noskip_flag)
+ {
+ DBG1(DBG_TNC, "%N/%N message must%s have NOSKIP flag set",
+ pen_names, vendor_id, msg_type_names, msg_type,
+ msg_infos[msg_type].has_noskip_flag ? "" : " not");
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+
+ if (msg_len < msg_infos[msg_type].min_size ||
+ (msg_infos[msg_type].exact_size &&
+ msg_len != msg_infos[msg_type].min_size))
+ {
+ DBG1(DBG_TNC, "%N/%N message length must be %s %u bytes but is %u bytes",
+ pen_names, vendor_id, msg_type_names, msg_type,
+ msg_infos[msg_type].exact_size ? "exactly" : "at least",
+ msg_infos[msg_type].min_size, msg_len);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+
+ if (msg_infos[msg_type].in_result_batch && this->type != PB_BATCH_RESULT)
+ {
+ if (this->is_server)
+ {
+ DBG1(DBG_TNC,"reject %N/%N message received from a PB-TNC client",
+ pen_names, vendor_id, msg_type_names, msg_type);
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+ else
+ {
+ DBG1(DBG_TNC,"ignore %N/%N message not received within RESULT batch",
+ pen_names, vendor_id, msg_type_names, msg_type);
+ this->offset += msg_len;
+ return SUCCESS;
+ }
+ }
+
+ DBG2(DBG_TNC, "processing %N/%N message (%u bytes)", pen_names, vendor_id,
+ msg_type_names, msg_type, msg_len);
+ data.len = msg_len;
+ msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE);
+ msg_pen_type = pen_type_create(vendor_id, msg_type);
+ pb_tnc_msg = pb_tnc_msg_create_from_data(msg_pen_type, msg_value);
+
+ status = pb_tnc_msg->process(pb_tnc_msg, &offset);
+ if (status == FAILED || status == VERIFY_ERROR)
+ {
+ msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
+ PB_ERROR_INVALID_PARAMETER, this->offset + offset);
+ this->errors->insert_last(this->errors, msg);
+ }
+ if (status == FAILED)
+ {
+ pb_tnc_msg->destroy(pb_tnc_msg);
+ return FAILED;
+ }
+ this->messages->insert_last(this->messages, pb_tnc_msg);
+ this->offset += msg_len;
+ return status;
+
+fatal:
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+METHOD(pb_tnc_batch_t, process, status_t,
+ private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine)
+{
+ status_t status;
+
+ status = process_batch_header(this, state_machine);
+ if (status != SUCCESS)
+ {
+ return FAILED;
+ }
+
+ while (this->offset < this->encoding.len)
+ {
+ switch (process_tnc_msg(this))
+ {
+ case FAILED:
+ return FAILED;
+ case VERIFY_ERROR:
+ status = VERIFY_ERROR;
+ break;
+ case SUCCESS:
+ default:
+ break;
+ }
+ }
+ return status;
+}
+
+METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*,
+ private_pb_tnc_batch_t *this)
+{
+ return this->messages->create_enumerator(this->messages);
+}
+
+METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*,
+ private_pb_tnc_batch_t *this)
+{
+ return this->errors->create_enumerator(this->errors);
+}
+
+METHOD(pb_tnc_batch_t, destroy, void,
+ private_pb_tnc_batch_t *this)
+{
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
+ this->errors->destroy_offset(this->errors,
+ offsetof(pb_tnc_msg_t, destroy));
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
+ size_t max_batch_len)
+{
+ private_pb_tnc_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .type = type,
+ .max_batch_len = max_batch_len,
+ .batch_len = PB_TNC_BATCH_HEADER_SIZE,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ );
+
+ DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
+{
+ private_pb_tnc_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
new file mode 100644
index 000000000..60cef7735
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_tnc_batch pb_tnc_batch
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_BATCH_H_
+#define PB_TNC_BATCH_H_
+
+typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t;
+typedef struct pb_tnc_batch_t pb_tnc_batch_t;
+
+#include "messages/pb_tnc_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <library.h>
+
+/**
+ * PB-TNC Batch Types as defined in section 4.1 of RFC 5793
+ */
+enum pb_tnc_batch_type_t {
+ PB_BATCH_NONE = 0, /* for internal use only */
+ PB_BATCH_CDATA = 1,
+ PB_BATCH_SDATA = 2,
+ PB_BATCH_RESULT = 3,
+ PB_BATCH_CRETRY = 4,
+ PB_BATCH_SRETRY = 5,
+ PB_BATCH_CLOSE = 6,
+ PB_BATCH_ROOF = 6
+};
+
+/**
+ * enum name for pb_tnc_batch_type_t.
+ */
+extern enum_name_t *pb_tnc_batch_type_names;
+
+/**
+ * Interface for all PB-TNC Batch Types.
+ */
+struct pb_tnc_batch_t {
+
+ /**
+ * Get the PB-TNC Message Type
+ *
+ * @return PB-TNC batch type
+ */
+ pb_tnc_batch_type_t (*get_type)(pb_tnc_batch_t *this);
+
+ /**
+ * Get the encoding of the PB-TNC Batch
+ *
+ * @return encoded PB-TNC batch
+ */
+ chunk_t (*get_encoding)(pb_tnc_batch_t *this);
+
+ /**
+ * Add a PB-TNC Message
+ *
+ * @param msg PB-TNC message to be addedd
+ * @return TRUE if message fit into batch and was added
+ */
+ bool (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg);
+
+ /**
+ * Build the PB-TNC Batch
+ */
+ void (*build)(pb_tnc_batch_t *this);
+
+ /**
+ * Process the PB-TNC Batch
+ *
+ * @param PB-TNC state machine
+ * @return return processing status
+ */
+ status_t (*process)(pb_tnc_batch_t *this,
+ pb_tnc_state_machine_t *state_machine);
+
+ /**
+ * Enumerates over all PB-TNC Messages
+ *
+ * @return return message enumerator
+ */
+ enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this);
+
+ /**
+ * Enumerates over all parsing errors
+ *
+ * @return return error enumerator
+ */
+ enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this);
+
+ /**
+ * Destroys a pb_tnc_batch_t object.
+ */
+ void (*destroy)(pb_tnc_batch_t *this);
+};
+
+/**
+ * Create an empty PB-TNC Batch of a given type
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param type PB-TNC batch type
+ * @param max_batch_len maximum size the PB-TNC batch
+ */
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
+ size_t max_batch_len);
+
+/**
+ * Create an unprocessed PB-TNC Batch from data
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param data encoded PB-TNC batch
+ */
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data);
+
+#endif /** PB_TNC_BATCH_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.c
new file mode 100644
index 000000000..5c4b5ae00
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_access_recommendation_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED,
+ "Access Allowed",
+ "Access Denied",
+ "Quarantined"
+);
+
+typedef struct private_pb_access_recommendation_msg_t private_pb_access_recommendation_msg_t;
+
+/**
+ * PB-Access-Recommendation message (see section 4.7 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Access Recommendation Code |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ACCESS_RECOMMENDATION_RESERVED 0x0000
+#define ACCESS_RECOMMENDATION_MSG_SIZE 4
+/**
+ * Private data of a pb_access_recommendation_msg_t object.
+ *
+ */
+struct private_pb_access_recommendation_msg_t {
+ /**
+ * Public pb_access_recommendation_msg_t interface.
+ */
+ pb_access_recommendation_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Access recommendation code
+ */
+ u_int16_t recommendation;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_access_recommendation_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE);
+ writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED);
+ writer->write_uint16(writer, this->recommendation);
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_access_recommendation_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int16_t reserved;
+
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &this->recommendation);
+ reader->destroy(reader);
+
+ if (this->recommendation < PB_REC_ACCESS_ALLOWED ||
+ this->recommendation > PB_REC_QUARANTINED)
+ {
+ DBG1(DBG_TNC, "invalid access recommendation code (%u)",
+ this->recommendation);
+ *offset = 2;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_access_recommendation_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+METHOD(pb_access_recommendation_msg_t, get_access_recommendation, u_int16_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->recommendation;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_access_recommendation_msg_create_from_data(chunk_t data)
+{
+ private_pb_access_recommendation_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_access_recommendation = _get_access_recommendation,
+ },
+ .type = { PEN_IETF, PB_MSG_ACCESS_RECOMMENDATION },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_access_recommendation_msg_create(u_int16_t recommendation)
+{
+ private_pb_access_recommendation_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_access_recommendation = _get_access_recommendation,
+ },
+ .type = { PEN_IETF, PB_MSG_ACCESS_RECOMMENDATION },
+ .recommendation = recommendation,
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.h
new file mode 100644
index 000000000..d0dc6358b
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_access_recommendation_msg.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_access_recommendation_msg pb_access_recommendation_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ACCESS_RECOMMENDATION_MSG_H_
+#define PB_ACCESS_RECOMMENDATION_MSG_H_
+
+typedef enum pb_access_recommendation_code_t pb_access_recommendation_code_t;
+typedef struct pb_access_recommendation_msg_t pb_access_recommendation_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * PB Access Recommendation Codes as defined in section 4.7 of RFC 5793
+ */
+enum pb_access_recommendation_code_t {
+ PB_REC_ACCESS_ALLOWED = 1,
+ PB_REC_ACCESS_DENIED = 2,
+ PB_REC_QUARANTINED = 3,
+};
+
+/**
+ * enum name for pb_access_recommendation_code_t.
+ */
+extern enum_name_t *pb_access_recommendation_code_names;
+
+
+/**
+ * Class representing the PB-Access-Recommendation message type.
+ */
+struct pb_access_recommendation_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Access Recommendation
+ *
+ * @return PB Access Recommendation
+ */
+ u_int16_t (*get_access_recommendation)(pb_access_recommendation_msg_t *this);
+};
+
+/**
+ * Create a PB-Access-Recommendation message from parameters
+ *
+ * @param recommendation Access Recommendation code
+ */
+pb_tnc_msg_t* pb_access_recommendation_msg_create(u_int16_t recommendation);
+
+/**
+ * Create an unprocessed PB-Access-Recommendation message from raw data
+ *
+ * @param data PB-Access-Recommendation message data
+ */
+pb_tnc_msg_t* pb_access_recommendation_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.c
new file mode 100644
index 000000000..e23493569
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_assessment_result_msg.h"
+
+#include <tncifimv.h>
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t;
+
+/**
+ * PB-Assessment-Result message (see section 4.6 of RFC 5793)
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Assessment Result |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ASSESSMENT_RESULT_MSG_SIZE 4
+
+/**
+ * Private data of a pb_assessment_result_msg_t object.
+ *
+ */
+struct private_pb_assessment_result_msg_t {
+ /**
+ * Public pb_assessment_result_msg_t interface.
+ */
+ pb_assessment_result_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Assessment result code
+ */
+ u_int32_t assessment_result;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_assessment_result_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(ASSESSMENT_RESULT_MSG_SIZE);
+ writer->write_uint32(writer, this->assessment_result);
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_assessment_result_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint32(reader, &this->assessment_result);
+ reader->destroy(reader);
+
+ if (this->assessment_result < TNC_IMV_EVALUATION_RESULT_COMPLIANT ||
+ this->assessment_result > TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+ {
+ DBG1(DBG_TNC, "invalid assessment result (%u)",
+ this->assessment_result);
+ *offset = 0;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_assessment_result_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+METHOD(pb_assessment_result_msg_t, get_assessment_result, u_int32_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->assessment_result;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_assessment_result_msg_create_from_data(chunk_t data)
+{
+ private_pb_assessment_result_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_assessment_result = _get_assessment_result,
+ },
+ .type = { PEN_IETF, PB_MSG_ASSESSMENT_RESULT },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_assessment_result_msg_create(u_int32_t assessment_result)
+{
+ private_pb_assessment_result_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_assessment_result = _get_assessment_result,
+ },
+ .type = { PEN_IETF, PB_MSG_ASSESSMENT_RESULT },
+ .assessment_result = assessment_result,
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.h
new file mode 100644
index 000000000..11cfdbef2
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_assessment_result_msg.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_assessment_result_msg pb_assessment_result_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ASSESSMENT_RESULT_MSG_H_
+#define PB_ASSESSMENT_RESULT_MSG_H_
+
+typedef struct pb_assessment_result_msg_t pb_assessment_result_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Assessment-Result message type.
+ */
+struct pb_assessment_result_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Assessment result
+ *
+ * @return PB Assessment result
+ */
+ u_int32_t (*get_assessment_result)(pb_assessment_result_msg_t *this);
+};
+
+/**
+ * Create a PB-Assessment-Result message from parameters
+ *
+ * @param assessment_result Assessment result code
+ */
+pb_tnc_msg_t* pb_assessment_result_msg_create(u_int32_t assessment_result);
+
+/**
+ * Create an unprocessed PB-Assessment-Result message from raw data
+ *
+ * @param data PB-Assessment-Result message data
+ */
+pb_tnc_msg_t* pb_assessment_result_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.c
new file mode 100644
index 000000000..d9910f660
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_error_msg.h"
+
+#include <tnc/tnccs/tnccs.h>
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE,
+ PB_ERROR_VERSION_NOT_SUPPORTED,
+ "Unexpected Batch Type",
+ "Invalid Parameter",
+ "Local Error",
+ "Unsupported Mandatory Message",
+ "Version Not Supported"
+);
+
+typedef struct private_pb_error_msg_t private_pb_error_msg_t;
+
+/**
+ * PB-Error message (see section 4.9 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Error Code Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Error Code | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Error Parameters (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ERROR_FLAG_NONE 0x00
+#define ERROR_FLAG_FATAL (1<<7)
+#define ERROR_RESERVED 0x0000
+#define ERROR_HEADER_SIZE 8
+
+/**
+ * Private data of a pb_error_msg_t object.
+ *
+ */
+struct private_pb_error_msg_t {
+ /**
+ * Public pb_error_msg_t interface.
+ */
+ pb_error_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Fatal flag
+ */
+ bool fatal;
+
+ /**
+ * PB Error Code Vendor ID
+ */
+ u_int32_t vendor_id;
+
+ /**
+ * PB Error Code
+ */
+ u_int16_t error_code;
+
+ /**
+ * PB Error Offset
+ */
+ u_int32_t error_offset;
+
+ /**
+ * Bad PB-TNC version received
+ */
+ u_int8_t bad_version;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_error_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_error_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_error_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+
+ /* build message header */
+ writer = bio_writer_create(ERROR_HEADER_SIZE);
+ writer->write_uint8 (writer, this->fatal ?
+ ERROR_FLAG_FATAL : ERROR_FLAG_NONE);
+ writer->write_uint24(writer, this->vendor_id);
+ writer->write_uint16(writer, this->error_code);
+ writer->write_uint16(writer, ERROR_RESERVED);
+
+ /* build message body */
+ if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
+ {
+ /* Bad version */
+ writer->write_uint8(writer, this->bad_version);
+ writer->write_uint8(writer, PB_TNC_VERSION); /* Max version */
+ writer->write_uint8(writer, PB_TNC_VERSION); /* Min version */
+ writer->write_uint8(writer, 0x00); /* Reserved */
+ }
+ else
+ {
+ /* Error Offset */
+ writer->write_uint32(writer, this->error_offset);
+ }
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_error_msg_t *this, u_int32_t *offset)
+{
+ u_int8_t flags, max_version, min_version;
+ u_int16_t reserved;
+ bio_reader_t *reader;
+
+ if (this->encoding.len < ERROR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes",
+ pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE);
+ *offset = 0;
+ return FAILED;
+ }
+
+ /* process message header */
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->vendor_id);
+ reader->read_uint16(reader, &this->error_code);
+ reader->read_uint16(reader, &reserved);
+ this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE;
+
+ if (this->vendor_id == PEN_IETF && reader->remaining(reader) == 4)
+ {
+ if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
+ {
+ reader->read_uint8(reader, &this->bad_version);
+ reader->read_uint8(reader, &max_version);
+ reader->read_uint8(reader, &min_version);
+ }
+ else
+ {
+ reader->read_uint32(reader, &this->error_offset);
+ }
+ }
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, get_ref, pb_tnc_msg_t*,
+ private_pb_error_msg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pb_interface;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_error_msg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->encoding.ptr);
+ free(this);
+ }
+}
+
+METHOD(pb_error_msg_t, get_fatal_flag, bool,
+ private_pb_error_msg_t *this)
+{
+ return this->fatal;
+}
+
+METHOD(pb_error_msg_t, get_vendor_id, u_int32_t,
+ private_pb_error_msg_t *this)
+{
+ return this->vendor_id;
+}
+
+METHOD(pb_error_msg_t, get_error_code, u_int16_t,
+ private_pb_error_msg_t *this)
+{
+ return this->error_code;
+}
+
+METHOD(pb_error_msg_t, get_offset, u_int32_t,
+ private_pb_error_msg_t *this)
+{
+ return this->error_offset;
+}
+
+METHOD(pb_error_msg_t, get_bad_version, u_int8_t,
+ private_pb_error_msg_t *this)
+{
+ return this->bad_version;
+}
+
+METHOD(pb_error_msg_t, set_bad_version, void,
+ private_pb_error_msg_t *this, u_int8_t version)
+{
+ this->bad_version = version;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = { PEN_IETF, PB_MSG_ERROR },
+ .ref = 1,
+ .fatal = fatal,
+ .vendor_id = vendor_id,
+ .error_code = error_code,
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code,
+ u_int32_t error_offset)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = { PEN_IETF, PB_MSG_ERROR },
+ .ref = 1,
+ .fatal = fatal,
+ .vendor_id = vendor_id,
+ .error_code = error_code,
+ .error_offset = error_offset,
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_error_msg_create_from_data(chunk_t data)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = { PEN_IETF, PB_MSG_ERROR },
+ .ref = 1,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.h
new file mode 100644
index 000000000..9c0ad82a6
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_error_msg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_error_msg pb_error_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ERROR_MSG_H_
+#define PB_ERROR_MSG_H_
+
+typedef enum pb_tnc_error_code_t pb_tnc_error_code_t;
+typedef struct pb_error_msg_t pb_error_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * PB-TNC Error Codes as defined in section 4.9.1 of RFC 5793
+ */
+enum pb_tnc_error_code_t {
+ PB_ERROR_UNEXPECTED_BATCH_TYPE = 0,
+ PB_ERROR_INVALID_PARAMETER = 1,
+ PB_ERROR_LOCAL_ERROR = 2,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG = 3,
+ PB_ERROR_VERSION_NOT_SUPPORTED = 4
+};
+
+/**
+ * enum name for pb_tnc_error_code_t.
+ */
+extern enum_name_t *pb_tnc_error_code_names;
+
+/**
+ * Class representing the PB-Error message type.
+ */
+struct pb_error_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get the fatal flag
+ *
+ * @return fatal flag
+ */
+ bool (*get_fatal_flag)(pb_error_msg_t *this);
+
+ /**
+ * Get PB Error code Vendor ID
+ *
+ * @return PB Error Code Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pb_error_msg_t *this);
+
+ /**
+ * Get PB Error Code
+ *
+ * @return PB Error Code
+ */
+ u_int16_t (*get_error_code)(pb_error_msg_t *this);
+
+ /**
+ * Get the PB Error Offset
+ *
+ * @return PB Error Offset
+ */
+ u_int32_t (*get_offset)(pb_error_msg_t *this);
+
+ /**
+ * Get the PB Bad Version
+ *
+ * @return PB Bad Version
+ */
+ u_int8_t (*get_bad_version)(pb_error_msg_t *this);
+
+ /**
+ * Set the PB Bad Version
+ *
+ * @param version PB Bad Version
+ */
+ void (*set_bad_version)(pb_error_msg_t *this, u_int8_t version);
+};
+
+/**
+ * Create a PB-Error message from parameters
+ *
+ * @param fatal fatal flag
+ * @param vendor_id Error Code Vendor ID
+ * @param error_code Error Code
+ */
+pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code);
+
+/**
+ * Create a PB-Error message from parameters with offset field
+ *
+ * @param fatal fatal flag
+ * @param vendor_id Error Code Vendor ID
+ * @param error_code Error Code
+ * @param error_offset Error Offset
+ */
+pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code,
+ u_int32_t error_offset);
+
+/**
+ * Create an unprocessed PB-Error message from raw data
+ *
+ * @param data PB-Error message data
+ */
+pb_tnc_msg_t* pb_error_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.c
new file mode 100644
index 000000000..c6290887c
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_experimental_msg.h"
+
+typedef struct private_pb_experimental_msg_t private_pb_experimental_msg_t;
+
+/**
+ * Private data of a pb_experimental_msg_t object.
+ *
+ */
+struct private_pb_experimental_msg_t {
+ /**
+ * Public pb_experimental_msg_t interface.
+ */
+ pb_experimental_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_experimental_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_experimental_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_experimental_msg_t *this)
+{
+ /* nothing to do since message contents equal encoding */
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_experimental_msg_t *this, u_int32_t *offset)
+{
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_experimental_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_experimental_msg_create_from_data(chunk_t data)
+{
+ private_pb_experimental_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_IETF, PB_MSG_EXPERIMENTAL },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_experimental_msg_create(chunk_t body)
+{
+ return pb_experimental_msg_create_from_data(body);
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.h
new file mode 100644
index 000000000..fb9ede1a8
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_experimental_msg.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_experimental_msg pb_experimental_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_EXPERIMENTAL_MSG_H_
+#define PB_EXPERIMENTAL_MSG_H_
+
+typedef struct pb_experimental_msg_t pb_experimental_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Experimental message type.
+ */
+struct pb_experimental_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+};
+
+/**
+ * Create a PB-Experimental message from parameters
+ *
+ * @param body message body
+ */
+pb_tnc_msg_t* pb_experimental_msg_create(chunk_t body);
+
+/**
+ * Create an unprocessed PB-Experimental message from raw data
+ *
+ * @param data PB-Experimental message data
+ */
+pb_tnc_msg_t* pb_experimental_msg_create_from_data(chunk_t data);
+
+#endif /** PB_EXPERIMENTAL_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.c
new file mode 100644
index 000000000..f14f28980
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_language_preference_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t;
+
+/**
+ * PB-Language-Preference message (see section 4.10 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Language Preference (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_LANG_PREFIX "Accept-Language: "
+#define PB_LANG_PREFIX_LEN strlen(PB_LANG_PREFIX)
+
+/**
+ * Private data of a pb_language_preference_msg_t object.
+ *
+ */
+struct private_pb_language_preference_msg_t {
+ /**
+ * Public pb_access_recommendation_msg_t interface.
+ */
+ pb_language_preference_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Language preference
+ */
+ chunk_t language_preference;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_language_preference_msg_t *this)
+{
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ this->encoding = chunk_cat("cc",
+ chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN),
+ this->language_preference);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_language_preference_msg_t *this, u_int32_t *offset)
+{
+ chunk_t lang;
+
+ if (this->encoding.len >= PB_LANG_PREFIX_LEN &&
+ memeq(this->encoding.ptr, PB_LANG_PREFIX, PB_LANG_PREFIX_LEN))
+ {
+ lang = chunk_skip(this->encoding, PB_LANG_PREFIX_LEN);
+ this->language_preference = lang.len ? chunk_clone(lang) : chunk_empty;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "language preference must be preceded by '%s'",
+ PB_LANG_PREFIX);
+ *offset = 0;
+ return FAILED;
+ }
+
+ if (this->language_preference.len &&
+ this->language_preference.ptr[this->language_preference.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "language preference must not be null terminated");
+ *offset = PB_LANG_PREFIX_LEN + this->language_preference.len - 1;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_language_preference_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->language_preference.ptr);
+ free(this);
+}
+
+METHOD(pb_language_preference_msg_t, get_language_preference, chunk_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->language_preference;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_language_preference_msg_create_from_data(chunk_t data)
+{
+ private_pb_language_preference_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_language_preference = _get_language_preference,
+ },
+ .type = { PEN_IETF, PB_MSG_LANGUAGE_PREFERENCE },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_language_preference_msg_create(chunk_t language_preference)
+{
+ private_pb_language_preference_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_language_preference = _get_language_preference,
+ },
+ .type = { PEN_IETF, PB_MSG_LANGUAGE_PREFERENCE },
+ .language_preference = chunk_clone(language_preference),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.h
new file mode 100644
index 000000000..512cab301
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_language_preference_msg.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_language_preference_msg pb_language_preference_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_LANGUAGE_PREFERENCE_MSG_H_
+#define PB_LANGUAGE_PREFERENCE_MSG_H_
+
+typedef struct pb_language_preference_msg_t pb_language_preference_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Language-Preference message type.
+ */
+struct pb_language_preference_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Language Preference
+ *
+ * @return Language preference
+ */
+ chunk_t (*get_language_preference)(pb_language_preference_msg_t *this);
+};
+
+/**
+ * Create a PB-Language-Preference message from parameters
+ *
+ * @param language_preference Preferred language(s)
+ */
+pb_tnc_msg_t* pb_language_preference_msg_create(chunk_t language_preference);
+
+/**
+ * Create an unprocessed PB-Language-Preference message from raw data
+ *
+ * @param data PB-Language-Preference message data
+ */
+pb_tnc_msg_t* pb_language_preference_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c
new file mode 100644
index 000000000..a9a097bd4
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
+ * Copyright (C) 2010 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_pa_msg.h"
+
+#include <tnc/tnccs/tnccs.h>
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+typedef struct private_pb_pa_msg_t private_pb_pa_msg_t;
+
+/**
+ * PB-PA message
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PA Message Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA Subtype |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Posture Collector Identifier | Posture Validator Identifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA Message Body (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PA_FLAG_NONE 0x00
+#define PA_FLAG_EXCL (1<<7)
+#define PA_RESERVED_SUBTYPE 0xffffffff
+
+
+/**
+ * Private data of a pb_pa_msg_t object.
+ *
+ */
+struct private_pb_pa_msg_t {
+ /**
+ * Public pb_pa_msg_t interface.
+ */
+ pb_pa_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Exclusive flag
+ */
+ bool excl;
+
+ /**
+ * Vendor-specific PA Subtype
+ */
+ pen_type_t subtype;
+
+ /**
+ * Posture Validator Identifier
+ */
+ u_int16_t collector_id;
+
+ /**
+ * Posture Validator Identifier
+ */
+ u_int16_t validator_id;
+
+ /**
+ * PA Message Body
+ */
+ chunk_t msg_body;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_pa_msg_t *this)
+{
+ chunk_t msg_header;
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+
+ /* build message header */
+ writer = bio_writer_create(64);
+ writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE);
+ writer->write_uint24(writer, this->subtype.vendor_id);
+ writer->write_uint32(writer, this->subtype.type);
+ writer->write_uint16(writer, this->collector_id);
+ writer->write_uint16(writer, this->validator_id);
+ msg_header = writer->get_buf(writer);
+
+ /* create encoding by concatenating message header and message body */
+ this->encoding = chunk_cat("cc", msg_header, this->msg_body);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_pa_msg_t *this, u_int32_t *offset)
+{
+ u_int8_t flags;
+ size_t msg_body_len;
+ bio_reader_t *reader;
+
+ /* process message header */
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->subtype.vendor_id);
+ reader->read_uint32(reader, &this->subtype.type);
+ reader->read_uint16(reader, &this->collector_id);
+ reader->read_uint16(reader, &this->validator_id);
+ this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
+
+ /* process message body */
+ msg_body_len = reader->remaining(reader);
+ if (msg_body_len)
+ {
+ reader->read_data(reader, msg_body_len, &this->msg_body);
+ this->msg_body = chunk_clone(this->msg_body);
+ }
+ reader->destroy(reader);
+
+ if (this->subtype.vendor_id == PEN_RESERVED)
+ {
+ DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
+ *offset = 1;
+ return FAILED;
+ }
+
+ if (this->subtype.type == PA_RESERVED_SUBTYPE)
+ {
+ DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
+ *offset = 4;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_pa_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->msg_body.ptr);
+ free(this);
+}
+
+METHOD(pb_pa_msg_t, get_subtype, pen_type_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->subtype;
+}
+
+METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->collector_id;
+}
+
+METHOD(pb_pa_msg_t, get_validator_id, u_int16_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->validator_id;
+}
+
+METHOD(pb_pa_msg_t, get_body, chunk_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->msg_body;
+}
+
+METHOD(pb_pa_msg_t, get_exclusive_flag, bool,
+ private_pb_pa_msg_t *this)
+{
+ return this->excl;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
+{
+ private_pb_pa_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_subtype = _get_subtype,
+ .get_collector_id = _get_collector_id,
+ .get_validator_id = _get_validator_id,
+ .get_body = _get_body,
+ .get_exclusive_flag = _get_exclusive_flag,
+ },
+ .type = { PEN_IETF, PB_MSG_PA },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
+ u_int16_t collector_id, u_int16_t validator_id,
+ bool excl, chunk_t msg_body)
+{
+ private_pb_pa_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_subtype= _get_subtype,
+ .get_collector_id = _get_collector_id,
+ .get_validator_id = _get_validator_id,
+ .get_body = _get_body,
+ .get_exclusive_flag = _get_exclusive_flag,
+ },
+ .type = { PEN_IETF, PB_MSG_PA },
+ .subtype = { vendor_id, subtype },
+ .collector_id = collector_id,
+ .validator_id = validator_id,
+ .excl = excl,
+ .msg_body = chunk_clone(msg_body),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h
new file mode 100644
index 000000000..093bb45ae
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_pa_msg pb_pa_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_PA_MSG_H_
+#define PB_PA_MSG_H_
+
+typedef struct pb_pa_msg_t pb_pa_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+#include <pen/pen.h>
+
+/**
+ * Class representing the PB-PA message type.
+ */
+struct pb_pa_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PA Message Vendor ID and Subtype
+ *
+ * @return Vendor-specific PA Subtype
+ */
+ pen_type_t (*get_subtype)(pb_pa_msg_t *this);
+
+ /**
+ * Get Posture Collector ID
+ *
+ * @return Posture Collector ID
+ */
+ u_int16_t (*get_collector_id)(pb_pa_msg_t *this);
+
+ /**
+ * Get Posture Validator ID
+ *
+ * @return Posture Validator ID
+ */
+ u_int16_t (*get_validator_id)(pb_pa_msg_t *this);
+
+ /**
+ * Get the PA Message Body
+ *
+ * @return PA Message Body
+ */
+ chunk_t (*get_body)(pb_pa_msg_t *this);
+
+ /**
+ * Get the exclusive flag
+ *
+ * @return exclusive flag
+ */
+ bool (*get_exclusive_flag)(pb_pa_msg_t *this);
+
+};
+
+/**
+ * Create a PB-PA message from parameters
+ *
+ * @param vendor_id PA Message Vendor ID
+ * @param subtype PA Subtype
+ * @param collector_id Posture Collector ID
+ * @param validator_id Posture Validator ID
+ * @param excl Exclusive Flag
+ * @param msg_body PA Message Body
+ */
+pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
+ u_int16_t collector_id, u_int16_t validator_id,
+ bool excl, chunk_t msg_body);
+
+/**
+ * Create an unprocessed PB-PA message from raw data
+ *
+ * @param data PB-PA message data
+ */
+pb_tnc_msg_t* pb_pa_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.c
new file mode 100644
index 000000000..cafc4ec54
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_reason_string_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t;
+
+/**
+ * PB-Language-Preference message (see section 4.11 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reason String Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reason String (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Lang Code Len | Reason String Language Code (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of a pb_reason_string_msg_t object.
+ *
+ */
+struct private_pb_reason_string_msg_t {
+ /**
+ * Public pb_reason_string_msg_t interface.
+ */
+ pb_reason_string_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Reason string
+ */
+ chunk_t reason_string;
+
+ /**
+ * Language code
+ */
+ chunk_t language_code;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_reason_string_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(64);
+ writer->write_data32(writer, this->reason_string);
+ writer->write_data8 (writer, this->language_code);
+
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_reason_string_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ reader = bio_reader_create(this->encoding);
+ if (!reader->read_data32(reader, &this->reason_string))
+ {
+ DBG1(DBG_TNC, "could not parse reason string");
+ reader->destroy(reader);
+ *offset = 0;
+ return FAILED;
+ };
+ this->reason_string = chunk_clone(this->reason_string);
+
+ if (this->reason_string.len &&
+ this->reason_string.ptr[this->reason_string.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "reason string must not be null terminated");
+ reader->destroy(reader);
+ *offset = 3 + this->reason_string.len;
+ return FAILED;
+ }
+
+ if (!reader->read_data8(reader, &this->language_code))
+ {
+ DBG1(DBG_TNC, "could not parse language code");
+ reader->destroy(reader);
+ *offset = 4 + this->reason_string.len;
+ return FAILED;
+ };
+ this->language_code = chunk_clone(this->language_code);
+ reader->destroy(reader);
+
+ if (this->language_code.len &&
+ this->language_code.ptr[this->language_code.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "language code must not be null terminated");
+ *offset = 4 + this->reason_string.len + this->language_code.len;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_reason_string_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->reason_string.ptr);
+ free(this->language_code.ptr);
+ free(this);
+}
+
+METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->reason_string;
+}
+
+METHOD(pb_reason_string_msg_t, get_language_code, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->language_code;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data)
+{
+ private_pb_reason_string_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_reason_string = _get_reason_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = { PEN_IETF, PB_MSG_REASON_STRING },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string,
+ chunk_t language_code)
+{
+ private_pb_reason_string_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_reason_string = _get_reason_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = { PEN_IETF, PB_MSG_REASON_STRING },
+ .reason_string = chunk_clone(reason_string),
+ .language_code = chunk_clone(language_code),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.h
new file mode 100644
index 000000000..65e3e880d
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_reason_string_msg.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_reason_string_msg pb_reason_string_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_REASON_STRING_MSG_H_
+#define PB_REASON_STRING_MSG_H_
+
+typedef struct pb_reason_string_msg_t pb_reason_string_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Reason-String message type.
+ */
+struct pb_reason_string_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get Reason String
+ *
+ * @return Reason string
+ */
+ chunk_t (*get_reason_string)(pb_reason_string_msg_t *this);
+
+ /**
+ * Get Reason String Language Code
+ *
+ * @return Language code
+ */
+ chunk_t (*get_language_code)(pb_reason_string_msg_t *this);
+};
+
+/**
+ * Create a PB-Reason-String message from parameters
+ *
+ * @param reason_string Reason string
+ * @param language_code Language code
+ */
+pb_tnc_msg_t* pb_reason_string_msg_create(chunk_t reason_string,
+ chunk_t language_code);
+
+/**
+ * Create an unprocessed PB-Reason-String message from raw data
+ *
+ * @param data PB-Reason-String message data
+ */
+pb_tnc_msg_t* pb_reason_string_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.c
new file mode 100644
index 000000000..8dc590657
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_remediation_parameters_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING,
+ "Remediation-URI",
+ "Remediation-String"
+);
+
+typedef struct private_pb_remediation_parameters_msg_t private_pb_remediation_parameters_msg_t;
+
+/**
+ * PB-Remediation-Parameters message (see section 4.8 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Remediation Parameters Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation Parameters Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation Parameters (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation String Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation String (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Lang Code Len | Remediation String Lang Code (Variable Len) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of a pb_remediation_parameters_msg_t object.
+ *
+ */
+struct private_pb_remediation_parameters_msg_t {
+ /**
+ * Public pb_remediation_parameters_msg_t interface.
+ */
+ pb_remediation_parameters_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Remediation Parameters Type
+ */
+ pen_type_t parameters_type;
+
+ /**
+ * Remediation Parameters
+ */
+ chunk_t parameters;
+
+ /**
+ * Remediation String
+ */
+ chunk_t string;
+
+ /**
+ * Remediation Language Code
+ */
+ chunk_t lang_code;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(64);
+ writer->write_uint32(writer, this->parameters_type.vendor_id);
+ writer->write_uint32(writer, this->parameters_type.type);
+ writer->write_data (writer, this->parameters);
+
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_remediation_parameters_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t reserved;
+ status_t status = SUCCESS;
+ u_char *pos;
+
+ *offset = 0;
+
+ /* process message */
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &this->parameters_type.vendor_id);
+ reader->read_uint32(reader, &this->parameters_type.type);
+ reader->read_data (reader, reader->remaining(reader), &this->parameters);
+
+ this->parameters = chunk_clone(this->parameters);
+ reader->destroy(reader);
+
+ if (this->parameters_type.vendor_id == PEN_IETF &&
+ this->parameters_type.type == PB_REMEDIATION_STRING)
+ {
+ reader = bio_reader_create(this->parameters);
+ status = FAILED;
+ *offset = 8;
+
+ if (!reader->read_data32(reader, &this->string))
+ {
+ DBG1(DBG_TNC, "insufficient data for remediation string");
+ goto end;
+ };
+ *offset += 4;
+
+ pos = memchr(this->string.ptr, '\0', this->string.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in remediation string");
+ *offset += (pos - this->string.ptr);
+ goto end;
+ }
+ *offset += this->string.len;
+
+ if (!reader->read_data8(reader, &this->lang_code))
+ {
+ DBG1(DBG_TNC, "insufficient data for remediation string lang code");
+ goto end;
+ };
+ *offset += 1;
+
+ pos = memchr(this->lang_code.ptr, '\0', this->lang_code.len);
+
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in remediation string lang code");
+ *offset += (pos - this->lang_code.ptr);
+ goto end;
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ }
+ return status;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->parameters.ptr);
+ free(this);
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_parameters_type, pen_type_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->parameters_type;
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_parameters, chunk_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->parameters;
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_string, chunk_t,
+ private_pb_remediation_parameters_msg_t *this, chunk_t *lang_code)
+{
+ if (lang_code)
+ {
+ *lang_code = this->lang_code;
+ }
+ return this->string;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
+ chunk_t parameters)
+{
+ private_pb_remediation_parameters_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_parameters,
+ .get_string = _get_string,
+ },
+ .type = { PEN_IETF, PB_MSG_REMEDIATION_PARAMETERS },
+ .parameters_type = parameters_type,
+ .parameters = chunk_clone(parameters),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * Described in header.
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri)
+{
+ pen_type_t type = { PEN_IETF, PB_REMEDIATION_URI };
+
+ return pb_remediation_parameters_msg_create(type, uri);
+}
+
+/**
+ * Described in header.
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
+ chunk_t lang_code)
+{
+ pb_tnc_msg_t *msg;
+ bio_writer_t *writer;
+ pen_type_t type = { PEN_IETF, PB_REMEDIATION_STRING };
+
+ /* limit language code to 255 octets */
+ lang_code.len = min(255, lang_code.len);
+
+ writer = bio_writer_create(4 + string.len + 1 + lang_code.len);
+ writer->write_data32(writer, string);
+ writer->write_data8 (writer, lang_code);
+
+ msg = pb_remediation_parameters_msg_create(type, writer->get_buf(writer));
+ writer->destroy(writer);
+
+ return msg;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
+{
+ private_pb_remediation_parameters_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_parameters,
+ .get_string = _get_string,
+ },
+ .type = { PEN_IETF, PB_MSG_REMEDIATION_PARAMETERS },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.h
new file mode 100644
index 000000000..c07e52747
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_remediation_parameters_msg.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_remediation_parameters_msg pb_remediation_parameters_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_REMEDIATION_PARAMETERS_MSG_H_
+#define PB_REMEDIATION_PARAMETERS_MSG_H_
+
+typedef enum pb_tnc_remed_param_type_t pb_tnc_remed_param_type_t;
+typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+#include <pen/pen.h>
+
+/**
+ * PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793
+ */
+enum pb_tnc_remed_param_type_t {
+ PB_REMEDIATION_URI = 1,
+ PB_REMEDIATION_STRING = 2,
+};
+
+/**
+ * enum name for pb_tnc_remed_param_type_t.
+ */
+extern enum_name_t *pb_tnc_remed_param_type_names;
+
+/**
+ * Class representing the PB-Remediation-Parameters message type.
+ */
+struct pb_remediation_parameters_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get the Remediation Parameters Type (Vendor ID and Type)
+ *
+ * @return Remediation Parameters Type
+ */
+ pen_type_t (*get_parameters_type)(pb_remediation_parameters_msg_t *this);
+
+ /**
+ * Get the Remediation Parameters
+ *
+ * @return Remediation Parameters
+ */
+ chunk_t (*get_parameters)(pb_remediation_parameters_msg_t *this);
+
+ /**
+ * Get the Remediation URI
+ *
+ * @return Remediation URI
+ */
+ chunk_t (*get_uri)(pb_remediation_parameters_msg_t *this);
+
+ /**
+ * Get the Remediation String
+ *
+ * @param lang_code Optional Language Code
+ * @return Remediation String
+ */
+ chunk_t (*get_string)(pb_remediation_parameters_msg_t *this,
+ chunk_t *lang_code);
+
+};
+
+/**
+ * Create a general PB-Remediation-Parameters message
+ *
+ * @param parameters_type Remediation Parameters Type
+ * @param parameters Remediation Parameters
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type,
+ chunk_t parameters);
+
+/**
+ * Create a PB-Remediation-Parameters message of IETF Type Remediation URI
+ *
+ * @param uri Remediation URI
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri);
+
+/**
+ * Create a PB-Remediation-Parameters message of IETF Type Remediation String
+ *
+ * @param string Remediation String
+ * @param lang_code Remediation String Language Code
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string,
+ chunk_t lang_code);
+
+/**
+ * Create an unprocessed PB-Remediation-Parameters message from raw data
+ *
+ * @param data PB-Remediation-Parameters message data
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c
new file mode 100644
index 000000000..ec43490f4
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_msg.h"
+#include "ietf/pb_experimental_msg.h"
+#include "ietf/pb_pa_msg.h"
+#include "ietf/pb_error_msg.h"
+#include "ietf/pb_language_preference_msg.h"
+#include "ietf/pb_assessment_result_msg.h"
+#include "ietf/pb_access_recommendation_msg.h"
+#include "ietf/pb_remediation_parameters_msg.h"
+#include "ietf/pb_reason_string_msg.h"
+#include "tcg/pb_pdp_referral_msg.h"
+
+#include <library.h>
+
+ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING,
+ "PB-Experimental",
+ "PB-PA",
+ "PB-Assessment-Result",
+ "PB-Access-Recommendation",
+ "PB-Remediation-Parameters",
+ "PB-Error",
+ "PB-Language-Preference",
+ "PB-Reason-String"
+);
+
+ENUM(pb_tnc_tcg_msg_type_names, PB_TCG_MSG_PDP_REFERRAL, PB_TCG_MSG_PDP_REFERRAL,
+ "PB-PDP-Referral"
+);
+
+pb_tnc_msg_info_t pb_tnc_msg_infos[] = {
+ { 12, FALSE, FALSE, TRUE_OR_FALSE },
+ { 24, FALSE, FALSE, TRUE },
+ { 16, TRUE, TRUE, TRUE },
+ { 16, TRUE, TRUE, FALSE },
+ { 20, FALSE, TRUE, FALSE },
+ { 20, FALSE, FALSE, TRUE },
+ { 12, FALSE, FALSE, FALSE },
+ { 17, FALSE, TRUE, FALSE },
+};
+
+pb_tnc_msg_info_t pb_tnc_tcg_msg_infos[] = {
+ { 0 }, /* dummy entry because pb_tnc_tcg_msg_type_t starts with 1 */
+ { 20, FALSE, FALSE, FALSE },
+};
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_tnc_msg_create_from_data(pen_type_t msg_type, chunk_t value)
+{
+ if (msg_type.vendor_id == PEN_IETF)
+ {
+ switch (msg_type.type)
+ {
+ case PB_MSG_PA:
+ return pb_pa_msg_create_from_data(value);
+ case PB_MSG_ERROR:
+ return pb_error_msg_create_from_data(value);
+ case PB_MSG_EXPERIMENTAL:
+ return pb_experimental_msg_create_from_data(value);
+ case PB_MSG_LANGUAGE_PREFERENCE:
+ return pb_language_preference_msg_create_from_data(value);
+ case PB_MSG_ASSESSMENT_RESULT:
+ return pb_assessment_result_msg_create_from_data(value);
+ case PB_MSG_ACCESS_RECOMMENDATION:
+ return pb_access_recommendation_msg_create_from_data(value);
+ case PB_MSG_REMEDIATION_PARAMETERS:
+ return pb_remediation_parameters_msg_create_from_data(value);
+ case PB_MSG_REASON_STRING:
+ return pb_reason_string_msg_create_from_data(value);
+ }
+ }
+ else if (msg_type.vendor_id == PEN_TCG)
+ {
+ if (msg_type.type == PB_TCG_MSG_PDP_REFERRAL)
+ {
+ return pb_pdp_referral_msg_create_from_data(value);
+ }
+ }
+ return NULL;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
new file mode 100644
index 000000000..6eeed5156
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010-213 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_tnc_msg pb_tnc_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_MSG_H_
+#define PB_TNC_MSG_H_
+
+typedef enum pb_tnc_msg_type_t pb_tnc_msg_type_t;
+typedef struct pb_tnc_msg_info_t pb_tnc_msg_info_t;
+typedef struct pb_tnc_msg_t pb_tnc_msg_t;
+
+#include <library.h>
+#include <pen/pen.h>
+
+#define PB_TNC_VERSION 2
+
+/**
+ * PB-TNC Message Types as defined in section 4.3 of RFC 5793
+ */
+enum pb_tnc_msg_type_t {
+ PB_MSG_EXPERIMENTAL = 0,
+ PB_MSG_PA = 1,
+ PB_MSG_ASSESSMENT_RESULT = 2,
+ PB_MSG_ACCESS_RECOMMENDATION = 3,
+ PB_MSG_REMEDIATION_PARAMETERS = 4,
+ PB_MSG_ERROR = 5,
+ PB_MSG_LANGUAGE_PREFERENCE = 6,
+ PB_MSG_REASON_STRING = 7,
+ PB_MSG_ROOF = 7
+};
+
+/**
+ * enum name for pb_tnc_msg_type_t.
+ */
+extern enum_name_t *pb_tnc_msg_type_names;
+
+/**
+ * PB-TNC Message Type defined in the TCG namespace
+ */
+enum pb_tnc_tcg_msg_type_t {
+ PB_TCG_MSG_PDP_REFERRAL = 1,
+ PB_TCG_MSG_ROOF = 1
+};
+
+/**
+ * enum name for pb_tnc_tcg_msg_type_t.
+ */
+extern enum_name_t *pb_tnc_tcg_msg_type_names;
+
+/**
+ * Information entry describing a PB-TNC Message Type
+ */
+struct pb_tnc_msg_info_t {
+ u_int32_t min_size;
+ bool exact_size;
+ bool in_result_batch;
+ signed char has_noskip_flag;
+};
+
+#define TRUE_OR_FALSE 2
+
+/**
+ * Information on PB-TNC Message Types
+ */
+extern pb_tnc_msg_info_t pb_tnc_msg_infos[];
+
+/**
+ * Information on PB-TNC TCG Message Types
+ */
+extern pb_tnc_msg_info_t pb_tnc_tcg_msg_infos[];
+
+/**
+ * Generic interface for all PB-TNC message types.
+ *
+ * To handle all messages in a generic way, this interface
+ * must be implemented by each message type.
+ */
+struct pb_tnc_msg_t {
+
+ /**
+ * Get the PB-TNC Message Type
+ *
+ * @return PB-TNC Message Type
+ */
+ pen_type_t (*get_type)(pb_tnc_msg_t *this);
+
+ /**
+ * Get the encoding of the PB-TNC Message Value
+ *
+ * @return encoded PB-TNC Message Value
+ */
+ chunk_t (*get_encoding)(pb_tnc_msg_t *this);
+
+ /**
+ * Build the PB-TNC Message Value
+ */
+ void (*build)(pb_tnc_msg_t *this);
+
+ /**
+ * Process the PB-TNC Message Value
+ *
+ * @param relative offset where an error occurred
+ * @return return processing status
+ */
+ status_t (*process)(pb_tnc_msg_t *this, u_int32_t *offset);
+
+ /**
+ * Get a new reference to the message.
+ *
+ * @return this, with an increased refcount
+ */
+ pb_tnc_msg_t* (*get_ref)(pb_tnc_msg_t *this);
+
+ /**
+ * Destroys a pb_tnc_msg_t object.
+ */
+ void (*destroy)(pb_tnc_msg_t *this);
+};
+
+/**
+ * Create an unprocessed PB-TNC message
+ *
+ * Useful for the parser which wants a generic constructor for all
+ * pb_tnc_message_t types.
+ *
+ * @param msg_type PB-TNC message type
+ * @param value PB-TNC message value
+ */
+pb_tnc_msg_t* pb_tnc_msg_create_from_data(pen_type_t msg_type, chunk_t value);
+
+#endif /** PB_TNC_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.c b/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.c
new file mode 100644
index 000000000..1c8538e6b
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_pdp_referral_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+ENUM(pb_tnc_pdp_identifier_type_names, PB_PDP_ID_FQDN, PB_PDP_ID_IPV6,
+ "PDP FQDN ID",
+ "PDP IPv4 ID",
+ "PDP IPv6 ID"
+);
+
+typedef struct private_pb_pdp_referral_msg_t private_pb_pdp_referral_msg_t;
+
+/**
+ * PB-PDP-Referral message (see section 3.1.1.1 of
+ * TCG TNC PDP Discovery and Validation Specification 1.0
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | PDP Identifier Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PDP Identifier Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PDP Identifier (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Section 3.1.1.2.1 FQDN Identifier
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Protocol | Port Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | FQDN (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Section 3.1.1.2.2 IPv4 Identifier
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Protocol | Port Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IPv4 Address |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Section 3.1.1.2.3 IPv6 Identifier
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Protocol | Port Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IPv6 Address (octets 1-4) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IPv6 Address (octets 5-8) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IPv6 Address (octets 9-12) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IPv6 Address (octets 13-16) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+# define PDP_REFERRAL_HEADER_SIZE 8
+# define PDP_REFERRAL_ID_HEADER_SIZE 4
+# define PDP_REFERRAL_RESERVED 0x00
+# define PDP_REFERRAL_PROTOCOL 0x00
+
+/**
+ * Private data of a pb_pdp_referral_msg_t object.
+ *
+ */
+struct private_pb_pdp_referral_msg_t {
+ /**
+ * Public pb_pdp_referral_msg_t interface.
+ */
+ pb_pdp_referral_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * PDP Identifier Type
+ */
+ pen_type_t identifier_type;
+
+ /**
+ * PDP Identifier Value
+ */
+ chunk_t identifier;
+
+ /**
+ * PDP FQDN Identifier
+ */
+ chunk_t fqdn;
+
+ /**
+ * PT protocol the PDP is using
+ */
+ u_int8_t protocol;
+
+ /**
+ * PT port the PDP is using
+ */
+ u_int16_t port;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_pdp_referral_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_pdp_referral_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_pdp_referral_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PDP_REFERRAL_HEADER_SIZE + this->identifier.len);
+ writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
+ writer->write_uint24(writer, this->identifier_type.vendor_id);
+ writer->write_uint32(writer, this->identifier_type.type);
+ writer->write_data (writer, this->identifier);
+
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_pdp_referral_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t reserved;
+
+ *offset = 0;
+
+ /* process message */
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &this->identifier_type.vendor_id);
+ reader->read_uint32(reader, &this->identifier_type.type);
+ reader->read_data (reader, reader->remaining(reader), &this->identifier);
+
+ this->identifier = chunk_clone(this->identifier);
+ reader->destroy(reader);
+
+ if (this->identifier_type.vendor_id == PEN_TCG &&
+ this->identifier_type.type == PB_PDP_ID_FQDN)
+ {
+ reader = bio_reader_create(this->identifier);
+ *offset += PDP_REFERRAL_HEADER_SIZE;
+
+ if (this->identifier.len <= PDP_REFERRAL_ID_HEADER_SIZE)
+ {
+ reader->destroy(reader);
+ return FAILED;
+ }
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint8 (reader, &this->protocol);
+ reader->read_uint16(reader, &this->port);
+ reader->read_data (reader, reader->remaining(reader), &this->fqdn);
+ this->fqdn = chunk_clone(this->fqdn);
+ reader->destroy(reader);
+ }
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_pdp_referral_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->identifier.ptr);
+ free(this->fqdn.ptr);
+ free(this);
+}
+
+METHOD(pb_pdp_referral_msg_t, get_identifier_type, pen_type_t,
+ private_pb_pdp_referral_msg_t *this)
+{
+ return this->identifier_type;
+}
+
+METHOD(pb_pdp_referral_msg_t, get_identifier, chunk_t,
+ private_pb_pdp_referral_msg_t *this)
+{
+ return this->identifier;
+}
+
+METHOD(pb_pdp_referral_msg_t, get_fqdn, chunk_t,
+ private_pb_pdp_referral_msg_t *this, u_int8_t *protocol, u_int16_t *port)
+{
+ if (protocol)
+ {
+ *protocol = this->protocol;
+ }
+ if (port)
+ {
+ *port = this->port;
+ }
+ return this->fqdn;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create(pen_type_t identifier_type,
+ chunk_t identifier)
+{
+ private_pb_pdp_referral_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_identifier_type = _get_identifier_type,
+ .get_identifier = _get_identifier,
+ },
+ .type = { PEN_TCG, PB_TCG_MSG_PDP_REFERRAL },
+ .identifier_type = identifier_type,
+ .identifier = chunk_clone(identifier),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create_from_fqdn(chunk_t fqdn, u_int16_t port)
+{
+ pb_tnc_msg_t *msg;
+ bio_writer_t *writer;
+ pen_type_t type = { PEN_TCG, PB_PDP_ID_FQDN };
+
+ writer = bio_writer_create(PDP_REFERRAL_ID_HEADER_SIZE + fqdn.len);
+ writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
+ writer->write_uint8 (writer, PDP_REFERRAL_PROTOCOL);
+ writer->write_uint16(writer, port);
+ writer->write_data (writer, fqdn);
+
+ msg = pb_pdp_referral_msg_create(type, writer->get_buf(writer));
+ writer->destroy(writer);
+
+ return msg;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_pdp_referral_msg_create_from_data(chunk_t data)
+{
+ private_pb_pdp_referral_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_identifier_type = _get_identifier_type,
+ .get_identifier = _get_identifier,
+ .get_fqdn = _get_fqdn,
+ },
+ .type = { PEN_TCG, PB_TCG_MSG_PDP_REFERRAL },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.h b/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.h
new file mode 100644
index 000000000..b225f3381
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/tcg/pb_pdp_referral_msg.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_pdp_referral_msg pb_pdp_referral_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_PDP_REFERRAL_MSG_H_
+#define PB_PDP_REFERRAL_MSG_H_
+
+typedef enum pb_pdp_identifier_type_t pb_pdp_identifier_type_t;
+typedef struct pb_pdp_referral_msg_t pb_pdp_referral_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+#include <pen/pen.h>
+
+/**
+ * PB-TNC PDP Identifier Types as defined in section 3.1.1.2 of the
+ * TCG TNC PDP Discovery and Validation Specification 1.0
+ */
+enum pb_pdp_identifier_type_t {
+ PB_PDP_ID_FQDN = 0,
+ PB_PDP_ID_IPV4 = 1,
+ PB_PDP_ID_IPV6 = 2
+};
+
+/**
+ * enum name for pb_pdp_identifier_type_t.
+ */
+extern enum_name_t *pb_pdp_identifier_type_names;
+
+/**
+ * Class representing the PB-Remediation-Parameters message type.
+ */
+struct pb_pdp_referral_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get the PDP Identifier Type (Vendor ID and Type)
+ *
+ * @return PDP Identifier Type
+ */
+ pen_type_t (*get_identifier_type)(pb_pdp_referral_msg_t *this);
+
+ /**
+ * Get the PDP Identifier Value
+ *
+ * @return PDP Identifier Value
+ */
+ chunk_t (*get_identifier)(pb_pdp_referral_msg_t *this);
+
+ /**
+ * Get the PDP Identifier Value
+ *
+ * @param protocol PT transport protocol
+ * @param port PT port the PDP is listening on
+ * @return Fully Qualified Domain Name of PDP
+ */
+ chunk_t (*get_fqdn)(pb_pdp_referral_msg_t *this, u_int8_t *protocol,
+ u_int16_t *port);
+
+};
+
+/**
+ * Create a general PB-PDP-Referral message
+ *
+ * @param identifier_type PDP Identifier Type
+ * @param identifier PDP Identifier
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create(pen_type_t identifier_type,
+ chunk_t identifier);
+
+/**
+ * Create a PB-PDP-Referral message of TCG Type PDP FQDN Identifier
+ *
+ * @param fqdn Fully Qualified Domain Name of PDP
+ * @param port PT-TLS port the PDP is listening on
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create_from_fqdn(chunk_t fqdn, u_int16_t port);
+
+/**
+ * Create an unprocessed PB-PDP-Referral message from raw data
+ *
+ * @param data PB-PDP-Referral message data
+ */
+pb_tnc_msg_t* pb_pdp_referral_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
new file mode 100644
index 000000000..43f185440
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_state_machine.h"
+
+#include <utils/debug.h>
+
+ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END,
+ "Init",
+ "Server Working",
+ "Client Working",
+ "Decided",
+ "End"
+);
+
+/**
+ * PB-TNC State Machine (see section 3.2 of RFC 5793)
+ *
+ * Receive CRETRY SRETRY
+ * or SRETRY +----------------+
+ * +--+ | |
+ * v | v |
+ * +---------+ CRETRY +---------+
+ * CDATA | Server |<---------| Decided | CLOSE
+ * +----------->| Working |--------->| |-------+
+ * | +---------+ RESULT +---------+ |
+ * | ^ | | v
+ * | | | +---------------------->=======
+ * ======== | | CLOSE " End "
+ * " Init " CDATA| |SDATA =======
+ * ======== | | ^ ^
+ * | | | v | |
+ * | | SDATA +---------+ CLOSE | |
+ * | +-------->| Client |----------------------+ |
+ * | | Working | |
+ * | +---------+ |
+ * | | ^ |
+ * | +--+ |
+ * | Receive CRETRY |
+ * | CLOSE |
+ * +--------------------------------------------------+
+ */
+
+typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t;
+
+/**
+ * Private data of a pb_tnc_state_machine_t object.
+ *
+ */
+struct private_pb_tnc_state_machine_t {
+ /**
+ * Public pb_pa_message_t interface.
+ */
+ pb_tnc_state_machine_t public;
+
+ /**
+ * PB-TNC Server if TRUE, PB-TNC Client if FALSE
+ */
+ bool is_server;
+
+ /**
+ * Informs whether last received PB-TNC CDATA Batch was empty
+ */
+ bool empty_cdata;
+
+ /**
+ * Current PB-TNC state
+ */
+ pb_tnc_state_t state;
+};
+
+METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t,
+ private_pb_tnc_state_machine_t *this)
+{
+ return this->state;
+}
+
+METHOD(pb_tnc_state_machine_t, receive_batch, bool,
+ private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
+{
+ pb_tnc_state_t old_state = this->state;
+
+ switch (this->state)
+ {
+ case PB_STATE_INIT:
+ if (this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (!this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_SERVER_WORKING:
+ if (!this->is_server && (type == PB_BATCH_SDATA ||
+ type == PB_BATCH_SRETRY))
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (!this->is_server && type == PB_BATCH_RESULT)
+ {
+ this->state = PB_STATE_DECIDED;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_CRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_CLIENT_WORKING:
+ if (this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_CRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_DECIDED:
+ if ((this->is_server && type == PB_BATCH_CRETRY) ||
+ (!this->is_server && type == PB_BATCH_SRETRY))
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_END:
+ if (type == PB_BATCH_CLOSE)
+ {
+ break;
+ }
+ return FALSE;
+ }
+
+ if (this->state != old_state)
+ {
+ DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
+ pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
+ }
+ return TRUE;
+}
+
+METHOD(pb_tnc_state_machine_t, send_batch, bool,
+ private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
+{
+ pb_tnc_state_t old_state = this->state;
+
+ switch (this->state)
+ {
+ case PB_STATE_INIT:
+ if (!this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_SERVER_WORKING:
+ if (this->is_server && (type == PB_BATCH_SDATA ||
+ type == PB_BATCH_SRETRY))
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_RESULT)
+ {
+ this->state = PB_STATE_DECIDED;
+ break;
+ }
+ if (!this->is_server && type == PB_BATCH_CRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_CLIENT_WORKING:
+ if (!this->is_server && (type == PB_BATCH_CDATA ||
+ type == PB_BATCH_CRETRY))
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_SRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_DECIDED:
+ if ((this->is_server && type == PB_BATCH_SRETRY) ||
+ (!this->is_server && type == PB_BATCH_CRETRY))
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_END:
+ if (type == PB_BATCH_CLOSE)
+ {
+ break;
+ }
+ return FALSE;
+ }
+
+ if (this->state != old_state)
+ {
+ DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
+ pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
+ }
+ return TRUE;
+}
+
+METHOD(pb_tnc_state_machine_t, get_empty_cdata, bool,
+ private_pb_tnc_state_machine_t *this)
+{
+ return this->empty_cdata;
+}
+
+METHOD(pb_tnc_state_machine_t, set_empty_cdata, void,
+ private_pb_tnc_state_machine_t *this, bool empty)
+{
+ if (empty)
+ {
+ DBG2(DBG_TNC, "received empty PB-TNC CDATA batch");
+ }
+ this->empty_cdata = empty;
+}
+
+METHOD(pb_tnc_state_machine_t, destroy, void,
+ private_pb_tnc_state_machine_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server)
+{
+ private_pb_tnc_state_machine_t *this;
+
+ INIT(this,
+ .public = {
+ .get_state = _get_state,
+ .receive_batch = _receive_batch,
+ .send_batch = _send_batch,
+ .get_empty_cdata = _get_empty_cdata,
+ .set_empty_cdata = _set_empty_cdata,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .state = PB_STATE_INIT,
+ );
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
new file mode 100644
index 000000000..aa317041e
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pb_tnc_state_machine pb_tnc_state_machine
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_STATE_MACHINE_H_
+#define PB_TNC_STATE_MACHINE_H_
+
+typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t;
+typedef enum pb_tnc_state_t pb_tnc_state_t;
+
+#include "batch/pb_tnc_batch.h"
+
+#include <library.h>
+
+/**
+ * PB-TNC States (state machine) as defined in section 3.2 of RFC 5793
+ */
+enum pb_tnc_state_t {
+ PB_STATE_INIT,
+ PB_STATE_SERVER_WORKING,
+ PB_STATE_CLIENT_WORKING,
+ PB_STATE_DECIDED,
+ PB_STATE_END,
+};
+
+/**
+ * enum name for pb_tnc_state_t.
+ */
+extern enum_name_t *pb_tnc_state_names;
+
+/**
+ * Interface for the PB-TNC state machine.
+ */
+struct pb_tnc_state_machine_t {
+
+ /**
+ * Get the current PB-TNC STATE
+ *
+ * @return current state
+ */
+ pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this);
+
+ /**
+ * Compute state transition due to received PB-TNC Batch
+ *
+ * @param type type of received batch
+ * @result TRUE if a valid transition was found, FALSE otherwise
+ */
+ bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
+
+ /**
+ * Compute state transition due to sent PB-TNC Batch
+ *
+ * @param type type of sent batch
+ * @result TRUE if a valid transition was found, FALSE otherwise
+ */
+ bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
+
+ /**
+ * Informs whether the last received PB-TNC CDATA Batch was empty
+ *
+ * @result TRUE if last received PB-TNC CDATA Batch was empty
+ */
+ bool (*get_empty_cdata)(pb_tnc_state_machine_t *this);
+
+ /**
+ * Store information whether the received PB-TNC CDATA Batch was empty
+ *
+ * @param empty set to TRUE if received PB-TNC CDATA Batch was empty
+ */
+ void (*set_empty_cdata)(pb_tnc_state_machine_t *this, bool empty);
+
+ /**
+ * Destroys a pb_tnc_state_machine_t object.
+ */
+ void (*destroy)(pb_tnc_state_machine_t *this);
+};
+
+/**
+ * Create and initialize a PB-TNC state machine
+ *
+ * @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client
+ */
+pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server);
+
+#endif /** PB_TNC_STATE_MACHINE_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.c b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
new file mode 100644
index 000000000..b631ef579
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
@@ -0,0 +1,1073 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_20.h"
+#include "batch/pb_tnc_batch.h"
+#include "messages/pb_tnc_msg.h"
+#include "messages/ietf/pb_pa_msg.h"
+#include "messages/ietf/pb_error_msg.h"
+#include "messages/ietf/pb_assessment_result_msg.h"
+#include "messages/ietf/pb_access_recommendation_msg.h"
+#include "messages/ietf/pb_remediation_parameters_msg.h"
+#include "messages/ietf/pb_reason_string_msg.h"
+#include "messages/ietf/pb_language_preference_msg.h"
+#include "messages/tcg/pb_pdp_referral_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <tnc/tnc.h>
+#include <tnc/tnccs/tnccs_manager.h>
+#include <tnc/imc/imc_manager.h>
+#include <tnc/imv/imv_manager.h>
+
+#include <threading/mutex.h>
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <pen/pen.h>
+
+typedef struct private_tnccs_20_t private_tnccs_20_t;
+
+/**
+ * Private data of a tnccs_20_t object.
+ */
+struct private_tnccs_20_t {
+
+ /**
+ * Public tnccs_t interface.
+ */
+ tnccs_t public;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * Server identity
+ */
+ identification_t *server;
+
+ /**
+ * Client identity
+ */
+ identification_t *peer;
+
+ /**
+ * Underlying TNC IF-T transport protocol
+ */
+ tnc_ift_type_t transport;
+
+ /**
+ * Type of TNC client authentication
+ */
+ u_int32_t auth_type;
+
+ /**
+ * PB-TNC State Machine
+ */
+ pb_tnc_state_machine_t *state_machine;
+
+ /**
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * PB-TNC messages to be sent
+ */
+ linked_list_t *messages;
+
+ /**
+ * Type of PB-TNC batch being constructed
+ */
+ pb_tnc_batch_type_t batch_type;
+
+ /**
+ * Maximum PB-TNC batch size
+ */
+ size_t max_batch_len;
+
+ /**
+ * Maximum PA-TNC message size
+ */
+ size_t max_msg_len;
+
+ /**
+ * Mutex locking the batch in construction
+ */
+ mutex_t *mutex;
+
+ /**
+ * Flag set while processing
+ */
+ bool fatal_error;
+
+ /**
+ * Flag set by IMC/IMV RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * SendMessage() by IMC/IMV only allowed if flag is set
+ */
+ bool send_msg;
+
+ /**
+ * Set of IMV recommendations (TNC Server only)
+ */
+ recommendations_t *recs;
+
+ /**
+ * Callback function to communicate recommendation (TNC Server only)
+ */
+ tnccs_cb_t callback;
+
+ /**
+ * Data to pass to callback function (TNC Server only)
+ */
+ void *cb_data;
+
+ /**
+ * PDP server FQDN
+ */
+ chunk_t pdp_server;
+
+ /**
+ * PDP server port
+ */
+ u_int16_t pdp_port;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+
+};
+
+/**
+ * If the batch type changes then delete all accumulated PB-TNC messages
+ */
+void change_batch_type(private_tnccs_20_t *this, pb_tnc_batch_type_t batch_type)
+{
+ pb_tnc_msg_t *msg;
+
+ if (batch_type != this->batch_type)
+ {
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
+ pb_tnc_batch_type_names, this->batch_type);
+
+ while (this->messages->remove_last(this->messages,
+ (void**)&msg) == SUCCESS)
+ {
+ msg->destroy(msg);
+ }
+ }
+ this->batch_type = batch_type;
+ }
+}
+
+METHOD(tnccs_t, send_msg, TNC_Result,
+ private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype)
+{
+ pb_tnc_msg_t *pb_tnc_msg;
+ pb_tnc_batch_type_t batch_type;
+ enum_name_t *pa_subtype_names;
+ bool excl;
+
+ if (!this->send_msg)
+ {
+ DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
+ this->is_server ? "IMV" : "IMC",
+ this->is_server ? imv_id : imc_id);
+ return TNC_RESULT_ILLEGAL_OPERATION;
+ }
+ excl = (msg_flags & TNC_MESSAGE_FLAGS_EXCLUSIVE) != 0;
+
+ pb_tnc_msg = pb_pa_msg_create(msg_vid, msg_subtype, imc_id, imv_id,
+ excl, chunk_create(msg, msg_len));
+
+ pa_subtype_names = get_pa_subtype_names(msg_vid);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "creating PB-PA message type '%N/%N' 0x%06x/0x%08x",
+ pen_names, msg_vid, pa_subtype_names, msg_subtype,
+ msg_vid, msg_subtype);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "creating PB-PA message type '%N' 0x%06x/0x%08x",
+ pen_names, msg_vid, msg_vid, msg_subtype);
+ }
+
+ /* adding PA message to SDATA or CDATA batch only */
+ batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA;
+ this->mutex->lock(this->mutex);
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ this->batch_type = batch_type;
+ }
+ if (this->batch_type == batch_type)
+ {
+ this->messages->insert_last(this->messages, pb_tnc_msg);
+ }
+ else
+ {
+ pb_tnc_msg->destroy(pb_tnc_msg);
+ }
+ this->mutex->unlock(this->mutex);
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * Handle a single PB-TNC IETF standard message according to its type
+ */
+static void handle_ietf_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_MSG_EXPERIMENTAL:
+ /* nothing to do */
+ break;
+ case PB_MSG_PA:
+ {
+ pb_pa_msg_t *pa_msg;
+ pen_type_t msg_subtype;
+ u_int16_t imc_id, imv_id;
+ chunk_t msg_body;
+ bool excl;
+ enum_name_t *pa_subtype_names;
+
+ pa_msg = (pb_pa_msg_t*)msg;
+ msg_subtype = pa_msg->get_subtype(pa_msg);
+ msg_body = pa_msg->get_body(pa_msg);
+ imc_id = pa_msg->get_collector_id(pa_msg);
+ imv_id = pa_msg->get_validator_id(pa_msg);
+ excl = pa_msg->get_exclusive_flag(pa_msg);
+
+ pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, pa_subtype_names,
+ msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
+ msg_subtype.type);
+ }
+
+ this->send_msg = TRUE;
+ if (this->is_server)
+ {
+ tnc->imvs->receive_message(tnc->imvs, this->connection_id,
+ excl, msg_body.ptr, msg_body.len,
+ msg_subtype.vendor_id,
+ msg_subtype.type, imc_id, imv_id);
+ }
+ else
+ {
+ tnc->imcs->receive_message(tnc->imcs, this->connection_id,
+ excl, msg_body.ptr, msg_body.len,
+ msg_subtype.vendor_id,
+ msg_subtype.type, imv_id, imc_id);
+ }
+ this->send_msg = FALSE;
+ break;
+ }
+ case PB_MSG_ASSESSMENT_RESULT:
+ {
+ pb_assessment_result_msg_t *assess_msg;
+ u_int32_t result;
+
+ assess_msg = (pb_assessment_result_msg_t*)msg;
+ result = assess_msg->get_assessment_result(assess_msg);
+ DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
+ TNC_IMV_Evaluation_Result_names, result);
+ break;
+ }
+ case PB_MSG_ACCESS_RECOMMENDATION:
+ {
+ pb_access_recommendation_msg_t *rec_msg;
+ pb_access_recommendation_code_t rec;
+ TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+ rec_msg = (pb_access_recommendation_msg_t*)msg;
+ rec = rec_msg->get_access_recommendation(rec_msg);
+ DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
+ pb_access_recommendation_code_names, rec);
+ switch (rec)
+ {
+ case PB_REC_ACCESS_ALLOWED:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ break;
+ case PB_REC_ACCESS_DENIED:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ break;
+ case PB_REC_QUARANTINED:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ }
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ state);
+ break;
+ }
+ case PB_MSG_REMEDIATION_PARAMETERS:
+ {
+ pb_remediation_parameters_msg_t *rem_msg;
+ pen_type_t parameters_type;
+ chunk_t parameters, string, lang_code;
+
+ rem_msg = (pb_remediation_parameters_msg_t*)msg;
+ parameters_type = rem_msg->get_parameters_type(rem_msg);
+ parameters = rem_msg->get_parameters(rem_msg);
+
+ if (parameters_type.vendor_id == PEN_IETF)
+ {
+ switch (parameters_type.type)
+ {
+ case PB_REMEDIATION_URI:
+ DBG1(DBG_TNC, "remediation uri: %.*s",
+ parameters.len, parameters.ptr);
+ break;
+ case PB_REMEDIATION_STRING:
+ string = rem_msg->get_string(rem_msg, &lang_code);
+ DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s",
+ lang_code.len, lang_code.ptr,
+ string.len, string.ptr);
+ break;
+ default:
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
+ break;
+ }
+ case PB_MSG_ERROR:
+ {
+ pb_error_msg_t *err_msg;
+ bool fatal;
+ u_int32_t vendor_id;
+ u_int16_t error_code;
+
+ err_msg = (pb_error_msg_t*)msg;
+ fatal = err_msg->get_fatal_flag(err_msg);
+ vendor_id = err_msg->get_vendor_id(err_msg);
+ error_code = err_msg->get_error_code(err_msg);
+
+ if (fatal)
+ {
+ this->fatal_error = TRUE;
+ }
+
+ if (vendor_id == PEN_IETF)
+ {
+ switch (error_code)
+ {
+ case PB_ERROR_INVALID_PARAMETER:
+ case PB_ERROR_UNSUPPORTED_MANDATORY_MSG:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
+ "(offset %u bytes)",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_offset(err_msg));
+ break;
+ case PB_ERROR_VERSION_NOT_SUPPORTED:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
+ "caused by bad version 0x%02x",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_bad_version(err_msg));
+ break;
+ case PB_ERROR_UNEXPECTED_BATCH_TYPE:
+ case PB_ERROR_LOCAL_ERROR:
+ default:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N'",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code);
+ break;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "received %s PB-TNC error (%u) "
+ "with Vendor ID 0x%06x",
+ fatal ? "fatal" : "non-fatal",
+ error_code, vendor_id);
+ }
+ break;
+ }
+ case PB_MSG_LANGUAGE_PREFERENCE:
+ {
+ pb_language_preference_msg_t *lang_msg;
+ chunk_t lang;
+
+ lang_msg = (pb_language_preference_msg_t*)msg;
+ lang = lang_msg->get_language_preference(lang_msg);
+
+ if (this->recs)
+ {
+ DBG2(DBG_TNC, "setting language preference to '%.*s'",
+ (int)lang.len, lang.ptr);
+ this->recs->set_preferred_language(this->recs, lang);
+ }
+ break;
+ }
+ case PB_MSG_REASON_STRING:
+ {
+ pb_reason_string_msg_t *reason_msg;
+ chunk_t reason_string, language_code;
+
+ reason_msg = (pb_reason_string_msg_t*)msg;
+ reason_string = reason_msg->get_reason_string(reason_msg);
+ language_code = reason_msg->get_language_code(reason_msg);
+ DBG1(DBG_TNC, "reason string is '%.*s' [%.*s]",
+ (int)reason_string.len, reason_string.ptr,
+ (int)language_code.len, language_code.ptr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC TCG standard message according to its type
+ */
+static void handle_tcg_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_TCG_MSG_PDP_REFERRAL:
+ {
+ pb_pdp_referral_msg_t *pdp_msg;
+ pen_type_t pdp_id_type;
+ u_int8_t pdp_protocol;
+
+ pdp_msg = (pb_pdp_referral_msg_t*)msg;
+ pdp_id_type = pdp_msg->get_identifier_type(pdp_msg);
+
+ if (pdp_id_type.vendor_id == PEN_TCG &&
+ pdp_id_type.type == PB_PDP_ID_FQDN)
+ {
+ this->pdp_server = chunk_clone(pdp_msg->get_fqdn(pdp_msg,
+ &pdp_protocol, &this->pdp_port));
+ if (pdp_protocol != 0)
+ {
+ DBG1(DBG_TNC, "unsupported PDP transport protocol");
+ break;
+ }
+ DBG1(DBG_TNC, "PDP server '%.*s' is listening on port %u",
+ this->pdp_server.len, this->pdp_server.ptr,
+ this->pdp_port);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC message according to its type
+ */
+static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.vendor_id)
+ {
+ case PEN_IETF:
+ handle_ietf_message(this, msg);
+ break;
+ case PEN_TCG:
+ handle_tcg_message(this, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Build a CRETRY or SRETRY batch
+ */
+static void build_retry_batch(private_tnccs_20_t *this)
+{
+ pb_tnc_batch_type_t batch_retry_type;
+
+ batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
+ if (this->batch_type == batch_retry_type)
+ {
+ /* retry batch has already been selected */
+ return;
+ }
+
+ change_batch_type(this, batch_retry_type);
+
+ if (this->is_server)
+ {
+ this->recs->clear_recommendation(this->recs);
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+ }
+}
+
+METHOD(tls_t, process, status_t,
+ private_tnccs_20_t *this, void *buf, size_t buflen)
+{
+ chunk_t data;
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
+ enumerator_t *enumerator;
+ identification_t *pdp_server;
+ u_int16_t *pdp_port;
+ status_t status;
+
+ if (this->is_server && !this->connection_id)
+ {
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_2_0, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, &this->recs);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+
+ /* Send a PB-TNC TCG PDP Referral message if PDP is known */
+ pdp_server = (identification_t*)lib->get(lib, "pt-tls-server");
+ pdp_port = (u_int16_t*)lib->get(lib, "pt-tls-port");
+
+ if ((this->transport == TNC_IFT_EAP_1_1 ||
+ this->transport == TNC_IFT_EAP_2_0) && pdp_server && pdp_port)
+ {
+ msg = pb_pdp_referral_msg_create_from_fqdn(
+ pdp_server->get_encoding(pdp_server), *pdp_port);
+ this->messages->insert_last(this->messages, msg);
+ }
+
+ }
+
+ data = chunk_create(buf, buflen);
+ DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u",
+ data.len, this->connection_id);
+ DBG3(DBG_TNC, "%B", &data);
+ batch = pb_tnc_batch_create_from_data(this->is_server, data);
+ status = batch->process(batch, this->state_machine);
+
+ if (status != FAILED)
+ {
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ pb_tnc_batch_type_t batch_type;
+ bool empty = TRUE;
+
+ batch_type = batch->get_type(batch);
+
+ if (batch_type == PB_BATCH_CRETRY)
+ {
+ /* Send an SRETRY batch in response */
+ this->mutex->lock(this->mutex);
+ build_retry_batch(this);
+ this->mutex->unlock(this->mutex);
+ }
+ else if (batch_type == PB_BATCH_SRETRY)
+ {
+ /* Restart the measurements */
+ tnc->imcs->notify_connection_change(tnc->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
+ tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ handle_message(this, msg);
+ empty = FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ /* received an empty CLOSE batch from PB-TNC client */
+ if (this->is_server && batch_type == PB_BATCH_CLOSE && empty)
+ {
+ batch->destroy(batch);
+ if (this->fatal_error)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, "
+ "terminating connection");
+ return FAILED;
+ }
+ else
+ {
+ return SUCCESS;
+ }
+ }
+
+ this->send_msg = TRUE;
+ if (this->is_server)
+ {
+ tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
+ }
+ else
+ {
+ tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
+ }
+ this->send_msg = FALSE;
+ }
+
+ switch (status)
+ {
+ case FAILED:
+ this->fatal_error = TRUE;
+ this->mutex->lock(this->mutex);
+ change_batch_type(this, PB_BATCH_CLOSE);
+ this->mutex->unlock(this->mutex);
+ /* fall through to add error messages to outbound batch */
+ case VERIFY_ERROR:
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg->get_ref(msg));
+ this->mutex->unlock(this->mutex);
+ }
+ enumerator->destroy(enumerator);
+ break;
+ case SUCCESS:
+ default:
+ break;
+ }
+ batch->destroy(batch);
+
+ return NEED_MORE;
+}
+
+/**
+ * Build a RESULT batch if a final recommendation is available
+ */
+static void check_and_build_recommendation(private_tnccs_20_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_ConnectionState state;
+ TNC_IMVID id;
+ chunk_t reason, language;
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ pb_access_recommendation_code_t pb_rec;
+
+ if (!this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
+ }
+ if (this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ this->batch_type = PB_BATCH_RESULT;
+
+ msg = pb_assessment_result_msg_create(eval);
+ this->messages->insert_last(this->messages, msg);
+
+ /**
+ * Map IMV Action Recommendation codes to PB Access Recommendation codes
+ * and communicate Access Recommendation to IMVs
+ */
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ pb_rec = PB_REC_ACCESS_ALLOWED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ pb_rec = PB_REC_QUARANTINED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ default:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ pb_rec = PB_REC_ACCESS_DENIED;
+ }
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ state);
+
+ msg = pb_access_recommendation_msg_create(pb_rec);
+ this->messages->insert_last(this->messages, msg);
+
+ enumerator = this->recs->create_reason_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &id, &reason, &language))
+ {
+ msg = pb_reason_string_msg_create(reason, language);
+ this->messages->insert_last(this->messages, msg);
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+METHOD(tls_t, build, status_t,
+ private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ status_t status;
+ pb_tnc_state_t state;
+
+ /* Initialize the connection */
+ if (!this->is_server && !this->connection_id)
+ {
+ pb_tnc_msg_t *msg;
+ char *pref_lang;
+
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_2_0, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, NULL);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+
+ /* Create PB-TNC Language Preference message */
+ pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
+ msg = pb_language_preference_msg_create(chunk_create(pref_lang,
+ strlen(pref_lang)));
+ this->mutex->lock(this->mutex);
+ this->batch_type = PB_BATCH_CDATA;
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
+ tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ state = this->state_machine->get_state(this->state_machine);
+
+ if (this->fatal_error && state == PB_STATE_END)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
+ return FAILED;
+ }
+
+ /* Do not allow any asynchronous IMCs or IMVs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->request_handshake_retry)
+ {
+ if (state != PB_STATE_INIT)
+ {
+ build_retry_batch(this);
+ }
+
+ /* Reset the flag for the next handshake retry request */
+ this->request_handshake_retry = FALSE;
+ }
+
+ if (this->is_server && state == PB_STATE_SERVER_WORKING &&
+ this->recs->have_recommendation(this->recs, NULL, NULL))
+ {
+ check_and_build_recommendation(this);
+ }
+
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ if (this->is_server)
+ {
+ if (state == PB_STATE_SERVER_WORKING)
+ {
+ if (this->state_machine->get_empty_cdata(this->state_machine))
+ {
+ check_and_build_recommendation(this);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "no recommendation available yet, "
+ "sending empty PB-TNC SDATA batch");
+ this->batch_type = PB_BATCH_SDATA;
+ }
+ }
+ }
+ else
+ {
+ switch (state)
+ {
+ case PB_STATE_CLIENT_WORKING:
+ DBG2(DBG_TNC, "no client data to send, "
+ "sending empty PB-TNC CDATA batch");
+ this->batch_type = PB_BATCH_CDATA;
+ break;
+ case PB_STATE_DECIDED:
+ /**
+ * In the DECIDED state and if no CRETRY is under way,
+ * a PB-TNC client replies with an empty CLOSE batch.
+ */
+ this->batch_type = PB_BATCH_CLOSE;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
+ chunk_t data;
+ int msg_count;
+ enumerator_t *enumerator;
+
+ if (this->state_machine->send_batch(this->state_machine, this->batch_type))
+ {
+ batch = pb_tnc_batch_create(this->is_server, this->batch_type,
+ min(this->max_batch_len, *buflen));
+
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ if (batch->add_msg(batch, msg))
+ {
+ this->messages->remove_at(this->messages, enumerator);
+ }
+ else
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ batch->build(batch);
+ data = batch->get_encoding(batch);
+ DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
+ pb_tnc_batch_type_names, this->batch_type, data.len,
+ this->connection_id);
+ DBG3(DBG_TNC, "%B", &data);
+
+ *buflen = data.len;
+ *msglen = 0;
+ memcpy(buf, data.ptr, *buflen);
+ batch->destroy(batch);
+
+ msg_count = this->messages->get_count(this->messages);
+ if (msg_count)
+ {
+ DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
+ msg_count, (msg_count == 1) ? "" : "s",
+ pb_tnc_batch_type_names, this->batch_type);
+ }
+ else
+ {
+ this->batch_type = PB_BATCH_NONE;
+ }
+
+ status = ALREADY_DONE;
+ }
+ else
+ {
+ change_batch_type(this, PB_BATCH_NONE);
+ status = INVALID_STATE;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "no PB-TNC batch to send");
+ status = INVALID_STATE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
+}
+
+METHOD(tls_t, is_server, bool,
+ private_tnccs_20_t *this)
+{
+ return this->is_server;
+}
+
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_20_t *this)
+{
+ return this->server;
+}
+
+METHOD(tls_t, set_peer_id, void,
+ private_tnccs_20_t *this, identification_t *id)
+{
+ DESTROY_IF(this->peer);
+ this->peer = id->clone(id);
+}
+
+METHOD(tls_t, get_peer_id, identification_t*,
+ private_tnccs_20_t *this)
+{
+ return this->peer;
+}
+
+METHOD(tls_t, get_purpose, tls_purpose_t,
+ private_tnccs_20_t *this)
+{
+ return TLS_PURPOSE_EAP_TNC;
+}
+
+METHOD(tls_t, is_complete, bool,
+ private_tnccs_20_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+
+ if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ return this->callback ? this->callback(rec, eval) : TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+METHOD(tls_t, get_eap_msk, chunk_t,
+ private_tnccs_20_t *this)
+{
+ return chunk_empty;
+}
+
+METHOD(tls_t, destroy, void,
+ private_tnccs_20_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
+ this->is_server);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ this->state_machine->destroy(this->state_machine);
+ this->mutex->destroy(this->mutex);
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
+ free(this->pdp_server.ptr);
+ free(this);
+ }
+}
+
+METHOD(tnccs_t, get_transport, tnc_ift_type_t,
+ private_tnccs_20_t *this)
+{
+ return this->transport;
+}
+
+METHOD(tnccs_t, set_transport, void,
+ private_tnccs_20_t *this, tnc_ift_type_t transport)
+{
+ this->transport = transport;
+}
+
+METHOD(tnccs_t, get_auth_type, u_int32_t,
+ private_tnccs_20_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(tnccs_t, set_auth_type, void,
+ private_tnccs_20_t *this, u_int32_t auth_type)
+{
+ this->auth_type = auth_type;
+}
+
+METHOD(tnccs_t, get_pdp_server, chunk_t,
+ private_tnccs_20_t *this, u_int16_t *port)
+{
+ *port = this->pdp_port;
+
+ return this->pdp_server;
+}
+
+METHOD(tnccs_t, get_ref, tnccs_t*,
+ private_tnccs_20_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+tnccs_t* tnccs_20_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb)
+{
+ private_tnccs_20_t *this;
+
+ INIT(this,
+ .public = {
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_id,
+ .set_peer_id = _set_peer_id,
+ .get_peer_id = _get_peer_id,
+ .get_purpose = _get_purpose,
+ .is_complete = _is_complete,
+ .get_eap_msk = _get_eap_msk,
+ .destroy = _destroy,
+ },
+ .get_transport = _get_transport,
+ .set_transport = _set_transport,
+ .get_auth_type = _get_auth_type,
+ .set_auth_type = _set_auth_type,
+ .get_pdp_server = _get_pdp_server,
+ .get_ref = _get_ref,
+ },
+ .is_server = is_server,
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
+ .callback = cb,
+ .state_machine = pb_tnc_state_machine_create(is_server),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .messages = linked_list_create(),
+ .max_batch_len = lib->settings->get_int(lib->settings,
+ "libtnccs.plugins.tnccs-20.max_batch_size", 65522),
+ .max_msg_len = lib->settings->get_int(lib->settings,
+ "libtnccs.plugins.tnccs-20.max_message_size", 65490),
+ .ref = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.h b/src/libtnccs/plugins/tnccs_20/tnccs_20.h
new file mode 100644
index 000000000..2857b1408
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_20_h tnccs_20
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef TNCCS_20_H_
+#define TNCCS_20_H_
+
+#include <library.h>
+
+#include <tnc/tnccs/tnccs.h>
+
+/**
+ * Create an instance of the TNC IF-TNCCS 2.0 protocol handler.
+ *
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @param cb Callback function if TNC Server, NULL if TNC Client
+ * @return TNC_IF_TNCCS 2.0 protocol stack
+ */
+tnccs_t* tnccs_20_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb);
+
+#endif /** TNCCS_20_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.c
new file mode 100644
index 000000000..f74306c8c
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_20_plugin.h"
+#include "tnccs_20.h"
+
+#include <tnc/tnccs/tnccs_manager.h>
+
+METHOD(plugin_t, get_name, char*,
+ tnccs_20_plugin_t *this)
+{
+ return "tnccs-20";
+}
+
+METHOD(plugin_t, get_features, int,
+ tnccs_20_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnccs_method_register, tnccs_20_create),
+ PLUGIN_PROVIDE(CUSTOM, "tnccs-2.0"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ tnccs_20_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnccs_20_plugin_create()
+{
+ tnccs_20_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->plugin;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h
new file mode 100644
index 000000000..1c4ecf4c9
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_20 tnccs_20
+ * @ingroup cplugins
+ *
+ * @defgroup tnccs_20_plugin tnccs_20_plugin
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef TNCCS_20_PLUGIN_H_
+#define TNCCS_20_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnccs_20_plugin_t tnccs_20_plugin_t;
+
+/**
+ * EAP-TNC plugin
+ */
+struct tnccs_20_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNCCS_20_PLUGIN_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.am b/src/libtnccs/plugins/tnccs_dynamic/Makefile.am
new file mode 100644
index 000000000..1a2887816
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.am
@@ -0,0 +1,22 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+libstrongswan_tnccs_dynamic_la_LIBADD = \
+ $(top_builddir)/src/libtncif/libtncif.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnccs_dynamic_la_SOURCES = \
+ tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c
+
+libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
new file mode 100644
index 000000000..d38aa13cc
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
@@ -0,0 +1,762 @@
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libtnccs/plugins/tnccs_dynamic
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+am_libstrongswan_tnccs_dynamic_la_OBJECTS = tnccs_dynamic_plugin.lo \
+ tnccs_dynamic.lo
+libstrongswan_tnccs_dynamic_la_OBJECTS = \
+ $(am_libstrongswan_tnccs_dynamic_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_tnccs_dynamic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_tnccs_dynamic_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_tnccs_dynamic_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_tnccs_dynamic_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_tnccs_dynamic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnccs_dynamic_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libtnccs
+
+AM_CFLAGS = \
+ -rdynamic
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_LIBADD = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
+
+libstrongswan_tnccs_dynamic_la_SOURCES = \
+ tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c
+
+libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_dynamic/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libtnccs/plugins/tnccs_dynamic/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-tnccs-dynamic.la: $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_DEPENDENCIES) $(EXTRA_libstrongswan_tnccs_dynamic_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_tnccs_dynamic_la_LINK) $(am_libstrongswan_tnccs_dynamic_la_rpath) $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_dynamic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_dynamic_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# 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/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c
new file mode 100644
index 000000000..e08236eb7
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_dynamic.h"
+
+#include <tnc/tnc.h>
+
+#include <utils/debug.h>
+
+typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t;
+
+/**
+ * Private data of a tnccs_dynamic_t object.
+ */
+struct private_tnccs_dynamic_t {
+
+ /**
+ * Public tnccs_t interface.
+ */
+ tnccs_t public;
+
+ /**
+ * Server identity
+ */
+ identification_t *server;
+
+ /**
+ * Client identity
+ */
+ identification_t *peer;
+
+ /**
+ * Detected TNC IF-TNCCS stack
+ */
+ tls_t *tls;
+
+ /**
+ * Underlying TNC IF-T transport protocol
+ */
+ tnc_ift_type_t transport;
+
+ /**
+ * Type of TNC client authentication
+ */
+ u_int32_t auth_type;
+
+ /**
+ * Callback function to communicate recommendation (TNC Server only)
+ */
+ tnccs_cb_t callback;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+
+};
+
+/**
+ * Determine the version of the IF-TNCCS protocol used by analyzing the first
+ * byte of the TNCCS batch received from a TNC Client according to the rules
+ * defined by section 3.5 "Interoperability with older IF-TNCCS versions" of
+ * the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard.
+ */
+tnccs_type_t determine_tnccs_protocol(char version)
+{
+ switch (version)
+ {
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ':
+ case '<':
+ return TNCCS_1_1;
+ case 0x00:
+ return TNCCS_SOH;
+ case 0x02:
+ return TNCCS_2_0;
+ default:
+ return TNCCS_UNKNOWN;
+ }
+}
+
+METHOD(tls_t, process, status_t,
+ private_tnccs_dynamic_t *this, void *buf, size_t buflen)
+{
+ tnccs_type_t type;
+ tnccs_t *tnccs;
+
+ if (!this->tls)
+ {
+ if (buflen == 0)
+ {
+ return FAILED;
+ }
+ type = determine_tnccs_protocol(*(char*)buf);
+ DBG1(DBG_TNC, "%N protocol detected dynamically",
+ tnccs_type_names, type);
+ tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE,
+ this->server, this->peer, this->transport,
+ this->callback);
+ if (!tnccs)
+ {
+ DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type);
+ return FAILED;
+ }
+ tnccs->set_auth_type(tnccs, this->auth_type);
+ this->tls = &tnccs->tls;
+ }
+ return this->tls->process(this->tls, buf, buflen);
+}
+
+METHOD(tls_t, build, status_t,
+ private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ return this->tls->build(this->tls, buf, buflen, msglen);
+}
+
+METHOD(tls_t, is_server, bool,
+ private_tnccs_dynamic_t *this)
+{
+ return TRUE;
+}
+
+METHOD(tls_t, get_server_id, identification_t*,
+ private_tnccs_dynamic_t *this)
+{
+ return this->server;
+}
+
+METHOD(tls_t, set_peer_id, void,
+ private_tnccs_dynamic_t *this, identification_t *id)
+{
+ DESTROY_IF(this->peer);
+ this->peer = id->clone(id);
+ if (this->tls)
+ {
+ this->tls->set_peer_id(this->tls, id);
+ }
+}
+
+METHOD(tls_t, get_peer_id, identification_t*,
+ private_tnccs_dynamic_t *this)
+{
+ return this->peer;
+}
+
+METHOD(tls_t, get_purpose, tls_purpose_t,
+ private_tnccs_dynamic_t *this)
+{
+ return TLS_PURPOSE_EAP_TNC;
+}
+
+METHOD(tls_t, is_complete, bool,
+ private_tnccs_dynamic_t *this)
+{
+ return this->tls ? this->tls->is_complete(this->tls) : FALSE;
+}
+
+METHOD(tls_t, get_eap_msk, chunk_t,
+ private_tnccs_dynamic_t *this)
+{
+ return chunk_empty;
+}
+
+METHOD(tls_t, destroy, void,
+ private_tnccs_dynamic_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ DESTROY_IF(this->tls);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ free(this);
+ }
+}
+
+METHOD(tnccs_t, get_transport, tnc_ift_type_t,
+ private_tnccs_dynamic_t *this)
+{
+ return this->transport;
+}
+
+METHOD(tnccs_t, set_transport, void,
+ private_tnccs_dynamic_t *this, tnc_ift_type_t transport)
+{
+ this->transport = transport;
+}
+
+METHOD(tnccs_t, get_auth_type, u_int32_t,
+ private_tnccs_dynamic_t *this)
+{
+ return this->auth_type;
+}
+
+METHOD(tnccs_t, set_auth_type, void,
+ private_tnccs_dynamic_t *this, u_int32_t auth_type)
+{
+ this->auth_type = auth_type;
+}
+
+METHOD(tnccs_t, get_pdp_server, chunk_t,
+ private_tnccs_dynamic_t *this, u_int16_t *port)
+{
+ tnccs_t *tnccs = (tnccs_t*)this->tls;
+
+ return tnccs->get_pdp_server(tnccs, port);
+}
+
+METHOD(tnccs_t, get_ref, tnccs_t*,
+ private_tnccs_dynamic_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+tnccs_t* tnccs_dynamic_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb)
+{
+ private_tnccs_dynamic_t *this;
+
+ INIT(this,
+ .public = {
+ .tls = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_server_id = _get_server_id,
+ .set_peer_id = _set_peer_id,
+ .get_peer_id = _get_peer_id,
+ .get_purpose = _get_purpose,
+ .is_complete = _is_complete,
+ .get_eap_msk = _get_eap_msk,
+ .destroy = _destroy,
+ },
+ .get_transport = _get_transport,
+ .set_transport = _set_transport,
+ .get_auth_type = _get_auth_type,
+ .set_auth_type = _set_auth_type,
+ .get_pdp_server = _get_pdp_server,
+ .get_ref = _get_ref,
+ },
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ .transport = transport,
+ .callback = cb,
+ .ref = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h
new file mode 100644
index 000000000..cbdc80b83
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_dynamic_h tnccs_dynamic
+ * @{ @ingroup tnccs_dynamic
+ */
+
+#ifndef TNCCS_DYNAMIC_H_
+#define TNCCS_DYNAMIC_H_
+
+#include <library.h>
+
+#include <tnc/tnccs/tnccs.h>
+
+/**
+ * Create an instance of a dynamic TNC IF-TNCCS protocol handler.
+ *
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @param server Server identity
+ * @param peer Client identity
+ * @param transport Underlying IF-T transport protocol
+ * @param cb Callback function if TNC Server, NULL if TNC Client
+ * @return dynamic TNC IF-TNCCS protocol stack
+ */
+tnccs_t* tnccs_dynamic_create(bool is_server,
+ identification_t *server, identification_t *peer,
+ tnc_ift_type_t transport, tnccs_cb_t cb);
+
+#endif /** TNCCS_DYNAMIC_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
new file mode 100644
index 000000000..aac57813a
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_dynamic_plugin.h"
+#include "tnccs_dynamic.h"
+
+#include <tnc/tnccs/tnccs_manager.h>
+
+METHOD(plugin_t, get_name, char*,
+ tnccs_dynamic_plugin_t *this)
+{
+ return "tnccs-dynamic";
+}
+
+METHOD(plugin_t, get_features, int,
+ tnccs_dynamic_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(tnccs_method_register, tnccs_dynamic_create),
+ PLUGIN_PROVIDE(CUSTOM, "tnccs-dynamic"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-1.1"),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-2.0"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ tnccs_dynamic_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnccs_dynamic_plugin_create()
+{
+ tnccs_dynamic_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->plugin;
+}
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
new file mode 100644
index 000000000..b518e1278
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup tnccs_dynamic tnccs_dynamic
+ * @ingroup cplugins
+ *
+ * @defgroup tnccs_dynamic_plugin tnccs_dynamic_plugin
+ * @{ @ingroup tnccs_dynamic
+ */
+
+#ifndef TNCCS_DYNAMIC_PLUGIN_H_
+#define TNCCS_DYNAMIC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnccs_dynamic_plugin_t tnccs_dynamic_plugin_t;
+
+/**
+ * EAP-TNC plugin
+ */
+struct tnccs_dynamic_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNCCS_DYNAMIC_PLUGIN_H_ @}*/