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