Return to vici_builder.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / vici |
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: }