summaryrefslogtreecommitdiff
path: root/src/libimcv/ietf
diff options
context:
space:
mode:
Diffstat (limited to 'src/libimcv/ietf')
-rw-r--r--src/libimcv/ietf/ietf_attr.c32
-rw-r--r--src/libimcv/ietf/ietf_attr_assess_result.c4
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.c14
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.h2
-rw-r--r--src/libimcv/ietf/ietf_attr_default_pwd_enabled.c222
-rw-r--r--src/libimcv/ietf/ietf_attr_default_pwd_enabled.h63
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.c221
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.h64
-rw-r--r--src/libimcv/ietf/ietf_attr_installed_packages.c335
-rw-r--r--src/libimcv/ietf/ietf_attr_installed_packages.h73
-rw-r--r--src/libimcv/ietf/ietf_attr_numeric_version.c282
-rw-r--r--src/libimcv/ietf/ietf_attr_numeric_version.h84
-rw-r--r--src/libimcv/ietf/ietf_attr_op_status.c314
-rw-r--r--src/libimcv/ietf/ietf_attr_op_status.h107
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.c10
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.h7
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.c16
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.c30
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.h6
-rw-r--r--src/libimcv/ietf/ietf_attr_remediation_instr.c363
-rw-r--r--src/libimcv/ietf/ietf_attr_remediation_instr.h109
-rw-r--r--src/libimcv/ietf/ietf_attr_string_version.c300
-rw-r--r--src/libimcv/ietf/ietf_attr_string_version.h67
23 files changed, 2675 insertions, 50 deletions
diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c
index fc89c5716..2f3819898 100644
--- a/src/libimcv/ietf/ietf_attr.c
+++ b/src/libimcv/ietf/ietf_attr.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -13,11 +14,19 @@
*/
#include "ietf_attr.h"
+#include "ietf/ietf_attr_assess_result.h"
+#include "ietf/ietf_attr_attr_request.h"
+#include "ietf/ietf_attr_fwd_enabled.h"
+#include "ietf/ietf_attr_default_pwd_enabled.h"
+#include "ietf/ietf_attr_installed_packages.h"
+#include "ietf/ietf_attr_numeric_version.h"
+#include "ietf/ietf_attr_op_status.h"
#include "ietf/ietf_attr_pa_tnc_error.h"
#include "ietf/ietf_attr_port_filter.h"
#include "ietf/ietf_attr_product_info.h"
-#include "ietf/ietf_attr_attr_request.h"
-#include "ietf/ietf_attr_assess_result.h"
+#include "ietf/ietf_attr_remediation_instr.h"
+#include "ietf/ietf_attr_string_version.h"
+
ENUM(ietf_attr_names, IETF_ATTR_TESTING, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED,
"Testing",
@@ -46,20 +55,27 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value)
return ietf_attr_attr_request_create_from_data(value);
case IETF_ATTR_PRODUCT_INFORMATION:
return ietf_attr_product_info_create_from_data(value);
+ case IETF_ATTR_NUMERIC_VERSION:
+ return ietf_attr_numeric_version_create_from_data(value);
+ case IETF_ATTR_STRING_VERSION:
+ return ietf_attr_string_version_create_from_data(value);
+ case IETF_ATTR_OPERATIONAL_STATUS:
+ return ietf_attr_op_status_create_from_data(value);
case IETF_ATTR_PORT_FILTER:
return ietf_attr_port_filter_create_from_data(value);
+ case IETF_ATTR_INSTALLED_PACKAGES:
+ return ietf_attr_installed_packages_create_from_data(value);
case IETF_ATTR_PA_TNC_ERROR:
return ietf_attr_pa_tnc_error_create_from_data(value);
case IETF_ATTR_ASSESSMENT_RESULT:
return ietf_attr_assess_result_create_from_data(value);
- case IETF_ATTR_TESTING:
- case IETF_ATTR_NUMERIC_VERSION:
- case IETF_ATTR_STRING_VERSION:
- case IETF_ATTR_OPERATIONAL_STATUS:
- case IETF_ATTR_INSTALLED_PACKAGES:
case IETF_ATTR_REMEDIATION_INSTRUCTIONS:
+ return ietf_attr_remediation_instr_create_from_data(value);
case IETF_ATTR_FORWARDING_ENABLED:
+ return ietf_attr_fwd_enabled_create_from_data(value);
case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
+ return ietf_attr_default_pwd_enabled_create_from_data(value);
+ case IETF_ATTR_TESTING:
case IETF_ATTR_RESERVED:
default:
return NULL;
diff --git a/src/libimcv/ietf/ietf_attr_assess_result.c b/src/libimcv/ietf/ietf_attr_assess_result.c
index 6893730bf..1c0d6b0eb 100644
--- a/src/libimcv/ietf/ietf_attr_assess_result.c
+++ b/src/libimcv/ietf/ietf_attr_assess_result.c
@@ -18,7 +18,7 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
-#include <debug.h>
+#include <utils/debug.h>
typedef struct private_ietf_attr_assess_result_t private_ietf_attr_assess_result_t;
@@ -192,6 +192,8 @@ pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(chunk_t data)
.pa_tnc_attribute = {
.get_type = _get_type,
.get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
.get_ref = _get_ref,
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c
index c0dcd0983..c93c9276e 100644
--- a/src/libimcv/ietf/ietf_attr_attr_request.c
+++ b/src/libimcv/ietf/ietf_attr_attr_request.c
@@ -19,9 +19,9 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
-#include <utils/linked_list.h>
+#include <collections/linked_list.h>
-#include <debug.h>
+#include <utils/debug.h>
typedef struct private_ietf_attr_attr_request_t private_ietf_attr_attr_request_t;
@@ -114,12 +114,12 @@ METHOD(pa_tnc_attr_t, build, void,
{
return;
}
- writer = bio_writer_create(ATTR_REQUEST_ENTRY_SIZE *
+ writer = bio_writer_create(ATTR_REQUEST_ENTRY_SIZE *
this->list->get_count(this->list));
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
- {
+ {
writer->write_uint32(writer, entry->vendor_id);
writer->write_uint32(writer, entry->type);
}
@@ -161,7 +161,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
reader = bio_reader_create(this->value);
while (count--)
{
- reader->read_uint8 (reader, &reserved);
+ reader->read_uint8 (reader, &reserved);
reader->read_uint24(reader, &vendor_id);
reader->read_uint32(reader, &type);
@@ -251,6 +251,8 @@ pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
.pa_tnc_attribute = {
.get_type = _get_type,
.get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
.get_ref = _get_ref,
@@ -259,7 +261,7 @@ pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
.add = _add,
.create_enumerator = _create_enumerator,
},
- .type = { PEN_IETF,IETF_ATTR_ATTRIBUTE_REQUEST },
+ .type = { PEN_IETF, IETF_ATTR_ATTRIBUTE_REQUEST },
.value = chunk_clone(data),
.list = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.h b/src/libimcv/ietf/ietf_attr_attr_request.h
index 22c5be0a0..387ba345d 100644
--- a/src/libimcv/ietf/ietf_attr_attr_request.h
+++ b/src/libimcv/ietf/ietf_attr_attr_request.h
@@ -50,7 +50,7 @@ struct ietf_attr_attr_request_t {
* Creates an enumerator over all attribute types contained
* in the attribute request
*
- * @return Attribute Type enumerator returns (vendor ID, type)
+ * @return Attribute Type enumerator returns { vendor ID, type }
*/
enumerator_t* (*create_enumerator)(ietf_attr_attr_request_t *this);
};
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
new file mode 100644
index 000000000..2022f45cf
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 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 "ietf_attr_default_pwd_enabled.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_ietf_attr_default_pwd_enabled_t private_ietf_attr_default_pwd_enabled_t;
+
+/**
+ * PA-TNC Factory Default Password Enabled type (see section 4.2.12 of RFC 5792)
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Factory Default Password Enabled |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define DEFAULT_PWD_ENABLED_SIZE 4
+
+/**
+ * Private data of an ietf_attr_default_pwd_enabled_t object.
+ */
+struct private_ietf_attr_default_pwd_enabled_t {
+
+ /**
+ * Public members of ietf_attr_default_pwd_enabled_t
+ */
+ ietf_attr_default_pwd_enabled_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Factory Default Password Enabled status
+ */
+ bool status;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_default_pwd_enabled_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(DEFAULT_PWD_ENABLED_SIZE);
+ writer->write_uint32(writer, this->status);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_default_pwd_enabled_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t status;
+
+ *offset = 0;
+
+ if (this->value.len != DEFAULT_PWD_ENABLED_SIZE)
+ {
+ DBG1(DBG_TNC, "incorrect size for IETF factory default password "
+ "enabled attribute");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32(reader, &status);
+ reader->destroy(reader);
+
+ if (status > TRUE)
+ {
+ DBG1(DBG_TNC, "IETF factory default password enabled field "
+ "has unknown value %u", status);
+ return FAILED;
+ }
+ this->status = status;
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_default_pwd_enabled_t, get_status, bool,
+ private_ietf_attr_default_pwd_enabled_t *this)
+{
+ return this->status;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
+{
+ private_ietf_attr_default_pwd_enabled_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ },
+ .type = { PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED },
+ .status = status,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(chunk_t data)
+{
+ private_ietf_attr_default_pwd_enabled_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ },
+ .type = { PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
new file mode 100644
index 000000000..f6026b0e8
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 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 ietf_attr_default_pwd_enabled ietf_attr_default_pwd_enabled
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_PWD_ENABLED_H_
+#define IETF_ATTR_PWD_ENABLED_H_
+
+typedef struct ietf_attr_default_pwd_enabled_t ietf_attr_default_pwd_enabled_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the IETF PA-TNC Factory Default Password Enabled attribute.
+ *
+ */
+struct ietf_attr_default_pwd_enabled_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Factory Default Password Enabled status
+ *
+ * @return Factory Default Password Enabled status
+ */
+ bool (*get_status)(ietf_attr_default_pwd_enabled_t *this);
+
+};
+
+/**
+ * Creates an ietf_attr_default_pwd_enabled_t object
+ *
+ * @param status Factory Default Password Enabled status
+ */
+pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create(bool status);
+
+/**
+ * Creates an ietf_attr_default_pwd_enabled_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_PWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.c b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
new file mode 100644
index 000000000..911ee5b89
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 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 "ietf_attr_fwd_enabled.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_ietf_attr_fwd_enabled_t private_ietf_attr_fwd_enabled_t;
+
+/**
+ * PA-TNC Forwarding Enabled type (see section 4.2.11 of RFC 5792)
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Forwarding Enabled |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define FORWARDING_ENABLED_SIZE 4
+
+/**
+ * Private data of an ietf_attr_fwd_enabled_t object.
+ */
+struct private_ietf_attr_fwd_enabled_t {
+
+ /**
+ * Public members of ietf_attr_fwd_enabled_t
+ */
+ ietf_attr_fwd_enabled_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Forwarding Enabled status
+ */
+ os_fwd_status_t fwd_status;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_fwd_enabled_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(FORWARDING_ENABLED_SIZE);
+ writer->write_uint32(writer, this->fwd_status);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_fwd_enabled_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t fwd_status;
+
+ *offset = 0;
+
+ if (this->value.len != FORWARDING_ENABLED_SIZE)
+ {
+ DBG1(DBG_TNC, "incorrect size for IETF forwarding enabled attribute");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32(reader, &fwd_status);
+ reader->destroy(reader);
+
+ if (fwd_status > OS_FWD_UNKNOWN)
+ {
+ DBG1(DBG_TNC, "IETF forwarding enabled field has unknown value %u",
+ fwd_status);
+ return FAILED;
+ }
+ this->fwd_status = fwd_status;
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_fwd_enabled_t, get_status, os_fwd_status_t,
+ private_ietf_attr_fwd_enabled_t *this)
+{
+ return this->fwd_status;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
+{
+ private_ietf_attr_fwd_enabled_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ },
+ .type = { PEN_IETF, IETF_ATTR_FORWARDING_ENABLED },
+ .fwd_status = fwd_status,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(chunk_t data)
+{
+ private_ietf_attr_fwd_enabled_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ },
+ .type = { PEN_IETF, IETF_ATTR_FORWARDING_ENABLED },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.h b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
new file mode 100644
index 000000000..bfde1a7b1
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 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 ietf_attr_fwd_enabled ietf_attr_fwd_enabled
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_FWD_ENABLED_H_
+#define IETF_ATTR_FWD_ENABLED_H_
+
+typedef struct ietf_attr_fwd_enabled_t ietf_attr_fwd_enabled_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "os_info/os_info.h"
+
+/**
+ * Class implementing the IETF PA-TNC Forwarding Enabled attribute.
+ *
+ */
+struct ietf_attr_fwd_enabled_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Forwarding Enabled status
+ *
+ * @return Forwarding Enabled status
+ */
+ os_fwd_status_t (*get_status)(ietf_attr_fwd_enabled_t *this);
+
+};
+
+/**
+ * Creates an ietf_attr_fwd_enabled_t object
+ *
+ * @param fwd_status Forwarding Enabled status
+ */
+pa_tnc_attr_t* ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status);
+
+/**
+ * Creates an ietf_attr_fwd_enabled_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_fwd_enabled_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_FWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.c b/src/libimcv/ietf/ietf_attr_installed_packages.c
new file mode 100644
index 000000000..72a3c1344
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 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 "ietf_attr_installed_packages.h"
+
+#include <string.h>
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+
+typedef struct private_ietf_attr_installed_packages_t private_ietf_attr_installed_packages_t;
+typedef struct package_entry_t package_entry_t;
+
+/**
+ * PA-TNC Installed Packages Type (see section 4.2.7 of RFC 5792)
+ *
+ * 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 | Package Count |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Pkg Name Len | Package Name (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version Len | Package Version Number (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define INSTALLED_PACKAGES_MIN_SIZE 4
+
+/**
+ * Private data of an ietf_attr_installed_packages_t object.
+ */
+struct private_ietf_attr_installed_packages_t {
+
+ /**
+ * Public members of ietf_attr_installed_packages_t
+ */
+ ietf_attr_installed_packages_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * List of Installed Package entries
+ */
+ linked_list_t *packages;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+/**
+ * Package entry
+ */
+struct package_entry_t {
+ chunk_t name;
+ chunk_t version;
+};
+
+/**
+ * Free a package entry
+ */
+static void free_package_entry(package_entry_t *entry)
+{
+ free(entry->name.ptr);
+ free(entry->version.ptr);
+ free(entry);
+}
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_installed_packages_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_installed_packages_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_installed_packages_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_installed_packages_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_installed_packages_t *this)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ package_entry_t *entry;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(INSTALLED_PACKAGES_MIN_SIZE);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_uint16(writer, this->packages->get_count(this->packages));
+
+ enumerator = this->packages->create_enumerator(this->packages);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ writer->write_data8(writer, entry->name);
+ writer->write_data8(writer, entry->version);
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_installed_packages_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ package_entry_t *entry;
+ status_t status = FAILED;
+ chunk_t name, version;
+ u_int16_t reserved, count;
+ u_char *pos;
+
+ *offset = 0;
+
+ if (this->value.len < INSTALLED_PACKAGES_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF installed packages");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &count);
+ *offset = INSTALLED_PACKAGES_MIN_SIZE;
+
+ while (reader->remaining(reader))
+ {
+ if (!reader->read_data8(reader, &name))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF installed package name");
+ goto end;
+ }
+ pos = memchr(name.ptr, '\0', name.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF installed package name");
+ *offset += 1 + (pos - name.ptr);
+ goto end;
+ }
+ *offset += 1 + name.len;
+
+ if (!reader->read_data8(reader, &version))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF installed package version");
+ goto end;
+ }
+ pos = memchr(version.ptr, '\0', version.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF installed package version");
+ *offset += 1 + (pos - version.ptr);
+ goto end;
+ }
+ *offset += 1 + version.len;
+
+ entry = malloc_thing(package_entry_t);
+ entry->name = chunk_clone(name);
+ entry->version = chunk_clone(version);
+ this->packages->insert_last(this->packages, entry);
+ }
+
+ if (count != this->packages->get_count(this->packages))
+ {
+ DBG1(DBG_TNC, "IETF installed package count unequal to "
+ "number of included packages");
+ goto end;
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_installed_packages_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_installed_packages_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->packages->destroy_function(this->packages, (void*)free_package_entry);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_installed_packages_t, add, void,
+ private_ietf_attr_installed_packages_t *this, chunk_t name, chunk_t version)
+{
+ package_entry_t *entry;
+
+ /* restrict package name and package version number fields to 255 octets */
+ name.len = min(255, name.len);
+ version.len = min(255, version.len);
+
+ entry = malloc_thing(package_entry_t);
+ entry->name = chunk_clone(name);
+ entry->version = chunk_clone(version);
+ this->packages->insert_last(this->packages, entry);
+}
+
+/**
+ * Enumerate package filter entries
+ */
+static bool package_filter(void *null, package_entry_t **entry, chunk_t *name,
+ void *i2, chunk_t *version)
+{
+ *name = (*entry)->name;
+ *version = (*entry)->version;
+ return TRUE;
+}
+
+METHOD(ietf_attr_installed_packages_t, create_enumerator, enumerator_t*,
+ private_ietf_attr_installed_packages_t *this)
+{
+ return enumerator_create_filter(
+ this->packages->create_enumerator(this->packages),
+ (void*)package_filter, NULL, NULL);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_installed_packages_create(void)
+{
+ private_ietf_attr_installed_packages_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = { PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
+ .packages = linked_list_create(),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(chunk_t data)
+{
+ private_ietf_attr_installed_packages_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = {PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
+ .value = chunk_clone(data),
+ .packages = linked_list_create(),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.h b/src/libimcv/ietf/ietf_attr_installed_packages.h
new file mode 100644
index 000000000..a9f6768e0
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 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 ietf_attr_installed_packagest ietf_attr_installed_packages
+ * @{ @ingroup ietf_attr_installed_packages
+ */
+
+#ifndef IETF_ATTR_INSTALLED_PACKAGES_H_
+#define IETF_ATTR_INSTALLED_PACKAGES_H_
+
+typedef struct ietf_attr_installed_packages_t ietf_attr_installed_packages_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the IETF PA-TNC Installed Packages attribute.
+ *
+ */
+struct ietf_attr_installed_packages_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Add a package entry
+ *
+ * @param name package name
+ * @param version package version number
+ */
+ void (*add)(ietf_attr_installed_packages_t *this, chunk_t name,
+ chunk_t version);
+
+ /**
+ * Enumerates over all packages
+ * Format: chunk_t name, chunk_t version
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_enumerator)(ietf_attr_installed_packages_t *this);
+
+};
+
+/**
+ * Creates an ietf_attr_installed_packages_t object
+ *
+ */
+pa_tnc_attr_t* ietf_attr_installed_packages_create(void);
+
+/**
+ * Creates an ietf_attr_installed_packages_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_installed_packages_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_INSTALLED_PACKAGES_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.c b/src/libimcv/ietf/ietf_attr_numeric_version.c
new file mode 100644
index 000000000..797205473
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_numeric_version.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 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 "ietf_attr_numeric_version.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_ietf_attr_numeric_version_t private_ietf_attr_numeric_version_t;
+
+/**
+ * PA-TNC Numeric Version type (see section 4.2.3 of RFC 5792)
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Major Version Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Minor Version Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Build Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Service Pack Major | Service Pack Minor |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define NUMERIC_VERSION_SIZE 16
+
+/**
+ * Private data of an ietf_attr_numeric_version_t object.
+ */
+struct private_ietf_attr_numeric_version_t {
+
+ /**
+ * Public members of ietf_attr_numeric_version_t
+ */
+ ietf_attr_numeric_version_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Major Version Number
+ */
+ u_int32_t major_version;
+
+ /**
+ * Minor Version Number
+ */
+ u_int32_t minor_version;
+
+ /**
+ * IBuild Number
+ */
+ u_int32_t build;
+
+ /**
+ * Service Pack Major Number
+ */
+ u_int16_t service_pack_major;
+
+ /**
+ * Service Pack Minor Number
+ */
+ u_int16_t service_pack_minor;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_numeric_version_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_numeric_version_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_numeric_version_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_numeric_version_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_numeric_version_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ writer = bio_writer_create(NUMERIC_VERSION_SIZE);
+ writer->write_uint32(writer, this->major_version);
+ writer->write_uint32(writer, this->minor_version);
+ writer->write_uint32(writer, this->build);
+ writer->write_uint16(writer, this->service_pack_major);
+ writer->write_uint16(writer, this->service_pack_minor);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_numeric_version_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ if (this->value.len < NUMERIC_VERSION_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF numeric version");
+ *offset = 0;
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32(reader, &this->major_version);
+ reader->read_uint32(reader, &this->minor_version);
+ reader->read_uint32(reader, &this->build);
+ reader->read_uint16(reader, &this->service_pack_major);
+ reader->read_uint16(reader, &this->service_pack_minor);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_numeric_version_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_numeric_version_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_numeric_version_t, get_version, void,
+ private_ietf_attr_numeric_version_t *this, u_int32_t *major, u_int32_t *minor)
+{
+ if (major)
+ {
+ *major = this->major_version;
+ }
+ if (minor)
+ {
+ *minor = this->minor_version;
+ }
+}
+
+METHOD(ietf_attr_numeric_version_t, get_build, u_int32_t,
+ private_ietf_attr_numeric_version_t *this)
+{
+ return this->build;
+}
+
+METHOD(ietf_attr_numeric_version_t, get_service_pack, void,
+ private_ietf_attr_numeric_version_t *this, u_int16_t *major, u_int16_t *minor)
+{
+ if (major)
+ {
+ *major = this->service_pack_major;
+ }
+ if (minor)
+ {
+ *minor = this->service_pack_minor;
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_numeric_version_create(u_int32_t major, u_int32_t minor,
+ u_int32_t build,
+ u_int16_t service_pack_major,
+ u_int16_t service_pack_minor)
+{
+ private_ietf_attr_numeric_version_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_version = _get_version,
+ .get_build = _get_build,
+ .get_service_pack = _get_service_pack,
+ },
+ .type = { PEN_IETF, IETF_ATTR_NUMERIC_VERSION },
+ .major_version = major,
+ .minor_version = minor,
+ .build = build,
+ .service_pack_major = service_pack_major,
+ .service_pack_minor = service_pack_minor,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(chunk_t data)
+{
+ private_ietf_attr_numeric_version_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_version = _get_version,
+ .get_build = _get_build,
+ .get_service_pack = _get_service_pack,
+ },
+ .type = { PEN_IETF, IETF_ATTR_NUMERIC_VERSION },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.h b/src/libimcv/ietf/ietf_attr_numeric_version.h
new file mode 100644
index 000000000..f7d6c909d
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_numeric_version.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 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 ietf_attr_numeric_versiont ietf_attr_numeric_version
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_NUMERIC_VERSION_H_
+#define IETF_ATTR_NUMERIC_VERSION_H_
+
+typedef struct ietf_attr_numeric_version_t ietf_attr_numeric_version_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the IETF PA-TNC String Version attribute.
+ *
+ */
+struct ietf_attr_numeric_version_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Major and Minor Version Numbers
+ *
+ * @param major Major Version Number
+ * @param minor Minor Version Number
+ */
+ void (*get_version)(ietf_attr_numeric_version_t *this,
+ u_int32_t *major, u_int32_t *minor);
+
+ /**
+ * Gets the Build Number
+ *
+ * @param major Major Version Number
+ * @param minor Minor Version Number
+ */
+ u_int32_t (*get_build)(ietf_attr_numeric_version_t *this);
+
+ /**
+ * Gets the Major and Minor Numbers of the Service Pack
+ *
+ * @param major Service Pack Major Number
+ * @param minor Servcie Pack Minor Number
+ */
+ void (*get_service_pack)(ietf_attr_numeric_version_t *this,
+ u_int16_t *major, u_int16_t *minor);
+};
+
+/**
+ * Creates an ietf_attr_numeric_version_t object
+ *
+ */
+pa_tnc_attr_t* ietf_attr_numeric_version_create(u_int32_t major, u_int32_t minor,
+ u_int32_t build,
+ u_int16_t service_pack_major,
+ u_int16_t service_pack_minor);
+
+/**
+ * Creates an ietf_attr_numeric_version_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_numeric_version_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_NUMERIC_VERSION_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_op_status.c b/src/libimcv/ietf/ietf_attr_op_status.c
new file mode 100644
index 000000000..d9610b29d
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_op_status.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 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 "ietf_attr_op_status.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+#include <time.h>
+
+typedef struct private_ietf_attr_op_status_t private_ietf_attr_op_status_t;
+
+ENUM(op_status_names, OP_STATUS_UNKNOWN, OP_STATUS_OPERATIONAL,
+ "unknown",
+ "not installed",
+ "installed",
+ "operational"
+);
+
+ENUM(op_result_names, OP_RESULT_UNKNOWN, OP_RESULT_UNSUCCESSFUL,
+ "unknown",
+ "successful",
+ "errored",
+ "unsuccessful"
+);
+
+/**
+ * PA-TNC Operational Status type (see section 4.2.5 of RFC 5792)
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Status | Result | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Use |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Use (continued) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Use (continued) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Use (continued) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Use (continued) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define OP_STATUS_SIZE 24
+
+/**
+ * Private data of an ietf_attr_op_status_t object.
+ */
+struct private_ietf_attr_op_status_t {
+
+ /**
+ * Public members of ietf_attr_op_status_t
+ */
+ ietf_attr_op_status_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Status
+ */
+ u_int8_t status;
+
+ /**
+ * Result
+ */
+ u_int8_t result;
+
+ /**
+ * Last Use
+ */
+ time_t last_use;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_op_status_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_op_status_t *this)
+{
+ bio_writer_t *writer;
+ char last_use[24];
+ struct tm t;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ /* Conversion from time_t to RFC 3339 ASCII string */
+ gmtime_r(&this->last_use, &t);
+ snprintf(last_use, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.tm_year,
+ t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
+
+ writer = bio_writer_create(OP_STATUS_SIZE);
+ writer->write_uint8 (writer, this->status);
+ writer->write_uint8 (writer, this->result);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_data (writer, chunk_create(last_use, 20));
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_op_status_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ chunk_t last_use;
+ u_int16_t reserved;
+ struct tm t;
+
+ *offset = 0;
+
+ if (this->value.len != OP_STATUS_SIZE)
+ {
+ DBG1(DBG_TNC, "incorrect size for IETF operational status");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &this->status);
+ reader->read_uint8 (reader, &this->result);
+ reader->read_uint16(reader, &reserved);
+ reader->read_data (reader, 20, &last_use);
+ reader->destroy(reader);
+
+ if (this->status > OP_STATUS_ROOF)
+ {
+ DBG1(DBG_TNC, "invalid status value %c for IETF operational status",
+ this->status);
+ return FAILED;
+ }
+
+ *offset = 1;
+
+ if (this->result > OP_RESULT_ROOF)
+ {
+ DBG1(DBG_TNC, "invalid result value %c for IETF operational status",
+ this->result);
+ return FAILED;
+ }
+
+ *offset = 4;
+
+ /* Conversion from RFC 3339 ASCII string to time_t */
+ if (sscanf(last_use.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t.tm_year, &t.tm_mon,
+ &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+ {
+ DBG1(DBG_TNC, "invalid last_use time format in IETF operational status");
+ return FAILED;
+ }
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ t.tm_isdst = 0;
+ this->last_use = mktime(&t) - timezone;
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_op_status_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_op_status_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_op_status_t, get_status, u_int8_t,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->status;
+}
+
+METHOD(ietf_attr_op_status_t, get_result, u_int8_t,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->result;
+}
+
+METHOD(ietf_attr_op_status_t, get_last_use, time_t,
+ private_ietf_attr_op_status_t *this)
+{
+ return this->last_use;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_op_status_create(u_int8_t status, u_int8_t result,
+ time_t last_use)
+{
+ private_ietf_attr_op_status_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ .get_result = _get_result,
+ .get_last_use = _get_last_use,
+ },
+ .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS },
+ .status = status,
+ .result = result,
+ .last_use = last_use,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_op_status_create_from_data(chunk_t data)
+{
+ private_ietf_attr_op_status_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_status = _get_status,
+ .get_result = _get_result,
+ .get_last_use = _get_last_use,
+ },
+ .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_op_status.h b/src/libimcv/ietf/ietf_attr_op_status.h
new file mode 100644
index 000000000..2e14148c4
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_op_status.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 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 ietf_attr_op_statust ietf_attr_op_status
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_OP_STATUS_H_
+#define IETF_ATTR_OP_STATUS_H_
+
+typedef struct ietf_attr_op_status_t ietf_attr_op_status_t;
+typedef enum op_status_t op_status_t;
+typedef enum op_result_t op_result_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Operational Status type
+ */
+enum op_status_t {
+ OP_STATUS_UNKNOWN = 0,
+ OP_STATUS_NOT_INSTALLED = 1,
+ OP_STATUS_INSTALLED = 2,
+ OP_STATUS_OPERATIONAL = 3,
+ OP_STATUS_ROOF = 3
+};
+
+extern enum_name_t *op_status_names;
+
+/**
+ * Operational Result type
+ */
+enum op_result_t {
+ OP_RESULT_UNKNOWN = 0,
+ OP_RESULT_SUCCESSFUL = 1,
+ OP_RESULT_ERRORED = 2,
+ OP_RESULT_UNSUCCESSFUL = 3,
+ OP_RESULT_ROOF = 3
+};
+
+extern enum_name_t *op_result_names;
+
+/**
+ * Class implementing the IETF PA-TNC Operational Status attribute.
+ *
+ */
+struct ietf_attr_op_status_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Operational Status
+ *
+ * @return Operational Status
+ */
+ u_int8_t (*get_status)(ietf_attr_op_status_t *this);
+
+ /**
+ * Gets the Operational Result
+ *
+ * @return Operational Result
+ */
+ u_int8_t (*get_result)(ietf_attr_op_status_t *this);
+
+ /**
+ * Gets the time of last use
+ *
+ * @return Time of last use
+ */
+ time_t (*get_last_use)(ietf_attr_op_status_t *this);
+};
+
+/**
+ * Creates an ietf_attr_op_status_t object
+ *
+ * @param status Operational Status
+ * @param result Operational Result
+ * @param last_use Time of last use
+ */
+pa_tnc_attr_t* ietf_attr_op_status_create(u_int8_t status, u_int8_t result,
+ time_t last_use);
+
+/**
+ * Creates an ietf_attr_op_status_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_op_status_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_OP_STATUS_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
index 46f5d6716..f92022fe0 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
@@ -18,7 +18,7 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
-#include <debug.h>
+#include <utils/debug.h>
ENUM(pa_tnc_error_code_names, PA_ERROR_RESERVED,
PA_ERROR_ATTR_TYPE_NOT_SUPPORTED,
@@ -80,7 +80,7 @@ typedef struct private_ietf_attr_pa_tnc_error_t private_ietf_attr_pa_tnc_error_t
* | Max Version | Min Version | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-
+
#define PA_ERROR_VERSION_RESERVED 0x0000
/**
@@ -186,7 +186,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_uint24(writer, this->error_code.vendor_id);
writer->write_uint32(writer, this->error_code.type);
writer->write_data (writer, this->msg_info);
-
+
if (this->error_code.vendor_id == PEN_IETF)
{
switch (this->error_code.type)
@@ -272,7 +272,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
reader->destroy(reader);
- return SUCCESS;
+ return SUCCESS;
}
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
@@ -420,6 +420,8 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data)
.pa_tnc_attribute = {
.get_type = _get_type,
.get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
.get_ref = _get_ref,
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
index d28c524aa..a5a10d470 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
@@ -55,13 +55,6 @@ struct ietf_attr_pa_tnc_error_t {
pa_tnc_attr_t pa_tnc_attribute;
/**
- * Get PA-TNC error code vendor ID
- *
- * @return error code vendor ID
- */
- pen_t (*get_vendor_id)(ietf_attr_pa_tnc_error_t *this);
-
- /**
* Get Vendor-specific PA-TNC error code
*
* @return error code
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c
index 5ea52256b..8b8da3a41 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.c
+++ b/src/libimcv/ietf/ietf_attr_port_filter.c
@@ -17,8 +17,8 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
-#include <utils/linked_list.h>
-#include <debug.h>
+#include <collections/linked_list.h>
+#include <utils/debug.h>
typedef struct private_ietf_attr_port_filter_t private_ietf_attr_port_filter_t;
@@ -36,8 +36,8 @@ struct port_entry_t {
/**
* PA-TNC Port Filter Type (see section 4.2.6 of RFC 5792)
*
- * 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
+ * 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 |B| Protocol | Port Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -152,7 +152,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
while (reader->remaining(reader))
{
- entry = malloc_thing(port_entry_t);
+ entry = malloc_thing(port_entry_t);
reader->read_uint8 (reader, &blocked);
entry->blocked = blocked & 0x01;
reader->read_uint8 (reader, &entry->protocol);
@@ -161,7 +161,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
reader->destroy(reader);
- return SUCCESS;
+ return SUCCESS;
}
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
@@ -192,7 +192,7 @@ METHOD(ietf_attr_port_filter_t, add_port, void,
entry->blocked = blocked;
entry->protocol = protocol;
entry->port = port;
- this->ports->insert_last(this->ports, entry);
+ this->ports->insert_last(this->ports, entry);
}
/**
@@ -257,6 +257,8 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
.pa_tnc_attribute = {
.get_type = _get_type,
.get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
.get_ref = _get_ref,
diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c
index dcc0e0294..115f00130 100644
--- a/src/libimcv/ietf/ietf_attr_product_info.c
+++ b/src/libimcv/ietf/ietf_attr_product_info.c
@@ -17,7 +17,7 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
-#include <debug.h>
+#include <utils/debug.h>
typedef struct private_ietf_attr_product_info_t private_ietf_attr_product_info_t;
@@ -73,7 +73,7 @@ struct private_ietf_attr_product_info_t {
/**
* Product Name
*/
- char *product_name;
+ chunk_t product_name;
/**
* Reference count
@@ -109,18 +109,15 @@ METHOD(pa_tnc_attr_t, build, void,
private_ietf_attr_product_info_t *this)
{
bio_writer_t *writer;
- chunk_t product_name;
if (this->value.ptr)
{
return;
}
- product_name = chunk_create(this->product_name, strlen(this->product_name));
-
writer = bio_writer_create(PRODUCT_INFO_MIN_SIZE);
writer->write_uint24(writer, this->product_vendor_id);
writer->write_uint16(writer, this->product_id);
- writer->write_data (writer, product_name);
+ writer->write_data (writer, this->product_name);
this->value = chunk_clone(writer->get_buf(writer));
writer->destroy(writer);
@@ -144,9 +141,14 @@ METHOD(pa_tnc_attr_t, process, status_t,
reader->read_data (reader, reader->remaining(reader), &product_name);
reader->destroy(reader);
- this->product_name = malloc(product_name.len + 1);
- memcpy(this->product_name, product_name.ptr, product_name.len);
- this->product_name[product_name.len] = '\0';
+ if (!this->product_vendor_id && this->product_id)
+ {
+ DBG1(DBG_TNC, "IETF product information vendor ID is 0 "
+ "but product ID is not 0");
+ *offset = 3;
+ return FAILED;
+ }
+ this->product_name = chunk_clone(product_name);
return SUCCESS;
}
@@ -163,13 +165,13 @@ METHOD(pa_tnc_attr_t, destroy, void,
{
if (ref_put(&this->ref))
{
- free(this->product_name);
+ free(this->product_name.ptr);
free(this->value.ptr);
free(this);
}
}
-METHOD(ietf_attr_product_info_t, get_info, char*,
+METHOD(ietf_attr_product_info_t, get_info, chunk_t,
private_ietf_attr_product_info_t *this, pen_t *vendor_id, u_int16_t *id)
{
if (vendor_id)
@@ -187,7 +189,7 @@ METHOD(ietf_attr_product_info_t, get_info, char*,
* Described in header.
*/
pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
- char *name)
+ chunk_t name)
{
private_ietf_attr_product_info_t *this;
@@ -208,7 +210,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
.type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION },
.product_vendor_id = vendor_id,
.product_id = id,
- .product_name = strdup(name),
+ .product_name = chunk_clone(name),
.ref = 1,
);
@@ -227,6 +229,8 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data)
.pa_tnc_attribute = {
.get_type = _get_type,
.get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
.get_ref = _get_ref,
diff --git a/src/libimcv/ietf/ietf_attr_product_info.h b/src/libimcv/ietf/ietf_attr_product_info.h
index f1dfc3e83..dfaa67d6c 100644
--- a/src/libimcv/ietf/ietf_attr_product_info.h
+++ b/src/libimcv/ietf/ietf_attr_product_info.h
@@ -45,8 +45,8 @@ struct ietf_attr_product_info_t {
* @param id Product ID
* @return Product Name
*/
- char* (*get_info)(ietf_attr_product_info_t *this,
- pen_t *vendor_id, u_int16_t *id);
+ chunk_t (*get_info)(ietf_attr_product_info_t *this,
+ pen_t *vendor_id, u_int16_t *id);
};
@@ -55,7 +55,7 @@ struct ietf_attr_product_info_t {
*
*/
pa_tnc_attr_t* ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
- char *name);
+ chunk_t name);
/**
* Creates an ietf_attr_product_info_t object from received data
diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.c b/src/libimcv/ietf/ietf_attr_remediation_instr.c
new file mode 100644
index 000000000..f3b4e83dd
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_remediation_instr.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 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 "ietf_attr_remediation_instr.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_ietf_attr_remediation_instr_t private_ietf_attr_remediation_instr_t;
+
+/**
+ * PA-TNC Remediation Instructions type (see section 4.2.10 of RFC 5792)
+ *
+ * 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) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define REMEDIATION_INSTR_MIN_SIZE 8
+#define REMEDIATION_INSTR_RESERVED 0x00
+
+/**
+ * IETF Remediation Parameters URI type (see section 4.2.10.1 of RFC 5792)
+ *
+ * 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 URI (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * IETF Remediation Parameters String type (see section 4.2.10.2 of RFC 5792)
+ *
+ * 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 an ietf_attr_remediation_instr_t object.
+ */
+struct private_ietf_attr_remediation_instr_t {
+
+ /**
+ * Public members of ietf_attr_remediation_instr_t
+ */
+ ietf_attr_remediation_instr_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * 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;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_remediation_instr_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ writer = bio_writer_create(REMEDIATION_INSTR_MIN_SIZE);
+ writer->write_uint8 (writer, REMEDIATION_INSTR_RESERVED);
+ writer->write_uint24(writer, this->parameters_type.vendor_id);
+ writer->write_uint32(writer, this->parameters_type.type);
+ writer->write_data (writer, this->parameters);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_remediation_instr_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t reserved;
+ status_t status = SUCCESS;
+ u_char *pos;
+
+ *offset = 0;
+
+ if (this->value.len < REMEDIATION_INSTR_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF remediation instructions");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ 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 == IETF_REMEDIATION_PARAMETERS_STRING)
+ {
+ reader = bio_reader_create(this->parameters);
+ status = FAILED;
+ *offset = 8;
+
+ if (!reader->read_data32(reader, &this->string))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF remediation string");
+ goto end;
+ }
+ pos = memchr(this->string.ptr, '\0', this->string.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF remediation string");
+ *offset += 1 + (pos - this->string.ptr);
+ goto end;
+ }
+ *offset += 4 + this->string.len;
+
+ if (!reader->read_data8(reader, &this->lang_code))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF remediation lang code");
+ goto end;
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ }
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->parameters.ptr);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_remediation_instr_t, get_parameters_type, pen_type_t,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->parameters_type;
+}
+
+METHOD(ietf_attr_remediation_instr_t, get_parameters, chunk_t,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->parameters;
+}
+
+METHOD(ietf_attr_remediation_instr_t, get_uri, chunk_t,
+ private_ietf_attr_remediation_instr_t *this)
+{
+ return this->parameters;
+}
+
+METHOD(ietf_attr_remediation_instr_t, get_string, chunk_t,
+ private_ietf_attr_remediation_instr_t *this, chunk_t *lang_code)
+{
+ if (lang_code)
+ {
+ *lang_code = this->lang_code;
+ }
+ return this->string;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_remediation_instr_create(pen_type_t parameters_type,
+ chunk_t parameters)
+{
+ private_ietf_attr_remediation_instr_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_uri,
+ .get_string = _get_string,
+ },
+ .type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS },
+ .parameters_type = parameters_type,
+ .parameters = chunk_clone(parameters),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_uri(chunk_t uri)
+{
+ pen_type_t type = { PEN_IETF, IETF_REMEDIATION_PARAMETERS_URI };
+
+ return ietf_attr_remediation_instr_create(type, uri);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_string(chunk_t string,
+ chunk_t lang_code)
+{
+ pa_tnc_attr_t *attr;
+ bio_writer_t *writer;
+ pen_type_t type = { PEN_IETF, IETF_REMEDIATION_PARAMETERS_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);
+
+ attr = ietf_attr_remediation_instr_create(type, writer->get_buf(writer));
+ writer->destroy(writer);
+
+ return attr;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data)
+{
+ private_ietf_attr_remediation_instr_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_parameters_type = _get_parameters_type,
+ .get_parameters = _get_parameters,
+ .get_uri = _get_uri,
+ .get_string = _get_string,
+ },
+ .type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.h b/src/libimcv/ietf/ietf_attr_remediation_instr.h
new file mode 100644
index 000000000..473280c33
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_remediation_instr.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 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 ietf_attr_remediation_instrt ietf_attr_remediation_instr
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_REMEDIATION_INSTR_H_
+#define IETF_ATTR_REMEDIATION_INSTR_H_
+
+typedef struct ietf_attr_remediation_instr_t ietf_attr_remediation_instr_t;
+typedef enum ietf_remediation_parameters_t ietf_remediation_parameters_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+enum ietf_remediation_parameters_t {
+ IETF_REMEDIATION_PARAMETERS_URI = 1,
+ IETF_REMEDIATION_PARAMETERS_STRING = 2
+};
+
+/**
+ * Class implementing the IETF PA-TNC Remediation Instructions attribute.
+ *
+ */
+struct ietf_attr_remediation_instr_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get the Remediation Parameters Type (Vendor ID and Type)
+ *
+ * @return Remediation Parameters Type
+ */
+ pen_type_t (*get_parameters_type)(ietf_attr_remediation_instr_t *this);
+
+ /**
+ * Get the Remediation Parameters
+ *
+ * @return Remediation Parameters
+ */
+ chunk_t (*get_parameters)(ietf_attr_remediation_instr_t *this);
+
+ /**
+ * Get the Remediation URI
+ *
+ * @return Remediation URI
+ */
+ chunk_t (*get_uri)(ietf_attr_remediation_instr_t *this);
+
+ /**
+ * Get the Remediation String
+ *
+ * @param lang_code Optional Language Code
+ * @return Remediation String
+ */
+ chunk_t (*get_string)(ietf_attr_remediation_instr_t *this,
+ chunk_t *lang_code);
+};
+
+/**
+ * Creates a general ietf_attr_remediation_instr_t object
+ *
+ * @param parameters_type Remediation Parameters Type
+ * @param parameters Remediation Parameters
+ */
+pa_tnc_attr_t* ietf_attr_remediation_instr_create(pen_type_t parameters_type,
+ chunk_t parameters);
+
+/**
+ * Creates an ietf_attr_remediation_instr_t object of Remediation URI Type
+ *
+ * @param uri Remediation URI
+ */
+pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_uri(chunk_t uri);
+
+/**
+ * Creates an ietf_attr_remediation_instr_t object of Remediation String Type
+ *
+ * @param string Remediation String
+ * @param lang_code Remediation String Language Code
+ */
+pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_string(chunk_t string,
+ chunk_t lang_code);
+
+/**
+ * Creates an ietf_attr_remediation_instr_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_REMEDIATION_INSTR_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_string_version.c b/src/libimcv/ietf/ietf_attr_string_version.c
new file mode 100644
index 000000000..8f4129eac
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_string_version.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 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 "ietf_attr_string_version.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_ietf_attr_string_version_t private_ietf_attr_string_version_t;
+
+/**
+ * PA-TNC String Version type (see section 4.2.4 of RFC 5792)
+ *
+ * 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 Len | Product Version Number (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Build Num Len | Internal Build Number (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Config. Len | Configuration Version Number (Variable Length)|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define STRING_VERSION_MIN_SIZE 3
+
+/**
+ * Private data of an ietf_attr_string_version_t object.
+ */
+struct private_ietf_attr_string_version_t {
+
+ /**
+ * Public members of ietf_attr_string_version_t
+ */
+ ietf_attr_string_version_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Product Version Number
+ */
+ chunk_t version;
+
+ /**
+ * Internal Build Number
+ */
+ chunk_t build;
+
+ /**
+ * Configuration Version Number
+ */
+ chunk_t config;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_string_version_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_string_version_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_string_version_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_string_version_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_string_version_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ writer = bio_writer_create(STRING_VERSION_MIN_SIZE);
+ writer->write_data8(writer, this->version);
+ writer->write_data8(writer, this->build);
+ writer->write_data8(writer, this->config);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_string_version_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ status_t status = FAILED;
+ chunk_t version, build, config;
+ u_char *pos;
+
+ *offset = 0;
+
+ if (this->value.len < STRING_VERSION_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF string version");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+
+ if (!reader->read_data8(reader, &version))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF product version number");
+ goto end;
+
+ }
+ pos = memchr(version.ptr, '\0', version.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF product version number");
+ *offset += 1 + (pos - version.ptr);
+ goto end;
+ }
+ *offset += 1 + version.len;
+
+ if (!reader->read_data8(reader, &build))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF internal build number");
+ goto end;
+
+ }
+ pos = memchr(build.ptr, '\0', build.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF internal build number");
+ *offset += 1 + (pos - build.ptr);
+ goto end;
+ }
+ *offset += 1 + build.len;
+
+ if (!reader->read_data8(reader, &config))
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF configuration version number");
+ goto end;
+
+ }
+ pos = memchr(config.ptr, '\0', config.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in IETF configuration version number");
+ *offset += 1 + (pos - config.ptr);
+ goto end;
+ }
+
+ this->version = chunk_clone(version);
+ this->build = chunk_clone(build);
+ this->config = chunk_clone(config);
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_string_version_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_string_version_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->version.ptr);
+ free(this->build.ptr);
+ free(this->config.ptr);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_string_version_t, get_version, chunk_t,
+ private_ietf_attr_string_version_t *this, chunk_t *build, chunk_t *config)
+{
+ if (build)
+ {
+ *build = this->build;
+ }
+ if (config)
+ {
+ *config = this->config;
+ }
+ return this->version;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_string_version_create(chunk_t version, chunk_t build,
+ chunk_t config)
+{
+ private_ietf_attr_string_version_t *this;
+
+ /* limit version numbers to 255 octets */
+ version.len = min(255, version.len);
+ build.len = min(255, build.len);
+ config.len = min(255, config.len);
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_version = _get_version,
+ },
+ .type = { PEN_IETF, IETF_ATTR_STRING_VERSION },
+ .version = chunk_clone(version),
+ .build = chunk_clone(build),
+ .config = chunk_clone(config),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_string_version_create_from_data(chunk_t data)
+{
+ private_ietf_attr_string_version_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_version = _get_version,
+ },
+ .type = { PEN_IETF, IETF_ATTR_STRING_VERSION },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_string_version.h b/src/libimcv/ietf/ietf_attr_string_version.h
new file mode 100644
index 000000000..5ffbea8e0
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_string_version.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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 ietf_attr_string_versiont ietf_attr_string_version
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_STRING_VERSION_H_
+#define IETF_ATTR_STRING_VERSION_H_
+
+typedef struct ietf_attr_string_version_t ietf_attr_string_version_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the IETF PA-TNC String Version attribute.
+ *
+ */
+struct ietf_attr_string_version_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Product Version Number and optionally the Internal Build
+ * and Configuration Version Numbers
+ *
+ * @param build Internal Build Number (if build != NULL)
+ * @param config Configuration Version Number (if config != NULL)
+ * @return Product Version Number
+ */
+ chunk_t (*get_version)(ietf_attr_string_version_t *this, chunk_t *build,
+ chunk_t *config);
+};
+
+/**
+ * Creates an ietf_attr_string_version_t object
+ *
+ */
+pa_tnc_attr_t* ietf_attr_string_version_create(chunk_t version, chunk_t build,
+ chunk_t config);
+
+/**
+ * Creates an ietf_attr_string_version_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_string_version_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_STRING_VERSION_H_ @}*/