Removed VICI protocol versioning
[strongswan.git] / src / libcharon / plugins / vici / libvici.c
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 "libvici.h"
17 #include "vici_builder.h"
18 #include "vici_dispatcher.h"
19 #include "vici_socket.h"
20
21 #include <library.h>
22 #include <threading/mutex.h>
23 #include <threading/condvar.h>
24 #include <collections/hashtable.h>
25
26 #include <errno.h>
27
28 /**
29 * Event registration
30 */
31 typedef struct {
32 /** name of event */
33 char *name;
34 /** callback function */
35 vici_event_cb_t cb;
36 /** user data for callback */
37 void *user;
38 } event_t;
39
40 /**
41 * Wait state signaled by asynchronous on_read callback
42 */
43 typedef enum {
44 WAIT_IDLE = 0,
45 WAIT_SUCCESS,
46 WAIT_FAILURE,
47 WAIT_READ_ERROR,
48 } wait_state_t;
49
50 /**
51 * Private vici connection contex.
52 */
53 struct vici_conn_t {
54 /** connection stream */
55 stream_t *stream;
56 /** event registrations, as char* => event_t */
57 hashtable_t *events;
58 /** connection lock */
59 mutex_t *mutex;
60 /** condvar to signal incoming response */
61 condvar_t *cond;
62 /** queued response message */
63 chunk_t queue;
64 /** asynchronous read error */
65 int error;
66 /** wait state */
67 wait_state_t wait;
68 };
69
70 /**
71 * Private vici request message.
72 */
73 struct vici_req_t {
74 /** connection context */
75 vici_conn_t *conn;
76 /** name of request message */
77 char *name;
78 /** message builder */
79 vici_builder_t *b;
80 };
81
82 /**
83 * Private vici response/event message.
84 */
85 struct vici_res_t {
86 /** response message */
87 vici_message_t *message;
88 /** allocated strings */
89 linked_list_t *strings;
90 /** item enumerator */
91 enumerator_t *enumerator;
92 /** currently enumerating type */
93 vici_type_t type;
94 /** currently enumerating name */
95 char *name;
96 /** currently enumerating value */
97 chunk_t value;
98 /** section nesting level of callback parser */
99 int level;
100 };
101
102 /**
103 * Signal wait result for waiting user thread
104 */
105 static bool wait_result(vici_conn_t *conn, wait_state_t wait)
106 {
107 conn->mutex->lock(conn->mutex);
108 conn->wait = wait;
109 conn->mutex->unlock(conn->mutex);
110 conn->cond->signal(conn->cond);
111 return FALSE;
112 }
113
114 /**
115 * Signal wait error result for waiting user thread
116 */
117 static bool read_error(vici_conn_t *conn, int err)
118 {
119 conn->error = err;
120 return wait_result(conn, WAIT_READ_ERROR);
121 }
122
123 /**
124 * Handle a command response message
125 */
126 static bool handle_response(vici_conn_t *conn, u_int32_t len)
127 {
128 chunk_t buf;
129
130 buf = chunk_alloc(len);
131 if (!conn->stream->read_all(conn->stream, buf.ptr, buf.len))
132 {
133 free(buf.ptr);
134 return read_error(conn, errno);
135 }
136 conn->queue = buf;
137 return wait_result(conn, WAIT_SUCCESS);
138 }
139
140 /**
141 * Dispatch received event message
142 */
143 static bool handle_event(vici_conn_t *conn, u_int32_t len)
144 {
145 vici_message_t *message;
146 event_t *event;
147 u_int8_t namelen;
148 char name[257], *buf;
149
150 if (len < sizeof(namelen))
151 {
152 return read_error(conn, EBADMSG);
153 }
154 if (!conn->stream->read_all(conn->stream, &namelen, sizeof(namelen)))
155 {
156 return read_error(conn, errno);
157 }
158 if (namelen > len - sizeof(namelen))
159 {
160 return read_error(conn, EBADMSG);
161 }
162 if (!conn->stream->read_all(conn->stream, name, namelen))
163 {
164 return read_error(conn, errno);
165 }
166 name[namelen] = '\0';
167 len -= sizeof(namelen) + namelen;
168 buf = malloc(len);
169 if (!conn->stream->read_all(conn->stream, buf, len))
170 {
171 free(buf);
172 return read_error(conn, errno);
173 }
174 message = vici_message_create_from_data(chunk_create(buf, len), TRUE);
175
176 conn->mutex->lock(conn->mutex);
177 event = conn->events->get(conn->events, name);
178 if (event)
179 {
180 vici_res_t res = {
181 .message = message,
182 .enumerator = message->create_enumerator(message),
183 .strings = linked_list_create(),
184 };
185
186 event->cb(event->user, name, &res);
187
188 res.enumerator->destroy(res.enumerator);
189 res.strings->destroy_function(res.strings, free);
190 }
191 conn->mutex->unlock(conn->mutex);
192
193 message->destroy(message);
194
195 return TRUE;
196 }
197
198 CALLBACK(on_read, bool,
199 vici_conn_t *conn, stream_t *stream)
200 {
201 u_int32_t len;
202 u_int8_t op;
203 ssize_t hlen;
204
205 hlen = stream->read(stream, &len, sizeof(len), FALSE);
206 if (hlen <= 0)
207 {
208 if (errno == EWOULDBLOCK)
209 {
210 return TRUE;
211 }
212 return read_error(conn, errno);
213 }
214 if (hlen < sizeof(len))
215 {
216 if (!stream->read_all(stream, ((void*)&len) + hlen, sizeof(len) - hlen))
217 {
218 return read_error(conn, errno);
219 }
220 }
221
222 len = ntohl(len);
223 if (len > VICI_MESSAGE_SIZE_MAX)
224 {
225 return read_error(conn, EBADMSG);
226 }
227 if (len-- < sizeof(op))
228 {
229 return read_error(conn, EBADMSG);
230 }
231 if (!stream->read_all(stream, &op, sizeof(op)))
232 {
233 return read_error(conn, errno);
234 }
235 switch (op)
236 {
237 case VICI_EVENT:
238 return handle_event(conn, len);
239 case VICI_CMD_RESPONSE:
240 return handle_response(conn, len);
241 case VICI_EVENT_CONFIRM:
242 return wait_result(conn, WAIT_SUCCESS);
243 case VICI_CMD_UNKNOWN:
244 case VICI_EVENT_UNKNOWN:
245 return wait_result(conn, WAIT_FAILURE);
246 case VICI_CMD_REQUEST:
247 case VICI_EVENT_REGISTER:
248 case VICI_EVENT_UNREGISTER:
249 default:
250 return read_error(conn, EBADMSG);
251 }
252 }
253
254 vici_conn_t* vici_connect(char *uri)
255 {
256 vici_conn_t *conn;
257 stream_t *stream;
258
259 stream = lib->streams->connect(lib->streams, uri ?: VICI_DEFAULT_URI);
260 if (!stream)
261 {
262 return NULL;
263 }
264
265 INIT(conn,
266 .stream = stream,
267 .events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
268 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
269 .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
270 );
271
272 stream->on_read(stream, on_read, conn);
273
274 return conn;
275 }
276
277 void vici_disconnect(vici_conn_t *conn)
278 {
279 enumerator_t *enumerator;
280 event_t *event;
281
282 conn->stream->destroy(conn->stream);
283 enumerator = conn->events->create_enumerator(conn->events);
284 while (enumerator->enumerate(enumerator, NULL, &event))
285 {
286 free(event->name);
287 free(event);
288 }
289 enumerator->destroy(enumerator);
290 conn->events->destroy(conn->events);
291 conn->mutex->destroy(conn->mutex);
292 conn->cond->destroy(conn->cond);
293 free(conn);
294 }
295
296 vici_req_t* vici_begin(char *name)
297 {
298 vici_req_t *req;
299
300 INIT(req,
301 .name = strdup(name),
302 .b = vici_builder_create(),
303 );
304
305 return req;
306 }
307
308 void vici_begin_section(vici_req_t *req, char *name)
309 {
310 req->b->add(req->b, VICI_SECTION_START, name);
311 }
312
313 void vici_end_section(vici_req_t *req)
314 {
315 req->b->add(req->b, VICI_SECTION_END);
316 }
317
318 void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len)
319 {
320 req->b->add(req->b, VICI_KEY_VALUE, key, chunk_create(buf, len));
321 }
322
323 void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...)
324 {
325 va_list args;
326
327 va_start(args, fmt);
328 req->b->vadd_kv(req->b, key, fmt, args);
329 va_end(args);
330 }
331
332 void vici_begin_list(vici_req_t *req, char *name)
333 {
334 req->b->add(req->b, VICI_LIST_START, name);
335 }
336
337 void vici_add_list_item(vici_req_t *req, void *buf, int len)
338 {
339 req->b->add(req->b, VICI_LIST_ITEM, chunk_create(buf, len));
340 }
341
342 void vici_add_list_itemf(vici_req_t *req, char *fmt, ...)
343 {
344 va_list args;
345
346 va_start(args, fmt);
347 req->b->vadd_li(req->b, fmt, args);
348 va_end(args);
349 }
350
351 void vici_end_list(vici_req_t *req)
352 {
353 req->b->add(req->b, VICI_LIST_END);
354 }
355
356 vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn)
357 {
358 vici_message_t *message;
359 vici_res_t *res;
360 chunk_t data;
361 u_int32_t len;
362 u_int8_t namelen, op;
363
364 message = req->b->finalize(req->b);
365 if (!message)
366 {
367 errno = EINVAL;
368 return NULL;
369 }
370
371 op = VICI_CMD_REQUEST;
372 namelen = strlen(req->name);
373 data = message->get_encoding(message);
374 len = htonl(sizeof(op) + sizeof(namelen) + namelen + data.len);
375
376 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
377 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
378 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
379 !conn->stream->write_all(conn->stream, req->name, namelen) ||
380 !conn->stream->write_all(conn->stream, data.ptr, data.len))
381 {
382 free(req->name);
383 free(req);
384 message->destroy(message);
385 return NULL;
386 }
387 free(req->name);
388 free(req);
389 message->destroy(message);
390
391 message = NULL;
392 conn->mutex->lock(conn->mutex);
393 while (conn->wait == WAIT_IDLE)
394 {
395 conn->cond->wait(conn->cond, conn->mutex);
396 }
397 switch (conn->wait)
398 {
399 case WAIT_SUCCESS:
400 message = vici_message_create_from_data(conn->queue, TRUE);
401 conn->queue = chunk_empty;
402 break;
403 case WAIT_READ_ERROR:
404 errno = conn->error;
405 break;
406 case WAIT_FAILURE:
407 default:
408 errno = ENOENT;
409 break;
410 }
411 conn->wait = WAIT_IDLE;
412 conn->mutex->unlock(conn->mutex);
413
414 conn->stream->on_read(conn->stream, on_read, conn);
415
416 if (message)
417 {
418 INIT(res,
419 .message = message,
420 .enumerator = message->create_enumerator(message),
421 .strings = linked_list_create(),
422 );
423 return res;
424 }
425 return NULL;
426 }
427
428 void vici_free_req(vici_req_t *req)
429 {
430 free(req->name);
431 req->b->destroy(req->b);
432 free(req);
433 }
434
435 int vici_dump(vici_res_t *res, char *label, int pretty, FILE *out)
436 {
437 if (res->message->dump(res->message, label, pretty, out))
438 {
439 return 0;
440 }
441 errno = EBADMSG;
442 return 1;
443 }
444
445 vici_parse_t vici_parse(vici_res_t *res)
446 {
447 if (!res->enumerator->enumerate(res->enumerator,
448 &res->type, &res->name, &res->value))
449 {
450 return VICI_PARSE_ERROR;
451 }
452 switch (res->type)
453 {
454 case VICI_END:
455 return VICI_PARSE_END;
456 case VICI_SECTION_START:
457 return VICI_PARSE_BEGIN_SECTION;
458 case VICI_SECTION_END:
459 return VICI_PARSE_END_SECTION;
460 case VICI_LIST_START:
461 return VICI_PARSE_BEGIN_LIST;
462 case VICI_LIST_ITEM:
463 return VICI_PARSE_LIST_ITEM;
464 case VICI_LIST_END:
465 return VICI_PARSE_END_LIST;
466 case VICI_KEY_VALUE:
467 return VICI_PARSE_KEY_VALUE;
468 default:
469 return VICI_PARSE_ERROR;
470 }
471 }
472
473 char* vici_parse_name(vici_res_t *res)
474 {
475 char *name;
476
477 switch (res->type)
478 {
479 case VICI_SECTION_START:
480 case VICI_LIST_START:
481 case VICI_KEY_VALUE:
482 name = strdup(res->name);
483 res->strings->insert_last(res->strings, name);
484 return name;
485 default:
486 errno = EINVAL;
487 return NULL;
488 }
489 }
490
491 int vici_parse_name_eq(vici_res_t *res, char *name)
492 {
493 switch (res->type)
494 {
495 case VICI_SECTION_START:
496 case VICI_LIST_START:
497 case VICI_KEY_VALUE:
498 return streq(name, res->name) ? 1 : 0;
499 default:
500 return 0;
501 }
502 }
503
504 void* vici_parse_value(vici_res_t *res, int *len)
505 {
506 switch (res->type)
507 {
508 case VICI_LIST_ITEM:
509 case VICI_KEY_VALUE:
510 *len = res->value.len;
511 return res->value.ptr;
512 default:
513 *len = 0;
514 errno = EINVAL;
515 return NULL;
516 }
517 }
518
519 char* vici_parse_value_str(vici_res_t *res)
520 {
521 char *val;
522
523 switch (res->type)
524 {
525 case VICI_LIST_ITEM:
526 case VICI_KEY_VALUE:
527 if (!chunk_printable(res->value, NULL, 0))
528 {
529 errno = EBADMSG;
530 return NULL;
531 }
532 val = strndup(res->value.ptr, res->value.len);
533 res->strings->insert_last(res->strings, val);
534 return val;
535 default:
536 errno = EINVAL;
537 return NULL;
538 }
539 }
540
541 int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
542 vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
543 void *user)
544 {
545 char *name, *list = NULL;
546 void *value;
547 int base, len, ret;
548
549 base = res->level;
550
551 while (TRUE)
552 {
553 switch (vici_parse(res))
554 {
555 case VICI_PARSE_KEY_VALUE:
556 if (res->level == base)
557 {
558 if (kv)
559 {
560 name = vici_parse_name(res);
561 value = vici_parse_value(res, &len);
562 if (name && value)
563 {
564 ret = kv(user, res, name, value, len);
565 if (ret)
566 {
567 return ret;
568 }
569 }
570 }
571 }
572 break;
573 case VICI_PARSE_BEGIN_SECTION:
574 if (res->level++ == base)
575 {
576 if (section)
577 {
578 name = vici_parse_name(res);
579 if (name)
580 {
581 ret = section(user, res, name);
582 if (ret)
583 {
584 return ret;
585 }
586 }
587 }
588 }
589 break;
590 case VICI_PARSE_END_SECTION:
591 if (res->level-- == base)
592 {
593 return 0;
594 }
595 break;
596 case VICI_PARSE_END:
597 res->level = 0;
598 return 0;
599 case VICI_PARSE_BEGIN_LIST:
600 if (res->level == base)
601 {
602 list = vici_parse_name(res);
603 }
604 break;
605 case VICI_PARSE_LIST_ITEM:
606 if (list && li)
607 {
608 value = vici_parse_value(res, &len);
609 if (value)
610 {
611 ret = li(user, res, list, value, len);
612 if (ret)
613 {
614 return ret;
615 }
616 }
617 }
618 break;
619 case VICI_PARSE_END_LIST:
620 if (res->level == base)
621 {
622 list = NULL;
623 }
624 break;
625 case VICI_PARSE_ERROR:
626 res->level = 0;
627 errno = EBADMSG;
628 return 1;
629 }
630 }
631 }
632
633 void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
634 {
635 va_list args;
636 chunk_t value;
637
638 va_start(args, fmt);
639 value = res->message->vget_value(res->message, chunk_empty, fmt, args);
640 va_end(args);
641
642 *len = value.len;
643 return value.ptr;
644 }
645
646 char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...)
647 {
648 va_list args;
649 char *str;
650
651 va_start(args, fmt);
652 str = res->message->vget_str(res->message, def, fmt, args);
653 va_end(args);
654
655 return str;
656 }
657
658 int vici_find_int(vici_res_t *res, int def, char *fmt, ...)
659 {
660 va_list args;
661 int val;
662
663 va_start(args, fmt);
664 val = res->message->vget_int(res->message, def, fmt, args);
665 va_end(args);
666
667 return val;
668 }
669
670 void vici_free_res(vici_res_t *res)
671 {
672 res->strings->destroy_function(res->strings, free);
673 res->message->destroy(res->message);
674 res->enumerator->destroy(res->enumerator);
675 free(res);
676 }
677
678 int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
679 {
680 event_t *event;
681 u_int32_t len;
682 u_int8_t namelen, op;
683 int ret = 1;
684
685 op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
686 namelen = strlen(name);
687 len = htonl(sizeof(op) + sizeof(namelen) + namelen);
688 if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
689 !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
690 !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
691 !conn->stream->write_all(conn->stream, name, namelen))
692 {
693 return 1;
694 }
695
696 conn->mutex->lock(conn->mutex);
697 while (conn->wait == WAIT_IDLE)
698 {
699 conn->cond->wait(conn->cond, conn->mutex);
700 }
701 switch (conn->wait)
702 {
703 case WAIT_SUCCESS:
704 ret = 0;
705 break;
706 case WAIT_READ_ERROR:
707 errno = conn->error;
708 break;
709 case WAIT_FAILURE:
710 default:
711 errno = ENOENT;
712 break;
713 }
714 conn->wait = WAIT_IDLE;
715 conn->mutex->unlock(conn->mutex);
716
717 conn->stream->on_read(conn->stream, on_read, conn);
718
719 if (ret == 0)
720 {
721 conn->mutex->lock(conn->mutex);
722 if (cb)
723 {
724 INIT(event,
725 .name = strdup(name),
726 .cb = cb,
727 .user = user,
728 );
729 event = conn->events->put(conn->events, event->name, event);
730 }
731 else
732 {
733 event = conn->events->remove(conn->events, name);
734 }
735 conn->mutex->unlock(conn->mutex);
736
737 if (event)
738 {
739 free(event->name);
740 free(event);
741 }
742 }
743 return ret;
744 }
745
746 void vici_init()
747 {
748 library_init(NULL, "vici");
749 if (lib->processor->get_total_threads(lib->processor) < 4)
750 {
751 dbg_default_set_level(0);
752 lib->processor->set_threads(lib->processor, 4);
753 dbg_default_set_level(1);
754 }
755 }
756
757 void vici_deinit()
758 {
759 lib->processor->cancel(lib->processor);
760 library_deinit();
761 }