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>