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, &timestamp));
                    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, &timestamp) ||
                    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>