Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_builder.c, revision 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>