Annotation of embedaddon/strongswan/src/libimcv/ietf/swima/ietf_swima_attr_sw_ev.c, revision 1.1.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>