Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_builder.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2014 Martin Willi
                      3:  * Copyright (C) 2014 revosec AG
                      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 "vici_builder.h"
                     17: 
                     18: #include <bio/bio_writer.h>
                     19: 
                     20: typedef struct private_vici_builder_t private_vici_builder_t;
                     21: 
                     22: /**
                     23:  * Private data of an vici_builder_t object.
                     24:  */
                     25: struct private_vici_builder_t {
                     26: 
                     27:        /**
                     28:         * Public vici_builder_t interface.
                     29:         */
                     30:        vici_builder_t public;
                     31: 
                     32:        /**
                     33:         * Writer for elements
                     34:         */
                     35:        bio_writer_t *writer;
                     36: 
                     37:        /**
                     38:         * Errors encountered
                     39:         */
                     40:        u_int error;
                     41: 
                     42:        /**
                     43:         * Section nesting level
                     44:         */
                     45:        u_int section;
                     46: 
                     47:        /**
                     48:         * In list element?
                     49:         */
                     50:        bool list;
                     51: };
                     52: 
                     53: METHOD(vici_builder_t, add, void,
                     54:        private_vici_builder_t *this, vici_type_t type, ...)
                     55: {
                     56:        va_list args;
                     57:        char *name = NULL;
                     58:        chunk_t value = chunk_empty;
                     59: 
                     60:        va_start(args, type);
                     61:        switch (type)
                     62:        {
                     63:                case VICI_SECTION_END:
                     64:                case VICI_LIST_END:
                     65:                case VICI_END:
                     66:                        break;
                     67:                case VICI_LIST_START:
                     68:                case VICI_SECTION_START:
                     69:                        name = va_arg(args, char*);
                     70:                        break;
                     71:                case VICI_KEY_VALUE:
                     72:                        name = va_arg(args, char*);
                     73:                        value = va_arg(args, chunk_t);
                     74:                        break;
                     75:                case VICI_LIST_ITEM:
                     76:                        value = va_arg(args, chunk_t);
                     77:                        break;
                     78:                default:
                     79:                        va_end(args);
                     80:                        this->error++;
                     81:                        return;
                     82:        }
                     83:        va_end(args);
                     84: 
                     85:        if (value.len > 0xffff)
                     86:        {
                     87:                DBG1(DBG_ENC, "vici value exceeds size limit (%zu > %u)",
                     88:                         value.len, 0xffff);
                     89:                this->error++;
                     90:                return;
                     91:        }
                     92:        if (!vici_verify_type(type, this->section, this->list))
                     93:        {
                     94:                this->error++;
                     95:                return;
                     96:        }
                     97:        if (type != VICI_END)
                     98:        {
                     99:                this->writer->write_uint8(this->writer, type);
                    100:        }
                    101:        switch (type)
                    102:        {
                    103:                case VICI_SECTION_START:
                    104:                        this->writer->write_data8(this->writer, chunk_from_str(name));
                    105:                        this->section++;
                    106:                        break;
                    107:                case VICI_SECTION_END:
                    108:                        this->section--;
                    109:                        break;
                    110:                case VICI_KEY_VALUE:
                    111:                        this->writer->write_data8(this->writer, chunk_from_str(name));
                    112:                        this->writer->write_data16(this->writer, value);
                    113:                        break;
                    114:                case VICI_LIST_START:
                    115:                        this->writer->write_data8(this->writer, chunk_from_str(name));
                    116:                        this->list = TRUE;
                    117:                        break;
                    118:                case VICI_LIST_ITEM:
                    119:                        this->writer->write_data16(this->writer, value);
                    120:                        break;
                    121:                case VICI_LIST_END:
                    122:                        this->list = FALSE;
                    123:                        break;
                    124:                default:
                    125:                        this->error++;
                    126:                        break;
                    127:        }
                    128: }
                    129: 
                    130: /**
                    131:  * Add a list item or a key/value, if key given
                    132:  */
                    133: static void vadd_kv_or_li(private_vici_builder_t *this, char *key,
                    134:                                                  char *fmt, va_list args)
                    135: {
                    136:        u_char buf[512];
                    137:        chunk_t value;
                    138:        ssize_t len;
                    139:        va_list copy;
                    140: 
                    141:        va_copy(copy, args);
                    142:        len = vsnprintf(buf, sizeof(buf), fmt, copy);
                    143:        va_end(copy);
                    144:        if (len >= sizeof(buf))
                    145:        {
                    146:                value = chunk_alloc(len + 1);
                    147:                len = vsnprintf(value.ptr, value.len, fmt, args);
                    148:        }
                    149:        else
                    150:        {
                    151:                value = chunk_create(buf, len);
                    152:        }
                    153: 
                    154:        if (len < 0)
                    155:        {
                    156:                DBG1(DBG_ENC, "vici builder format print failed");
                    157:                this->error++;
                    158:        }
                    159:        else
                    160:        {
                    161:                if (key)
                    162:                {
                    163:                        add(this, VICI_KEY_VALUE, key, value);
                    164:                }
                    165:                else
                    166:                {
                    167:                        add(this, VICI_LIST_ITEM, value);
                    168:                }
                    169:        }
                    170:        if (value.ptr != buf)
                    171:        {
                    172:                free(value.ptr);
                    173:        }
                    174: }
                    175: 
                    176: METHOD(vici_builder_t, vadd_kv, void,
                    177:        private_vici_builder_t *this, char *key, char *fmt, va_list args)
                    178: {
                    179:        vadd_kv_or_li(this, key, fmt, args);
                    180: }
                    181: 
                    182: METHOD(vici_builder_t, add_kv, void,
                    183:        private_vici_builder_t *this, char *key, char *fmt, ...)
                    184: {
                    185:        va_list args;
                    186: 
                    187:        va_start(args, fmt);
                    188:        vadd_kv(this, key, fmt, args);
                    189:        va_end(args);
                    190: }
                    191: 
                    192: METHOD(vici_builder_t, vadd_li, void,
                    193:        private_vici_builder_t *this, char *fmt, va_list args)
                    194: {
                    195:        vadd_kv_or_li(this, NULL, fmt, args);
                    196: }
                    197: 
                    198: METHOD(vici_builder_t, add_li, void,
                    199:        private_vici_builder_t *this, char *fmt, ...)
                    200: {
                    201:        va_list args;
                    202: 
                    203:        va_start(args, fmt);
                    204:        vadd_li(this, fmt, args);
                    205:        va_end(args);
                    206: }
                    207: 
                    208: METHOD(vici_builder_t, begin_section, void,
                    209:        private_vici_builder_t *this, char *name)
                    210: {
                    211:        add(this, VICI_SECTION_START, name);
                    212: }
                    213: 
                    214: METHOD(vici_builder_t, end_section, void,
                    215:        private_vici_builder_t *this)
                    216: {
                    217:        add(this, VICI_SECTION_END);
                    218: }
                    219: 
                    220: METHOD(vici_builder_t, begin_list, void,
                    221:        private_vici_builder_t *this, char *name)
                    222: {
                    223:        add(this, VICI_LIST_START, name);
                    224: }
                    225: 
                    226: METHOD(vici_builder_t, end_list, void,
                    227:        private_vici_builder_t *this)
                    228: {
                    229:        add(this, VICI_LIST_END);
                    230: }
                    231: 
                    232: METHOD(vici_builder_t, destroy, void,
                    233:        private_vici_builder_t *this)
                    234: {
                    235:        this->writer->destroy(this->writer);
                    236:        free(this);
                    237: }
                    238: 
                    239: METHOD(vici_builder_t, finalize, vici_message_t*,
                    240:        private_vici_builder_t *this)
                    241: {
                    242:        vici_message_t *product;
                    243: 
                    244:        if (this->error || this->section || this->list)
                    245:        {
                    246:                DBG1(DBG_ENC, "vici builder error: %u errors (section: %u, list %u)",
                    247:                         this->error, this->section, this->list);
                    248:                destroy(this);
                    249:                return NULL;
                    250:        }
                    251:        product = vici_message_create_from_data(
                    252:                                                                this->writer->extract_buf(this->writer), TRUE);
                    253:        destroy(this);
                    254:        return product;
                    255: }
                    256: 
                    257: /**
                    258:  * See header
                    259:  */
                    260: vici_builder_t *vici_builder_create()
                    261: {
                    262:        private_vici_builder_t *this;
                    263: 
                    264:        INIT(this,
                    265:                .public = {
                    266:                        .add = _add,
                    267:                        .add_kv = _add_kv,
                    268:                        .vadd_kv = _vadd_kv,
                    269:                        .add_li = _add_li,
                    270:                        .vadd_li = _vadd_li,
                    271:                        .begin_section = _begin_section,
                    272:                        .end_section = _end_section,
                    273:                        .begin_list = _begin_list,
                    274:                        .end_list = _end_list,
                    275:                        .finalize = _finalize,
                    276:                        .destroy = _destroy,
                    277:                },
                    278:                .writer = bio_writer_create(0),
                    279:        );
                    280: 
                    281:        return &this->public;
                    282: }

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