strongswan/src/libcharon/plugins/vici/libvici.h

477 lines
15 KiB
C

/*
* 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 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>
#ifdef __cplusplus
extern "C" {
#endif
/**
* 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, 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_ @}*/