Annotation of embedaddon/strongswan/src/libimcv/ietf/ietf_attr_op_status.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2014 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_attr_op_status.h"
                     17: 
                     18: #include <pa_tnc/pa_tnc_msg.h>
                     19: #include <bio/bio_writer.h>
                     20: #include <bio/bio_reader.h>
                     21: #include <utils/debug.h>
                     22: 
                     23: #include <time.h>
                     24: 
                     25: typedef struct private_ietf_attr_op_status_t private_ietf_attr_op_status_t;
                     26: 
                     27: ENUM(op_status_names, OP_STATUS_UNKNOWN, OP_STATUS_OPERATIONAL,
                     28:        "unknown",
                     29:        "not installed",
                     30:        "installed",
                     31:        "operational"
                     32: );
                     33: 
                     34: ENUM(op_result_names, OP_RESULT_UNKNOWN, OP_RESULT_UNSUCCESSFUL,
                     35:        "unknown",
                     36:        "successful",
                     37:        "errored",
                     38:        "unsuccessful"
                     39: );
                     40: 
                     41: /**
                     42:  * PA-TNC Operational Status type  (see section 4.2.5 of RFC 5792)
                     43:  *
                     44:  *                       1                   2                   3
                     45:  *   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
                     46:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     47:  *  |    Status     |     Result    |         Reserved              |
                     48:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     49:  *  |                          Last Use                             |
                     50:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     51:  *  |                     Last Use (continued)                      |
                     52:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     53:  *  |                     Last Use (continued)                      |
                     54:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     55:  *  |                     Last Use (continued)                      |
                     56:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     57:  *  |                     Last Use (continued)                      |
                     58:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     59:  */
                     60: 
                     61: #define OP_STATUS_SIZE         24
                     62: 
                     63: /**
                     64:  * Private data of an ietf_attr_op_status_t object.
                     65:  */
                     66: struct private_ietf_attr_op_status_t {
                     67: 
                     68:        /**
                     69:         * Public members of ietf_attr_op_status_t
                     70:         */
                     71:        ietf_attr_op_status_t public;
                     72: 
                     73:        /**
                     74:         * Vendor-specific attribute type
                     75:         */
                     76:        pen_type_t type;
                     77: 
                     78:        /**
                     79:         * Length of attribute value
                     80:         */
                     81:        size_t length;
                     82: 
                     83:        /**
                     84:         * Attribute value or segment
                     85:         */
                     86:        chunk_t value;
                     87: 
                     88:        /**
                     89:         * Noskip flag
                     90:         */
                     91:        bool noskip_flag;
                     92: 
                     93:        /**
                     94:         * Status
                     95:         */
                     96:        uint8_t status;
                     97: 
                     98:        /**
                     99:         * Result
                    100:         */
                    101:        uint8_t result;
                    102: 
                    103:        /**
                    104:         * Last Use
                    105:         */
                    106:        time_t last_use;
                    107: 
                    108:        /**
                    109:         * Reference count
                    110:         */
                    111:        refcount_t ref;
                    112: };
                    113: 
                    114: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
                    115:        private_ietf_attr_op_status_t *this)
                    116: {
                    117:        return this->type;
                    118: }
                    119: 
                    120: METHOD(pa_tnc_attr_t, get_value, chunk_t,
                    121:        private_ietf_attr_op_status_t *this)
                    122: {
                    123:        return this->value;
                    124: }
                    125: 
                    126: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
                    127:        private_ietf_attr_op_status_t *this)
                    128: {
                    129:        return this->noskip_flag;
                    130: }
                    131: 
                    132: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
                    133:        private_ietf_attr_op_status_t *this, bool noskip)
                    134: {
                    135:        this->noskip_flag = noskip;
                    136: }
                    137: 
                    138: METHOD(pa_tnc_attr_t, build, void,
                    139:        private_ietf_attr_op_status_t *this)
                    140: {
                    141:        bio_writer_t *writer;
                    142:        char last_use[24];
                    143:        struct tm t;
                    144: 
                    145:        if (this->value.ptr)
                    146:        {
                    147:                return;
                    148:        }
                    149: 
                    150:        /* Conversion from time_t to RFC 3339 ASCII string */
                    151:        gmtime_r(&this->last_use, &t);
                    152:        snprintf(last_use, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.tm_year,
                    153:                         t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
                    154: 
                    155:        writer = bio_writer_create(OP_STATUS_SIZE);
                    156:        writer->write_uint8 (writer, this->status);
                    157:        writer->write_uint8 (writer, this->result);
                    158:        writer->write_uint16(writer, 0x0000);
                    159:        writer->write_data  (writer, chunk_create(last_use, 20));
                    160: 
                    161:        this->value = writer->extract_buf(writer);
                    162:        this->length = this->value.len;
                    163:        writer->destroy(writer);
                    164: }
                    165: 
                    166: METHOD(pa_tnc_attr_t, process, status_t,
                    167:        private_ietf_attr_op_status_t *this, uint32_t *offset)
                    168: {
                    169:        bio_reader_t *reader;
                    170:        chunk_t last_use;
                    171:        uint16_t reserved;
                    172:        struct tm t;
                    173:        char buf[BUF_LEN];
                    174: 
                    175:        *offset = 0;
                    176: 
                    177:        if (this->value.len < this->length)
                    178:        {
                    179:                return NEED_MORE;
                    180:        }
                    181:        if (this->value.len != OP_STATUS_SIZE)
                    182:        {
                    183:                DBG1(DBG_TNC, "incorrect size for IETF operational status");
                    184:                return FAILED;
                    185:        }
                    186:        reader = bio_reader_create(this->value);
                    187:        reader->read_uint8 (reader, &this->status);
                    188:        reader->read_uint8 (reader, &this->result);
                    189:        reader->read_uint16(reader, &reserved);
                    190:        reader->read_data  (reader, 20, &last_use);
                    191:        reader->destroy(reader);
                    192: 
                    193:        if (this->status > OP_STATUS_ROOF)
                    194:        {
                    195:                DBG1(DBG_TNC, "invalid status value %c for IETF operational status",
                    196:                                           this->status);
                    197:                return FAILED;
                    198:        }
                    199: 
                    200:        *offset = 1;
                    201: 
                    202:        if (this->result > OP_RESULT_ROOF)
                    203:        {
                    204:                DBG1(DBG_TNC, "invalid result value %c for IETF operational status",
                    205:                                           this->result);
                    206:                return FAILED;
                    207:        }
                    208: 
                    209:        *offset = 4;
                    210: 
                    211:        /* Conversion from RFC 3339 ASCII string to time_t */
                    212:        snprintf(buf, sizeof(buf), "%.*s", (int)last_use.len, last_use.ptr);
                    213:        if (sscanf(buf, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t.tm_year, &t.tm_mon,
                    214:                           &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
                    215:        {
                    216:                DBG1(DBG_TNC, "invalid last_use time format in IETF operational status");
                    217:                return FAILED;
                    218:        }
                    219:        t.tm_year -= 1900;
                    220:        t.tm_mon -= 1;
                    221:        t.tm_isdst = 0;
                    222:        this->last_use = mktime(&t) - timezone;
                    223: 
                    224:        return SUCCESS;
                    225: }
                    226: 
                    227: METHOD(pa_tnc_attr_t, add_segment, void,
                    228:        private_ietf_attr_op_status_t *this, chunk_t segment)
                    229: {
                    230:        this->value = chunk_cat("mc", this->value, segment);
                    231: }
                    232: 
                    233: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
                    234:        private_ietf_attr_op_status_t *this)
                    235: {
                    236:        ref_get(&this->ref);
                    237:        return &this->public.pa_tnc_attribute;
                    238: }
                    239: 
                    240: METHOD(pa_tnc_attr_t, destroy, void,
                    241:        private_ietf_attr_op_status_t *this)
                    242: {
                    243:        if (ref_put(&this->ref))
                    244:        {
                    245:                free(this->value.ptr);
                    246:                free(this);
                    247:        }
                    248: }
                    249: 
                    250: METHOD(ietf_attr_op_status_t, get_status, uint8_t,
                    251:        private_ietf_attr_op_status_t *this)
                    252: {
                    253:        return this->status;
                    254: }
                    255: 
                    256: METHOD(ietf_attr_op_status_t, get_result, uint8_t,
                    257:        private_ietf_attr_op_status_t *this)
                    258: {
                    259:        return this->result;
                    260: }
                    261: 
                    262: METHOD(ietf_attr_op_status_t, get_last_use, time_t,
                    263:        private_ietf_attr_op_status_t *this)
                    264: {
                    265:        return this->last_use;
                    266: }
                    267: 
                    268: /**
                    269:  * Described in header.
                    270:  */
                    271: pa_tnc_attr_t *ietf_attr_op_status_create(uint8_t status, uint8_t result,
                    272:                                                                                  time_t last_use)
                    273: {
                    274:        private_ietf_attr_op_status_t *this;
                    275: 
                    276:        INIT(this,
                    277:                .public = {
                    278:                        .pa_tnc_attribute = {
                    279:                                .get_type = _get_type,
                    280:                                .get_value = _get_value,
                    281:                                .get_noskip_flag = _get_noskip_flag,
                    282:                                .set_noskip_flag = _set_noskip_flag,
                    283:                                .build = _build,
                    284:                                .process = _process,
                    285:                                .add_segment = _add_segment,
                    286:                                .get_ref = _get_ref,
                    287:                                .destroy = _destroy,
                    288:                        },
                    289:                        .get_status = _get_status,
                    290:                        .get_result = _get_result,
                    291:                        .get_last_use = _get_last_use,
                    292:                },
                    293:                .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS },
                    294:                .status = status,
                    295:                .result = result,
                    296:                .last_use = last_use,
                    297:                .ref = 1,
                    298:        );
                    299: 
                    300:        return &this->public.pa_tnc_attribute;
                    301: }
                    302: 
                    303: /**
                    304:  * Described in header.
                    305:  */
                    306: pa_tnc_attr_t *ietf_attr_op_status_create_from_data(size_t length, chunk_t data)
                    307: {
                    308:        private_ietf_attr_op_status_t *this;
                    309: 
                    310:        INIT(this,
                    311:                .public = {
                    312:                        .pa_tnc_attribute = {
                    313:                                .get_type = _get_type,
                    314:                                .get_value = _get_value,
                    315:                                .get_noskip_flag = _get_noskip_flag,
                    316:                                .set_noskip_flag = _set_noskip_flag,
                    317:                                .build = _build,
                    318:                                .process = _process,
                    319:                                .add_segment = _add_segment,
                    320:                                .get_ref = _get_ref,
                    321:                                .destroy = _destroy,
                    322:                        },
                    323:                        .get_status = _get_status,
                    324:                        .get_result = _get_result,
                    325:                        .get_last_use = _get_last_use,
                    326:                },
                    327:                .type = { PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS },
                    328:                .value = chunk_clone(data),
                    329:                .ref = 1,
                    330:        );
                    331: 
                    332:        return &this->public.pa_tnc_attribute;
                    333: }
                    334: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>