Annotation of embedaddon/strongswan/src/libimcv/ietf/swima/ietf_swima_attr_sw_ev.c, revision 1.1
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_sw_ev.h"
! 17: #include "swima/swima_event.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:
! 24: #define SW_EV_TIMESTAMP_SIZE 20
! 25:
! 26: typedef struct private_ietf_swima_attr_sw_ev_t private_ietf_swima_attr_sw_ev_t;
! 27:
! 28: /**
! 29: * Software [Identifier] Events
! 30: * see sections 5.9/5.11 of RFC 8412 SWIMA
! 31: *
! 32: * 1 2 3
! 33: * 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
! 34: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 35: * | Flags | Software Identifier Count |
! 36: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 37: * | Request ID Copy / Subscription ID |
! 38: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 39: * | EID Epoch |
! 40: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 41: * | Last EID |
! 42: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 43: * | Last Consulted EID |
! 44: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 45: * | EID |
! 46: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 47: * | Timestamp |
! 48: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 49: * | Timestamp |
! 50: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 51: * | Timestamp |
! 52: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 53: * | Timestamp |
! 54: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 55: * | Timestamp |
! 56: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 57: * | Record Identifier |
! 58: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 59: * | Data Model Type PEN |Data Model Type|
! 60: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 61: * | Source ID Num | Action | Software Identifier Length |
! 62: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 63: * | Software Identifier (Variable Length) |
! 64: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 65: * | Software Locator Length | Software Locator (Var. Len) |
! 66: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 67: *
! 68: * Software Event only
! 69: * see section 5.11 of IETF SW Inventory Message and Attributes for PA-TNC
! 70: *
! 71: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 72: * | Record Length |
! 73: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 74: * | Record (Variable length) |
! 75: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 76: */
! 77:
! 78: /**
! 79: * Private data of an ietf_swima_attr_sw_ev_t object.
! 80: */
! 81: struct private_ietf_swima_attr_sw_ev_t {
! 82:
! 83: /**
! 84: * Public members of ietf_swima_attr_sw_ev_t
! 85: */
! 86: ietf_swima_attr_sw_ev_t public;
! 87:
! 88: /**
! 89: * Vendor-specific attribute type
! 90: */
! 91: pen_type_t type;
! 92:
! 93: /**
! 94: * Length of attribute value
! 95: */
! 96: size_t length;
! 97:
! 98: /**
! 99: * Offset up to which attribute value has been processed
! 100: */
! 101: size_t offset;
! 102:
! 103: /**
! 104: * Current position of attribute value pointer
! 105: */
! 106: chunk_t value;
! 107:
! 108: /**
! 109: * Contains complete attribute or current segment
! 110: */
! 111: chunk_t segment;
! 112:
! 113: /**
! 114: * Noskip flag
! 115: */
! 116: bool noskip_flag;
! 117:
! 118: /**
! 119: * Request ID
! 120: */
! 121: uint32_t request_id;
! 122:
! 123: /**
! 124: * Attribute flags
! 125: */
! 126: uint8_t flags;
! 127:
! 128: /**
! 129: * Number of unprocessed software events in attribute
! 130: */
! 131: uint32_t event_count;
! 132:
! 133: /**
! 134: * Event list
! 135: */
! 136: swima_events_t *events;
! 137:
! 138: /**
! 139: * Reference count
! 140: */
! 141: refcount_t ref;
! 142: };
! 143:
! 144: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
! 145: private_ietf_swima_attr_sw_ev_t *this)
! 146: {
! 147: return this->type;
! 148: }
! 149:
! 150: METHOD(pa_tnc_attr_t, get_value, chunk_t,
! 151: private_ietf_swima_attr_sw_ev_t *this)
! 152: {
! 153: return this->value;
! 154: }
! 155:
! 156: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
! 157: private_ietf_swima_attr_sw_ev_t *this)
! 158: {
! 159: return this->noskip_flag;
! 160: }
! 161:
! 162: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
! 163: private_ietf_swima_attr_sw_ev_t *this, bool noskip)
! 164: {
! 165: this->noskip_flag = noskip;
! 166: }
! 167:
! 168: /**
! 169: * This function is shared with ietf_swima_attr_sw_inv.c
! 170: **/
! 171: void ietf_swima_attr_sw_ev_build_sw_record(bio_writer_t *writer,
! 172: uint8_t action, swima_record_t *sw_record, bool has_record)
! 173: {
! 174: pen_type_t data_model;
! 175: chunk_t sw_locator;
! 176:
! 177: data_model = sw_record->get_data_model(sw_record);
! 178:
! 179: writer->write_uint32(writer, sw_record->get_record_id(sw_record));
! 180: writer->write_uint24(writer, data_model.vendor_id);
! 181: writer->write_uint8 (writer, data_model.type);
! 182: writer->write_uint8 (writer, sw_record->get_source_id(sw_record));
! 183: writer->write_uint8 (writer, action);
! 184: writer->write_data16(writer, sw_record->get_sw_id(sw_record, &sw_locator));
! 185: writer->write_data16(writer, sw_locator);
! 186:
! 187: if (has_record)
! 188: {
! 189: writer->write_data32(writer, sw_record->get_record(sw_record));
! 190: }
! 191: }
! 192:
! 193: METHOD(pa_tnc_attr_t, build, void,
! 194: private_ietf_swima_attr_sw_ev_t *this)
! 195: {
! 196: bio_writer_t *writer;
! 197: swima_event_t *sw_event;
! 198: swima_record_t *sw_record;
! 199: chunk_t timestamp;
! 200: uint32_t last_eid, last_consulted_eid, eid_epoch;
! 201: uint8_t action;
! 202: enumerator_t *enumerator;
! 203:
! 204: if (this->value.ptr)
! 205: {
! 206: return;
! 207: }
! 208: last_consulted_eid = this->events->get_eid(this->events, &eid_epoch,
! 209: &last_eid);
! 210:
! 211: writer = bio_writer_create(IETF_SWIMA_SW_EV_MIN_SIZE);
! 212: writer->write_uint8 (writer, this->flags);
! 213: writer->write_uint24(writer, this->events->get_count(this->events));
! 214: writer->write_uint32(writer, this->request_id);
! 215: writer->write_uint32(writer, eid_epoch);
! 216: writer->write_uint32(writer, last_eid);
! 217: writer->write_uint32(writer, last_consulted_eid);
! 218:
! 219: enumerator = this->events->create_enumerator(this->events);
! 220: while (enumerator->enumerate(enumerator, &sw_event))
! 221: {
! 222: action = sw_event->get_action(sw_event);
! 223: sw_record = sw_event->get_sw_record(sw_event);
! 224:
! 225: writer->write_uint32(writer, sw_event->get_eid(sw_event, ×tamp));
! 226: writer->write_data (writer, timestamp);
! 227:
! 228: ietf_swima_attr_sw_ev_build_sw_record(writer, action, sw_record,
! 229: this->type.type == IETF_ATTR_SW_EVENTS);
! 230: }
! 231: enumerator->destroy(enumerator);
! 232:
! 233: this->value = writer->extract_buf(writer);
! 234: this->segment = this->value;
! 235: this->length = this->value.len;
! 236: writer->destroy(writer);
! 237: }
! 238:
! 239: /**
! 240: * This function is shared with ietf_swima_attr_sw_inv.c
! 241: **/
! 242: bool ietf_swima_attr_sw_ev_process_sw_record(bio_reader_t *reader,
! 243: uint8_t *action, swima_record_t **sw_record, bool has_record)
! 244: {
! 245: pen_type_t data_model;
! 246: swima_record_t *sw_rec;
! 247: uint32_t data_model_pen, record_id;
! 248: uint8_t data_model_type, source_id, reserved;
! 249: chunk_t sw_id, sw_locator, record = chunk_empty;
! 250:
! 251: if (!reader->read_uint32(reader, &record_id) ||
! 252: !reader->read_uint24(reader, &data_model_pen) ||
! 253: !reader->read_uint8 (reader, &data_model_type) ||
! 254: !reader->read_uint8 (reader, &source_id) ||
! 255: !reader->read_uint8 (reader, &reserved) ||
! 256: !reader->read_data16(reader, &sw_id) ||
! 257: !reader->read_data16(reader, &sw_locator))
! 258: {
! 259: return FALSE;
! 260: }
! 261:
! 262: if (action)
! 263: {
! 264: *action = reserved;
! 265: }
! 266:
! 267: if (has_record && !reader->read_data32(reader, &record))
! 268: {
! 269: return FALSE;
! 270: }
! 271:
! 272: data_model = pen_type_create(data_model_pen, data_model_type);
! 273: sw_rec = swima_record_create(record_id, sw_id, sw_locator);
! 274: sw_rec->set_data_model(sw_rec, data_model);
! 275: sw_rec->set_source_id(sw_rec, source_id);
! 276: sw_rec->set_record(sw_rec, record);
! 277: *sw_record = sw_rec;
! 278:
! 279: return TRUE;
! 280: }
! 281:
! 282: METHOD(pa_tnc_attr_t, process, status_t,
! 283: private_ietf_swima_attr_sw_ev_t *this, uint32_t *offset)
! 284: {
! 285: bio_reader_t *reader;
! 286: uint32_t eid, eid_epoch, last_eid, last_consulted_eid;
! 287: uint8_t action;
! 288: chunk_t timestamp;
! 289: swima_event_t *sw_event;
! 290: swima_record_t *sw_record;
! 291: status_t status = NEED_MORE;
! 292:
! 293: if (this->offset == 0)
! 294: {
! 295: if (this->length < IETF_SWIMA_SW_EV_MIN_SIZE)
! 296: {
! 297: DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_IETF,
! 298: ietf_attr_names, this->type.type);
! 299: *offset = this->offset;
! 300: return FAILED;
! 301: }
! 302: if (this->value.len < IETF_SWIMA_SW_EV_MIN_SIZE)
! 303: {
! 304: return NEED_MORE;
! 305: }
! 306: reader = bio_reader_create(this->value);
! 307: reader->read_uint8 (reader, &this->flags);
! 308: reader->read_uint24(reader, &this->event_count);
! 309: reader->read_uint32(reader, &this->request_id);
! 310: reader->read_uint32(reader, &eid_epoch);
! 311: reader->read_uint32(reader, &last_eid);
! 312: reader->read_uint32(reader, &last_consulted_eid);
! 313: this->offset = IETF_SWIMA_SW_EV_MIN_SIZE;
! 314: this->events->set_eid(this->events, last_consulted_eid, eid_epoch);
! 315: this->events->set_last_eid(this->events, last_eid);
! 316: this->value = reader->peek(reader);
! 317: reader->destroy(reader);
! 318: }
! 319:
! 320: reader = bio_reader_create(this->value);
! 321:
! 322: while (this->event_count)
! 323: {
! 324: if (!reader->read_uint32(reader, &eid) ||
! 325: !reader->read_data (reader, SW_EV_TIMESTAMP_SIZE, ×tamp) ||
! 326: !ietf_swima_attr_sw_ev_process_sw_record(reader, &action, &sw_record,
! 327: this->type.type == IETF_ATTR_SW_EVENTS))
! 328: {
! 329: goto end;
! 330: }
! 331:
! 332: if (action == SWIMA_EVENT_ACTION_NONE ||
! 333: action > SWIMA_EVENT_ACTION_LAST)
! 334: {
! 335: DBG1(DBG_TNC, "invalid event action value for %N/%N", pen_names,
! 336: PEN_IETF, ietf_attr_names, this->type.type);
! 337: *offset = this->offset;
! 338: sw_record->destroy(sw_record);
! 339: reader->destroy(reader);
! 340:
! 341: return FAILED;
! 342: }
! 343:
! 344: sw_event = swima_event_create(eid, timestamp, action, sw_record);
! 345: this->events->add(this->events, sw_event);
! 346: this->offset += this->value.len - reader->remaining(reader);
! 347: this->value = reader->peek(reader);
! 348:
! 349: /* at least one software event was processed */
! 350: status = SUCCESS;
! 351: this->event_count--;
! 352: }
! 353:
! 354: if (this->length == this->offset)
! 355: {
! 356: status = SUCCESS;
! 357: }
! 358: else
! 359: {
! 360: DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_IETF,
! 361: ietf_attr_names, this->type.type);
! 362: *offset = this->offset;
! 363: status = FAILED;
! 364: }
! 365:
! 366: end:
! 367: reader->destroy(reader);
! 368: return status;
! 369: }
! 370:
! 371: METHOD(pa_tnc_attr_t, add_segment, void,
! 372: private_ietf_swima_attr_sw_ev_t *this, chunk_t segment)
! 373: {
! 374: this->value = chunk_cat("cc", this->value, segment);
! 375: chunk_free(&this->segment);
! 376: this->segment = this->value;
! 377: }
! 378:
! 379: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
! 380: private_ietf_swima_attr_sw_ev_t *this)
! 381: {
! 382: ref_get(&this->ref);
! 383: return &this->public.pa_tnc_attribute;
! 384: }
! 385:
! 386: METHOD(pa_tnc_attr_t, destroy, void,
! 387: private_ietf_swima_attr_sw_ev_t *this)
! 388: {
! 389: if (ref_put(&this->ref))
! 390: {
! 391: this->events->destroy(this->events);
! 392: free(this->segment.ptr);
! 393: free(this);
! 394: }
! 395: }
! 396:
! 397: METHOD(ietf_swima_attr_sw_ev_t, get_flags, uint8_t,
! 398: private_ietf_swima_attr_sw_ev_t *this)
! 399: {
! 400: return this->flags;
! 401: }
! 402:
! 403: METHOD(ietf_swima_attr_sw_ev_t, get_request_id, uint32_t,
! 404: private_ietf_swima_attr_sw_ev_t *this)
! 405: {
! 406: return this->request_id;
! 407: }
! 408:
! 409: METHOD(ietf_swima_attr_sw_ev_t, get_event_count, uint32_t,
! 410: private_ietf_swima_attr_sw_ev_t *this)
! 411: {
! 412: return this->event_count;
! 413: }
! 414:
! 415: METHOD(ietf_swima_attr_sw_ev_t, set_events, void,
! 416: private_ietf_swima_attr_sw_ev_t *this, swima_events_t *events)
! 417: {
! 418: this->events->destroy(this->events);
! 419: this->events = events->get_ref(events);
! 420: }
! 421:
! 422: METHOD(ietf_swima_attr_sw_ev_t, get_events, swima_events_t*,
! 423: private_ietf_swima_attr_sw_ev_t *this)
! 424: {
! 425: return this->events;
! 426: }
! 427:
! 428: METHOD(ietf_swima_attr_sw_ev_t, clear_events, void,
! 429: private_ietf_swima_attr_sw_ev_t *this)
! 430: {
! 431: this->events->clear(this->events);
! 432: }
! 433:
! 434: /**
! 435: * Described in header.
! 436: */
! 437: pa_tnc_attr_t *ietf_swima_attr_sw_ev_create(uint8_t flags, uint32_t request_id,
! 438: bool sw_id_only)
! 439: {
! 440: private_ietf_swima_attr_sw_ev_t *this;
! 441: ietf_attr_t type;
! 442:
! 443: type = sw_id_only ? IETF_ATTR_SW_ID_EVENTS : IETF_ATTR_SW_EVENTS;
! 444:
! 445: INIT(this,
! 446: .public = {
! 447: .pa_tnc_attribute = {
! 448: .get_type = _get_type,
! 449: .get_value = _get_value,
! 450: .get_noskip_flag = _get_noskip_flag,
! 451: .set_noskip_flag = _set_noskip_flag,
! 452: .build = _build,
! 453: .process = _process,
! 454: .add_segment = _add_segment,
! 455: .get_ref = _get_ref,
! 456: .destroy = _destroy,
! 457: },
! 458: .get_flags = _get_flags,
! 459: .get_request_id = _get_request_id,
! 460: .get_event_count = _get_event_count,
! 461: .set_events = _set_events,
! 462: .get_events = _get_events,
! 463: .clear_events = _clear_events,
! 464: },
! 465: .type = { PEN_IETF, type },
! 466: .flags = flags,
! 467: .request_id = request_id,
! 468: .events = swima_events_create(),
! 469: .ref = 1,
! 470: );
! 471:
! 472: return &this->public.pa_tnc_attribute;
! 473: }
! 474:
! 475:
! 476: /**
! 477: * Described in header.
! 478: */
! 479: pa_tnc_attr_t *ietf_swima_attr_sw_ev_create_from_data(size_t length,
! 480: chunk_t data, bool sw_id_only)
! 481: {
! 482: private_ietf_swima_attr_sw_ev_t *this;
! 483: ietf_attr_t type;
! 484:
! 485: type = sw_id_only ? IETF_ATTR_SW_ID_EVENTS : IETF_ATTR_SW_EVENTS;
! 486:
! 487: INIT(this,
! 488: .public = {
! 489: .pa_tnc_attribute = {
! 490: .get_type = _get_type,
! 491: .get_value = _get_value,
! 492: .get_noskip_flag = _get_noskip_flag,
! 493: .set_noskip_flag = _set_noskip_flag,
! 494: .build = _build,
! 495: .process = _process,
! 496: .add_segment = _add_segment,
! 497: .get_ref = _get_ref,
! 498: .destroy = _destroy,
! 499: },
! 500: .get_flags = _get_flags,
! 501: .get_request_id = _get_request_id,
! 502: .get_event_count = _get_event_count,
! 503: .set_events = _set_events,
! 504: .get_events = _get_events,
! 505: .clear_events = _clear_events,
! 506: },
! 507: .type = { PEN_IETF, type },
! 508: .length = length,
! 509: .segment = chunk_clone(data),
! 510: .events = swima_events_create(),
! 511: .ref = 1,
! 512: );
! 513:
! 514: /* received either complete attribute value or first segment */
! 515: this->value = this->segment;
! 516:
! 517: return &this->public.pa_tnc_attribute;
! 518: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>