aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/libhicnctrl/includes
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2019-07-26 23:20:30 +0200
committerMauro Sardara <msardara@cisco.com>2019-07-29 17:13:35 +0200
commit0a1c6b5565e20167d1f1f33a5a8b597f420b18b0 (patch)
tree98c5da8f231fbd3dc2ce6502040e29c8333d9ffc /ctrl/libhicnctrl/includes
parent05ca0aa8f612ee48fb66d4dbebe596b7f1e03181 (diff)
[HICN-252] Add per-application policy framework to hicn-light forwarder
Change-Id: I0531cd7a7de179581295ae34766c81cd9cf3e172 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com> Signed-off-by: Mauro Sardara <msardara@cisco.com> Co-authored-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'ctrl/libhicnctrl/includes')
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt26
l---------ctrl/libhicnctrl/includes/ctrl.h1
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl.h25
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h758
-rwxr-xr-xctrl/libhicnctrl/includes/hicn/ctrl/commands.h411
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/face.h179
6 files changed, 1400 insertions, 0 deletions
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
new file mode 100644
index 000000000..a85489a0c
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set(LIBHICNCTRL_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR} ""
+ CACHE INTERNAL
+ "" FORCE
+)
+
+set(TO_INSTALL_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/face.h
+ PARENT_SCOPE
+) \ No newline at end of file
diff --git a/ctrl/libhicnctrl/includes/ctrl.h b/ctrl/libhicnctrl/includes/ctrl.h
new file mode 120000
index 000000000..646630968
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/ctrl.h
@@ -0,0 +1 @@
+hicn/ctrl.h \ No newline at end of file
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl.h b/ctrl/libhicnctrl/includes/hicn/ctrl.h
new file mode 100644
index 000000000..e61b7a482
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file ctrl.h
+ * \brief Main interface for hICN control library
+ */
+#ifndef HICNCTRL_H
+#define HICNCTRL_H
+
+#include <hicn/ctrl/api.h>
+
+#endif /* HICNCTRL_H */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
new file mode 100644
index 000000000..45efb39f9
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file api.h
+ * \brief hICN control library API
+ *
+ * This API supports basic hICN objects (face, route, punting) plus
+ * implementation-specific ones (connection, listener). Currently, this library
+ * only supports the hicn-light forwarder.
+ *
+ * For each object, a set of methods is provided among:
+ * - CREATE, GET, UPDATE, DELETE, LIST
+ * - CMP, PARSE, SNPRINTF
+ * - additionally, attribute getters and/or setters are provided and denoted
+ * GET( attribute ) and SET( attribute )
+ *
+ * A summary per-object is presented here:
+ *
+ * | CRE GET UPD DEL LST | VAL CMP PAR SNP | attributes [GET/SET]
+ * +------------+---------------------+-------------+---------------------------
+ * | face | O O ! O O | ! ! O | state [-S]
+ * | route | O - ! O O | ! O - |
+ * | punting | ! - ! ! ! | ! ! ! |
+ * +------------+---------------------+-----------------+---------------------------
+ * | cache | | | store [!!], serve [!!]
+ * | strategy | | |
+ * | FIB | | |
+ * | PIT | | |
+ * | WLDR | | |
+ * | MAP-Me | | |
+ * +------------+---------------------+-----------------+---------------------------
+ * | connection | O O ! O O | O O O | state [-S]
+ * | listener | O O ! - O | O O O O |
+ * +------------+---------------------+-----------------+---------------------------
+ *
+ * LEGEND: [O] implemented, [!] in progress / TODO, [-] not supported
+ *
+ * NOTES:
+ *
+ * - Different extensions of the forwarder functionalities bring both new API
+ * calls, and new object attributes. While it is expected that the former will
+ * only raised NACK answers because of unsupported API calls, the latter will
+ * certainly trigger incompatibilities. It is expected that the forwarder
+ * validates the message length and returns a NACK too. In that case, we
+ * provide a set of defines to preserve backwards compatibility. At the
+ * moment, those defines are :
+ *
+ * WITH_POLICY:
+ *
+ */
+
+#ifndef HICNTRL_API
+#define HICNTRL_API
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "face.h"
+#include "util/types.h"
+
+#define LIBHICNCTRL_SUCCESS 0
+#define LIBHICNCTRL_FAILURE -1
+#define LIBHICNCTRL_NOT_IMPLEMENTED -99
+#define LIBHICNCTRL_IS_ERROR(x) (x < 0)
+
+
+/**
+ * This allows to selectively define convenience types to avoid any collision
+ * when using the library in conjunction with other frameworks including similar
+ * defines
+ */
+#ifdef _HICNTRL_NO_DEFS
+#define _HICNTRL_NO_DEF_TYPES
+#define _HICNTRL_NO_DEF_IPADDR
+#define _HICNTRL_NO_DEF_UNIONCAST
+#endif
+
+#ifndef _HICNTRL_NO_DEF_TYPES
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+#endif /* _HICNTRL_NO_DEF_TYPES */
+
+#ifndef _HICNTRL_NO_DEF_IPADDR
+#include "util/ip_address.h"
+#endif /* _HICNTRL_NO_DEF_IPADDR */
+
+#ifndef _HICNTRL_NO_DEF_UNIONCAST
+/* Helper for avoiding warnings about type-punning */
+#define UNION_CAST(x, destType) \
+ (((union {__typeof__(x) a; destType b;})x).b)
+#endif /* _HICNTRL_NO_DEF_UNIONCAST */
+
+/******************************************************************************
+ * Message helper types and aliases
+ ******************************************************************************/
+
+#define foreach_command \
+ _(UNDEFINED) \
+ _(CREATE) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(LIST) \
+ _(SET) \
+ _(N)
+
+typedef enum {
+#define _(x) ACTION_ ## x,
+foreach_command
+#undef _
+} hc_action_t;
+
+/**
+ * \brief hICN control message header
+ */
+typedef struct hc_msg_s hc_msg_t;
+
+/******************************************************************************
+ * Control Data
+ ******************************************************************************/
+
+struct hc_data_s;
+typedef int (*data_callback_t)(struct hc_data_s *, void *);
+
+/**
+ * \brief Holds the results of an hICN control request
+ */
+typedef struct hc_data_s {
+ size_t size;
+ size_t max_size_log;
+ size_t in_element_size;
+ size_t out_element_size;
+ u8 command_id; /**< Expected message type (should give element size) */
+ u8 * buffer;
+ bool complete;
+
+ /* Callbacks */
+ data_callback_t complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data);
+ void * complete_cb_data;
+} hc_data_t;
+
+/**
+ * Create a structure holding the results of an hICN control request.
+ * \result The newly create data structure.
+ */
+hc_data_t *
+hc_data_create(size_t in_element_size, size_t out_element_size);
+
+/**
+ * Free a structure holding the results of an hICN control request.
+ * \param [in] data - The data structure to free.
+ */
+void
+hc_data_free(hc_data_t * data);
+
+/**
+ * \brief Adds many new results at the end of the data structure, eventually
+ * allocating buffer space for it.
+ * \param [in] data - The data structure to which to add elements.
+ * \param [in] elements - The array of elements to add.
+ * \param [in] count - The number of elements to add.
+ * \return Error code
+ *
+ * NOTE: The size of the element should match the one declared at structure
+ * initialization.
+ */
+int
+hc_data_push_many(hc_data_t * data, const void * elements, size_t count);
+
+/**
+ * \brief Adds a new result at the end of the data structure, eventually
+ * allocating buffer space for it.
+ * \param [in] data - The data structure to which to add an element.
+ * \param [in] element - The element to add
+ * \return Error code
+ *
+ * NOTE: The size of the element should match the one declared at structure
+ * initialization.
+ */
+int
+hc_data_push(hc_data_t * data, const void * element);
+
+/**
+ * \brief Configure a callback (along with private data) to be called upon
+ * completion of a request
+ * \param [in] data - hICN control data
+ * \param [in] cb - Callback function
+ * \param [in] cb_data - Callback private data
+ */
+int
+hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data);
+
+/**
+ * \brief Mark the data structure as complete.
+ * \param [in] data - The data structure to which to add an element.
+ * \return The error code resulting from callback execution if any. 0 is
+ * returned if the callback executed successfully, or if no callback were
+ * defined.
+ */
+int
+hc_data_set_complete(hc_data_t * data);
+
+/**
+ * \brief Reset the data structure holding control data
+ * \param [in] data - hICN control data
+ * \return Error code
+ */
+int
+hc_data_reset(hc_data_t * data);
+
+/**
+ * \brief Find en element in the data structure
+ * \param [in] data - The data structure in which to find
+ * \param [in] element - The element to find
+ * \param [out] found - A pointer to the element, or NULL if not found.
+ * \return Error code
+ */
+#define GENERATE_FIND_HEADER(TYPE) \
+int \
+hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
+ hc_ ## TYPE ## _t **found)
+
+#define GENERATE_FIND(TYPE) \
+int \
+hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
+ hc_ ## TYPE ## _t **found) \
+{ \
+ foreach_type(hc_ ## TYPE ## _t, x, data) { \
+ if (hc_ ## TYPE ## _cmp(x, element) >= 0) { \
+ *found = x; \
+ return LIBHICNCTRL_SUCCESS; \
+ } \
+ }; \
+ *found = NULL; /* this is optional */ \
+ return LIBHICNCTRL_SUCCESS; \
+}
+
+/******************************************************************************
+ * Control socket
+ ******************************************************************************/
+
+/* This should be at least equal to the maximum packet size */
+#define RECV_BUFLEN 8192
+
+/**
+ * \brief Holds the state of an hICN control socket
+ */
+typedef struct {
+ char * url;
+ int fd;
+ u32 seq;
+
+ /* Partial receive buffer */
+ u8 buf[RECV_BUFLEN];
+ size_t roff; /**< Read offset */
+ size_t woff; /**< Write offset */
+
+ /*
+ * Because received messages are potentially unbounded in size, we might not
+ * guarantee that we can store a full packet before processing it. We must
+ * implement a very simple state machine remembering the current parsing
+ * status in order to partially process the packet.
+ */
+ size_t remaining;
+ u32 send_id;
+ u32 send_seq;
+ u32 recv_seq;
+} hc_sock_t;
+
+/**
+ * \brief Create an hICN control socket using the specified URL.
+ * \param [in] url - The URL to connect to.
+ * \return an hICN control socket
+ */
+hc_sock_t *
+hc_sock_create_url(const char * url);
+
+/**
+ * \brief Create an hICN control socket using the default connection type.
+ * \return an hICN control socket
+ */
+hc_sock_t *
+hc_sock_create(void);
+
+/**
+ * \brief Frees an hICN control socket
+ */
+void
+hc_sock_free(hc_sock_t *s);
+
+/**
+ * \brief Sets the socket as non-blocking
+ * \return Error code
+ */
+int
+hc_sock_set_nonblocking(hc_sock_t *s);
+
+/**
+ * \brief Connect the socket
+ * \return Error code
+ */
+int
+hc_sock_connect(hc_sock_t *s);
+
+/**
+ * \brief Return the offset and size of available buffer space
+ * \param [in] sock - hICN control socket
+ * \param [out] buffer - Offset in buffer
+ * \param [out] size - Remaining size
+ * \return Error code
+ */
+int
+hc_sock_get_available(hc_sock_t * s, u8 ** buffer, size_t * size);
+
+/**
+ * \brief Write/read iexchance on the control socket (internal helper function)
+ * \param [in] sock - hICN control socket
+ * \param [in] msg - Message to send
+ * \param [in] msglen - Length of the message to send
+ * \return Error code
+ */
+int
+hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen);
+
+/**
+ * \brief Helper for reading socket contents
+ * \param [in] sock - hICN control socket
+ * \param [in] data - Result data buffer
+ * \param [in] parse - Parse function to convert remote types into lib native
+ * types, or NULL not to perform any translation.
+ * \return Error code
+ */
+int
+hc_sock_recv(hc_sock_t * s, hc_data_t * data);
+
+/**
+ * \brief Processing data received by socket
+ * \param [in] sock - hICN control socket
+ * \param [in] data - Result data buffer
+ * \param [in] parse - Parse function to convert remote types into lib native
+ * types, or NULL not to perform any translation.
+ * \return Error code
+ */
+int
+hc_sock_process(hc_sock_t * s, hc_data_t * data,
+ int (*parse)(const u8 * src, u8 * dst));
+
+/**
+ * \brief Reset the state of the sock (eg. to handle a reconnecton)
+ * \param [in] sock - hICN control socket
+ * \return Error code
+ */
+int
+hc_sock_reset(hc_sock_t * s);
+
+/******************************************************************************
+ * Command-specific structures and functions
+ ******************************************************************************/
+
+/*
+ * The following definitions are organized by sections each dealing with a
+ * specific object being manipulated. All follow a similar structure.
+ *
+ * TYPE DEFINITIONS AND ALIASES
+ *
+ * We redefine command struct:
+ * - for uniformization
+ * - to use enum instead of type specifiers more appropriate for packet format
+ * - to use more flexible types such as for manipulating IP addresses
+ * - host endianness
+ * - more intuitive field name, ordering, consistency, and hierarchy removal
+ * - to have command types in between add/list/... commands
+ *
+ * COMMAND IMPLEMENTATION
+ *
+ * All commands return information in a common format
+ *
+ * RETURN DATA FIXME
+ *
+ * \param [out] pdata - Pointer to the structure storing the results of the call
+ * (NULL if no data has been received). If the pointer is NULL, no result will
+ * be stored and only the error code will be exposed to the caller. It is
+ * expected that the caller frees this structure using hc_data_free() after
+ * usage.
+ * \see hc_data_free.
+ *
+ * PARSING
+ *
+ * While this is not made mandatory by the library, the returned data can be
+ * converted to the library's own data structures as described before.
+ *
+ * ITERATORS
+ *
+ * Macros are defined to facilitate iteration on the returned data structures.
+ */
+
+#ifndef SPACES
+#define SPACES(x) x
+#endif
+#ifndef SPACE
+#define SPACE SPACES(1)
+#endif
+#ifndef NULLTERM
+#define NULLTERM 1
+#endif
+
+#define NAME_LEN 16 /* NULL-terminated right ? */
+#ifdef __linux__
+#define INTERFACE_LEN 16
+#endif
+#define MAXSZ_HC_NAME_ NAME_LEN
+#define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM
+
+#define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */
+#define MAXSZ_HC_ID MAXSZ_HC_ID_ + NULLTERM
+
+#define MAXSZ_HC_PROTO_ 8 /* inetX:// */
+#define MAXSZ_HC_PROTO MAXSZ_HC_PROTO_ + NULLTERM
+
+#define MAXSZ_HC_URL4_ MAXSZ_HC_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
+#define MAXSZ_HC_URL6_ MAXSZ_HC_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
+#define MAXSZ_HC_URL_ MAXSZ_HC_URL6_
+#define MAXSZ_HC_URL4 MAXSZ_HC_URL4_ + NULLTERM
+#define MAXSZ_HC_URL6 MAXSZ_HC_URL6_ + NULLTERM
+#define MAXSZ_HC_URL MAXSZ_HC_URL_ + NULLTERM
+
+int hc_url_snprintf(char * s, size_t size, int family,
+ const ip_address_t * ip_address, u16 port);
+
+#define foreach_type(TYPE, VAR, data) \
+ for (TYPE * VAR = (TYPE*)data->buffer; \
+ VAR < (TYPE*)(data->buffer + data->size * data->out_element_size); \
+ VAR++)
+
+/**
+ * New type is defined to reconciliate different enum for add and list.
+ * Also, values not implemented have been removed for clarity.
+ */
+#define foreach_connection_type \
+ _(UNDEFINED) \
+ _(TCP) \
+ _(UDP) \
+ _(HICN) \
+ _(N)
+
+typedef enum {
+#define _(x) CONNECTION_TYPE_ ## x,
+foreach_connection_type
+#undef _
+} hc_connection_type_t;
+
+#define MAXSZ_HC_CONNECTION_TYPE_ 9
+#define MAXSZ_HC_CONNECTION_TYPE MAXSZ_HC_CONNECTION_TYPE_ + NULLTERM
+
+extern const char * connection_type_str[];
+
+hc_connection_type_t
+connection_type_from_str(const char * str);
+
+/* Same order as connection_state_t in hicn/core/connectionState.h */
+#define foreach_connection_state \
+ _(UNDEFINED) \
+ _(DOWN) \
+ _(UP) \
+ _(N)
+
+typedef enum {
+#define _(x) HC_CONNECTION_STATE_ ## x,
+foreach_connection_state
+#undef _
+} hc_connection_state_t;
+
+#define MAXSZ_HC_CONNECTION_STATE_ 9
+#define MAXSZ_HC_CONNECTION_STATE MAXSZ_HC_CONNECTION_STATE_ + NULLTERM
+
+extern const char * connection_state_str[];
+
+typedef int (*HC_PARSE)(const u8 *, u8 *);
+
+/*----------------------------------------------------------------------------*
+ * Listeners
+ *----------------------------------------------------------------------------*/
+
+// FIXME the listener should not require any port for hICN...
+typedef struct {
+ char name[NAME_LEN]; /* K.w */ // XXX clarify what used for
+#ifdef __linux__
+ char interface_name[INTERFACE_LEN]; /* Kr. */
+#endif
+ u32 id;
+ hc_connection_type_t type; /* .rw */
+ int family; /* .rw */
+ ip_address_t local_addr; /* .rw */
+ u16 local_port; /* .rw */
+} hc_listener_t;
+
+int hc_listener_create(hc_sock_t * s, hc_listener_t * listener);
+int hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
+ hc_listener_t ** listener_found);
+int hc_listener_delete(hc_sock_t * s, hc_listener_t * listener);
+int hc_listener_list(hc_sock_t * s, hc_data_t ** pdata);
+
+int hc_listener_validate(const hc_listener_t * listener);
+int hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2);
+int hc_listener_parse(void * in, hc_listener_t * listener);
+
+#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data)
+
+#define MAXSZ_HC_LISTENER_ MAXSZ_HC_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_
+#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM
+
+GENERATE_FIND_HEADER(listener);
+
+int hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener);
+
+/*----------------------------------------------------------------------------*
+ * Connections
+ *----------------------------------------------------------------------------*/
+
+typedef struct {
+ u32 id; /* Kr. */
+ char name[NAME_LEN]; /* K.w */
+ hc_connection_type_t type; /* .rw */
+ int family; /* .rw */
+ ip_address_t local_addr; /* .rw */
+ u16 local_port; /* .rw */
+ ip_address_t remote_addr; /* .rw */
+ u16 remote_port; /* .rw */
+ hc_connection_state_t admin_state; /* .rw */
+#ifdef WITH_POLICY
+ policy_tags_t tags; /* .rw */
+#endif /* WITH_POLICY */
+ hc_connection_state_t state; /* .r. */
+} hc_connection_t;
+
+
+int hc_connection_create(hc_sock_t * s, hc_connection_t * connection);
+int hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
+ hc_connection_t ** connection_found);
+int hc_connection_update_by_id(hc_sock_t * s, int hc_connection_id,
+ hc_connection_t * connection);
+int hc_connection_update(hc_sock_t * s, hc_connection_t * connection_current,
+ hc_connection_t * connection_updated);
+int hc_connection_delete(hc_sock_t * s, hc_connection_t * connection);
+/*
+int hc_connection_remove_by_id(hc_sock_t * s, char * name);
+int hc_connection_remove_by_name(hc_sock_t * s, char * name);
+*/
+int hc_connection_list(hc_sock_t * s, hc_data_t ** pdata);
+
+int hc_connection_validate(const hc_connection_t * connection);
+int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2);
+int hc_connection_parse(void * in, hc_connection_t * connection);
+
+#ifdef WITH_POLICY
+int hc_connection_set_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+#endif /* WITH_POLICY */
+
+#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data)
+
+#define MAXSZ_HC_CONNECTION_ MAXSZ_HC_CONNECTION_STATE_ + \
+ 2 * MAXSZ_HC_URL_ + MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3)
+#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM
+
+GENERATE_FIND_HEADER(connection);
+
+int hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection);
+
+/*----------------------------------------------------------------------------*
+ * Routes
+ *----------------------------------------------------------------------------*/
+
+typedef struct {
+ u8 face_id; /* Kr. */
+ int family; /* Krw */
+ ip_address_t remote_addr; /* krw */
+ u8 len; /* krw */
+ u16 cost; /* .rw */
+} hc_route_t;
+
+int hc_route_parse(void * in, hc_route_t * route);
+
+int hc_route_create(hc_sock_t * s, hc_route_t * route);
+int hc_route_delete(hc_sock_t * s, hc_route_t * route);
+int hc_route_list(hc_sock_t * s, hc_data_t ** pdata);
+
+#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
+
+#define MAX_FACE_ID 255
+#define MAXSZ_FACE_ID 3
+#define MAX_COST 65535
+#define MAXSZ_COST 5
+#define MAX_LEN 255
+#define MAXSZ_LEN 3
+
+#define MAXSZ_HC_ROUTE_ MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN
+#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM
+
+int hc_route_snprintf(char * s, size_t size, hc_route_t * route);
+
+/*----------------------------------------------------------------------------*
+ * Faces
+ *
+ * A face is an abstraction introduced by the control library to abstract the
+ * forwarder implementation details. It encompasses connections and listeners
+ * and ensures the right dependencies are enforced, eg that we always have a
+ * listener when a connection is created.
+ *
+ *----------------------------------------------------------------------------*/
+
+typedef struct {
+ u32 id;
+ char name[NAME_LEN];
+ face_t face; // or embed ?
+ //face_id_t parent; /* Pointer from connection to listener */
+} hc_face_t;
+
+/**
+ * \brief Create a face
+ * \param [in] s - hICN socket
+ * \param [in,out] face - Parameters of the face to create
+ * \return Error code
+ *
+ * The face parameters will be updated with the face ID.
+ */
+int hc_face_create(hc_sock_t * s, hc_face_t * face);
+int hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found);
+int hc_face_delete(hc_sock_t * s, hc_face_t * face);
+int hc_face_list(hc_sock_t * s, hc_data_t ** pdata);
+
+#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data)
+
+#define MAXSZ_HC_FACE_ 0
+#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM
+
+int hc_face_snprintf(char * s, size_t size, hc_face_t * face);
+
+/////// XXX XXX XXX XXX missing face api functions, cf punting now...
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+typedef struct {
+ u8 face_id; /* Kr. */ // XXX listener id, could be NULL for all ?
+ int family; /* Krw */
+ ip_address_t prefix; /* krw */
+ u8 prefix_len; /* krw */
+} hc_punting_t;
+
+int hc_punting_create(hc_sock_t * s, hc_punting_t * punting);
+int hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found);
+int hc_punting_delete(hc_sock_t * s, hc_punting_t * punting);
+int hc_punting_list(hc_sock_t * s, hc_data_t ** pdata);
+
+int hc_punting_validate(const hc_punting_t * punting);
+int hc_punting_cmp(const hc_punting_t * c1, const hc_punting_t * c2);
+int hc_punting_parse(void * in, hc_punting_t * punting);
+
+#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data)
+
+#define MAXSZ_HC_PUNTING_ 0
+#define MAXSZ_HC_PUNTING MAXSZ_HC_PUNTING_ + NULLTERM
+
+GENERATE_FIND_HEADER(punting);
+
+int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting);
+
+
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
+
+int hc_cache_set_store(hc_sock_t * s, int enabled);
+int hc_cache_set_serve(hc_sock_t * s, int enabled);
+
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+#define MAXSZ_STRATEGY_NAME 255
+
+typedef struct {
+ char name[MAXSZ_STRATEGY_NAME];
+} hc_strategy_t;
+
+int hc_strategy_list(hc_sock_t * s, hc_data_t ** data);
+
+#define foreach_strategy(VAR, data) foreach_type(hc_strategy_t, VAR, data)
+
+#define MAXSZ_HC_STRATEGY_ MAXSZ_STRATEGY_NAME
+#define MAXSZ_HC_STRATEGY MAXSZ_HC_STRATEGY_ + NULLTERM
+
+int hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy);
+
+// per prefix
+int hc_strategy_set(hc_sock_t * s /* XXX */);
+
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+// per connection
+int hc_wldr_set(hc_sock_t * s /* XXX */);
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+int hc_mapme_set(hc_sock_t * s, int enabled);
+int hc_mapme_set_discovery(hc_sock_t * s, int enabled);
+int hc_mapme_set_timescale(hc_sock_t * s, double timescale);
+int hc_mapme_set_retx(hc_sock_t * s, double timescale);
+
+/*----------------------------------------------------------------------------*
+ * Policies
+ *----------------------------------------------------------------------------*/
+
+#ifdef WITH_POLICY
+
+typedef struct {
+ int family; /* Krw */
+ ip_address_t remote_addr; /* krw */
+ u8 len; /* krw */
+ policy_t policy; /* .rw */
+} hc_policy_t;
+
+int hc_policy_parse(void * in, hc_policy_t * policy);
+
+int hc_policy_create(hc_sock_t * s, hc_policy_t * policy);
+int hc_policy_delete(hc_sock_t * s, hc_policy_t * policy);
+int hc_policy_list(hc_sock_t * s, hc_data_t ** pdata);
+
+#define foreach_policy(VAR, data) foreach_type(hc_policy_t, VAR, data)
+
+/* TODO */
+#define MAXSZ_HC_POLICY_ 0
+#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM
+
+int hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy);
+
+#endif /* WITH_POLICY */
+
+#endif /* HICNTRL_API */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
new file mode 100755
index 000000000..1d07c9b72
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file commands.h
+ * @brief All hicn-light commands: 14 in total.
+ *
+ * Header and payload in binary format.
+ */
+
+#ifndef commands_h
+#define commands_h
+
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef WITH_POLICY
+#include "util/policy.h"
+#endif /* WITH_POLICY */
+
+typedef struct in6_addr ipv6_addr_t;
+typedef uint32_t ipv4_addr_t;
+
+union commandAddr {
+ ipv4_addr_t ipv4;
+ ipv6_addr_t ipv6;
+};
+
+typedef enum {
+ REQUEST_LIGHT = 0xc0, // this is a command
+ RESPONSE_LIGHT,
+ ACK_LIGHT,
+ NACK_LIGHT,
+ LAST_MSG_TYPE_VALUE
+} message_type;
+
+typedef enum {
+ ADD_LISTENER = 0,
+ ADD_CONNECTION,
+ LIST_CONNECTIONS,
+ ADD_ROUTE,
+ LIST_ROUTES,
+ REMOVE_CONNECTION,
+ REMOVE_ROUTE,
+ CACHE_STORE,
+ CACHE_SERVE,
+ CACHE_CLEAR,
+ SET_STRATEGY,
+ SET_WLDR,
+ ADD_PUNTING,
+ LIST_LISTENERS,
+ MAPME_ENABLE,
+ MAPME_DISCOVERY,
+ MAPME_TIMESCALE,
+ MAPME_RETX,
+ CONNECTION_SET_ADMIN_STATE,
+#ifdef WITH_POLICY
+ ADD_POLICY,
+ LIST_POLICIES,
+ REMOVE_POLICY,
+ UPDATE_CONNECTION,
+#endif /* WITH_POLICY */
+ REMOVE_LISTENER,
+ LAST_COMMAND_VALUE
+} command_id;
+
+typedef enum {
+ ADDR_INET = 1,
+ ADDR_INET6,
+ ADDR_LINK,
+ ADDR_IFACE,
+ ADDR_UNIX /* PF_UNIX */
+} address_type;
+
+typedef enum {
+ UDP_CONN,
+ TCP_CONN,
+ GRE_CONN, // not implemented
+ HICN_CONN
+} connection_type;
+
+typedef enum { ACTIVATE_ON, ACTIVATE_OFF } activate_type;
+
+//========== HEADER ==========
+
+typedef struct {
+ uint8_t messageType;
+ uint8_t commandID;
+ uint16_t length; // tells the number of structures in the payload
+ uint32_t seqNum;
+} header_control_message;
+// for the moment has to be at least 8 bytes
+
+// SIZE=8
+
+//========== [00] ADD LISTENER ==========
+
+typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
+
+typedef struct {
+ char symbolic[16];
+ char interfaceName[16];
+ union commandAddr address;
+ uint16_t port;
+ // uint16_t etherType;
+ uint8_t addressType;
+ uint8_t listenerMode;
+ uint8_t connectionType;
+} add_listener_command;
+
+// SIZE=40
+
+//========== [01] ADD CONNECTION ==========
+
+typedef struct {
+ char symbolic[16];
+ union commandAddr remoteIp;
+ union commandAddr localIp;
+ uint16_t remotePort;
+ uint16_t localPort;
+ uint8_t ipType;
+ uint8_t connectionType;
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+} add_connection_command;
+
+// SIZE=56
+
+//========== [02] LIST CONNECTIONS ==========
+
+typedef enum {
+ CONN_GRE,
+ CONN_TCP,
+ CONN_UDP,
+ CONN_MULTICAST,
+ CONN_L2,
+ CONN_HICN
+} list_connections_type;
+
+typedef enum {
+ IFACE_UP = 0,
+ IFACE_DOWN = 1,
+ IFACE_UNKNOWN = 2 // not used actually
+} connection_state;
+
+typedef struct {
+ add_connection_command connectionData;
+ uint32_t connid;
+ uint8_t state;
+#ifdef WITH_UPDATE
+ char connectionName[16];
+#endif /* WITH_UPDATE */
+} list_connections_command;
+
+// SIZE=64
+
+//========== [03] ADD ROUTE ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+} add_route_command;
+
+// SIZE=36
+
+//========== [04] LIST ROUTE ==========
+
+typedef struct {
+ union commandAddr address;
+ uint32_t connid;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+} list_routes_command;
+
+// SIZE=24
+
+//========== [05] REMOVE CONNECTION ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+} remove_connection_command;
+
+//========== [06] REMOVE LISTENER ==========
+typedef struct {
+ char symbolicOrListenerid[16];
+} remove_listener_command;
+
+// SIZE=16
+
+//========== [06] REMOVE ROUTE ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+} remove_route_command;
+
+// SIZE=36
+
+//========== [07] CACHE STORE ==========
+
+typedef struct {
+ uint8_t activate;
+} cache_store_command;
+
+// SIZE=1
+
+//========== [08] CACHE SERVE ==========
+
+typedef struct {
+ uint8_t activate;
+} cache_serve_command;
+
+// SIZE=1
+
+//========== [09] SET STRATEGY ==========
+
+typedef enum {
+ SET_STRATEGY_LOADBALANCER,
+ SET_STRATEGY_RANDOM,
+ SET_STRATEGY_RANDOM_PER_DASH_SEGMENT,
+ SET_STRATEGY_LOADBALANCER_WITH_DELAY,
+ SET_STRATEGY_LOADBALANCER_BY_RATE,
+ SET_STRATEGY_LOADBALANCER_BEST_ROUTE,
+ LAST_STRATEGY_VALUE
+} strategy_type;
+
+typedef struct {
+ union commandAddr address;
+ uint8_t strategyType;
+ uint8_t addressType;
+ uint8_t len;
+} set_strategy_command;
+
+// SIZE=20
+
+//========== [11] SET WLDR ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ uint8_t activate;
+} set_wldr_command;
+
+// SIZE=17
+
+//========== [12] ADD PUNTING ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+} add_punting_command;
+
+// SIZE=36
+
+//========== [13] LIST LISTENER ==========
+
+typedef struct {
+ union commandAddr address;
+#ifdef WITH_UPDATE
+ char listenerName[16];
+ char interfaceName[16];
+#endif /* WITH_UPDATE */
+ uint32_t connid;
+ uint16_t port;
+ uint8_t addressType;
+ uint8_t encapType;
+} list_listeners_command;
+
+// SIZE=56
+
+//========== [14] MAPME ==========
+
+// (enable/discovery/timescale/retx)
+
+typedef struct {
+ uint8_t activate;
+} mapme_activator_command;
+
+// SIZE=1
+
+typedef struct {
+ uint32_t timePeriod;
+} mapme_timing_command;
+
+// SIZE=1
+
+//========== NEW COMMANDS ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ uint8_t admin_state;
+} connection_set_admin_state_command;
+
+#ifdef WITH_POLICY
+
+typedef struct {
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+ policy_t policy;
+} add_policy_command;
+
+typedef struct {
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+ policy_t policy;
+} list_policies_command;
+
+typedef struct {
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+} remove_policy_command;
+
+typedef struct {
+ char symbolicOrConnid[16];
+ uint8_t admin_state;
+ policy_tags_t tags;
+} update_connection_command;
+
+#endif /* WITH_POLICY */
+
+//===== size of commands ======
+// REMINDER: when a new_command is added, the following switch has to be
+// updated.
+static inline int payloadLengthDaemon(command_id id) {
+ switch (id) {
+ case ADD_LISTENER:
+ return sizeof(add_listener_command);
+ case ADD_CONNECTION:
+ return sizeof(add_connection_command);
+ case LIST_CONNECTIONS:
+ return 0; // list connections: payload always 0
+ case ADD_ROUTE:
+ return sizeof(add_route_command);
+ case LIST_ROUTES:
+ return 0; // list routes: payload always 0
+ case REMOVE_CONNECTION:
+ return sizeof(remove_connection_command);
+ case REMOVE_LISTENER:
+ return sizeof(remove_listener_command);
+ case REMOVE_ROUTE:
+ return sizeof(remove_route_command);
+ case CACHE_STORE:
+ return sizeof(cache_store_command);
+ case CACHE_SERVE:
+ return sizeof(cache_serve_command);
+ case CACHE_CLEAR:
+ return 0; // cache clear
+ case SET_STRATEGY:
+ return sizeof(set_strategy_command);
+ case SET_WLDR:
+ return sizeof(set_wldr_command);
+ case ADD_PUNTING:
+ return sizeof(add_punting_command);
+ case LIST_LISTENERS:
+ return 0; // list listeners: payload always 0
+ case MAPME_ENABLE:
+ return sizeof(mapme_activator_command);
+ case MAPME_DISCOVERY:
+ return sizeof(mapme_activator_command);
+ case MAPME_TIMESCALE:
+ return sizeof(mapme_timing_command);
+ case MAPME_RETX:
+ return sizeof(mapme_timing_command);
+ case CONNECTION_SET_ADMIN_STATE:
+ return sizeof(connection_set_admin_state_command);
+#ifdef WITH_POLICY
+ case ADD_POLICY:
+ return sizeof(add_policy_command);
+ case LIST_POLICIES:
+ return 0; // list policies: payload always 0
+ case REMOVE_POLICY:
+ return sizeof(remove_policy_command);
+ case UPDATE_CONNECTION:
+ return sizeof(update_connection_command);
+#endif /* WITH_POLICY */
+ case LAST_COMMAND_VALUE:
+ return 0;
+ default:
+ return 0;
+ }
+}
+#endif
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
new file mode 100644
index 000000000..2856ce89b
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file face.h
+ * \brief Face abstraction
+ */
+#ifndef HICN_FACE_H
+#define HICN_FACE_H
+
+#ifndef SPACES
+#define SPACES(x) x
+#endif
+#ifndef SPACE
+#define SPACE 1
+#endif
+#ifndef NULLTERM
+#define NULLTERM 1
+#endif
+
+#ifndef _HICNTRL_NO_DEF_IPADDR
+#include "util/ip_address.h"
+#endif /* _HICNTRL_NO_DEF_IPADDR */
+#include "util/policy.h"
+#include "util/types.h"
+
+
+/* Netdevice type */
+
+#include <net/if.h> // IFNAMSIZ
+
+#define foreach_netdevice_type \
+ _(UNDEFINED) \
+ _(WIRED) \
+ _(WIFI) \
+ _(CELLULAR) \
+ _(VPN) \
+ _(N)
+
+#define MAXSZ_NETDEVICE_TYPE_ 9
+#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM
+
+typedef enum {
+#define _(x) NETDEVICE_TYPE_ ## x,
+foreach_netdevice_type
+#undef _
+} netdevice_type_t;
+
+extern const char * netdevice_type_str[];
+
+
+/* Netdevice */
+
+typedef struct {
+ u32 index;
+ char name[IFNAMSIZ];
+} netdevice_t;
+
+#define NETDEVICE_UNDEFINED_INDEX 0
+
+/* Face state */
+
+#define foreach_face_state \
+ _(UNDEFINED) \
+ _(PENDING_UP) \
+ _(UP) \
+ _(PENDING_DOWN) \
+ _(DOWN) \
+ _(ERROR) \
+ _(N)
+
+#define MAXSZ_FACE_STATE_ 12
+#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1
+
+typedef enum {
+#define _(x) FACE_STATE_ ## x,
+foreach_face_state
+#undef _
+} face_state_t;
+
+extern const char * face_state_str[];
+
+
+/* Face type */
+
+#define foreach_face_type \
+ _(UNDEFINED) \
+ _(HICN) \
+ _(HICN_LISTENER) \
+ _(TCP) \
+ _(TCP_LISTENER) \
+ _(UDP) \
+ _(UDP_LISTENER) \
+ _(N)
+
+#define MAXSZ_FACE_TYPE_ 13
+#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1
+
+typedef enum {
+#define _(x) FACE_TYPE_ ## x,
+foreach_face_type
+#undef _
+} face_type_t;
+
+extern const char * face_type_str[];
+
+#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_IP_ADDRESS + 2 * MAXSZ_PORT + 9
+#define MAXSZ_FACE MAXSZ_FACE_ + 1
+
+/* Face */
+
+typedef union {
+ int family; /* To access family independently of face type */
+ struct {
+ int family;
+ netdevice_t netdevice;
+ ip_address_t local_addr;
+ ip_address_t remote_addr;
+ } hicn;
+ struct {
+ int family;
+ ip_address_t local_addr;
+ u16 local_port;
+ ip_address_t remote_addr;
+ u16 remote_port;
+ } tunnel;
+} face_params_t;
+
+typedef struct {
+ face_type_t type;
+ face_params_t params;
+ face_state_t admin_state;
+ face_state_t state;
+#ifdef WITH_POLICY
+ policy_tags_t tags; /**< \see policy_tag_t */
+#endif /* WITH_POLICY */
+} face_t;
+
+int face_initialize(face_t * face);
+int face_initialize_udp(face_t * face, const ip_address_t * local_addr,
+ u16 local_port, const ip_address_t * remote_addr, u16 remote_port,
+ int family);
+int face_initialize_udp_sa(face_t * face,
+ const struct sockaddr * local_addr, const struct sockaddr * remote_addr);
+
+face_t * face_create();
+face_t * face_create_udp(const ip_address_t * local_addr, u16 local_port,
+ const ip_address_t * remote_addr, u16 remote_port, int family);
+face_t * face_create_udp_sa(const struct sockaddr * local_addr,
+ const struct sockaddr * remote_addr);
+
+int face_finalize(face_t * face);
+
+void face_free(face_t * face);
+
+typedef int (*face_cmp_t)(const face_t * f1, const face_t * f2);
+
+int face_cmp(const face_t * f1, const face_t * f2);
+hash_t face_hash(const face_t * face);
+
+size_t
+face_snprintf(char * s, size_t size, const face_t * face);
+
+int face_set_tags(face_t * face, policy_tags_t tags);
+
+#endif /* HICN_FACE_H */
+