Annotation of embedaddon/strongswan/src/libimcv/pa_tnc/pa_tnc_attr_manager.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011-2014 Andreas Steffen
! 3: *
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "pa_tnc_attr_manager.h"
! 18:
! 19: #include "imcv.h"
! 20: #include "pa_tnc_attr.h"
! 21: #include "ietf/ietf_attr_pa_tnc_error.h"
! 22:
! 23: #include <collections/linked_list.h>
! 24: #include <utils/debug.h>
! 25:
! 26: typedef struct private_pa_tnc_attr_manager_t private_pa_tnc_attr_manager_t;
! 27: typedef struct entry_t entry_t;
! 28:
! 29: struct entry_t {
! 30: pen_t vendor_id;
! 31: enum_name_t *attr_names;
! 32: pa_tnc_attr_create_t attr_create;
! 33: };
! 34:
! 35: /**
! 36: * Private data of a pa_tnc_attr_manager_t object.
! 37: *
! 38: */
! 39: struct private_pa_tnc_attr_manager_t {
! 40:
! 41: /**
! 42: * Public pa_tnc_attr_manager_t interface.
! 43: */
! 44: pa_tnc_attr_manager_t public;
! 45:
! 46: /**
! 47: * List of PA-TNC vendor attributes
! 48: */
! 49: linked_list_t *list;
! 50: };
! 51:
! 52: METHOD(pa_tnc_attr_manager_t, add_vendor, void,
! 53: private_pa_tnc_attr_manager_t *this, pen_t vendor_id,
! 54: pa_tnc_attr_create_t attr_create, enum_name_t *attr_names)
! 55: {
! 56: entry_t *entry;
! 57:
! 58: entry = malloc_thing(entry_t);
! 59: entry->vendor_id = vendor_id;
! 60: entry->attr_create = attr_create;
! 61: entry->attr_names = attr_names;
! 62:
! 63: this->list->insert_last(this->list, entry);
! 64: DBG2(DBG_TNC, "added %N attributes", pen_names, vendor_id);
! 65: }
! 66:
! 67: METHOD(pa_tnc_attr_manager_t, remove_vendor, void,
! 68: private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
! 69: {
! 70: enumerator_t *enumerator;
! 71: entry_t *entry;
! 72:
! 73: enumerator = this->list->create_enumerator(this->list);
! 74: while (enumerator->enumerate(enumerator, &entry))
! 75: {
! 76: if (entry->vendor_id == vendor_id)
! 77: {
! 78: this->list->remove_at(this->list, enumerator);
! 79: free(entry);
! 80: DBG2(DBG_TNC, "removed %N attributes", pen_names, vendor_id);
! 81: }
! 82: }
! 83: enumerator->destroy(enumerator);
! 84: }
! 85:
! 86: METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*,
! 87: private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
! 88: {
! 89: enumerator_t *enumerator;
! 90: entry_t *entry;
! 91: enum_name_t *attr_names = NULL;
! 92:
! 93: enumerator = this->list->create_enumerator(this->list);
! 94: while (enumerator->enumerate(enumerator, &entry))
! 95: {
! 96: if (entry->vendor_id == vendor_id)
! 97: {
! 98: attr_names = entry->attr_names;
! 99: break;
! 100: }
! 101: }
! 102: enumerator->destroy(enumerator);
! 103:
! 104: return attr_names;
! 105: }
! 106:
! 107: /**
! 108: * PA-TNC attribute
! 109: *
! 110: * 1 2 3
! 111: * 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
! 112: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 113: * | Flags | PA-TNC Attribute Vendor ID |
! 114: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 115: * | PA-TNC Attribute Type |
! 116: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 117: * | PA-TNC Attribute Length |
! 118: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 119: * | Attribute Value (Variable Length) |
! 120: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 121: */
! 122:
! 123: METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
! 124: private_pa_tnc_attr_manager_t *this, bio_reader_t *reader, bool segmented,
! 125: uint32_t *offset, chunk_t msg_info, pa_tnc_attr_t **error)
! 126: {
! 127: uint8_t flags;
! 128: uint32_t type, length, value_len;
! 129: chunk_t value;
! 130: ietf_attr_pa_tnc_error_t *error_attr;
! 131: pen_t vendor_id;
! 132: pen_type_t unsupported_type;
! 133: pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
! 134: enum_name_t *pa_attr_names;
! 135: pa_tnc_attr_t *attr = NULL;
! 136: enumerator_t *enumerator;
! 137: entry_t *entry;
! 138:
! 139: /* properly initialize error return argument in case of no error */
! 140: *error = NULL;
! 141:
! 142: if (reader->remaining(reader) < PA_TNC_ATTR_HEADER_SIZE)
! 143: {
! 144: DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
! 145: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 146: msg_info, *offset);
! 147: return NULL;
! 148: }
! 149: reader->read_uint8 (reader, &flags);
! 150: reader->read_uint24(reader, &vendor_id);
! 151: reader->read_uint32(reader, &type);
! 152: reader->read_uint32(reader, &length);
! 153:
! 154: pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
! 155: vendor_id);
! 156: if (pa_attr_names)
! 157: {
! 158: DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
! 159: "0x%06x/0x%08x", pen_names, vendor_id,
! 160: pa_attr_names, type, vendor_id, type);
! 161: }
! 162: else
! 163: {
! 164: DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
! 165: "0x%06x/0x%08x", pen_names, vendor_id,
! 166: vendor_id, type);
! 167: }
! 168:
! 169: if (length < PA_TNC_ATTR_HEADER_SIZE)
! 170: {
! 171: DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
! 172: length);
! 173: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 174: msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
! 175: return NULL;
! 176: }
! 177: length -= PA_TNC_ATTR_HEADER_SIZE;
! 178: value_len = segmented ? reader->remaining(reader) : length;
! 179:
! 180: if (!reader->read_data(reader, value_len, &value))
! 181: {
! 182: DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
! 183: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 184: msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
! 185: return NULL;
! 186: }
! 187: DBG3(DBG_TNC, "%B", &value);
! 188:
! 189: if (vendor_id == PEN_RESERVED)
! 190: {
! 191: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 192: msg_info, *offset + 1);
! 193: return NULL;
! 194: }
! 195: if (type == IETF_ATTR_RESERVED)
! 196: {
! 197: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 198: msg_info, *offset + 4);
! 199: return NULL;
! 200: }
! 201:
! 202: /* check if the attribute type is registered */
! 203: enumerator = this->list->create_enumerator(this->list);
! 204: while (enumerator->enumerate(enumerator, &entry))
! 205: {
! 206: if (entry->vendor_id == vendor_id)
! 207: {
! 208: if (entry->attr_create)
! 209: {
! 210: attr = entry->attr_create(type, length, value);
! 211: }
! 212: break;
! 213: }
! 214: }
! 215: enumerator->destroy(enumerator);
! 216:
! 217: if (!attr)
! 218: {
! 219: if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
! 220: {
! 221: DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
! 222: (*offset) += PA_TNC_ATTR_HEADER_SIZE + length;
! 223: return NULL;
! 224: }
! 225:
! 226: DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
! 227: unsupported_type = pen_type_create(vendor_id, type);
! 228: error_code = pen_type_create(PEN_IETF, PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
! 229: *error = ietf_attr_pa_tnc_error_create(error_code, msg_info);
! 230: error_attr = (ietf_attr_pa_tnc_error_t*)(*error);
! 231: error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
! 232: return NULL;
! 233: }
! 234: (*offset) += PA_TNC_ATTR_HEADER_SIZE;
! 235:
! 236: return attr;
! 237: }
! 238:
! 239: METHOD(pa_tnc_attr_manager_t, construct, pa_tnc_attr_t*,
! 240: private_pa_tnc_attr_manager_t *this, pen_t vendor_id, uint32_t type,
! 241: chunk_t value)
! 242: {
! 243: enum_name_t *pa_attr_names;
! 244: pa_tnc_attr_t *attr = NULL;
! 245: enumerator_t *enumerator;
! 246: entry_t *entry;
! 247:
! 248: pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
! 249: vendor_id);
! 250: if (pa_attr_names)
! 251: {
! 252: DBG2(DBG_TNC, "generating PA-TNC attribute type '%N/%N' "
! 253: "0x%06x/0x%08x", pen_names, vendor_id,
! 254: pa_attr_names, type, vendor_id, type);
! 255: }
! 256: else
! 257: {
! 258: DBG2(DBG_TNC, "generating PA-TNC attribute type '%N' "
! 259: "0x%06x/0x%08x", pen_names, vendor_id,
! 260: vendor_id, type);
! 261: }
! 262: enumerator = this->list->create_enumerator(this->list);
! 263: while (enumerator->enumerate(enumerator, &entry))
! 264: {
! 265: if (entry->vendor_id == vendor_id)
! 266: {
! 267: if (entry->attr_create)
! 268: {
! 269: attr = entry->attr_create(type, value.len, value);
! 270: }
! 271: break;
! 272: }
! 273: }
! 274: enumerator->destroy(enumerator);
! 275: return attr;
! 276: }
! 277:
! 278: METHOD(pa_tnc_attr_manager_t, destroy, void,
! 279: private_pa_tnc_attr_manager_t *this)
! 280: {
! 281: this->list->destroy_function(this->list, free);
! 282: free(this);
! 283: }
! 284:
! 285: /**
! 286: * See header
! 287: */
! 288: pa_tnc_attr_manager_t *pa_tnc_attr_manager_create(void)
! 289: {
! 290: private_pa_tnc_attr_manager_t *this;
! 291:
! 292: INIT(this,
! 293: .public = {
! 294: .add_vendor = _add_vendor,
! 295: .remove_vendor = _remove_vendor,
! 296: .get_names = _get_names,
! 297: .create = _create,
! 298: .construct = _construct,
! 299: .destroy = _destroy,
! 300: },
! 301: .list = linked_list_create(),
! 302: );
! 303:
! 304: return &this->public;
! 305: }
! 306:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>