1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
|
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup libvici libvici
* @{ @ingroup vici
*
* libvici is a low-level client library for the "Versatile IKE Control
* Interface" protocol. While it uses libstrongswan and its thread-pool for
* asynchronous message delivery, this interface does not directly depend on
* libstrongswan interfaces and should be stable.
*
* This interface provides the following basic functions:
*
* - vici_init()/vici_deinit(): Library initialization functions
* - vici_connect(): Connect to a vici service
* - vici_disconnect(): Disconnect from a vici service
*
* Library initialization implicitly initializes libstrongswan and a small
* thread pool.
*
* Connecting requires an uri, which is currently either a UNIX socket path
* prefixed with unix://, or a hostname:port touple prefixed with tcp://.
* Passing NULL takes the system default socket path.
*
* After the connection has been established, request messages can be sent.
* Only a single thread may operate on a single connection instance
* simultaneously. To construct request messages, use the following functions:
*
* - vici_add_key_value() / vici_add_key_valuef(): Add key/value pairs
* - vici_begin(): Start constructing a new request message
* - vici_begin_section(): Open a new section to add contents to
* - vici_end_section(): Close a previously opened session
* - vici_begin_list(): Open a new list to add list items to
* - vici_end_list(): Close a previously opened list
* - vici_add_list_item() / vici_add_list_itemf(): Add list item
*
* Once the request message is complete, it can be sent or cancelled with:
*
* - vici_submit()
* - vici_free_req()
*
* If submitting a message is successful, a response message is returned. It
* can be processed using the following functions:
*
* - vici_parse(): Parse content type
* - vici_parse_name(): Parse name if content type provides one
* - vici_parse_name_eq(): Parse name and check if matches string
* - vici_parse_value() / vici_parse_value_str(): Parse value for content type
* - vici_dump(): Dump a full response to a FILE stream
* - vici_free_res(): Free response after use
*
* Usually vici_parse() is called in a loop, and depending on the returned
* type the name and value can be inspected.
*
* To register or unregister for asynchronous event messages vici_register() is
* used. The registered callback gets invoked by an asynchronous thread. To
* parse the event message, the vici_parse*() functions can be used.
*/
#ifndef LIBVICI_H_
#define LIBVICI_H_
#include <stdio.h>
#include <utils/utils.h>
/**
* Opaque vici connection contex.
*/
typedef struct vici_conn_t vici_conn_t;
/**
* Opaque vici request message.
*/
typedef struct vici_req_t vici_req_t;
/**
* Opaque vici response/event message.
*/
typedef struct vici_res_t vici_res_t;
/**
* Vici parse result, as returned by vici_parse().
*/
typedef enum {
/** encountered a section start, has a name */
VICI_PARSE_BEGIN_SECTION,
/** encountered a section end */
VICI_PARSE_END_SECTION,
/** encountered a list start, has a name */
VICI_PARSE_BEGIN_LIST,
/** encountered a list element, has a value */
VICI_PARSE_LIST_ITEM,
/** encountered a list end */
VICI_PARSE_END_LIST,
/** encountered a key/value pair, has a name and a value */
VICI_PARSE_KEY_VALUE,
/** encountered valid end of message */
VICI_PARSE_END,
/** parse error */
VICI_PARSE_ERROR,
} vici_parse_t;
/**
* Callback function invoked for received event messages.
*
* It is not allowed to call vici_submit() from this callback.
*
* @param user user data, as passed to vici_connect
* @param name name of received event
* @param msg associated event message, destroyed by libvici
*/
typedef void (*vici_event_cb_t)(void *user, char *name, vici_res_t *msg);
/**
* Callback function for key/value and list items, invoked by vici_parse_cb().
*
* @param user user data, as passed to vici_parse_cb()
* @param res message currently parsing
* @param name name of key or list
* @param value value buffer
* @param len length of value buffer
* @return 0 if parsed successfully
*/
typedef int (*vici_parse_value_cb_t)(void *user, vici_res_t *res, char *name,
void *value, int len);
/**
* Callback function for sections, invoked by vici_parse_cb().
*
* @param user user data, as passed to vici_parse_cb()
* @param res message currently parsing
* @param name name of the section
* @return 0 if parsed successfully
*/
typedef int (*vici_parse_section_cb_t)(void *user, vici_res_t *res, char *name);
/**
* Open a new vici connection.
*
* On error, NULL is returned and errno is set appropriately.
*
* @param uri URI to connect to, NULL to use system default
* @return opaque vici connection context, NULL on error
*/
vici_conn_t* vici_connect(char *uri);
/**
* Close a vici connection.
*
* @param conn connection context
*/
void vici_disconnect(vici_conn_t *conn);
/**
* Begin a new vici message request.
*
* This function always succeeds.
*
* @param name name of request command
* @return request message, to add contents
*/
vici_req_t* vici_begin(char *name);
/**
* Begin a new section in a vici request message.
*
* @param req request message to create a new section in
* @param name name of section to create
*/
void vici_begin_section(vici_req_t *req, char *name);
/**
* End a previously opened section.
*
* @param req request message to close an open section in
*/
void vici_end_section(vici_req_t *req);
/**
* Add a key/value pair, using an as-is blob as value.
*
* @param req request message to add key/value pair to
* @param key key name of key/value pair
* @param buf pointer to blob to add as value
* @param len length of value blob to add
*/
void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len);
/**
* Add a key/value pair, setting value from a printf() format string.
*
* @param req request message to add key/value pair to
* @param key key name of key/value pair
* @param fmt format string for value
* @param ... arguments to format string
*/
void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...);
/**
* Begin a list in a request message.
*
* After starting a list, only list items can be added until the list gets
* closed by vici_end_list().
*
* @param req request message to begin list in
* @param name name of list to begin
*/
void vici_begin_list(vici_req_t *req, char *name);
/**
* Add a list item to a currently open list, using an as-is blob.
*
* @param req request message to add list item to
* @param buf pointer to blob to add as value
* @param len length of value blob to add
*/
void vici_add_list_item(vici_req_t *req, void *buf, int len);
/**
* Add a list item to a currently open list, using a printf() format string.
*
* @param req request message to add list item to
* @param fmt format string to create value from
* @param ... arguments to format string
*/
void vici_add_list_itemf(vici_req_t *req, char *fmt, ...);
/**
* End a previously opened list in a request message.
*
* @param req request message to end list in
*/
void vici_end_list(vici_req_t *req);
/**
* Submit a request message, and wait for response.
*
* The request messages gets cleaned up by this call and gets invalid.
* On error, NULL is returned an errno is set to:
* - EINVAL if the request is invalid/incomplete
* - ENOENT if the command is unknown
* - EBADMSG if the response is invalid
* - Any other IO related errno
*
* @param req request message to send
* @param conn connection context to send message over
* @return response message, NULL on error
*/
vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn);
/**
* Cancel a request message started.
*
* If a request created by vici_begin() does not get submitted using
* vici_submit(), it has to get freed using this call.
*
* @param req request message to clean up
*/
void vici_free_req(vici_req_t *req);
/**
* Dump a message text representation to a FILE stream.
*
* On error, errno is set to:
* - EBADMSG if the message is invalid
*
* @param res response message to dump
* @param label a label to print for this message
* @param pretty use pretty print with indentation
* @param out FILE to dump to
* @return 0 if dumped complete message, 1 on error
*/
int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out);
/**
* Parse next element from a vici response message.
*
* @param res response message to parse
* @return parse result
*/
vici_parse_t vici_parse(vici_res_t *res);
/**
* Parse name tag / key of a previously parsed element.
*
* This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
* VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
*
* The string is valid until vici_free_res() is called.
*
* On error, errno is set to:
*- EINVAL if not in valid parser state
*
* @param res response message to parse
* @return name tag / key, NULL on error
*/
char* vici_parse_name(vici_res_t *res);
/**
* Compare name tag / key of a previusly parsed element.
*
* This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
* VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
*
* @param res response message to parse
* @param name string to compare
* @return 1 if name equals, 0 if not
*/
int vici_parse_name_eq(vici_res_t *res, char *name);
/**
* Parse value of a previously parsed element, as a blob.
*
* This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
* VICI_PARSE_LIST_ITEM.
*
* The string is valid until vici_free_res() is called.
*
* On error, errno is set to:
* - EINVAL if not in valid parser state
*
* @param res response message to parse
* @param len pointer receiving value length
* @return pointer to value, NULL on error
*/
void* vici_parse_value(vici_res_t *res, int *len);
/**
* Parse value of a previously parsed element, as a string.
*
* This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
* VICI_PARSE_LIST_ITEM.
*
* This call is successful only if the value contains no non-printable
* characters. The string is valid until vici_free_res() is called.
*
* On error, errno is set to:
* - EBADMSG if value is not a printable string
* - EINVAL if not in valid parser state
*
* @param res response message to parse
* @return value as string, NULL on error
*/
char* vici_parse_value_str(vici_res_t *res);
/**
* Parse a complete message with callbacks.
*
* Any of the callbacks may be NULL to skip this kind of item. Callbacks are
* invoked for the current section level only. To descent into sections, call
* vici_parse_cb() from within a section callback.
*
* On error, errno is set to:
* - EBADMSG if message encoding invalid
* - Any other errno set by the invoked callbacks
*
* @param res message to parse
* @param section callback invoked for each section
* @param kv callback invoked for key/value pairs
* @param li callback invoked for list items
* @param user user data to pass to callbacks
* @return 0 if parsing successful
*/
int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
void *user);
/*
* Find a blob value in a message for a given key.
*
* Sections can be selected by prefixing them separated by dots.
*
* @param res response message to parse
* @param len length of returned object
* @param fmt printf format string of key and sections
* @param ... arguments to format string
* @return blob value, having *len bytes, NULL if not found
*/
void *vici_find(vici_res_t *res, int *len, char *fmt, ...);
/**
* Find a string value in a message for a given key.
*
* Sections can be selected by prefixing them separated by dots.
*
* @param res response message to parse
* @param def default value, if key not found
* @param fmt printf format string of key and sections
* @param ... arguments to format string
* @return string, def if not found
*/
char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...);
/**
* Find an integer value in a message for a given key.
*
* Sections can be selected by prefixing them separated by dots.
*
* @param res response message to parse
* @param def default value, if key not found
* @param fmt printf format string of key and sections
* @param ... arguments to format string
* @return integer value, def if not found
*/
int vici_find_int(vici_res_t *res, int def, char *fmt, ...);
/**
* Clean up a received response message.
*
* Event messages get cleaned up by the library, it is not allowed to call
* vici_free_res() from within a vici_event_cb_t.
*
* @param res response message to free
*/
void vici_free_res(vici_res_t *res);
/**
* (Un-)Register for events of a given kind.
*
* Events callbacks get invoked by a different thread from the libstrongswan
* thread pool.
* On failure, errno is set to:
* - ENOENT if the event name is unknown
* - EBADMSG if the response is invalid
* - Any other IO related errno
*
* @param conn connection context
* @param name name of event messages to register to
* @param cb callback function to register, NULL to unregister
* @param user user data passed to callback invocations
* @return 0 if registered successfully
*/
int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user);
/**
* Initialize libvici before first time use.
*/
void vici_init();
/**
* Deinitialize libvici after use.
*/
void vici_deinit();
#endif /** LIBVICI_H_ @}*/
|