/* * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * * libvici.h is MIT-licensed to simplify reuse, but please note that libvici.c * is not, as it depends on the GPLv2 licensed libstrongswan. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /** * @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 tuple 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 canceled 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 #ifdef __cplusplus extern "C" { #endif /** * Opaque vici connection context. */ 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, int 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 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. * * @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(); #ifdef __cplusplus } #endif #endif /** LIBVICI_H_ @}*/