Return to libvici.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 "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, uint32_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, uint32_t len) 144: { 145: vici_message_t *message; 146: event_t *event; 147: uint8_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: uint32_t len; 202: uint8_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: uint32_t len; 362: uint8_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: uint32_t len; 682: uint8_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: }