Return to ietf_swima_attr_req.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libimcv / ietf / swima |
1.1 misho 1: /* 2: * Copyright (C) 2017 Andreas Steffen 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include "ietf_swima_attr_req.h" 17: #include "swima/swima_record.h" 18: 19: #include <pa_tnc/pa_tnc_msg.h> 20: #include <bio/bio_writer.h> 21: #include <bio/bio_reader.h> 22: #include <utils/debug.h> 23: #include <collections/linked_list.h> 24: 25: typedef struct private_ietf_swima_attr_req_t private_ietf_swima_attr_req_t; 26: 27: /** 28: * SW Request 29: * see section 5.7 of RFC 8412 SWIMA 30: * 31: * 1 2 3 32: * 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 33: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 34: * |C|S|R| Reserved| Software Identifier Count | 35: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36: * | Request ID | 37: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 38: * | Earliest EID | 39: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40: * | Software Identifier Length | Software Identifier (Var Len) | 41: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 42: */ 43: 44: #define SW_REQ_RESERVED_MASK 0xE0 45: 46: /** 47: * Private data of an ietf_swima_attr_req_t object. 48: */ 49: struct private_ietf_swima_attr_req_t { 50: 51: /** 52: * Public members of ietf_swima_attr_req_t 53: */ 54: ietf_swima_attr_req_t public; 55: 56: /** 57: * Vendor-specific attribute type 58: */ 59: pen_type_t type; 60: 61: /** 62: * Length of attribute value 63: */ 64: size_t length; 65: 66: /** 67: * Attribute value or segment 68: */ 69: chunk_t value; 70: 71: /** 72: * Noskip flag 73: */ 74: bool noskip_flag; 75: 76: /** 77: * SWID request flags 78: */ 79: uint8_t flags; 80: 81: /** 82: * Request ID 83: */ 84: uint32_t request_id; 85: 86: /** 87: * Inventory of Target Software Identifiers 88: */ 89: swima_inventory_t *targets; 90: 91: /** 92: * Reference count 93: */ 94: refcount_t ref; 95: }; 96: 97: METHOD(pa_tnc_attr_t, get_type, pen_type_t, 98: private_ietf_swima_attr_req_t *this) 99: { 100: return this->type; 101: } 102: 103: METHOD(pa_tnc_attr_t, get_value, chunk_t, 104: private_ietf_swima_attr_req_t *this) 105: { 106: return this->value; 107: } 108: 109: METHOD(pa_tnc_attr_t, get_noskip_flag, bool, 110: private_ietf_swima_attr_req_t *this) 111: { 112: return this->noskip_flag; 113: } 114: 115: METHOD(pa_tnc_attr_t, set_noskip_flag,void, 116: private_ietf_swima_attr_req_t *this, bool noskip) 117: { 118: this->noskip_flag = noskip; 119: } 120: 121: METHOD(pa_tnc_attr_t, build, void, 122: private_ietf_swima_attr_req_t *this) 123: { 124: bio_writer_t *writer; 125: swima_record_t *sw_record; 126: uint32_t earliest_eid; 127: chunk_t sw_id; 128: enumerator_t *enumerator; 129: 130: if (this->value.ptr) 131: { 132: return; 133: } 134: earliest_eid = this->targets->get_eid(this->targets, NULL); 135: 136: writer = bio_writer_create(IETF_SWIMA_REQ_MIN_SIZE); 137: writer->write_uint8 (writer, this->flags); 138: writer->write_uint24(writer, this->targets->get_count(this->targets)); 139: writer->write_uint32(writer, this->request_id); 140: writer->write_uint32(writer, earliest_eid); 141: 142: enumerator = this->targets->create_enumerator(this->targets); 143: while (enumerator->enumerate(enumerator, &sw_record)) 144: { 145: sw_id = sw_record->get_sw_id(sw_record, NULL); 146: writer->write_data16(writer, sw_id); 147: } 148: enumerator->destroy(enumerator); 149: 150: this->value = writer->extract_buf(writer); 151: this->length = this->value.len; 152: writer->destroy(writer); 153: } 154: 155: METHOD(pa_tnc_attr_t, process, status_t, 156: private_ietf_swima_attr_req_t *this, uint32_t *offset) 157: { 158: bio_reader_t *reader; 159: swima_record_t *sw_record; 160: uint32_t sw_id_count, earliest_eid; 161: chunk_t sw_id; 162: 163: *offset = 0; 164: 165: if (this->value.len < this->length) 166: { 167: return NEED_MORE; 168: } 169: if (this->value.len < IETF_SWIMA_REQ_MIN_SIZE) 170: { 171: DBG1(DBG_TNC, "insufficient data for SW Request"); 172: return FAILED; 173: } 174: 175: reader = bio_reader_create(this->value); 176: reader->read_uint8 (reader, &this->flags); 177: reader->read_uint24(reader, &sw_id_count); 178: reader->read_uint32(reader, &this->request_id); 179: reader->read_uint32(reader, &earliest_eid); 180: 181: *offset = IETF_SWIMA_REQ_MIN_SIZE; 182: this->flags &= SW_REQ_RESERVED_MASK; 183: this->targets->set_eid(this->targets, earliest_eid, 0); 184: 185: while (sw_id_count--) 186: { 187: if (!reader->read_data16(reader, &sw_id)) 188: { 189: DBG1(DBG_TNC, "insufficient data for Software ID"); 190: reader->destroy(reader); 191: return FAILED; 192: } 193: *offset += 2 + sw_id.len; 194: 195: sw_record = swima_record_create(0, sw_id, chunk_empty); 196: this->targets->add(this->targets, sw_record); 197: } 198: reader->destroy(reader); 199: 200: return SUCCESS; 201: } 202: 203: METHOD(pa_tnc_attr_t, add_segment, void, 204: private_ietf_swima_attr_req_t *this, chunk_t segment) 205: { 206: this->value = chunk_cat("mc", this->value, segment); 207: } 208: 209: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, 210: private_ietf_swima_attr_req_t *this) 211: { 212: ref_get(&this->ref); 213: return &this->public.pa_tnc_attribute; 214: } 215: 216: METHOD(pa_tnc_attr_t, destroy, void, 217: private_ietf_swima_attr_req_t *this) 218: { 219: if (ref_put(&this->ref)) 220: { 221: this->targets->destroy(this->targets); 222: free(this->value.ptr); 223: free(this); 224: } 225: } 226: 227: METHOD(ietf_swima_attr_req_t, get_flags, uint8_t, 228: private_ietf_swima_attr_req_t *this) 229: { 230: return this->flags; 231: } 232: 233: METHOD(ietf_swima_attr_req_t, get_request_id, uint32_t, 234: private_ietf_swima_attr_req_t *this) 235: { 236: return this->request_id; 237: } 238: 239: METHOD(ietf_swima_attr_req_t, set_targets, void, 240: private_ietf_swima_attr_req_t *this, swima_inventory_t *targets) 241: { 242: this->targets->destroy(this->targets); 243: this->targets = targets->get_ref(targets); 244: } 245: 246: METHOD(ietf_swima_attr_req_t, get_targets, swima_inventory_t*, 247: private_ietf_swima_attr_req_t *this) 248: { 249: return this->targets; 250: } 251: 252: /** 253: * Described in header. 254: */ 255: pa_tnc_attr_t *ietf_swima_attr_req_create(uint8_t flags, uint32_t request_id) 256: { 257: private_ietf_swima_attr_req_t *this; 258: 259: INIT(this, 260: .public = { 261: .pa_tnc_attribute = { 262: .get_type = _get_type, 263: .get_value = _get_value, 264: .get_noskip_flag = _get_noskip_flag, 265: .set_noskip_flag = _set_noskip_flag, 266: .build = _build, 267: .process = _process, 268: .add_segment = _add_segment, 269: .get_ref = _get_ref, 270: .destroy = _destroy, 271: }, 272: .get_flags = _get_flags, 273: .get_request_id = _get_request_id, 274: .set_targets = _set_targets, 275: .get_targets = _get_targets, 276: }, 277: .type = { PEN_IETF, IETF_ATTR_SWIMA_REQUEST }, 278: .flags = flags & SW_REQ_RESERVED_MASK, 279: .request_id = request_id, 280: .targets = swima_inventory_create(), 281: .ref = 1, 282: ); 283: 284: return &this->public.pa_tnc_attribute; 285: } 286: 287: /** 288: * Described in header. 289: */ 290: pa_tnc_attr_t *ietf_swima_attr_req_create_from_data(size_t length, chunk_t data) 291: { 292: private_ietf_swima_attr_req_t *this; 293: 294: INIT(this, 295: .public = { 296: .pa_tnc_attribute = { 297: .get_type = _get_type, 298: .get_value = _get_value, 299: .get_noskip_flag = _get_noskip_flag, 300: .set_noskip_flag = _set_noskip_flag, 301: .build = _build, 302: .process = _process, 303: .add_segment = _add_segment, 304: .get_ref = _get_ref, 305: .destroy = _destroy, 306: }, 307: .get_flags = _get_flags, 308: .get_request_id = _get_request_id, 309: .set_targets = _set_targets, 310: .get_targets = _get_targets, 311: }, 312: .type = { PEN_IETF, IETF_ATTR_SWIMA_REQUEST }, 313: .length = length, 314: .value = chunk_clone(data), 315: .targets = swima_inventory_create(), 316: .ref = 1, 317: ); 318: 319: return &this->public.pa_tnc_attribute; 320: }