summaryrefslogtreecommitdiffstats
path: root/ctrl/libhicnctrl
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/libhicnctrl')
-rw-r--r--ctrl/libhicnctrl/CMakeLists.txt88
-rw-r--r--ctrl/libhicnctrl/cmake/packaging.cmake (renamed from ctrl/libhicnctrl/cmake/Modules/Packaging.cmake)10
-rw-r--r--ctrl/libhicnctrl/examples/create_face.c191
-rw-r--r--ctrl/libhicnctrl/examples/update_priority.c61
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt17
-rw-r--r--ctrl/libhicnctrl/includes/ctrl.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h495
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/face.h206
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h427
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h (renamed from ctrl/libhicnctrl/includes/hicn/ctrl/commands.h)14
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h27
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt147
-rw-r--r--ctrl/libhicnctrl/src/api.c1735
-rw-r--r--ctrl/libhicnctrl/src/api_private.h223
-rw-r--r--ctrl/libhicnctrl/src/cli.c883
-rw-r--r--ctrl/libhicnctrl/src/face.c430
-rw-r--r--ctrl/libhicnctrl/src/hicnctrl.c805
-rw-r--r--ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in8
-rw-r--r--ctrl/libhicnctrl/src/modules/CMakeLists.txt69
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_api.c2278
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.c33
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.h95
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c3111
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_plugin_api.c895
-rw-r--r--ctrl/libhicnctrl/src/route.c102
-rw-r--r--ctrl/libhicnctrl/src/util/hash.h379
27 files changed, 6909 insertions, 5824 deletions
diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt
index 22f81401f..bf5ffd699 100644
--- a/ctrl/libhicnctrl/CMakeLists.txt
+++ b/ctrl/libhicnctrl/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -11,50 +11,65 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Project and cmake version
+##############################################################
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-
project(libhicnctrl)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif()
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
-include(BuildMacros)
-
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED ON)
-
-set(CMAKE_MACOSX_RPATH ON)
-
+##############################################################
+# Libs and Bins names
+##############################################################
set(LIBHICNCTRL hicnctrl)
-
set(LIBHICNCTRL ${LIBHICNCTRL} CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static CACHE INTERNAL "" FORCE)
set(HICNCTRL hicnctrl CACHE INTERNAL "" FORCE)
-set(LIBHICNCTRL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE)
+set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
+set(LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules)
+
+
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+
+##############################################################
+# C Standard
+##############################################################
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+
+set(CMAKE_MACOSX_RPATH ON)
+
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- find_package_wrapper(HicnPlugin REQUIRED)
- endif()
+ include(CommonSetup)
- find_package_wrapper(Libhicn REQUIRED)
- list(APPEND HICN_LIBRARIES ${LIBHICN_SHARED})
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
- set(HICN_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS})
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
@@ -65,36 +80,21 @@ else()
list(APPEND DEPENDENCIES
${LIBHICN_STATIC}
)
- elseif (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- set(
- HICN_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
- )
-
- list(APPEND DEPENDENCIES
- hicn_plugin
- ${SAFE_VAPI_SHARED}
- )
else ()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
${LIBHICN_SHARED}
)
endif ()
-
endif()
-set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
-set (LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules)
+##############################################################
+# Include directories
+##############################################################
add_subdirectory(includes)
add_subdirectory(src)
-include(Packaging)
-
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
+ make_packages()
endif()
diff --git a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake b/ctrl/libhicnctrl/cmake/packaging.cmake
index 2851375be..74905d6c4 100644
--- a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
+++ b/ctrl/libhicnctrl/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -31,7 +31,7 @@ set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES
)
set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} (>= stable_version)"
+ "${LIBHICNCTRL_COMPONENT} (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
@@ -41,16 +41,16 @@ set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES
)
set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} >= stable_version"
+ "${LIBHICNCTRL_COMPONENT} = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBHICNCTRL_COMPONENT_MODULES}_DEB_DEPENDENCIES
- "hicn-plugin (>= stable_version)"
+ "hicn-plugin (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBHICNCTRL_COMPONENT_MODULES}_RPM_DEPENDENCIES
- "hicn-plugin >= stable_version"
+ "hicn-plugin = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c
index 5f92f5906..ebd451de1 100644
--- a/ctrl/libhicnctrl/examples/create_face.c
+++ b/ctrl/libhicnctrl/examples/create_face.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -22,125 +22,122 @@
*/
#include <stdlib.h>
-#include <sys/types.h> // getifaddrs
-#include <ifaddrs.h> // getifaddrs
+#include <sys/types.h> // getifaddrs
+#include <ifaddrs.h> // getifaddrs
#include <stdio.h>
-#include <string.h> /* for strncpy */
-#include <sys/socket.h> // socket
-#include <sys/ioctl.h> // ioctl
+#include <sys/socket.h> // socket
+#include <sys/ioctl.h> // ioctl
#include <unistd.h>
#include <hicn/ctrl.h>
#include <hicn/util/log.h>
-int get_local_info(char * if_name, ip_address_t * local_ip) {
- struct ifaddrs *addrs;
- struct ifreq ifr = {
- .ifr_addr.sa_family = AF_INET,
- };
- int ret = -1;
-
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
-
- getifaddrs(&addrs);
-
- for (struct ifaddrs * tmp = addrs; tmp; tmp = tmp->ifa_next) {
- if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET)
- continue;
- if (strcmp(tmp->ifa_name, "lo") == 0)
- continue;
- snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name);
-
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name);
- if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
- //perror("ioctl");
- continue;
- }
-
- *local_ip = IP_ADDRESS_EMPTY;
- local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
- if (ip_address_empty(local_ip))
- continue;
-
- ret = 0;
- break;
- }
-
- freeifaddrs(addrs);
- close(fd);
- return ret;
-}
+int get_local_info(char *if_name, ip_address_t *local_ip) {
+ struct ifaddrs *addrs;
+ struct ifreq ifr = {
+ .ifr_addr.sa_family = AF_INET,
+ };
+ int ret = -1;
-int main() {
- char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1";
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
- ip_address_t local_ip;
- ip_address_t remote_ip;
- char if_name[IFNAMSIZ];
+ getifaddrs(&addrs);
- /* Retrieving local info */
+ for (struct ifaddrs *tmp = addrs; tmp; tmp = tmp->ifa_next) {
+ if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET) continue;
+ if (strcmp(tmp->ifa_name, "lo") == 0) continue;
+ snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name);
- if (get_local_info(if_name, &local_ip) < 0) {
- DEBUG("Error getting local information");
- goto ERR_INIT;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name);
+ if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
+ // perror("ioctl");
+ continue;
}
- char local_ip_str[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip, AF_INET);
- DEBUG("Local information :");
- DEBUG(" - Interface name : %s", if_name);
- DEBUG(" - IP address : %s", local_ip_str);
+ *local_ip = IP_ADDRESS_EMPTY;
+ local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+ if (ip_address_empty(local_ip)) continue;
- if (ip_address_pton (remote_ip_str, &remote_ip) < 0){
- DEBUG("Error parsing remote IP address");
- goto ERR_INIT;
- }
+ ret = 0;
+ break;
+ }
+
+ freeifaddrs(addrs);
+ close(fd);
+ return ret;
+}
- /* Filling face information */
- hc_face_t face = {
- .face = {
- .type = FACE_TYPE_UDP,
- .family = AF_INET,
- .local_addr = local_ip,
- .remote_addr = remote_ip,
- .local_port = 6000,
- .remote_port = 6000,
- .admin_state = FACE_STATE_UNDEFINED,
- .state = FACE_STATE_UNDEFINED,
+int main() {
+ char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1";
+
+ ip_address_t local_ip;
+ ip_address_t remote_ip;
+ char if_name[IFNAMSIZ];
+
+ /* Retrieving local info */
+
+ if (get_local_info(if_name, &local_ip) < 0) {
+ DEBUG("Error getting local information");
+ goto ERR_INIT;
+ }
+
+ char local_ip_str[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip, AF_INET);
+ DEBUG("Local information :");
+ DEBUG(" - Interface name : %s", if_name);
+ DEBUG(" - IP address : %s", local_ip_str);
+
+ if (ip_address_pton(remote_ip_str, &remote_ip) < 0) {
+ DEBUG("Error parsing remote IP address");
+ goto ERR_INIT;
+ }
+
+ /* Filling face information */
+ hc_face_t face = {
+ .face =
+ {
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET,
+ .local_addr = local_ip,
+ .remote_addr = remote_ip,
+ .local_port = 6000,
+ .remote_port = 6000,
+ .admin_state = FACE_STATE_UNDEFINED,
+ .state = FACE_STATE_UNDEFINED,
#ifdef WITH_POLICY
- .priority = 0,
- .tags = POLICY_TAGS_EMPTY,
+ .priority = 0,
+ .tags = POLICY_TAGS_EMPTY,
#endif /* WITH_POLICY */
- },
- };
- if (netdevice_set_name(&face.face.netdevice, if_name) < 0) {
- DEBUG("Error setting face netdevice name");
- goto ERR_INIT;
- }
+ },
+ };
+ if (netdevice_set_name(&face.face.netdevice, if_name) < 0) {
+ DEBUG("Error setting face netdevice name");
+ goto ERR_INIT;
+ }
- /* Connecting to socket and creating face */
+ /* Connecting to socket and creating face */
- hc_sock_t * socket = hc_sock_create();
- if (!socket){
- DEBUG("Error creating libhicnctrl socket");
- goto ERR_SOCK;
- }
+ hc_sock_t *socket = hc_sock_create();
+ if (!socket) {
+ DEBUG("Error creating libhicnctrl socket");
+ goto ERR_SOCK;
+ }
- if (hc_sock_connect(socket) < 0){
- DEBUG("Error connecting to forwarder");
- goto ERR;
- }
+ if (hc_sock_connect(socket) < 0) {
+ DEBUG("Error connecting to forwarder");
+ goto ERR;
+ }
- if (hc_face_create(socket, &face) < 0){
- DEBUG("Error creating face");
- goto ERR;
- }
+ if (hc_face_create(socket, &face) < 0) {
+ DEBUG("Error creating face");
+ goto ERR;
+ }
- DEBUG("Face created successfully");
+ DEBUG("Face created successfully");
ERR:
- hc_sock_free(socket);
+ hc_sock_free(socket);
ERR_SOCK:
ERR_INIT:
- return 0;
+ return 0;
}
diff --git a/ctrl/libhicnctrl/examples/update_priority.c b/ctrl/libhicnctrl/examples/update_priority.c
index d350f71c9..bbe174c2f 100644
--- a/ctrl/libhicnctrl/examples/update_priority.c
+++ b/ctrl/libhicnctrl/examples/update_priority.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -24,37 +24,36 @@
#include <hicn/ctrl.h>
#include <hicn/util/log.h>
-int main(int argc, char **argv)
-{
- if (argc != 3) {
- fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- unsigned face_id = atoi(argv[1]);
- unsigned priority = atoi(argv[2]);
- char face_id_s[SYMBOLIC_NAME_LEN];
-
- hc_sock_t * socket = hc_sock_create();
- if (!socket){
- DEBUG("Error creating libhicnctrl socket");
- goto ERR_SOCK;
- }
-
- if (hc_sock_connect(socket) < 0){
- DEBUG("Error connecting to forwarder");
- goto ERR;
- }
-
- snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id);
- if (hc_face_set_priority(socket, face_id_s, priority) < 0) {
- DEBUG("Error setting face priority");
- goto ERR;
- }
-
- DEBUG("Face priority updated successfully");
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ unsigned face_id = atoi(argv[1]);
+ unsigned priority = atoi(argv[2]);
+ char face_id_s[SYMBOLIC_NAME_LEN];
+
+ hc_sock_t *socket = hc_sock_create();
+ if (!socket) {
+ DEBUG("Error creating libhicnctrl socket");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(socket) < 0) {
+ DEBUG("Error connecting to forwarder");
+ goto ERR;
+ }
+
+ snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id);
+ if (hc_face_set_priority(socket, face_id_s, priority) < 0) {
+ DEBUG("Error setting face priority");
+ goto ERR;
+ }
+
+ DEBUG("Face priority updated successfully");
ERR:
- hc_sock_free(socket);
+ hc_sock_free(socket);
ERR_SOCK:
- return 0;
+ return 0;
}
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
index 50cfa4ad5..1a90690a4 100644
--- a/ctrl/libhicnctrl/includes/CMakeLists.txt
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -11,17 +11,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(LIBHICNCTRL_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR} ""
+##############################################################
+# Public headers directory
+##############################################################
+set(Libhicnctrl_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
CACHE INTERNAL
"" FORCE
)
+
+##############################################################
+# To install header files
+##############################################################
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
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light-ng.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h
PARENT_SCOPE
)
diff --git a/ctrl/libhicnctrl/includes/ctrl.h b/ctrl/libhicnctrl/includes/ctrl.h
index e61b7a482..477afd152 100644
--- a/ctrl/libhicnctrl/includes/ctrl.h
+++ b/ctrl/libhicnctrl/includes/ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl.h b/ctrl/libhicnctrl/includes/hicn/ctrl.h
index e61b7a482..477afd152 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index b5a968800..8a59cf4d8 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -67,15 +67,24 @@
#include <stdbool.h>
#include <stdint.h>
+#include <stddef.h> // object_offset_t
#include <hicn/util/ip_address.h>
-#include <hicn/ctrl/commands.h>
-#include "face.h"
+#include <hicn/face.h>
+#include <hicn/strategy.h>
+/*
+ * This has to be common between hicn-light and hicn-plugin. We now we keep the
+ * minimum of the two
+ */
+#define SYMBOLIC_NAME_LEN 16
#define HICN_DEFAULT_PORT 9695
#define HOTFIXMARGIN 0
+#define INVALID_FACE_ID ~0
+#define INVALID_NETDEVICE_ID ~0
+
/**
* \brief Defines the default size for the allocated data arrays holding the
* results of API calls.
@@ -99,26 +108,70 @@
* Message helper types and aliases
******************************************************************************/
-#define foreach_command \
- _(UNDEFINED) \
- _(CREATE) \
- _(UPDATE) \
- _(DELETE) \
- _(LIST) \
- _(SET) \
+/* Action */
+
+#define foreach_action \
+ _(UNDEFINED) \
+ _(CREATE) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(LIST) \
+ _(SET) \
+ _(SERVE) \
+ _(STORE) \
+ _(CLEAR) \
_(N)
typedef enum {
#define _(x) ACTION_##x,
- foreach_command
+ foreach_action
#undef _
} hc_action_t;
+extern const char *action_str[];
+
+#define action_str(x) action_str[x]
+
+hc_action_t action_from_str(const char *action_str);
+
+/* Object type */
+
+#define foreach_object \
+ _(UNDEFINED) \
+ _(CONNECTION) \
+ _(LISTENER) \
+ _(ROUTE) \
+ _(FACE) \
+ _(STRATEGY) \
+ _(PUNTING) \
+ _(POLICY) \
+ _(CACHE) \
+ _(MAPME) \
+ _(LOCAL_PREFIX) \
+ _(PROBE) \
+ _(SUBSCRIPTION) \
+ _(N)
+
+typedef enum {
+#define _(x) OBJECT_##x,
+ foreach_object
+#undef _
+} hc_object_type_t;
+
+extern const char *object_str[];
+
+#define object_str(x) object_str[x]
+
+hc_object_type_t object_from_str(const char *object_str);
+
+#define IS_VALID_OBJECT_TYPE(x) IS_VALID_ENUM_TYPE(OBJECT, x)
+#define IS_VALID_ACTION(x) IS_VALID_ENUM_TYPE(ACTION, x)
+
/**
* \brief hICN control message header
*/
typedef struct hc_msg_s hc_msg_t;
-
+typedef struct hc_result_s hc_result_t;
/******************************************************************************
* Control Data
******************************************************************************/
@@ -140,7 +193,8 @@ typedef struct hc_data_s {
bool complete;
/* Callbacks */
- data_callback_t complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data);
+ data_callback_t
+ complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data);
void *complete_cb_data;
int ret;
} hc_data_t;
@@ -149,7 +203,8 @@ typedef struct hc_data_s {
* 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, data_callback_t complete_cb);
+hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size,
+ data_callback_t complete_cb);
/**
* Free a structure holding the results of an hICN control request.
@@ -214,38 +269,49 @@ int hc_data_reset(hc_data_t *data);
* \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 0; \
- } \
- }; \
- *found = NULL; /* this is optional */ \
- return 0; \
-}
+#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 0; \
+ } \
+ }; \
+ *found = NULL; /* this is optional */ \
+ return 0; \
+ }
/******************************************************************************
* Control socket
******************************************************************************/
-/* This should be at least equal to the maximum packet size */
-#define RECV_BUFLEN 8192
+/* With UDP, the buffer should be able to receieve a full packet, and thus MTU
+ * (max 9000) is sufficient. Messages will be received fully one by one.
+ * With TCP, the buffer should be at least able to receive a message header and
+ * the maximum size of a data element, so any reasonable size will be correct,
+ * it might just optimize performance. Messages might arrive in chunks that the
+ * library is able to parse.
+ */
+#define JUMBO_MTU 9000
+#define RECV_BUFLEN 65535
+
+#define foreach_forwarder_type \
+ _(UNDEFINED) \
+ _(HICNLIGHT) \
+ _(HICNLIGHT_NG) \
+ _(VPP) \
+ _(N)
typedef enum {
- HICNLIGHT,
- VPP,
- UNDEFINED
-} forwarder_t;
+#define _(x) x,
+ foreach_forwarder_type
+#undef _
+} forwarder_type_t;
/**
* \brief Holds the state of an hICN control socket
@@ -257,22 +323,26 @@ typedef struct hc_sock_s hc_sock_t;
* \param [in] url - The URL to connect to.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create_url(const char * url);
+hc_sock_t *hc_sock_create_url(const char *url);
/**
* \brief Create an hICN control socket using the provided forwarder.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create_forwarder(forwarder_t forwarder);
+hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder);
+
+/**
+ * \brief Create an hICN control socket using the provided forwarder and a URL.
+ * \return an hICN control socket
+ */
+hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder,
+ 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);
+hc_sock_t *hc_sock_create(void);
/**
* \brief Frees an hICN control socket
@@ -324,7 +394,7 @@ int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size);
* \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, int seq);
+int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq);
/**
* \brief Helper for reading socket contents
@@ -356,6 +426,13 @@ int hc_sock_callback(hc_sock_t *s, hc_data_t **data);
*/
int hc_sock_reset(hc_sock_t *s);
+void hc_sock_increment_woff(hc_sock_t *s, size_t bytes);
+
+int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb, void *complete_cb_data);
+
+int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms);
+
/******************************************************************************
* Command-specific structures and functions
******************************************************************************/
@@ -420,50 +497,11 @@ int hc_sock_reset(hc_sock_t *s);
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 + HOTFIXMARGIN
-
-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 *);
+#define INPUT_ERROR -2
+#define UNSUPPORTED_CMD_ERROR -3
+
/*----------------------------------------------------------------------------*
* Listeners
*----------------------------------------------------------------------------*/
@@ -473,27 +511,28 @@ typedef struct {
char name[SYMBOLIC_NAME_LEN]; /* K.w */ // XXX clarify what used for
char interface_name[INTERFACE_LEN]; /* Kr. */
u32 id;
- hc_connection_type_t type; /* .rw */
- int family; /* .rw */
- ip_address_t local_addr; /* .rw */
- u16 local_port; /* .rw */
+ face_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);
/* listener_found might eventually be allocated, and needs to be freed */
+hc_result_t *hc_listener_create_conf(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);
+hc_result_t *hc_listener_list_conf(hc_sock_t *s);
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_ \
- INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_
+ INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_FACE_TYPE_
#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM
GENERATE_FIND_HEADER(listener);
@@ -506,28 +545,30 @@ int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener);
/*
* NOTE :
- * - interface_name is mainly used to derive listeners from connections, but is
- * not itself used to create connections.
+ * - interface_name is mainly used to derive listeners from connections,
+ * but is not itself used to create connections.
*/
typedef struct {
u32 id; /* Kr. */
char name[SYMBOLIC_NAME_LEN]; /* K.w */
char interface_name[INTERFACE_LEN]; /* Kr. */
- hc_connection_type_t type; /* .rw */
+ face_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 */
+ face_state_t admin_state; /* .rw */
#ifdef WITH_POLICY
- uint32_t priority; /* .rw */
- policy_tags_t tags; /* .rw */
-#endif /* WITH_POLICY */
- hc_connection_state_t state; /* .r. */
+ uint32_t priority; /* .rw */
+ policy_tags_t tags; /* .rw */
+#endif /* WITH_POLICY */
+ face_state_t state; /* .r. */
} hc_connection_t;
int hc_connection_create(hc_sock_t *s, hc_connection_t *connection);
+hc_result_t *hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection);
/* connection_found will be allocated, and must be freed */
int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
hc_connection_t **connection_found);
@@ -536,6 +577,8 @@ int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
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);
+hc_result_t *hc_connection_delete_conf(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);
@@ -544,19 +587,21 @@ 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);
-int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
-int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
-int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
#endif /* WITH_POLICY */
#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data)
-#define MAXSZ_HC_CONNECTION_ \
- MAXSZ_HC_CONNECTION_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \
- MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3)
+#define MAXSZ_HC_CONNECTION_ \
+ MAXSZ_FACE_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \
+ MAXSZ_FACE_TYPE_ + SPACES(3)
#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM
GENERATE_FIND_HEADER(connection);
@@ -591,14 +636,17 @@ typedef struct {
*/
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_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener);
int hc_face_list(hc_sock_t *s, hc_data_t **pdata);
int hc_face_list_async(hc_sock_t *s); //, hc_data_t ** pdata);
-int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
-int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
-int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
#endif /* WITH_POLICY */
#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data)
@@ -609,7 +657,8 @@ int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t
#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN
#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM
-#define MAXSZ_HC_FACE_ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN
+#define MAXSZ_HC_FACE_ \
+ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN
#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM
int hc_face_snprintf(char *s, size_t size, hc_face_t *face);
@@ -619,20 +668,20 @@ int hc_face_snprintf(char *s, size_t size, hc_face_t *face);
*----------------------------------------------------------------------------*/
typedef struct {
- face_id_t face_id; /* Kr. */
- int family; /* Krw */
- ip_address_t remote_addr; /* krw */
- u8 len; /* krw */
- u16 cost; /* .rw */
- hc_face_t face;
+ face_id_t face_id; /* Kr. use when name == NULL */
+ char name[SYMBOLIC_NAME_LEN]; /* Kr. use by default vs face_id */
+ int family; /* Krw */
+ ip_address_t remote_addr; /* krw */
+ u8 len; /* krw */
+ u16 cost; /* .rw */
+ hc_face_t face; /* TODO remove, used by hicn_plugin_api */
} 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);
-int hc_route_list_async(hc_sock_t * s);
+int hc_route_create(hc_sock_t *s, hc_route_t *route);
+hc_result_t *hc_route_create_conf(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);
+int hc_route_list_async(hc_sock_t *s);
#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
@@ -646,6 +695,7 @@ int hc_route_list_async(hc_sock_t * s);
#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM
int hc_route_snprintf(char *s, size_t size, hc_route_t *route);
+int hc_route_validate(const hc_route_t *route);
/*----------------------------------------------------------------------------*
* Punting
@@ -653,9 +703,9 @@ int hc_route_snprintf(char *s, size_t size, hc_route_t *route);
typedef struct {
face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ?
- int family; /* Krw */
- ip_address_t prefix; /* krw */
- u8 prefix_len; /* krw */
+ 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);
@@ -666,7 +716,6 @@ 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)
@@ -681,8 +730,23 @@ 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);
+typedef struct {
+ uint8_t serve; // 1 = on, 0 = off
+ uint8_t store; // 1 = on, 0 = off
+} hc_cache_t;
+
+typedef struct {
+ bool store;
+ bool serve;
+ size_t cs_size;
+ size_t num_stale_entries;
+} hc_cache_info_t;
+
+int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_list(hc_sock_t *s, hc_data_t **pdata);
+int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info);
/*----------------------------------------------------------------------------*
* Strategy
@@ -691,7 +755,13 @@ int hc_cache_set_serve(hc_sock_t *s, int enabled);
#define MAXSZ_STRATEGY_NAME 255
typedef struct {
+ // The name is not set by the controller
+ // but populated by the daemon
char name[MAXSZ_STRATEGY_NAME];
+ strategy_type_t type;
+ ip_address_t address, local_address;
+ int family, local_family;
+ u8 len, local_len;
} hc_strategy_t;
int hc_strategy_list(hc_sock_t *s, hc_data_t **data);
@@ -704,8 +774,11 @@ int hc_strategy_list(hc_sock_t *s, hc_data_t **data);
int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy);
// per prefix
-int hc_strategy_set(hc_sock_t *s /* XXX */);
-
+int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy);
+hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy);
+int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy);
+hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s,
+ hc_strategy_t *strategy);
/*----------------------------------------------------------------------------*
* WLDR
*----------------------------------------------------------------------------*/
@@ -717,10 +790,45 @@ 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);
+typedef enum {
+ MAPME_TARGET_ENABLE,
+ MAPME_TARGET_DISCOVERY,
+ MAPME_TARGET_TIMESCALE,
+ MAPME_TARGET_RETX,
+} mapme_target_t;
+
+static inline mapme_target_t mapme_target_from_str(char *mapme_target_str) {
+ if (strcasecmp(mapme_target_str, "enable") == 0)
+ return MAPME_TARGET_ENABLE;
+ else if (strcasecmp(mapme_target_str, "discovery") == 0)
+ return MAPME_TARGET_DISCOVERY;
+ else if (strcasecmp(mapme_target_str, "timescale") == 0)
+ return MAPME_TARGET_TIMESCALE;
+ else
+ return MAPME_TARGET_RETX;
+}
+
+#define MAX_MAPME_ARG_LEN 30
+
+typedef struct {
+ mapme_target_t target;
+ // Command argument stored as a string
+ // before being parsed into 'enabled' or 'timescale'
+ char unparsed_arg[MAX_MAPME_ARG_LEN];
+
+ uint8_t enabled; // 1 = on, 0 = off
+ uint32_t timescale; // Milliseconds
+
+ ip_address_t address;
+ int family;
+ u8 len;
+} hc_mapme_t;
+
+int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme);
/*----------------------------------------------------------------------------*
* Policies
@@ -732,11 +840,9 @@ typedef struct {
int family; /* Krw */
ip_address_t remote_addr; /* krw */
u8 len; /* krw */
- hicn_policy_t policy; /* .rw */
+ hicn_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);
@@ -748,7 +854,114 @@ int hc_policy_list(hc_sock_t *s, hc_data_t **pdata);
#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM
int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy);
+int hc_policy_validate(const hc_policy_t *policy);
#endif /* WITH_POLICY */
+/*----------------------------------------------------------------------------*
+ * Subscription
+ *----------------------------------------------------------------------------*/
+// Topics
+
+#undef PUNTING // TODO(eloparco): Undefined to avoid collisions
+ // Fix the collision
+
+// Used only to create 'hc_topic_t'
+typedef struct {
+#define _(x) char x;
+ foreach_object
+#undef _
+} object_offset_t;
+
+// Flags for topic subscriptions
+typedef enum {
+#define _(x) TOPIC_##x = (1 << offsetof(object_offset_t, x)),
+ foreach_object
+#undef _
+} hc_topic_t;
+
+static inline hc_object_type_t object_from_topic(hc_topic_t topic) {
+#define _(x) \
+ if (topic == TOPIC_##x) return OBJECT_##x;
+ foreach_object
+#undef _
+ return OBJECT_UNDEFINED;
+}
+
+#define NUM_TOPICS OBJECT_N // Because a topic is created for each object
+#define ALL_TOPICS ~0
+
+// Subscriptions
+typedef uint32_t hc_topics_t;
+typedef struct {
+ hc_topics_t topics;
+} hc_subscription_t;
+
+int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription);
+int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription);
+hc_result_t *hc_subscription_create_conf(hc_sock_t *s,
+ hc_subscription_t *subscription);
+hc_result_t *hc_subscription_delete_conf(hc_sock_t *s,
+ hc_subscription_t *subscription);
+
+/*----------------------------------------------------------------------------*
+ * Events
+ *----------------------------------------------------------------------------*/
+#define foreach_event_type \
+ _(UNDEFINED) \
+ _(INTERFACE_UPDATE) \
+ _(N)
+typedef enum {
+#define _(x) EVENT_##x,
+ foreach_event_type
+#undef _
+} event_type_t;
+
+extern const char *event_str[];
+#define event_str(x) event_str[x]
+
+typedef enum {
+ FLAG_INTERFACE_TYPE_WIRED = 0x1,
+ FLAG_INTERFACE_TYPE_WIFI = 0x2,
+ FLAG_INTERFACE_TYPE_CELLULAR = 0x4,
+} flag_interface_type_t;
+
+typedef struct {
+ flag_interface_type_t interface_type;
+} hc_event_interface_update_t;
+
+/* Result */
+
+hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result);
+int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result);
+bool hc_result_get_success(hc_sock_t *s, hc_result_t *result);
+void hc_result_free(hc_result_t *result);
+
+/* Object */
+
+typedef struct {
+ hc_object_type_t type;
+ union {
+ hc_connection_t connection;
+ hc_listener_t listener;
+ hc_route_t route;
+ hc_face_t face;
+ // hc_data_t *data;
+ hc_punting_t punting;
+ hc_strategy_t strategy;
+#ifdef WITH_POLICY
+ hc_policy_t policy;
+#endif /* WITH_POLICY */
+ hc_subscription_t subscription;
+ hc_cache_t cache;
+ hc_mapme_t mapme;
+ uint8_t as_uint8;
+ };
+} hc_object_t;
+
+typedef struct {
+ hc_action_t action;
+ hc_object_t object;
+} hc_command_t;
+
#endif /* HICNTRL_API */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
deleted file mode 100644
index 49a6a783c..000000000
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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
-
-#include <hicn/policy.h>
-
-#include <hicn/util/ip_address.h>
-
-//typedef unsigned int hash_t; //incompatible with vpp
-
-/* Netdevice type */
-
-#include <net/if.h> // IFNAMSIZ
-
-#define foreach_netdevice_type \
- _(UNDEFINED) \
- _(LOOPBACK) \
- _(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 */
-
-/**
- * \brief Netdevice type
- *
- * NOTE
- * - This struct cannot be made opaque as it is currently part of face_t
- * - We recommand using the API as to keep redundant attributes consistent
- */
-typedef struct {
- u32 index;
- char name[IFNAMSIZ];
-} netdevice_t;
-
-#define NETDEVICE_EMPTY (netdevice_t) { \
- .index = 0, \
- .name = {0}, \
-}
-
-netdevice_t * netdevice_create_from_index(u32 index);
-netdevice_t * netdevice_create_from_name(const char * name);
-#define netdevice_initialize_from_index netdevice_set_index
-#define netdevice_initialize_from_name netdevice_set_name
-void netdevice_free(netdevice_t * netdevice);
-int netdevice_get_index(const netdevice_t * netdevice, u32 * index);
-int netdevice_set_index(netdevice_t * netdevice, u32 index);
-int netdevice_get_name(const netdevice_t * netdevice, const char ** name);
-int netdevice_set_name(netdevice_t * netdevice, const char * name);
-int netdevice_update_index(netdevice_t * netdevice);
-int netdevice_update_name(netdevice_t * netdevice);
-int netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2);
-
-#define NETDEVICE_UNDEFINED_INDEX 0
-
-/* Face state */
-
-#define foreach_face_state \
- _(UNDEFINED) \
- _(DOWN) \
- _(UP) \
- _(N)
-
-
-#define MAXSZ_FACE_STATE_ 9
-#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[];
-
-#ifdef WITH_POLICY
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + MAXSZ_POLICY_TAGS_ + 7
-#else
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + 4
-#endif /* WITH_POLICY */
-#define MAXSZ_FACE MAXSZ_FACE_ + 1
-
-/* Face */
-
-typedef u32 face_id_t;
-
-typedef struct {
- face_type_t type;
- face_state_t admin_state;
- face_state_t state;
-#ifdef WITH_POLICY
- uint32_t priority;
- policy_tags_t tags; /**< \see policy_tag_t */
-#endif /* WITH_POLICY */
-
- /*
- * Depending on the face type, some of the following fields will be unused
- */
- netdevice_t netdevice;
- int family; /* To access family independently of face type */
- ip_address_t local_addr;
- ip_address_t remote_addr;
- u16 local_port;
- u16 remote_port;
-} face_t;
-
-int face_initialize(face_t * face);
-int face_initialize_udp(face_t * face, const char * interface_name,
- 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 char * interface_name,
- const struct sockaddr * local_addr, const struct sockaddr * remote_addr);
-
-face_t * face_create();
-face_t * face_create_udp(const char * interface_name,
- 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 char * interface_name,
- 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);
-unsigned int face_hash(const face_t * face);
-
-size_t
-face_snprintf(char * s, size_t size, const face_t * face);
-
-policy_tags_t face_get_tags(const face_t * face);
-int face_set_tags(face_t * face, policy_tags_t tags);
-
-#endif /* HICN_FACE_H */
-
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
new file mode 100644
index 000000000..7d105a84b
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2021 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 HICN_CTRL_HICNLIGHTNG_H
+#define HICN_CTRL_HICNLIGHTNG_H
+
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <hicn/policy.h>
+#include <hicn/strategy.h>
+#include <hicn/util/ip_address.h>
+
+#define SYMBOLIC_NAME_LEN 16
+
+typedef struct in6_addr ipv6_addr_t;
+typedef uint32_t ipv4_addr_t;
+
+typedef enum {
+ MESSAGE_COMMAND_SUBTYPE_UNDEFINED,
+ REQUEST_LIGHT = 0xc0, // this is a command
+ RESPONSE_LIGHT,
+ ACK_LIGHT,
+ NACK_LIGHT,
+ NOTIFICATION_LIGHT,
+ MESSAGE_COMMAND_SUBTYPE_N
+} message_command_subtype_t;
+
+#define message_type_is_valid(message_type) \
+ ((message_type != MESSAGE_TYPE_UNDEFINED) && \
+ (message_type != MESSAGE_COMMAND_SUBTYPE_N))
+
+#define message_type_from_uchar(x) \
+ (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) \
+ ? MESSAGE_COMMAND_SUBTYPE_N \
+ : (message_command_subtype_t)(x))
+
+#define foreach_command_type \
+ _(listener_add, LISTENER_ADD) \
+ _(listener_remove, LISTENER_REMOVE) \
+ _(listener_list, LISTENER_LIST) \
+ _(connection_add, CONNECTION_ADD) \
+ _(connection_remove, CONNECTION_REMOVE) \
+ _(connection_list, CONNECTION_LIST) \
+ _(connection_set_admin_state, CONNECTION_SET_ADMIN_STATE) \
+ _(connection_update, CONNECTION_UPDATE) \
+ _(connection_set_priority, CONNECTION_SET_PRIORITY) \
+ _(connection_set_tags, CONNECTION_SET_TAGS) \
+ _(route_add, ROUTE_ADD) \
+ _(route_remove, ROUTE_REMOVE) \
+ _(route_list, ROUTE_LIST) \
+ _(cache_set_store, CACHE_SET_STORE) \
+ _(cache_set_serve, CACHE_SET_SERVE) \
+ _(cache_clear, CACHE_CLEAR) \
+ _(cache_list, CACHE_LIST) \
+ _(strategy_set, STRATEGY_SET) \
+ _(strategy_add_local_prefix, STRATEGY_ADD_LOCAL_PREFIX) \
+ _(wldr_set, WLDR_SET) \
+ _(punting_add, PUNTING_ADD) \
+ _(mapme_enable, MAPME_ENABLE) \
+ _(mapme_set_discovery, MAPME_SET_DISCOVERY) \
+ _(mapme_set_timescale, MAPME_SET_TIMESCALE) \
+ _(mapme_set_retx, MAPME_SET_RETX) \
+ _(mapme_send_update, MAPME_SEND_UPDATE) \
+ _(policy_add, POLICY_ADD) \
+ _(policy_remove, POLICY_REMOVE) \
+ _(policy_list, POLICY_LIST) \
+ _(subscription_add, SUBSCRIPTION_ADD) \
+ _(subscription_remove, SUBSCRIPTION_REMOVE)
+
+typedef enum {
+ COMMAND_TYPE_UNDEFINED,
+#define _(l, u) COMMAND_TYPE_##u,
+ foreach_command_type
+#undef _
+ COMMAND_TYPE_N,
+} command_type_t;
+
+extern const char *command_type_str[];
+
+#define command_type_str(x) command_type_str[x]
+
+#define command_type_is_valid(command_type) \
+ ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N))
+
+#define command_type_from_uchar(x) \
+ (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x))
+
+/* Should be at least 8 bytes */
+typedef struct {
+ uint8_t message_type;
+ uint8_t command_id;
+ uint16_t length; /* Number of structures in the payload */
+ uint32_t seq_num;
+} cmd_header_t;
+
+typedef struct {
+ cmd_header_t header;
+} msg_header_t;
+
+/* Listener */
+
+typedef struct {
+ char symbolic[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint16_t port;
+ uint8_t family;
+ uint8_t type;
+} cmd_listener_add_t;
+
+typedef struct {
+ char symbolicOrListenerid[SYMBOLIC_NAME_LEN];
+} cmd_listener_remove_t;
+
+typedef struct {
+ void *_; // Otherwise empty structs result in clang build error
+} cmd_listener_list_t;
+
+// Sync this struct with `hc_listener_t` in `api.h`
+typedef struct {
+ char name[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ uint32_t id;
+ uint8_t type;
+ uint8_t family;
+ ip_address_t address;
+ uint16_t port;
+} cmd_listener_list_item_t;
+
+/* Connection */
+
+typedef struct {
+ char symbolic[SYMBOLIC_NAME_LEN];
+ // char interface_name[SYMBOLIC_NAME_LEN];
+ ip_address_t remote_ip;
+ ip_address_t local_ip;
+ uint16_t remote_port;
+ uint16_t local_port;
+ uint8_t family;
+ uint8_t type;
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+} cmd_connection_add_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+} cmd_connection_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_connection_list_t;
+
+// Sync this struct with `hc_connection_t` in `api.h`
+typedef struct {
+ uint32_t id;
+ char name[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ uint8_t type;
+ uint8_t family;
+ ip_address_t local_addr;
+ uint16_t local_port;
+ ip_address_t remote_addr;
+ uint16_t remote_port;
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+ uint8_t state;
+} cmd_connection_list_item_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t admin_state;
+ uint8_t pad8[3];
+} cmd_connection_set_admin_state_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+} cmd_connection_update_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint32_t priority;
+} cmd_connection_set_priority_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ policy_tags_t tags;
+} cmd_connection_set_tags_t;
+
+/* Route */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint16_t cost;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_add_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_route_list_t;
+
+// Sync this struct with `hc_route_t` in `api.h`
+typedef struct {
+ ip_address_t address;
+ uint32_t connection_id;
+ uint16_t cost;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_list_item_t;
+
+/* Cache */
+
+typedef struct {
+ uint8_t activate;
+} cmd_cache_set_store_t;
+
+typedef struct {
+ uint8_t activate;
+} cmd_cache_set_serve_t;
+
+typedef struct {
+ void *_;
+} cmd_cache_clear_t;
+
+typedef struct {
+ void *_;
+} cmd_cache_list_t;
+
+typedef struct {
+ uint8_t store_in_cs;
+ uint8_t serve_from_cs;
+ uint32_t cs_size;
+ uint32_t num_stale_entries;
+} cmd_cache_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_cache_list_reply_t payload;
+} msg_cache_list_reply_t;
+
+/* WLDR */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t activate;
+} cmd_wldr_set_t;
+
+/* Strategy */
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ uint8_t type;
+ uint8_t related_prefixes;
+ union {
+ struct {
+ ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ } low_latency;
+ };
+} cmd_strategy_set_t;
+
+typedef struct {
+ uint8_t type;
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ ip_address_t local_address;
+ uint8_t local_family;
+ uint8_t local_len;
+} cmd_strategy_add_local_prefix_t;
+
+/* Punting */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_punting_add_t;
+
+/* MAP-Me */
+
+typedef struct {
+ uint8_t activate;
+} cmd_mapme_activator_t;
+
+typedef cmd_mapme_activator_t cmd_mapme_enable_t;
+typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t;
+
+typedef struct {
+ uint32_t timePeriod;
+} cmd_mapme_timing_t;
+
+typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t;
+typedef cmd_mapme_timing_t cmd_mapme_set_retx_t;
+
+typedef struct {
+ void *_;
+} cmd_mapme_send_update_t;
+
+/* Policy */
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ hicn_policy_t policy;
+} cmd_policy_add_t;
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_policy_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_policy_list_t;
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ hicn_policy_t policy;
+} cmd_policy_list_item_t;
+
+/* Subscription */
+
+typedef struct {
+ uint32_t topics;
+} cmd_subscription_add_t;
+
+typedef struct {
+ uint32_t topics;
+} cmd_subscription_remove_t;
+
+/* Full messages */
+
+#define _(l, u) \
+ typedef struct { \
+ cmd_header_t header; \
+ cmd_##l##_t payload; \
+ } msg_##l##_t;
+foreach_command_type
+#undef _
+
+ typedef struct {
+ cmd_header_t header;
+ cmd_listener_list_item_t payload;
+} msg_listener_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_connection_list_item_t payload;
+} msg_connection_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_route_list_item_t payload;
+} msg_route_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_policy_list_item_t payload;
+} msg_policy_list_reply_t;
+
+//===== size of commands ======
+// REMINDER: when a new_command is added, the following switch has to be
+// updated.
+static inline int command_get_payload_len(command_type_t command_type) {
+ switch (command_type) {
+#define _(l, u) \
+ case COMMAND_TYPE_##u: \
+ return sizeof(cmd_##l##_t);
+ foreach_command_type
+#undef _
+ case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N : return 0;
+ }
+}
+#endif /* HICN_CTRL_HICNLIGHTNG_H */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h
index 3758f0f41..69ede1985 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -20,8 +20,8 @@
* Header and payload in binary format.
*/
-#ifndef commands_h
-#define commands_h
+#ifndef HICN_CTRL_HICNLIGHT_H
+#define HICN_CTRL_HICNLIGHT_H
#ifndef _WIN32
#include <netinet/in.h>
@@ -43,7 +43,7 @@ typedef struct in6_addr ipv6_addr_t;
typedef uint32_t ipv4_addr_t;
typedef enum {
- REQUEST_LIGHT = 0xc0, // this is a command
+ REQUEST_LIGHT = 0xc0, // this is a command
RESPONSE_LIGHT,
ACK_LIGHT,
NACK_LIGHT,
@@ -133,7 +133,7 @@ typedef struct {
typedef struct {
char symbolic[SYMBOLIC_NAME_LEN];
- //char interfaceName[SYMBOLIC_NAME_LEN];
+ // char interfaceName[SYMBOLIC_NAME_LEN];
ip_address_t remoteIp;
ip_address_t localIp;
uint16_t remotePort;
@@ -415,7 +415,7 @@ static inline int payloadLengthDaemon(command_id id) {
case ADD_POLICY:
return sizeof(add_policy_command);
case LIST_POLICIES:
- return 0; // list policies: payload always 0
+ return 0; // list policies: payload always 0
case REMOVE_POLICY:
return sizeof(remove_policy_command);
case UPDATE_CONNECTION:
@@ -431,4 +431,4 @@ static inline int payloadLengthDaemon(command_id id) {
return 0;
}
}
-#endif
+#endif /* HICN_CTRL_HICNLIGHT_H */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
index d7ef6a26f..81f011d4d 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -21,7 +21,7 @@
#define HICN_ROUTE_H
#include <hicn/util/ip_address.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
typedef u16 route_cost_t;
@@ -30,18 +30,23 @@ typedef struct hicn_route_s hicn_route_t;
#define MAXSZ_ROUTE_ MAXSZ_PREFIX + 3 + MAXSZ_COST
#define MAXSZ_ROUTE MAXSZ_ROUTE_ + NULLTERM
-hicn_route_t * hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost);
-hicn_route_t * hicn_route_dup(const hicn_route_t * route);
-void hicn_route_free(hicn_route_t * route);
+#define MIN_ROUTE_COST 1
+#define MAX_ROUTE_COST 255
+#define IS_VALID_ROUTE_COST(x) ((x >= MIN_ROUTE_COST) && (x <= MAX_ROUTE_COST))
-int hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2);
+hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id,
+ route_cost_t cost);
+hicn_route_t* hicn_route_dup(const hicn_route_t* route);
+void hicn_route_free(hicn_route_t* route);
-int hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix);
-int hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix);
+int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2);
-int hicn_route_get_cost(const hicn_route_t * route, int * cost);
-int hicn_route_set_cost(hicn_route_t * route, const int cost);
+int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix);
+int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix);
-size_t hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route);
+int hicn_route_get_cost(const hicn_route_t* route, int* cost);
+int hicn_route_set_cost(hicn_route_t* route, const int cost);
+
+size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route);
#endif
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index f9934d70e..c8a93c56c 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -11,80 +11,127 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-list(APPEND COMPILER_DEFINITIONS
- "-DWITH_POLICY"
-)
-
+##############################################################
+# Source files
+##############################################################
set(SOURCE_FILES
- face.c
- route.c
- api.c
+ route.c
+ api.c
)
set(HEADER_FILES
- api_private.h
+ api_private.h
)
+
+##############################################################
+# Libraries to link
+##############################################################
set(LIBRARIES
- m
- dl
- ${HICN_LIBRARIES}
+ m
+ dl
+ ${HICN_LIBRARIES}
)
+
+##############################################################
+# Include directories
+##############################################################
set(INCLUDE_DIRS
+ PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/../includes/
- ${HICN_INCLUDE_DIRS}
+ PUBLIC
+ $<BUILD_INTERFACE:${Libhicnctrl_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
-# Android requires static libraries
+
+##############################################################
+# Library type
+##############################################################
if (DISABLE_SHARED_LIBRARIES)
- set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC})
- set(LINK_TYPE STATIC)
+ set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC})
+ set(LINK_TYPE STATIC)
else ()
- set(LINK_TYPE SHARED STATIC)
+ set(LINK_TYPE SHARED STATIC)
endif ()
+
+##############################################################
+# Do not use modules if Android
+##############################################################
if (${CMAKE_SYSTEM_NAME} MATCHES Android)
- list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_api.c
- )
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_ng_api.c
+ )
else()
- add_subdirectory(modules)
+ add_subdirectory(modules)
endif()
+
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build main hicnctrl library
+##############################################################
build_library(${LIBHICNCTRL}
- ${LINK_TYPE}
- SOURCES ${SOURCE_FILES} ${HEADER_FILES}
- INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
+ ${LINK_TYPE}
+ SOURCES ${SOURCE_FILES} ${HEADER_FILES}
+ INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS}
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME "${LIBHICNCTRL_COMPONENT}"
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Cmake config files
+##############################################################
+create_cmake_config (
+ ${LIBHICNCTRL_COMPONENT}
+ INCLUDE_DIRS ${Libhicnctrl_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ NAMESPACE hicn
+)
+
+
+##############################################################
+# Build executables
+##############################################################
+if (NOT DISABLE_EXECUTABLES)
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC})
+ set(DEPENDENCIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
+ set(DEPENDENCIES ${LIBHICNCTRL_SHARED})
+ endif ()
+
+ list(APPEND DAEMON_SRC
+ hicnctrl.c
+ )
+
+ build_executable(${HICNCTRL}
+ SOURCES ${DAEMON_SRC}
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBHICNCTRL_COMPONENT}
INCLUDE_DIRS ${INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
-)
-
-if (NOT DISABLE_EXECUTABLES)
- if (DISABLE_SHARED_LIBRARIES)
- set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC})
- set(DEPENDENCIES ${LIBHICNCTRL_STATIC})
- else ()
- set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
- set(DEPENDENCIES ${LIBHICNCTRL_SHARED})
- endif ()
-
- list(APPEND DAEMON_SRC
- cli.c
- )
-
- build_executable(${HICNCTRL}
- SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBRARIES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
+ LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
endif ()
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 4bb66c784..4156ceff9 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -18,22 +18,26 @@
* \brief Implementation of hICN control library API
*/
+#include <assert.h>
+#include <dlfcn.h> // dlopen
+#include <hicn/strategy.h>
#include <hicn/util/log.h>
-#include "api_private.h"
+#include <hicn/ctrl/route.h>
+#include <math.h> // log2
-#include <math.h> // log2
-#include <dlfcn.h> // dlopen
+#include "api_private.h"
+#if 0
/* /!\ Please update constants in public header file upon changes */
const char * connection_state_str[] = {
-#define _(x) [HC_CONNECTION_STATE_ ## x] = STRINGIZE(x),
+#define _(x) [HC_CONNECTION_STATE_##x] = STRINGIZE(x),
foreach_connection_state
#undef _
};
/* /!\ Please update constants in public header file upon changes */
const char * connection_type_str[] = {
-#define _(x) [CONNECTION_TYPE_ ## x] = STRINGIZE(x),
+#define _(x) [CONNECTION_TYPE_##x] = STRINGIZE(x),
foreach_connection_type
#undef _
};
@@ -48,151 +52,72 @@ connection_type_from_str(const char * str)
else if (strcasecmp(str, "HICN") == 0)
return CONNECTION_TYPE_HICN;
else
- return CONNECTION_TYPE_UNDEFINED;
+ return CONNECTION_TYPE_UNDEFINED;
}
-
-/* Conversions to shield lib user from heterogeneity */
-
-#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN))
-
-const hc_connection_type_t map_from_list_connections_type[] = {
- [CONN_GRE] = CONNECTION_TYPE_UNDEFINED,
- [CONN_TCP] = CONNECTION_TYPE_TCP,
- [CONN_UDP] = CONNECTION_TYPE_UDP,
- [CONN_MULTICAST] = CONNECTION_TYPE_UNDEFINED,
- [CONN_L2] = CONNECTION_TYPE_UNDEFINED,
- [CONN_HICN] = CONNECTION_TYPE_HICN,
-};
-
-#define IS_VALID_LIST_LISTENERS_TYPE(x) ((x >= ENCAP_TCP) && (x <= ENCAP_HICN))
-
-const hc_connection_type_t map_from_encap_type[] = {
- [ENCAP_TCP] = CONNECTION_TYPE_TCP,
- [ENCAP_UDP] = CONNECTION_TYPE_UDP,
- [ENCAP_ETHER] = CONNECTION_TYPE_UNDEFINED,
- [ENCAP_LOCAL] = CONNECTION_TYPE_UNDEFINED,
- [ENCAP_HICN] = CONNECTION_TYPE_HICN,
-};
-
-const connection_type map_to_connection_type[] = {
- [CONNECTION_TYPE_TCP] = TCP_CONN,
- [CONNECTION_TYPE_UDP] = UDP_CONN,
- [CONNECTION_TYPE_HICN] = HICN_CONN,
-};
-
-const listener_mode map_to_listener_mode[] = {
- [CONNECTION_TYPE_TCP] = IP_MODE,
- [CONNECTION_TYPE_UDP] = IP_MODE,
- [CONNECTION_TYPE_HICN] = HICN_MODE,
-};
-
-#define IS_VALID_LIST_CONNECTIONS_STATE(x) ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN))
-
-/*
-#define IS_VALID_CONNECTION_STATE(x) IS_VALID_ENUM_TYPE(CONNECTION_STATE, x)
-
-static const connection_state map_to_connection_state[] = {
- [HC_CONNECTION_STATE_UP] = IFACE_UP,
- [HC_CONNECTION_STATE_DOWN] = IFACE_DOWN,
-};
-
-*/
-
-const hc_connection_state_t map_from_list_connections_state[] = {
- [IFACE_UP] = HC_CONNECTION_STATE_UP,
- [IFACE_DOWN] = HC_CONNECTION_STATE_DOWN,
- [IFACE_UNKNOWN] = HC_CONNECTION_STATE_UNDEFINED,
-};
-
-
-const int map_from_addr_type[] = {
- [ADDR_INET] = AF_INET,
- [ADDR_INET6] = AF_INET6,
- [ADDR_LINK] = AF_UNSPEC,
- [ADDR_IFACE] = AF_UNSPEC,
- [ADDR_UNIX] = AF_UNSPEC,
-};
-
-const address_type map_to_addr_type[] = {
- [AF_INET] = ADDR_INET,
- [AF_INET6] = ADDR_INET6,
-};
+#endif
/******************************************************************************
* Control Data
******************************************************************************/
-hc_data_t *
-hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb)
-{
- hc_data_t * data = malloc(sizeof(hc_data_t));
- if (!data)
- goto ERR_MALLOC;
-
- /* FIXME Could be NULL thanks to realloc provided size is 0 */
- data->max_size_log = DEFAULT_SIZE_LOG;
- data->in_element_size = in_element_size;
- data->out_element_size = out_element_size;
- data->size = 0;
- data->complete = false;
- data->command_id = 0; // TODO this could also be a busy mark in the socket
- /* No callback needed in blocking code for instance */
- data->complete_cb = complete_cb;
-
- data->buffer = malloc((1 << data->max_size_log) * data->out_element_size);
- if (!data->buffer)
- goto ERR_BUFFER;
- data->ret = 0;
-
- return data;
+hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size,
+ data_callback_t complete_cb) {
+ hc_data_t *data = malloc(sizeof(hc_data_t));
+ if (!data) goto ERR_MALLOC;
+
+ /* FIXME Could be NULL thanks to realloc provided size is 0 */
+ data->max_size_log = DEFAULT_SIZE_LOG;
+ data->in_element_size = in_element_size;
+ data->out_element_size = out_element_size;
+ data->size = 0;
+ data->complete = false;
+ data->command_id = 0; // TODO this could also be a busy mark in the socket
+ /* No callback needed in blocking code for instance */
+ data->complete_cb = complete_cb;
+
+ data->buffer = malloc((1 << data->max_size_log) * data->out_element_size);
+ if (!data->buffer) goto ERR_BUFFER;
+ data->ret = 0;
+ data->current = 0;
+
+ return data;
ERR_BUFFER:
- hc_data_free(data);
+ hc_data_free(data);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void
-hc_data_free(hc_data_t * data)
-{
- if (data->buffer)
- free(data->buffer);
- free(data);
+void hc_data_free(hc_data_t *data) {
+ if (data) free(data->buffer);
+ free(data);
}
-int
-hc_data_ensure_available(hc_data_t * data, size_t count)
-{
- size_t new_size_log = (data->size + count - 1 > 0)
- ? log2(data->size + count - 1) + 1
- : 0;
- if (new_size_log > data->max_size_log) {
- data->max_size_log = new_size_log;
- data->buffer = realloc(data->buffer, (1 << new_size_log) * data->out_element_size);
- if (!data->buffer)
- return -1;
- }
+int hc_data_ensure_available(hc_data_t *data, size_t count) {
+ size_t new_size_log =
+ (data->size + count - 1 > 0) ? log2(data->size + count - 1) + 1 : 0;
+ if (new_size_log > data->max_size_log) {
+ data->max_size_log = new_size_log;
+ data->buffer =
+ realloc(data->buffer, (1 << new_size_log) * data->out_element_size);
+ if (!data->buffer) return -1;
+ }
- return 0;
+ return 0;
}
-int
-hc_data_push_many(hc_data_t * data, const void * elements, size_t count)
-{
- if (hc_data_ensure_available(data, count) < 0)
- return -1;
+int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) {
+ if (hc_data_ensure_available(data, count) < 0) return -1;
- memcpy(data->buffer + data->size * data->out_element_size, elements,
- count * data->out_element_size);
- data->size += count;
+ memcpy(data->buffer + data->size * data->out_element_size, elements,
+ count * data->out_element_size);
+ data->size += count;
- return 0;
+ return 0;
}
-int
-hc_data_push(hc_data_t * data, const void * element)
-{
- return hc_data_push_many(data, element, 1);
+int hc_data_push(hc_data_t *data, const void *element) {
+ return hc_data_push_many(data, element, 1);
}
/**
@@ -200,61 +125,48 @@ hc_data_push(hc_data_t * data, const void * element)
* NOTE: This function make sure there is enough room available in the data
* structure.
*/
-u8 *
-hc_data_get_next(hc_data_t * data)
-{
- if (hc_data_ensure_available(data, 1) < 0)
- return NULL;
+u8 *hc_data_get_next(hc_data_t *data) {
+ if (hc_data_ensure_available(data, 1) < 0) return NULL;
- return data->buffer + data->size * data->out_element_size;
+ return data->buffer + data->size * data->out_element_size;
}
-int
-hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data)
-{
- data->complete_cb = cb;
- data->complete_cb_data = cb_data;
- return 0;
+int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) {
+ data->complete_cb = cb;
+ data->complete_cb_data = cb_data;
+ return 0;
}
-int
-hc_data_set_complete(hc_data_t * data)
-{
- data->complete = true;
- data->ret = 0;
- if (data->complete_cb)
- return data->complete_cb(data, data->complete_cb_data);
- return 0;
+int hc_data_set_complete(hc_data_t *data) {
+ data->complete = true;
+ data->ret = 0;
+ if (data->complete_cb) return data->complete_cb(data, data->complete_cb_data);
+ return 0;
}
-int
-hc_data_set_error(hc_data_t * data)
-{
- data->ret = -1;
- return 0;
+int hc_data_set_error(hc_data_t *data) {
+ data->ret = -1;
+ return 0;
}
-int
-hc_data_reset(hc_data_t * data)
-{
- data->size = 0;
- return 0;
+int hc_data_reset(hc_data_t *data) {
+ data->size = 0;
+ return 0;
}
-static hc_sock_t * _open_module(const char *name)
-{
+static hc_sock_t *_open_module(const char *name, const char *url) {
char complete_name[128];
#ifdef __APPLE__
- sprintf(complete_name, "%s.dylib", name);
+ snprintf(complete_name, 128, "%s.dylib", name);
#elif defined(__linux__)
- sprintf(complete_name, "%s.so", name);
+ snprintf(complete_name, 128, "%s.so", name);
#else
- #error "System not supported for dynamic lynking"
+#error "System not supported for dynamic lynking"
#endif
void *handle = 0;
const char *error = 0;
- hc_sock_t *(*creator)(void) = 0;
+ hc_sock_t *(*creator)(const char *) = 0;
hc_sock_t *ret = 0;
// open module
@@ -263,307 +175,305 @@ static hc_sock_t * _open_module(const char *name)
if ((error = dlerror()) != 0) {
ERROR("%s", error);
}
-
return 0;
}
// get factory method
- creator = (hc_sock_t * (*)(void)) dlsym(handle, "_hc_sock_create");
+ creator =
+ (hc_sock_t * (*)(const char *)) dlsym(handle, "_hc_sock_create_url");
if (!creator) {
if ((error = dlerror()) != 0) {
ERROR("%s", error);
- return 0;
}
+ return 0;
}
- ret = (*creator)();
+ ret = (*creator)(NULL);
ret->handle = handle;
return ret;
}
-hc_sock_t *hc_sock_create_forwarder(forwarder_t forwarder)
-{
- switch (forwarder)
- {
- case HICNLIGHT:
- return _open_module("hicnlightctrl_module");
- case VPP:
- return _open_module("vppctrl_module");
- default:
- return NULL;
- }
+hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder,
+ const char *url) {
+ switch (forwarder) {
+ case HICNLIGHT:
+ return _open_module("hicnlightctrl_module", url);
+ case HICNLIGHT_NG:
+ return _open_module("hicnlightngctrl_module", url);
+ case VPP:
+ return _open_module("vppctrl_module", url);
+ default:
+ return NULL;
+ }
}
#ifdef ANDROID
// In android we do not load a module at runtime
// but we link the hicnlight implmentation directly
// to the main library
-extern hc_sock_t *_hc_sock_create();
+extern hc_sock_t *_hc_sock_create_url(const char *url);
#endif
-hc_sock_t *hc_sock_create(void)
-{
+hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder) {
#ifdef ANDROID
- hc_sock_t *ret = _hc_sock_create();
- ret->handle = NULL;
- return ret;
+ assert(forwarder == HICNLIGHT_NG);
+ hc_sock_t *ret = _hc_sock_create_url(NULL);
+ ret->handle = NULL;
+ return ret;
#else
- return hc_sock_create_forwarder(HICNLIGHT);
+ return hc_sock_create_forwarder_url(forwarder, NULL);
#endif
}
-void hc_sock_free(hc_sock_t *s)
-{
- void *handle = s->handle;
- s->hc_sock_free(s);
-
- if (handle) {
- dlclose(handle);
- }
+hc_sock_t *hc_sock_create(void) {
+ return hc_sock_create_forwarder(HICNLIGHT_NG);
}
-int hc_sock_get_next_seq(hc_sock_t *s)
-{
- return s->hc_sock_get_next_seq(s);
-}
+void hc_sock_free(hc_sock_t *s) {
+ void *handle = s->handle;
+ s->hc_sock_free(s);
-int hc_sock_set_nonblocking(hc_sock_t *s)
-{
- return s->hc_sock_get_next_seq(s);
+ if (handle) {
+ dlclose(handle);
+ }
}
-int hc_sock_get_fd(hc_sock_t *s)
-{
- return s->hc_sock_get_fd(s);
+int hc_sock_get_next_seq(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); }
+
+int hc_sock_set_nonblocking(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); }
+
+int hc_sock_get_fd(hc_sock_t *s) { return s->hc_sock_get_fd(s); }
+
+int hc_sock_connect(hc_sock_t *s) { return s->hc_sock_connect(s); }
+
+int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) {
+ return s->hc_sock_get_available(s, buffer, size);
}
-int hc_sock_connect(hc_sock_t *s)
-{
- return s->hc_sock_connect(s);
+int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq) {
+ return s->hc_sock_send(s, msg, msglen, seq);
}
-int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size)
-{
- return s->hc_sock_get_available(s, buffer, size);
+int hc_sock_recv(hc_sock_t *s) { return s->hc_sock_recv(s); }
+
+int hc_sock_process(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_sock_process(s, data);
}
-int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq)
-{
- return s->hc_sock_send(s, msg, msglen, seq);
+int hc_sock_callback(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_sock_callback(s, data);
}
-int hc_sock_recv(hc_sock_t *s)
-{
- return s->hc_sock_recv(s);
+int hc_sock_reset(hc_sock_t *s) { return s->hc_sock_reset(s); }
+
+void hc_sock_increment_woff(hc_sock_t *s, size_t bytes) {
+ s->hc_sock_increment_woff(s, bytes);
}
-int hc_sock_process(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_sock_process(s, data);
+int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb, void *complete_cb_data) {
+ return s->hc_sock_prepare_send(s, result, complete_cb, complete_cb_data);
}
-int hc_sock_callback(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_sock_callback(s, data);
+int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms) {
+ return s->hc_sock_set_recv_timeout_ms(s, timeout_ms);
}
-int hc_sock_reset(hc_sock_t *s)
-{
- return s->hc_sock_reset(s);
+/*----------------------------------------------------------------------------*
+ * LISTENER
+ *----------------------------------------------------------------------------*/
+
+int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_create(s, listener);
}
-int hc_listener_create(hc_sock_t *s, hc_listener_t *listener)
-{
- return s->hc_listener_create(s, listener);
+hc_result_t *hc_listener_create_conf(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_create_conf(s, listener);
}
int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
- hc_listener_t **listener_found)
-{
- return s->hc_listener_get(s, listener, listener_found);
+ hc_listener_t **listener_found) {
+ return s->hc_listener_get(s, listener, listener_found);
}
-int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener)
-{
- return s->hc_listener_delete(s, listener);
+int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_delete(s, listener);
}
-int hc_listener_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_listener_list(s, pdata);
+int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_listener_list(s, pdata);
}
GENERATE_FIND(listener);
/* LISTENER VALIDATE */
-int
-hc_listener_validate(const hc_listener_t * listener)
-{
- if (!IS_VALID_FAMILY(listener->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return -1;
+int hc_listener_validate(const hc_listener_t *listener) {
+ if (!IS_VALID_NAME(listener->name)) {
+ ERROR("[hc_listener_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) {
+ ERROR("[hc_listener_validate] Invalid interface_name specified");
+ return -1;
+ }
+ if (!IS_VALID_TYPE(listener->type)) {
+ ERROR("[hc_listener_validate] Invalid type specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(listener->family)) {
+ ERROR("[hc_listener_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&listener->local_addr, listener->family)) {
+ ERROR("[hc_listener_validate] Invalid local_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(listener->local_port)) {
+ ERROR("[hc_listener_validate] Invalid local_port specified");
+ return -1;
+ }
- return 0;
+ return 0;
}
/* LISTENER CMP */
-int
-hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2)
-{
- int rc;
-
- rc = INT_CMP(l1->type, l2->type);
- if (rc != 0)
- return rc;
-
- rc = INT_CMP(l1->family, l2->family);
- if (rc != 0)
- return rc;
+int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) {
+ int rc;
- rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(l1->type, l2->type);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(l1->family, l2->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(l1->local_port, l2->local_port);
- if (rc != 0)
- return rc;
+ rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
- return rc;
-}
+ rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family);
+ if (rc != 0) return rc;
-/* LISTENER PARSE */
+ rc = INT_CMP(l1->local_port, l2->local_port);
+ if (rc != 0) return rc;
-int
-hc_listener_parse(void * in, hc_listener_t * listener)
-{
- int rc;
-
- list_listeners_command * cmd = (list_listeners_command *)in;
-
- if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType))
- return -1;
-
- hc_connection_type_t type = map_from_encap_type[cmd->encapType];
- if (type == CONNECTION_TYPE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return -1;
-
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
- return -1;
-
- *listener = (hc_listener_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = UNION_CAST(cmd->address, ip_address_t),
- .local_port = ntohs(cmd->port),
- };
- rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", cmd->listenerName);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_listener_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_listener_parse] Unexpected truncation of interface name string");
- return 0;
+ return rc;
}
/* LISTENER SNPRINTF */
/* /!\ Please update constants in header file upon changes */
-int
-hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
-{
- char local[MAXSZ_URL];
- int rc;
- rc = url_snprintf(local, MAXSZ_URL,
- listener->family, &listener->local_addr, listener->local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_listener_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
+int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener) {
+ char local[MAXSZ_URL];
+ int rc;
+ rc = url_snprintf(local, MAXSZ_URL, listener->family, &listener->local_addr,
+ listener->local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_listener_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
- return snprintf(s, size, "%s %s %s", listener->interface_name, local,
- connection_type_str[listener->type]);
+ return snprintf(s, size, "%s %s %s interface=%s", listener->name, local,
+ face_type_str(listener->type), listener->interface_name);
}
-int hc_connection_create(hc_sock_t *s, hc_connection_t *connection)
-{
- return s->hc_connection_create(s, connection);
+/*----------------------------------------------------------------------------*
+ * CONNECTION
+ *----------------------------------------------------------------------------*/
+
+int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+ return s->hc_connection_create(s, connection);
+}
+
+hc_result_t *hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return s->hc_connection_create_conf(s, connection);
}
int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
- hc_connection_t **connection_found)
-{
- return s->hc_connection_get(s, connection, connection_found);
+ hc_connection_t **connection_found) {
+ return s->hc_connection_get(s, connection, connection_found);
}
int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection)
-{
- return s->hc_connection_update_by_id(s, hc_connection_id, connection);
+ hc_connection_t *connection) {
+ return s->hc_connection_update_by_id(s, hc_connection_id, connection);
}
int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated)
-{
- return s->hc_connection_update(s, connection_current, connection_updated);
+ hc_connection_t *connection_updated) {
+ return s->hc_connection_update(s, connection_current, connection_updated);
}
-int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection)
-{
- return s->hc_connection_delete(s, connection);
+int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+ return s->hc_connection_delete(s, connection);
}
-int hc_connection_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_connection_list(s, pdata);
+hc_result_t *hc_connection_delete_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return s->hc_connection_delete_conf(s, connection);
}
-int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
-{
- return s->hc_connection_set_admin_state(s, conn_id_or_name, state);
+int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_connection_list(s, pdata);
+}
+
+int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
+ return s->hc_connection_set_admin_state(s, conn_id_or_name, state);
}
#ifdef WITH_POLICY
-int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
-{
- return s->hc_connection_set_priority(s, conn_id_or_name, priority);
+int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return s->hc_connection_set_priority(s, conn_id_or_name, priority);
}
-int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
-{
- return s->hc_connection_set_tags(s, conn_id_or_name, tags);
+int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return s->hc_connection_set_tags(s, conn_id_or_name, tags);
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
GENERATE_FIND(connection);
/* CONNECTION VALIDATE */
-int
-hc_connection_validate(const hc_connection_t * connection)
-{
- if (!IS_VALID_FAMILY(connection->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(connection->type))
- return -1;
-
- /* TODO assert both local and remote have the right family */
+int hc_connection_validate(const hc_connection_t *connection) {
+ if (!IS_VALID_NAME(connection->name)) {
+ ERROR("[hc_connection_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) {
+ ERROR("[hc_connection_validate] Invalid interface_name specified");
+ return -1;
+ }
+ if (!IS_VALID_TYPE(connection->type)) {
+ ERROR("[hc_connection_validate] Invalid type specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(connection->family)) {
+ ERROR("[hc_connection_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&connection->local_addr, connection->family)) {
+ ERROR("[hc_connection_validate] Invalid local_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(connection->local_port)) {
+ ERROR("[hc_connection_validate] Invalid local_port specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&connection->remote_addr, connection->family)) {
+ ERROR("[hc_connection_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(connection->remote_port)) {
+ ERROR("[hc_connection_validate] Invalid remote_port specified");
+ return -1;
+ }
- return 0;
+ return 0;
}
/* CONNECTION CMP */
@@ -573,719 +483,692 @@ hc_connection_validate(const hc_connection_t * connection)
* As connections are specific to hicn-light, we can safely use IP and ports for
* comparison independently of the face type.
*/
-int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2)
-{
- int rc;
+int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) {
+ int rc;
- rc = INT_CMP(c1->type, c2->type);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->type, c2->type);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->family, c2->family);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->family, c2->family);
+ if (rc != 0) return rc;
- rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
- if (rc != 0)
- return rc;
+ rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family);
- if (rc != 0)
- return rc;
+ rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->local_port, c2->local_port);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->local_port, c2->local_port);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family);
- if (rc != 0)
- return rc;
+ rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->remote_port, c2->remote_port);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->remote_port, c2->remote_port);
+ if (rc != 0) return rc;
- return rc;
-}
-
-/* CONNECTION PARSE */
-
-int
-hc_connection_parse(void * in, hc_connection_t * connection)
-{
- int rc;
- list_connections_command * cmd = (list_connections_command *)in;
-
- if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connectionType))
- return -1;
-
- hc_connection_type_t type = map_from_list_connections_type[cmd->connectionData.connectionType];
- if (type == CONNECTION_TYPE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state))
- return -1;
-
- hc_connection_state_t state = map_from_list_connections_state[cmd->state];
- if (state == HC_CONNECTION_STATE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_ADDR_TYPE(cmd->connectionData.ipType))
- return -1;
-
- int family = map_from_addr_type[cmd->connectionData.ipType];
- if (!IS_VALID_FAMILY(family))
- return -1;
-
- *connection = (hc_connection_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = cmd->connectionData.localIp,
- //.local_addr = UNION_CAST(cmd->connectionData.localIp, ip_address_t),
- .local_port = ntohs(cmd->connectionData.localPort),
- .remote_addr = cmd->connectionData.remoteIp,
- //.remote_addr = UNION_CAST(cmd->connectionData.remoteIp, ip_address_t),
- .remote_port = ntohs(cmd->connectionData.remotePort),
- .admin_state = cmd->connectionData.admin_state,
-#ifdef WITH_POLICY
- .priority = cmd->connectionData.priority,
- .tags = cmd->connectionData.tags,
-#endif /* WITH_POLICY */
- .state = state,
- };
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", cmd->connectionData.symbolic);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_parse] Unexpected truncation of interface name string");
- return 0;
+ return rc;
}
/* CONNECTION SNPRINTF */
/* /!\ Please update constants in header file upon changes */
-int
-hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection)
-{
- char local[MAXSZ_URL];
- char remote[MAXSZ_URL];
- int rc;
-
- // assert(connection->connection_state)
-
- rc = url_snprintf(local, MAXSZ_URL, connection->family,
- &connection->local_addr, connection->local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = url_snprintf(remote, MAXSZ_URL, connection->family,
- &connection->remote_addr, connection->remote_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "%s %s %s %s %s",
- connection_state_str[connection->state],
- connection->interface_name,
- local,
- remote,
- connection_type_str[connection->type]);
-}
-
-int hc_face_create(hc_sock_t *s, hc_face_t *face)
-{
- return s->hc_face_create(s, face);
+int hc_connection_snprintf(char *s, size_t size,
+ const hc_connection_t *connection) {
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
+ int rc;
+
+ // assert(connection->connection_state)
+ if (strcmp(connection->name, "SELF") == 0) {
+ return snprintf(s, size, "%s", connection->name);
+ }
+
+ rc = url_snprintf(local, MAXSZ_URL, connection->family,
+ &connection->local_addr, connection->local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, connection->family,
+ &connection->remote_addr, connection->remote_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+
+ return snprintf(s, size, "%s %s %s %s", connection->name, local, remote,
+ face_type_str(connection->type));
}
-int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found)
-{
- return s->hc_face_get(s, face, face_found);
+int hc_face_create(hc_sock_t *s, hc_face_t *face) {
+ return s->hc_face_create(s, face);
}
-int hc_face_delete(hc_sock_t *s, hc_face_t *face)
-{
- return s->hc_face_delete(s, face);
+int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found) {
+ return s->hc_face_get(s, face, face_found);
}
-int hc_face_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_face_list(s, pdata);
+int hc_face_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener) {
+ return s->hc_face_delete(s, face, delete_listener);
}
-int hc_face_list_async(hc_sock_t *s)
-{
- return s->hc_face_list_async(s);
+int hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_face_list(s, pdata);
}
-int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
-{
- return s->hc_face_set_admin_state(s, conn_id_or_name, state);
+int hc_face_list_async(hc_sock_t *s) { return s->hc_face_list_async(s); }
+
+int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
+ return s->hc_face_set_admin_state(s, conn_id_or_name, state);
}
#ifdef WITH_POLICY
-int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
-{
- return s->hc_face_set_priority(s, conn_id_or_name, priority);
+int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return s->hc_face_set_priority(s, conn_id_or_name, priority);
}
-int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
-{
- return s->hc_face_set_tags(s, conn_id_or_name, tags);
+int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return s->hc_face_set_tags(s, conn_id_or_name, tags);
}
#endif /* WITH_POLICY */
/* /!\ Please update constants in header file upon changes */
-int
-hc_face_snprintf(char * s, size_t size, hc_face_t * face)
-{
- /* URLs are also big enough to contain IP addresses in the hICN case */
- char local[MAXSZ_URL];
- char remote[MAXSZ_URL];
+int hc_face_snprintf(char *s, size_t size, hc_face_t *face) {
+ /* URLs are also big enough to contain IP addresses in the hICN case */
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
#ifdef WITH_POLICY
- char tags[MAXSZ_POLICY_TAGS];
+ char tags[MAXSZ_POLICY_TAGS];
#endif /* WITH_POLICY */
- int rc;
-
- switch(face->face.type) {
- case FACE_TYPE_HICN:
- case FACE_TYPE_HICN_LISTENER:
- rc = ip_address_snprintf(local, MAXSZ_URL,
- &face->face.local_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = ip_address_snprintf(remote, MAXSZ_URL,
- &face->face.remote_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- rc = url_snprintf(local, MAXSZ_URL, face->face.family,
- &face->face.local_addr,
- face->face.local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
- &face->face.remote_addr,
- face->face.remote_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- default:
- return -1;
- }
+ int rc;
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ rc = ip_address_snprintf(local, MAXSZ_URL, &face->face.local_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = ip_address_snprintf(remote, MAXSZ_URL, &face->face.remote_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ break;
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ rc = url_snprintf(local, MAXSZ_URL, face->face.family,
+ &face->face.local_addr, face->face.local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
+ &face->face.remote_addr, face->face.remote_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ break;
+ default:
+ return -1;
+ }
// [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
#ifdef WITH_POLICY
- rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
- if (rc >= MAXSZ_POLICY_TAGS)
- WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state],
- face->face.priority,
- tags);
+ rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
+ if (rc >= MAXSZ_POLICY_TAGS)
+ WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
+ if (rc < 0) return rc;
+
+ return snprintf(
+ s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX
+ ? face->face.netdevice.name
+ : "*",
+ face_type_str(face->face.type), local, remote,
+ face_state_str(face->face.state), face_state_str(face->face.admin_state),
+ face->face.priority, tags);
#else
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state]);
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s", face->id, face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX
+ ? face->face.netdevice.name
+ : "*",
+ face_type_str(face->face.type), local, remote,
+ face_state_str(face->face.state),
+ face_state_str(face->face.admin_state));
#endif /* WITH_POLICY */
}
-int
-hc_connection_parse_to_face(void * in, hc_face_t * face)
-{
- hc_connection_t connection;
-
- if (hc_connection_parse(in, &connection) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not parse connection");
- return -1;
- }
+/*----------------------------------------------------------------------------*
+ * ROUTE
+ *----------------------------------------------------------------------------*/
- if (hc_connection_to_face(&connection, face) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not convert connection to face.");
- return -1;
- }
-
- return 0;
+int hc_route_create(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_create(s, route);
}
-int hc_route_create(hc_sock_t * s, hc_route_t * route)
-{
- return s->hc_route_create(s, route);
+hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_create_conf(s, route);
}
-int hc_route_delete(hc_sock_t * s, hc_route_t * route)
-{
- return s->hc_route_delete(s, route);
+int hc_route_delete(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_delete(s, route);
}
-int hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return s->hc_route_list(s, pdata);
+int hc_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_route_list(s, pdata);
}
-int hc_route_list_async(hc_sock_t * s)
-{
- return s->hc_route_list_async(s);
-}
+int hc_route_list_async(hc_sock_t *s) { return s->hc_route_list_async(s); }
-/* ROUTE PARSE */
+/* ROUTE SNPRINTF */
-int
-hc_route_parse(void * in, hc_route_t * route)
-{
- list_routes_command * cmd = (list_routes_command *) in;
+/* /!\ Please update constants in header file upon changes */
+int hc_route_snprintf(char *s, size_t size, hc_route_t *route) {
+ /* interface cost prefix length */
- if (!IS_VALID_ADDR_TYPE(cmd->addressType)) {
- ERROR("[hc_route_parse] Invalid address type");
- return -1;
- }
+ char prefix[MAXSZ_IP_ADDRESS];
+ int rc;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family)) {
- ERROR("[hc_route_parse] Invalid address family");
- return -1;
- }
+ rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr,
+ route->family);
+ if (rc >= MAXSZ_IP_ADDRESS)
+ ;
+ if (rc < 0) return rc;
- *route = (hc_route_t) {
- .face_id = cmd->connid,
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .cost = cmd->cost,
- };
- return 0;
+ return snprintf(s, size, "%s %*d %s %*d conn_id=%d", route->name, MAXSZ_COST,
+ route->cost, prefix, MAXSZ_LEN, route->len, route->face_id);
}
-/* ROUTE SNPRINTF */
-
-/* /!\ Please update constants in header file upon changes */
-int
-hc_route_snprintf(char * s, size_t size, hc_route_t * route)
-{
- /* interface cost prefix length */
-
- char prefix[MAXSZ_IP_ADDRESS];
- int rc;
-
- rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr,
- route->family);
- if (rc >= MAXSZ_IP_ADDRESS)
- ;
- if (rc < 0)
- return rc;
+int hc_route_validate(const hc_route_t *route) {
+ if (!IS_VALID_ID(route->connection_id)) {
+ ERROR("[hc_route_validate] Invalid connection id");
+ return -1;
+ }
+ if (!IS_VALID_NAME(route->name) && !IS_VALID_STR_ID(route->name)) {
+ ERROR("[hc_route_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(route->family)) {
+ ERROR("[hc_route_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&route->remote_addr, route->family)) {
+ ERROR("[hc_route_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_ROUTE_COST(route->cost)) {
+ ERROR("[hc_route_validate] Invalid cost");
+ return -1;
+ }
+ if (!IS_VALID_PREFIX_LEN(route->len)) {
+ ERROR("[hc_route_validate] Invalid len");
+ return -1;
+ }
- return snprintf(s, size, "%*d %*d %s %*d", MAXSZ_FACE_ID, route->face_id,
- MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, route->len);
+ return 0;
}
+/*----------------------------------------------------------------------------*
+ * FACE
+ *----------------------------------------------------------------------------*/
+
/* FACE -> LISTENER */
-int
-hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener)
-{
- const face_t * f = &face->face;
-
- switch(f->type) {
- case FACE_TYPE_HICN_LISTENER:
- break;
- case FACE_TYPE_TCP_LISTENER:
- break;
- case FACE_TYPE_UDP_LISTENER:
- break;
- default:
- return -1;
- }
- return -1; /* XXX Not implemented */
+int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) {
+ const face_t *f = &face->face;
+
+ switch (f->type) {
+ case FACE_TYPE_HICN_LISTENER:
+ break;
+ case FACE_TYPE_TCP_LISTENER:
+ break;
+ case FACE_TYPE_UDP_LISTENER:
+ break;
+ default:
+ return -1;
+ }
+ return -1; /* XXX Not implemented */
}
/* LISTENER -> FACE */
-int
-hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face)
-{
- return -1; /* XXX Not implemented */
+int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face) {
+ return -1; /* XXX Not implemented */
}
/* FACE -> CONNECTION */
-int
-hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name)
-{
- int rc;
- const face_t * f = &face->face;
-
- switch(f->type) {
- case FACE_TYPE_HICN:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_HICN,
- .family = f->family,
- .local_addr = f->local_addr,
- .local_port = 0,
- .remote_addr = f->remote_addr,
- .remote_port = 0,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection,
+ bool generate_name) {
+ int rc;
+
+ const face_t *f = &face->face;
+ switch (f->type) {
+ case FACE_TYPE_HICN:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_HICN,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = 0,
+ .remote_addr = f->remote_addr,
+ .remote_port = 0,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s",
+ };
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s",
f->netdevice.name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- break;
- case FACE_TYPE_TCP:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_TCP,
- .family = f->family,
- .local_addr = f->local_addr,
- .local_port = f->local_port,
- .remote_addr = f->remote_addr,
- .remote_port = f->remote_port,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of symbolic "
+ "name string");
+ break;
+ case FACE_TYPE_TCP:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_TCP,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- if (generate_name) {
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE());
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- } else {
- memset(connection->name, 0, SYMBOLIC_NAME_LEN);
- }
- break;
- case FACE_TYPE_UDP:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_UDP,
- .family = AF_INET,
- .local_addr = f->local_addr,
- .local_port = f->local_port,
- .remote_addr = f->remote_addr,
- .remote_port = f->remote_port,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+ };
+ if (generate_name) {
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE());
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of "
+ "symbolic name string");
+ } else {
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
+ }
+ break;
+ case FACE_TYPE_UDP:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_UDP,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- if (generate_name) {
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE());
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- } else {
- memset(connection->name, 0, SYMBOLIC_NAME_LEN);
- }
- snprintf(connection->interface_name, INTERFACE_LEN, "%s",
- f->netdevice.name);
- break;
- default:
- return -1;
- }
+ };
+ if (generate_name) {
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE());
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of "
+ "symbolic name string");
+ } else {
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
+ }
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
+ break;
+ default:
+ return -1;
+ }
- rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
- f->netdevice.name);
- if (rc >= INTERFACE_LEN)
- WARN("hc_face_to_connection] Unexpected truncation of interface name string");
+ connection->id = face->id;
+ rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "hc_face_to_connection] Unexpected truncation of interface name "
+ "string");
- return 0;
+ return 0;
}
/* CONNECTION -> FACE */
-int
-hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
-{
- int rc;
- switch (connection->type) {
- case CONNECTION_TYPE_TCP:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_TCP,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face) {
+ int rc;
+ switch (connection->type) {
+ case FACE_TYPE_TCP:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_TCP,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- case CONNECTION_TYPE_UDP:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_UDP,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+ },
+ };
+ break;
+ case FACE_TYPE_UDP:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_UDP,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- case CONNECTION_TYPE_HICN:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_HICN,
- .family = connection->family,
- .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
- .local_addr = connection->local_addr,
- .remote_addr = connection->remote_addr,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+ },
+ };
+ break;
+ case FACE_TYPE_HICN:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_HICN,
+ .family = connection->family,
+ .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
+ .local_addr = connection->local_addr,
+ .remote_addr = connection->remote_addr,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- default:
- return -1;
- }
- face->face.netdevice.name[0] = '\0';
- face->face.netdevice.index = 0;
- rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_to_face] Unexpected truncation of symbolic name string");
- rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", connection->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_to_face] Unexpected truncation of interface name string");
- netdevice_update_index(&face->face.netdevice);
- return 0;
+ },
+ };
+ break;
+ default:
+ return -1;
+ }
+ face->face.netdevice.name[0] = '\0';
+ face->face.netdevice.index = 0;
+ rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_to_face] Unexpected truncation of symbolic name "
+ "string");
+ rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s",
+ connection->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_to_face] Unexpected truncation of interface name "
+ "string");
+ netdevice_update_index(&face->face.netdevice);
+ return 0;
}
/* CONNECTION -> LISTENER */
-int
-hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener)
-{
- int rc;
- *listener = (hc_listener_t) {
- .id = ~0,
- .type = connection->type,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- };
- rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", RANDBYTE()); // generate name
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_to_local_listener] Unexpected truncation of symbolic name string");
- rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", connection->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_to_local_listener] Unexpected truncation of interface name string");
+int hc_connection_to_local_listener(const hc_connection_t *connection,
+ hc_listener_t *listener) {
+ int rc;
+
+ face_type_t listener_type;
+ switch (connection->type) {
+ case FACE_TYPE_UDP:
+ listener_type = FACE_TYPE_UDP_LISTENER;
+ break;
+ case FACE_TYPE_TCP:
+ listener_type = FACE_TYPE_TCP_LISTENER;
+ break;
+ default:
+ return -1;
+ }
- return 0;
+ *listener = (hc_listener_t){
+ .id = ~0,
+ .type = listener_type,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ };
+ rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u",
+ RANDBYTE()); // generate name
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_to_local_listener] Unexpected truncation of "
+ "symbolic name string");
+ rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s",
+ connection->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_to_local_listener] Unexpected truncation of "
+ "interface name string");
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+int hc_punting_create(hc_sock_t *s, hc_punting_t *punting) {
+ return s->hc_punting_create(s, punting);
}
-int hc_punting_create(hc_sock_t *s, hc_punting_t *punting)
-{
- return s->hc_punting_create(s, punting);
+int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found) {
+ return s->hc_punting_get(s, punting, punting_found);
}
-int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
- hc_punting_t **punting_found)
-{
- return s->hc_punting_get(s, punting, punting_found);
+int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
+ return s->hc_punting_delete(s, punting);
}
-int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting)
-{
- return s->hc_punting_delete(s, punting);
+int hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_punting_list(s, pdata);
}
-int hc_punting_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_punting_list(s, pdata);
+int hc_punting_validate(const hc_punting_t *punting) {
+ if (!IS_VALID_FAMILY(punting->family)) return -1;
+
+ /*
+ * We might use the zero value to add punting on all faces but this is not
+ * (yet) implemented
+ */
+ if (punting->face_id == 0) {
+ ERROR("Punting on all faces is not (yet) implemented.");
+ return -1;
+ }
+
+ return 0;
}
-int hc_punting_validate(const hc_punting_t * punting)
-{
- if (!IS_VALID_FAMILY(punting->family))
- return -1;
-
- /*
- * We might use the zero value to add punting on all faces but this is not
- * (yet) implemented
- */
- if (punting->face_id == 0) {
- ERROR("Punting on all faces is not (yet) implemented.");
- return -1;
- }
+int hc_punting_cmp(const hc_punting_t *p1, const hc_punting_t *p2) {
+ int rc;
- return 0;
+ rc = INT_CMP(p1->face_id, p2->face_id);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(p1->family, p2->family);
+ if (rc != 0) return rc;
+
+ rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(p1->prefix_len, p2->prefix_len);
+ if (rc != 0) return rc;
+
+ return rc;
}
-int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2)
-{
- int rc;
+int hc_punting_parse(void *in, hc_punting_t *punting) {
+ ERROR("hc_punting_parse not (yet) implemented.");
+ return -1;
+}
- rc = INT_CMP(p1->face_id, p2->face_id);
- if (rc != 0)
- return rc;
+int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting) {
+ ERROR("hc_punting_snprintf not (yet) implemented.");
+ return -1;
+}
- rc = INT_CMP(p1->family, p2->family);
- if (rc != 0)
- return rc;
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
- rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family);
- if (rc != 0)
- return rc;
+int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_set_store(s, cache);
+}
- rc = INT_CMP(p1->prefix_len, p2->prefix_len);
- if (rc != 0)
- return rc;
+int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_set_serve(s, cache);
+}
- return rc;
+int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_clear(s, cache);
}
-int hc_punting_parse(void * in, hc_punting_t * punting)
-{
- ERROR("hc_punting_parse not (yet) implemented.");
- return -1;
+int hc_cache_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_cache_list(s, pdata);
}
-int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting)
-{
- ERROR("hc_punting_snprintf not (yet) implemented.");
- return -1;
+int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info) {
+ return snprintf(
+ s, size, "Cache set_store=%s set_serve=%s size=%lu stale_entries=%lu",
+ cache_info->store ? "true" : "false",
+ cache_info->serve ? "true" : "false", (unsigned long)cache_info->cs_size,
+ (unsigned long)cache_info->num_stale_entries);
}
-int hc_cache_set_store(hc_sock_t *s, int enabled)
-{
- return s->hc_cache_set_store(s, enabled);
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+int hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_strategy_list(s, data);
}
-int hc_cache_set_serve(hc_sock_t *s, int enabled)
-{
- return s->hc_cache_set_serve(s, enabled);
+int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_set(s, strategy);
}
-int hc_strategy_list(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_strategy_list(s, data);
+int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_add_local_prefix(s, strategy);
}
-int hc_strategy_set(hc_sock_t *s /* XXX */)
-{
- return s->hc_strategy_set(s);
+hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_set_conf(s, strategy);
+}
+
+hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ return s->hc_strategy_add_local_prefix_conf(s, strategy);
}
/* /!\ Please update constants in header file upon changes */
-int
-hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy)
-{
- return snprintf(s, size, "%s", strategy->name);
+int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy) {
+ return snprintf(s, size, "%s", strategy->name);
}
-int hc_wldr_set(hc_sock_t *s /* XXX */)
-{
- return s->hc_wldr_set(s);
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+int hc_wldr_set(hc_sock_t *s /* XXX */) { return s->hc_wldr_set(s); }
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set(s, mapme->enabled);
}
-int hc_mapme_set(hc_sock_t *s, int enabled)
-{
- return s->hc_mapme_set(s, enabled);
+int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_discovery(s, mapme->enabled);
}
-int hc_mapme_set_discovery(hc_sock_t *s, int enabled)
-{
- return s->hc_mapme_set_discovery(s, enabled);
+int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_timescale(s, mapme->timescale);
}
-int hc_mapme_set_timescale(hc_sock_t *s, double timescale)
-{
- return s->hc_mapme_set_timescale(s, timescale);
+int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_retx(s, mapme->timescale);
}
-int hc_mapme_set_retx(hc_sock_t *s, double timescale)
-{
- return s->hc_mapme_set_retx(s, timescale);
+int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_send_update(s, mapme);
}
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
#ifdef WITH_POLICY
-/* POLICY PARSE */
+/* POLICY SNPRINTF */
-int
-hc_policy_parse(void * in, hc_policy_t * policy)
-{
- list_policies_command * cmd = (list_policies_command *) in;
+/* /!\ Please update constants in header file upon changes */
+int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy) { return 0; }
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return -1;
+int hc_policy_validate(const hc_policy_t *policy) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
- return -1;
+ return 0;
+}
- *policy = (hc_policy_t) {
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .policy = cmd->policy,
- };
- return 0;
+#endif /* WITH_POLICY */
+
+/*----------------------------------------------------------------------------*
+ * SUBSCRIPTION
+ *----------------------------------------------------------------------------*/
+int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) {
+ return s->hc_subscription_create(s, subscription);
}
-/* POLICY SNPRINTF */
+int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) {
+ return s->hc_subscription_delete(s, subscription);
+}
-/* /!\ Please update constants in header file upon changes */
-int
-hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy)
-{
- return 0;
+hc_result_t *hc_subscription_create_conf(hc_sock_t *s,
+ hc_subscription_t *subscription) {
+ return s->hc_subscription_create_conf(s, subscription);
+}
+
+hc_result_t *hc_subscription_delete_conf(hc_sock_t *s,
+ hc_subscription_t *subscription) {
+ return s->hc_subscription_delete_conf(s, subscription);
+}
+
+/*----------------------------------------------------------------------------*
+ * Result
+ *----------------------------------------------------------------------------*/
+
+hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_msg(result);
+}
+
+int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_cmd_id(result);
+}
+
+bool hc_result_get_success(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_success(result);
}
-#endif /* WITH_POLICY */ \ No newline at end of file
+void hc_result_free(hc_result_t *result) { free(result); }
diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h
index 3922e1f3c..11cb2e00e 100644
--- a/ctrl/libhicnctrl/src/api_private.h
+++ b/ctrl/libhicnctrl/src/api_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -17,10 +17,12 @@
#define HICN_API_PRIVATE_H
#include <hicn/ctrl/api.h>
-#include <hicn/ctrl/commands.h>
#include <hicn/util/token.h>
#include <hicn/util/log.h>
#include <hicn/util/map.h>
+#include <hicn/util/sstrncpy.h>
+#include <hicn/validation.h>
+#include <ctype.h>
#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0)
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
@@ -34,57 +36,64 @@
#endif
#define RANDBYTE() (u8)(rand() & 0xFF)
-hc_connection_type_t
-connection_type_from_str(const char * str);
-
-extern const hc_connection_type_t map_from_list_connections_type[];
-extern const hc_connection_type_t map_from_encap_type[];
-extern const connection_type map_to_connection_type[];
-extern const listener_mode map_to_listener_mode[];
-extern const hc_connection_state_t map_from_list_connections_state[];
-extern const int map_from_addr_type[];
-extern const address_type map_to_addr_type[];
-extern const char * connection_state_str[];
-extern const char * connection_type_str[];
-
-typedef enum {
- ENCAP_TCP,
- ENCAP_UDP,
- ENCAP_ETHER,
- ENCAP_LOCAL,
- ENCAP_HICN
-} EncapType;
-
-#define connection_state_to_face_state(x) ((face_state_t)(x))
-#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
+/*
+ * Input validation
+ */
+
+static inline bool IS_VALID_ADDRESS(const ip_address_t *addr, int family) {
+ char addr_str[INET6_ADDRSTRLEN];
+ return !ip_address_empty(addr) &&
+ ip_address_ntop(addr, addr_str, INET6_ADDRSTRLEN, family) >= 0;
+}
+
+static inline bool IS_VALID_PREFIX_LEN(u8 len) {
+ return len <= MAX_IPV6_PREFIX_LEN;
+}
+
+// https://github.com/shemminger/iproute2/blob/50b668bdbf0ebc270495eb4b352d0c3982159d0a/lib/utils.c#L825
+static inline bool IS_VALID_INTERFACE_NAME(const char *name) {
+ size_t len = strnlen_s(name, INTERFACE_LEN);
+ if (len == 0 || len >= IFNAMSIZ) return true;
+
+ while (*name) {
+ if (*name == '/' || isspace(*name)) return false;
+ ++name;
+ }
+ return true;
+}
+
+static inline bool IS_VALID_NAME(const char *name) {
+ return is_symbolic_name(name, SYMBOLIC_NAME_LEN);
+}
+
+static inline bool IS_VALID_STR_ID(const char *name) {
+ return is_number(name, SYMBOLIC_NAME_LEN);
+}
+
+#define IS_VALID_TYPE(x) IS_VALID_ENUM_TYPE(FACE_TYPE, x)
#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
-#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x)
+#define IS_VALID_ID(x) (1)
+#define IS_VALID_POLICY(x) (1)
typedef struct hc_sock_impl_s hc_sock_impl_t;
-int hc_data_ensure_available(hc_data_t * data, size_t count);
-u8 *hc_data_get_next(hc_data_t * data);
-int hc_data_set_error(hc_data_t * data);
+int hc_data_ensure_available(hc_data_t *data, size_t count);
+u8 *hc_data_get_next(hc_data_t *data);
+int hc_data_set_error(hc_data_t *data);
-int
-hc_connection_parse_to_face(void * in, hc_face_t * face);
+int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face);
-int
-hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face);
+int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face);
-int
-hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face);
+int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener);
-int
-hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener);
+int hc_connection_to_local_listener(const hc_connection_t *connection,
+ hc_listener_t *listener);
-int
-hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener);
-
-int
-hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name);
+int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection,
+ bool generate_name);
struct hc_sock_s {
int (*hc_sock_get_next_seq)(hc_sock_t *s);
@@ -92,17 +101,21 @@ struct hc_sock_s {
int (*hc_sock_get_fd)(hc_sock_t *s);
int (*hc_sock_connect)(hc_sock_t *s);
int (*hc_sock_get_available)(hc_sock_t *s, u8 **buffer, size_t *size);
- int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq);
+ int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq);
int (*hc_sock_recv)(hc_sock_t *s);
int (*hc_sock_process)(hc_sock_t *s, hc_data_t **data);
int (*hc_sock_callback)(hc_sock_t *s, hc_data_t **data);
int (*hc_sock_reset)(hc_sock_t *s);
void (*hc_sock_free)(hc_sock_t *s);
-
+ void (*hc_sock_increment_woff)(hc_sock_t *s, size_t bytes);
+ int (*hc_sock_prepare_send)(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb,
+ void *complete_cb_data);
+ int (*hc_sock_set_recv_timeout_ms)(hc_sock_t *s, long timeout_ms);
int (*hc_listener_create)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_create_async)(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);
+ hc_listener_t **listener_found);
int (*hc_listener_delete)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_delete_async)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_list)(hc_sock_t *s, hc_data_t **pdata);
@@ -114,81 +127,105 @@ struct hc_sock_s {
int (*hc_connection_create)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_create_async)(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);
+ hc_connection_t **connection_found);
int (*hc_connection_update_by_id)(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection);
+ hc_connection_t *connection);
int (*hc_connection_update)(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated);
+ hc_connection_t *connection_updated);
int (*hc_connection_delete)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_delete_async)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_connection_list_async)(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_cmp)(const hc_connection_t *c1,
+ const hc_connection_t *c2);
int (*hc_connection_parse)(void *in, hc_connection_t *connection);
- int (*hc_connection_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
- int (*hc_connection_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_connection_set_admin_state)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
+ int (*hc_connection_set_admin_state_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
- int (*hc_connection_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_connection_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_connection_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
- int (*hc_connection_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
-#endif // WITH_POLICY
+ int (*hc_connection_set_priority)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_connection_set_priority_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_connection_set_tags)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+ int (*hc_connection_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+#endif // WITH_POLICY
int (*hc_connection_snprintf)(char *s, size_t size,
- const hc_connection_t *connection);
+ const hc_connection_t *connection);
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_delete)(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener);
int (*hc_face_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_face_list_async)(hc_sock_t *s);
- int (*hc_face_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
- int (*hc_face_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_face_set_admin_state)(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
+ int (*hc_face_set_admin_state_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
- int (*hc_face_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_face_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_face_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
- int (*hc_face_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
-#endif // WITH_POLICY
+ int (*hc_face_set_priority)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_face_set_priority_async)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_face_set_tags)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+ int (*hc_face_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+#endif // WITH_POLICY
int (*hc_face_snprintf)(char *s, size_t size, hc_face_t *face);
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_create_async)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_delete)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_delete_async)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_list)(hc_sock_t * s, hc_data_t ** pdata);
- int (*hc_route_list_async)(hc_sock_t * s);
+ int (*hc_route_create)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_create_async)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_delete)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_delete_async)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_route_list_async)(hc_sock_t *s);
int (*hc_punting_create)(hc_sock_t *s, hc_punting_t *punting);
int (*hc_punting_create_async)(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);
+ 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);
- int (*hc_cache_set_store)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_serve)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_store_async)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_serve_async)(hc_sock_t *s, int enabled);
+ int (*hc_cache_parse)(void *in, hc_cache_info_t *cache_info);
+ int (*hc_cache_set_store)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_set_serve)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_clear)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_cache_set_store_async)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_set_serve_async)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_snprintf)(char *s, size_t size,
+ const hc_cache_info_t *cache_info);
int (*hc_strategy_list)(hc_sock_t *s, hc_data_t **data);
int (*hc_strategy_snprintf)(char *s, size_t size, hc_strategy_t *strategy);
- int (*hc_strategy_set)(hc_sock_t *s /* XXX */);
+ int (*hc_strategy_set)(hc_sock_t *s, hc_strategy_t *strategy);
+ int (*hc_strategy_add_local_prefix)(hc_sock_t *s, hc_strategy_t *strategy);
int (*hc_wldr_set)(hc_sock_t *s /* XXX */);
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);
+ int (*hc_mapme_set_timescale)(hc_sock_t *s, uint32_t timescale);
+ int (*hc_mapme_set_retx)(hc_sock_t *s, uint32_t timescale);
+ int (*hc_mapme_send_update)(hc_sock_t *s, hc_mapme_t *mapme);
#ifdef WITH_POLICY
int (*hc_policy_parse)(void *in, hc_policy_t *policy);
@@ -199,10 +236,34 @@ struct hc_sock_s {
int (*hc_policy_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_policy_list_async)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_policy_snprintf)(char *s, size_t size, hc_policy_t *policy);
-#endif // WITH_POLICY
+#endif // WITH_POLICY
+
+ int (*hc_subscription_create)(hc_sock_t *s, hc_subscription_t *subscription);
+ int (*hc_subscription_delete)(hc_sock_t *s, hc_subscription_t *subscription);
+
+ hc_result_t *(*hc_listener_create_conf)(hc_sock_t *s,
+ hc_listener_t *listener);
+ hc_result_t *(*hc_listener_list_conf)(hc_sock_t *s, hc_data_t **pdata);
+ hc_result_t *(*hc_connection_create_conf)(hc_sock_t *s,
+ hc_connection_t *connection);
+ hc_result_t *(*hc_connection_delete_conf)(hc_sock_t *s,
+ hc_connection_t *connection);
+ hc_result_t *(*hc_route_create_conf)(hc_sock_t *s, hc_route_t *route);
+ hc_result_t *(*hc_strategy_set_conf)(hc_sock_t *s, hc_strategy_t *strategy);
+ hc_result_t *(*hc_strategy_add_local_prefix_conf)(hc_sock_t *s,
+ hc_strategy_t *strategy);
+ hc_result_t *(*hc_subscription_create_conf)(hc_sock_t *s,
+ hc_subscription_t *subscription);
+ hc_result_t *(*hc_subscription_delete_conf)(hc_sock_t *s,
+ hc_subscription_t *subscription);
+
+ hc_msg_t *(*hc_result_get_msg)(hc_result_t *result);
+ bool (*hc_result_get_success)(hc_result_t *result);
+ int (*hc_result_get_cmd_id)(hc_result_t *result);
+ void (*hc_result_free)(hc_result_t *result);
// Reference to module containing the implementation
void *handle;
};
-#endif // HICN_API_PRIVATE_H \ No newline at end of file
+#endif // HICN_API_PRIVATE_H
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
deleted file mode 100644
index 064eb77e3..000000000
--- a/ctrl/libhicnctrl/src/cli.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * 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 cli.c
- * \brief Command line interface
- */
-#include <ctype.h> // isalpha isalnum
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h> // getopt
-
-#include <hicn/ctrl.h>
-#include <hicn/util/ip_address.h>
-#include <hicn/util/token.h>
-
-
-#define die(LABEL, MESSAGE) do { \
- printf(MESSAGE "\n"); \
- rc = -1; \
- goto ERR_ ## LABEL; \
-} while(0)
-
-#define foreach_object \
- _(UNDEFINED) \
- _(FACE) \
- _(ROUTE) \
- _(STRATEGY) \
- _(LISTENER) \
- _(CONNECTION) \
- _(N)
-
-typedef enum {
-#define _(x) OBJECT_ ## x,
-foreach_object
-#undef _
-} hc_object_t;
-
-#define HICNLIGHT_PARAM "hicnlight"
-#define VPP_PARAM "vpp"
-
-void
-usage_header()
-{
- fprintf(stderr, "Usage:\n");
-}
-
-void
-usage_face_create(const char * prog, bool header, bool verbose)
-{
-
- if (header)
- usage_header();
- fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a face on specified address and port.\n");
-}
-
-void
-usage_face_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -df ID\n", prog);
- //fprintf(stderr, "%s -df NAME\n", prog);
- fprintf(stderr, "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a face...\n");
-}
-
-void
-usage_face_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -F\n", prog);
- if (verbose)
- fprintf(stderr, " List all faces.\n");
-}
-
-void
-usage_face(const char * prog, bool header, bool verbose)
-{
- usage_face_create(prog, header, verbose);
- usage_face_delete(prog, header, verbose);
- usage_face_list(prog, header, verbose);
-}
-
-void
-usage_route_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
- //fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a route...\n");
-}
-
-void
-usage_route_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
- //fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a route...\n");
-}
-
-void
-usage_route_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -R\n", prog);
- if (verbose)
- fprintf(stderr, " List all routes.\n");
-}
-
-void
-usage_route(const char * prog, bool header, bool verbose)
-{
- usage_route_create(prog, header, verbose);
- usage_route_delete(prog, header, verbose);
- usage_route_list(prog, header, verbose);
-}
-
-void
-usage_forwarding_strategy_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-void
-usage_forwarding_strategy_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-
-void
-usage_forwarding_strategy_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -S\n", prog);
- if (verbose)
- fprintf(stderr, " List all availble forwarding strategies.\n");
-}
-
-void
-usage_forwarding_strategy(const char * prog, bool header, bool verbose)
-{
- usage_forwarding_strategy_create(prog, header, verbose);
- usage_forwarding_strategy_delete(prog, header, verbose);
- usage_forwarding_strategy_list(prog, header, verbose);
-}
-
-void
-usage_listener_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a listener on specified address and port.\n");
-}
-
-void
-usage_listener_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dl ID\n", prog);
- fprintf(stderr, "%s -dl NAME\n", prog);
- fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a listener...\n");
-}
-
-void
-usage_listener_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -L\n", prog);
- if (verbose)
- fprintf(stderr, " List all listeners.\n");
-}
-
-void
-usage_listener(const char * prog, bool header, bool verbose)
-{
- usage_listener_create(prog, header, verbose);
- usage_listener_delete(prog, header, verbose);
- usage_listener_list(prog, header, verbose);
-}
-void
-usage_connection_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a connection on specified address and port.\n");
-}
-
-void
-usage_connection_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dc ID\n", prog);
- fprintf(stderr, "%s -dc NAME\n", prog);
- fprintf(stderr, "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a connection...\n");
-}
-
-void
-usage_connection_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -C\n", prog);
- if (verbose)
- fprintf(stderr, " List all connections.\n");
-}
-
-void
-usage_connection(const char * prog, bool header, bool verbose)
-{
- usage_connection_create(prog, header, verbose);
- usage_connection_delete(prog, header, verbose);
- usage_connection_list(prog, header, verbose);
-}
-
-void usage(const char * prog)
-{
- fprintf(stderr, "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
- fprintf(stderr, "\n");
- fprintf(stderr, "High-level commands\n");
- fprintf(stderr, "\n");
- usage_face(prog, false, true);
- usage_route(prog, false, true);
- usage_forwarding_strategy(prog, false, true);
- fprintf(stderr, "\n");
- fprintf(stderr, "Low level commands (hicn-light specific)\n");
- fprintf(stderr, "\n");
- usage_listener(prog, false, true);
- usage_connection(prog, false, true);
-}
-
-typedef struct {
- hc_action_t action;
- hc_object_t object;
- union {
- hc_face_t face;
- hc_route_t route;
- hc_connection_t connection;
- hc_listener_t listener;
- };
-} hc_command_t;
-
-/**
- * Return true if string is purely an integer
- */
-static inline
-bool
-is_number(const char *string) {
- size_t len = strlen(string);
- for (size_t i = 0; i < len; i++)
- if (!isdigit(string[i]))
- return false;
- return true;
-}
-
-/**
- * A symbolic name must be at least 1 character and must begin with an alpha.
- * The remainder must be an alphanum.
- */
-static inline
-bool
-is_symbolic_name(const char *name)
-{
- size_t len = strlen(name);
- if (len <= 0)
- return false;
- if (!isalpha(name[0]))
- return false;
- for (size_t i = 1; i < len; i++) {
- if (!isalnum(name[i]))
- return false;
- }
- return true;
-}
-
-face_type_t
-face_type_from_str(const char * str)
-{
-#define _(x) \
- if (strcasecmp(str, STRINGIZE(x)) == 0) \
- return FACE_TYPE_ ## x; \
- else
-foreach_face_type
-#undef _
- return FACE_TYPE_UNDEFINED;
-}
-
-
-int
-parse_options(int argc, char *argv[], hc_command_t * command, forwarder_t *forwarder)
-{
- command->object = OBJECT_UNDEFINED;
- command->action = ACTION_CREATE;
- int opt;
- int family;
-
- while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) {
- switch (opt) {
- case 'z' :
- if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) {
- *forwarder = VPP;
- } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) {
- *forwarder = HICNLIGHT;
- } else {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 'd':
- command->action = ACTION_DELETE;
- break;
- case 'f':
- command->object = OBJECT_FACE;
- break;
- case 'l':
- command->object = OBJECT_LISTENER;
- break;
- case 'c':
- command->object = OBJECT_CONNECTION;
- break;
- case 'r':
- command->object = OBJECT_ROUTE;
- break;
- case 'F':
- command->action = ACTION_LIST;
- command->object = OBJECT_FACE;
- break;
- case 'L':
- command->action = ACTION_LIST;
- command->object = OBJECT_LISTENER;
- break;
- case 'C':
- command->action = ACTION_LIST;
- command->object = OBJECT_CONNECTION;
- break;
- case 'R':
- command->action = ACTION_LIST;
- command->object = OBJECT_ROUTE;
- break;
- case 'S':
- command->action = ACTION_LIST;
- command->object = OBJECT_STRATEGY;
- break;
- default: /* "h" */
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- }
- }
-
- if (command->object == OBJECT_UNDEFINED) {
- fprintf(stderr, "Missing object specification: connection | listener | route\n");
- return -1;
- }
-
- /* Parse and validate parameters for add/delete */
- switch(command->object) {
- case OBJECT_FACE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 5) && (argc - optind != 6)) {
- usage_face_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- /* NAME will be autogenerated (and currently not used) */
- //snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- command->face.face.netdevice.index = atoi(argv[optind++]);
- }
-
- break;
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_face_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->face.id = atoi(argv[optind++]);
- snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- //} else if (is_symbolic_name(argv[optind])) {
- // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- command->face.face.netdevice.index = atoi(argv[optind++]);
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_face_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_ROUTE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 2) && (argc - optind != 3)) {
- usage_route_create(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
-
- if (argc != optind) {
- printf("parse cost\n");
- command->route.cost = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if (argc - optind != 2) {
- usage_route_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_route_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_STRATEGY:
- switch(command->action) {
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_forwarding_strategy_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 4) && (argc - optind != 5)) {
- usage_listener_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) {
- usage_listener_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->listener.id = atoi(argv[optind++]);
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_listener_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_CONNECTION:
- switch(command->action) {
- case ACTION_CREATE:
- /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
- if ((argc - optind != 6) && (argc - optind != 7)) {
- usage_connection_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
-
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_connection_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->connection.id = atoi(argv[optind++]);
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_connection_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
-
- return 0;
-
-ERR_PARAM:
-ERR_COMMAND:
- return -1;
-}
-
-int main(int argc, char *argv[])
-{
- hc_data_t * data;
- int rc = 1;
- hc_command_t command = {0};
- char buf_listener[MAXSZ_HC_LISTENER];
- char buf_connection[MAXSZ_HC_CONNECTION];
- char buf_route[MAXSZ_HC_ROUTE];
- char buf_strategy[MAXSZ_HC_STRATEGY];
-
- forwarder_t forwarder = HICNLIGHT;
-
- if (parse_options(argc, argv, &command, &forwarder) < 0)
- die(OPTIONS, "Bad arguments");
-
- hc_sock_t * s = hc_sock_create_forwarder(forwarder);
- if (!s)
- die(SOCKET, "Error creating socket.");
-
- if (hc_sock_connect(s) < 0)
- die(CONNECT, "Error connecting to the forwarder.");
-
- switch(command.object) {
- case OBJECT_FACE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_face_create(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_face_delete(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_face_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Faces:\n");
- foreach_face(f, data) {
- if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", f->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
- case OBJECT_ROUTE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_route_create(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_route_delete(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_route_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Routes:\n");
- foreach_route(r, data) {
- if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= MAXSZ_HC_ROUTE)
- die(COMMAND, "Display error");
- printf("%s\n", buf_route);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for route");
- break;
- }
- break;
-
- case OBJECT_STRATEGY:
- switch(command.action) {
- case ACTION_LIST:
- if (hc_strategy_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Forwarding strategies:\n");
- foreach_strategy(st, data) {
- if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= MAXSZ_HC_STRATEGY)
- die(COMMAND, "Display error");
- printf("%s\n", buf_strategy);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for strategy");
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_listener_create(s, &command.listener) < 0)
- die(COMMAND, "Error creating listener");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_listener_delete(s, &command.listener) < 0)
- die(COMMAND, "Error deleting listener");
- printf("OK\n");
- break;
- break;
- case ACTION_LIST:
- if (hc_listener_list(s, &data) < 0)
- die(COMMAND, "Error getting listeners.");
-
- printf("Listeners:\n");
- foreach_listener(l, data) {
- if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
- die(COMMAND, "Display error");
- printf("[%d] %s\n", l->id, buf_listener);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for listener");
- break;
- }
- break;
-
- case OBJECT_CONNECTION:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_connection_create(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_connection_delete(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_LIST:
- if (hc_connection_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Connections:\n");
- foreach_connection(c, data) {
- if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", c->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
- default:
- die(COMMAND, "Unsupported object");
- break;
- }
-
-ERR_COMMAND:
-ERR_CONNECT:
- hc_sock_free(s);
-ERR_SOCKET:
-ERR_OPTIONS:
- return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c
deleted file mode 100644
index e617ff8a4..000000000
--- a/ctrl/libhicnctrl/src/face.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * 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.c
- * \brief Implementation of face abstraction
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <hicn/util/token.h>
-
-#include <hicn/ctrl/face.h>
-#include "util/hash.h"
-
-#define member_size(type, member) sizeof(((type *)0)->member)
-
-
-/* Netdevice */
-
-const char * netdevice_type_str[] = {
-#define _(x) [NETDEVICE_TYPE_ ## x] = STRINGIZE(x),
-foreach_netdevice_type
-#undef _
-};
-
-netdevice_t *
-netdevice_create_from_index(u32 index)
-{
- netdevice_t * netdevice = malloc(sizeof(netdevice_t));
- if (!netdevice)
- goto ERR_MALLOC;
-
- int rc = netdevice_set_index(netdevice, index);
- if (rc < 0)
- goto ERR_INIT;
-
- return netdevice;
-
-ERR_INIT:
- free(netdevice);
-ERR_MALLOC:
- return NULL;
-}
-
-netdevice_t *
-netdevice_create_from_name(const char * name)
-{
- netdevice_t * netdevice = malloc(sizeof(netdevice_t));
- if (!netdevice)
- goto ERR_MALLOC;
-
- int rc = netdevice_set_name(netdevice, name);
- if (rc < 0)
- goto ERR_INIT;
-
- return netdevice;
-
-ERR_INIT:
- free(netdevice);
-ERR_MALLOC:
- return NULL;
-}
-
-/**
- * \brief Update the index of the netdevice based on the name
- */
-int
-netdevice_update_index(netdevice_t * netdevice)
-{
- netdevice->index = if_nametoindex(netdevice->name);
- if (netdevice->index == 0)
- return -1;
- return 0;
-}
-
-int
-netdevice_update_name(netdevice_t * netdevice)
-{
- if (!if_indextoname(netdevice->index, netdevice->name))
- return -1;
- return 0;
-}
-
-void
-netdevice_free(netdevice_t * netdevice)
-{
- free(netdevice);
-}
-
-int
-netdevice_get_index(const netdevice_t * netdevice, u32 * index)
-{
- if (netdevice->index == 0)
- return -1;
- *index = netdevice->index;
- return 0;
-}
-
-int
-netdevice_set_index(netdevice_t * netdevice, u32 index)
-{
- netdevice->index = index;
- return netdevice_update_name(netdevice);
-}
-
-int
-netdevice_get_name(const netdevice_t * netdevice, const char ** name)
-{
- if (netdevice->name[0] == '\0')
- return -1;
- *name = netdevice->name;
- return 0;
-}
-
-int
-netdevice_set_name(netdevice_t * netdevice, const char * name)
-{
- memset(netdevice->name, 0, sizeof(netdevice->name));
- int rc = snprintf(netdevice->name, IFNAMSIZ, "%s", name);
- if (rc < 0)
- return -1;
- if (rc >= IFNAMSIZ)
- return -2; /* truncated */
- return netdevice_update_index(netdevice);
-}
-
-int
-netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2)
-{
- return (nd1->index - nd2->index);
-}
-
-
-/* Face state */
-
-const char * face_state_str[] = {
-#define _(x) [FACE_STATE_ ## x] = STRINGIZE(x),
-foreach_face_state
-#undef _
-};
-
-
-/* Face type */
-
-const char * face_type_str[] = {
-#define _(x) [FACE_TYPE_ ## x] = STRINGIZE(x),
-foreach_face_type
-#undef _
-};
-
-
-/* Face */
-
-int
-face_initialize(face_t * face)
-{
- memset(face, 0, sizeof(face_t)); /* 0'ed for hash */
- return 1;
-}
-
-int
-face_initialize_udp(face_t * face, const char * interface_name, const
- ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port,
- int family)
-{
- if (!local_addr)
- return -1;
-
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = family,
- .local_addr = *local_addr,
- .local_port = local_port,
- .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY,
- .remote_port = remote_port,
- };
-
- snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name);
-
- return 1;
-}
-
-int
-face_initialize_udp_sa(face_t * face, const char * interface_name,
- const struct sockaddr * local_addr,
- const struct sockaddr * remote_addr)
-{
- if (!local_addr)
- return -1;
-
- if (remote_addr && (local_addr->sa_family != remote_addr->sa_family))
- return -1;
-
- switch (local_addr->sa_family) {
- case AF_INET:
- {
- struct sockaddr_in *lsai = (struct sockaddr_in *)local_addr;
- struct sockaddr_in *rsai = (struct sockaddr_in *)remote_addr;
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = AF_INET,
- .local_addr.v4.as_inaddr = lsai->sin_addr,
- .local_port = lsai ? ntohs(lsai->sin_port) : 0,
- .remote_addr = IP_ADDRESS_EMPTY,
- .remote_port = rsai ? ntohs(rsai->sin_port) : 0,
- };
- if (rsai)
- face->remote_addr.v4.as_inaddr = rsai->sin_addr;
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 *lsai = (struct sockaddr_in6 *)local_addr;
- struct sockaddr_in6 *rsai = (struct sockaddr_in6 *)remote_addr;
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = AF_INET6,
- .local_addr.v6.as_in6addr = lsai->sin6_addr,
- .local_port = lsai ? ntohs(lsai->sin6_port) : 0,
- .remote_addr = IP_ADDRESS_EMPTY,
- .remote_port = rsai ? ntohs(rsai->sin6_port) : 0,
- };
- if (rsai)
- face->remote_addr.v6.as_in6addr = rsai->sin6_addr;
- }
- break;
- default:
- return -1;
- }
-
- snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name);
-
- return 1;
-}
-
-face_t * face_create()
-{
- face_t * face = calloc(1, sizeof(face_t)); /* 0'ed for hash */
- return face;
-}
-
-face_t * face_create_udp(const char * interface_name,
- const ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port, int family)
-{
- face_t * face = face_create();
- if (face_initialize_udp(face, interface_name, local_addr, local_port, remote_addr, remote_port, family) < 0)
- goto ERR_INIT;
- return face;
-
-ERR_INIT:
- free(face);
- return NULL;
-}
-
-face_t * face_create_udp_sa(const char * interface_name,
- const struct sockaddr * local_addr,
- const struct sockaddr * remote_addr)
-{
- face_t * face = face_create();
- if (face_initialize_udp_sa(face, interface_name, local_addr, remote_addr) < 0)
- goto ERR_INIT;
- return face;
-
-ERR_INIT:
- free(face);
- return NULL;
-}
-
-void face_free(face_t * face)
-{
- free(face);
-}
-
-/**
- * \brief Compare two faces
- * \param [in] f1 - First face
- * \param [in] f2 - Second face
- * \return whether faces are equal, ie both their types are parameters are
- * equal.
- *
- * NOTE: this function implements a partial order.
- */
-int
-face_cmp(const face_t * f1, const face_t * f2)
-{
-
- int ret = f1->type - f2->type;
- if (ret != 0)
- return ret;
-
- ret = f1->family - f2->family;
- if (ret != 0)
- return ret;
-
- /*
- * FIXME As hicn-light API might not return the netdevice, we can discard the
- * comparison when one of the two is not set for now...
- */
- if ((f1->netdevice.index != 0) && (f2->netdevice.index != 0)) {
- ret = netdevice_cmp(&f1->netdevice, &f2->netdevice);
- if (ret != 0)
- return ret;
- }
-
- switch(f1->type) {
- case FACE_TYPE_HICN:
- ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
- if (ret != 0)
- return ret;
-
- break;
-
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = f1->local_port - f2->local_port;
- if (ret != 0)
- return ret;
-
- ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = f1->remote_port - f2->remote_port;
- if (ret != 0)
- return ret;
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-unsigned int
-face_hash(const face_t * face)
-{
- /* Assuming the unused part of the struct is set to zero */
- return hash_struct(face);
-}
-
-/* /!\ Please update constants in header file upon changes */
-size_t
-face_snprintf(char * s, size_t size, const face_t * face)
-{
- switch(face->type) {
- case FACE_TYPE_HICN:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
- char tags[MAXSZ_POLICY_TAGS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->local_addr,
- face->family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->remote_addr,
- face->family);
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
- return snprintf(s, size, "%s [%s -> %s] [%s]",
- face_type_str[face->type],
- local,
- remote,
- tags);
- }
- case FACE_TYPE_UNDEFINED:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
- char tags[MAXSZ_POLICY_TAGS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->local_addr,
- face->family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->remote_addr,
- face->family);
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
-
- return snprintf(s, size, "%s [%s:%d -> %s:%d] [%s]",
- face_type_str[face->type],
- local,
- face->local_port,
- remote,
- face->remote_port,
- tags);
- }
- default:
- return -1;
- }
-
-}
-
-policy_tags_t face_get_tags(const face_t * face)
-{
- return face->tags;
-}
-
-int
-face_set_tags(face_t * face, policy_tags_t tags)
-{
- face->tags = tags;
- return 1;
-}
diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c
new file mode 100644
index 000000000..99d67b19f
--- /dev/null
+++ b/ctrl/libhicnctrl/src/hicnctrl.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2021 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 cli.c
+ * \brief Command line interface
+ */
+#include <ctype.h> // isalpha isalnum
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h> // getopt
+
+#include <hicn/ctrl.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/token.h>
+#include <hicn/validation.h>
+
+#define die(LABEL, MESSAGE) \
+ do { \
+ printf(MESSAGE "\n"); \
+ rc = -1; \
+ goto ERR_##LABEL; \
+ } while (0)
+
+const char HICNLIGHT_PARAM[] = "hicnlight";
+const char HICNLIGHT_NG_PARAM[] = "hicnlightng";
+const char VPP_PARAM[] = "vpp";
+
+void usage_header() { fprintf(stderr, "Usage:\n"); }
+
+void usage_face_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr,
+ "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a face on specified address and port.\n");
+}
+
+void usage_face_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -df ID\n", prog);
+ // fprintf(stderr, "%s -df NAME\n", prog);
+ fprintf(stderr,
+ "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a face...\n");
+}
+
+void usage_face_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -F\n", prog);
+ if (verbose) fprintf(stderr, " List all faces.\n");
+}
+
+void usage_face(const char *prog, bool header, bool verbose) {
+ usage_face_create(prog, header, verbose);
+ usage_face_delete(prog, header, verbose);
+ usage_face_list(prog, header, verbose);
+}
+
+void usage_route_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
+ // fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
+ if (verbose) fprintf(stderr, " Create a route...\n");
+}
+
+void usage_route_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
+ // fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
+ if (verbose) fprintf(stderr, " Delete a route...\n");
+}
+
+void usage_route_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -R\n", prog);
+ if (verbose) fprintf(stderr, " List all routes.\n");
+}
+
+void usage_route(const char *prog, bool header, bool verbose) {
+ usage_route_create(prog, header, verbose);
+ usage_route_delete(prog, header, verbose);
+ usage_route_list(prog, header, verbose);
+}
+
+void usage_forwarding_strategy_create(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+}
+void usage_forwarding_strategy_delete(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+}
+
+void usage_forwarding_strategy_list(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -S\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all availble forwarding strategies.\n");
+}
+
+void usage_forwarding_strategy(const char *prog, bool header, bool verbose) {
+ usage_forwarding_strategy_create(prog, header, verbose);
+ usage_forwarding_strategy_delete(prog, header, verbose);
+ usage_forwarding_strategy_list(prog, header, verbose);
+}
+
+void usage_listener_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a listener on specified address and port.\n");
+}
+
+void usage_listener_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dl ID\n", prog);
+ fprintf(stderr, "%s -dl NAME\n", prog);
+ fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a listener...\n");
+}
+
+void usage_listener_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -L\n", prog);
+ if (verbose) fprintf(stderr, " List all listeners.\n");
+}
+
+void usage_listener(const char *prog, bool header, bool verbose) {
+ usage_listener_create(prog, header, verbose);
+ usage_listener_delete(prog, header, verbose);
+ usage_listener_list(prog, header, verbose);
+}
+void usage_connection_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr,
+ "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a connection on specified address and port.\n");
+}
+
+void usage_connection_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dc ID\n", prog);
+ fprintf(stderr, "%s -dc NAME\n", prog);
+ fprintf(stderr,
+ "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a connection...\n");
+}
+
+void usage_connection_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -C\n", prog);
+ if (verbose) fprintf(stderr, " List all connections.\n");
+}
+
+void usage_connection(const char *prog, bool header, bool verbose) {
+ usage_connection_create(prog, header, verbose);
+ usage_connection_delete(prog, header, verbose);
+ usage_connection_list(prog, header, verbose);
+}
+
+void usage(const char *prog) {
+ fprintf(stderr,
+ "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] "
+ "PARAMETERS | [-F|-L|-C|-R] ]\n",
+ prog);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "High-level commands\n");
+ fprintf(stderr, "\n");
+ usage_face(prog, false, true);
+ usage_route(prog, false, true);
+ usage_forwarding_strategy(prog, false, true);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Low level commands (hicn-light specific)\n");
+ fprintf(stderr, "\n");
+ usage_listener(prog, false, true);
+ usage_connection(prog, false, true);
+}
+
+#if 0
+typedef struct {
+ hc_action_t action;
+ hc_object_t object;
+ union {
+ hc_face_t face;
+ hc_route_t route;
+ hc_connection_t connection;
+ hc_listener_t listener;
+ };
+} hc_command_t;
+#endif
+
+int parse_options(int argc, char *argv[], hc_command_t *command,
+ forwarder_type_t *forwarder) {
+ command->object.type = OBJECT_UNDEFINED;
+ command->action = ACTION_CREATE;
+ int opt;
+ int family;
+
+ while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) {
+ switch (opt) {
+ case 'z':
+ if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) {
+ *forwarder = VPP;
+ } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) {
+ *forwarder = HICNLIGHT;
+ } else if (strncmp(optarg, HICNLIGHT_NG_PARAM,
+ strlen(HICNLIGHT_NG_PARAM))) {
+ *forwarder = HICNLIGHT_NG;
+ } else {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'd':
+ command->action = ACTION_DELETE;
+ break;
+ case 'f':
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'c':
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'F':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'L':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_LISTENER;
+ break;
+ case 'C':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'R':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_ROUTE;
+ break;
+ case 'S':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_STRATEGY;
+ break;
+ default: /* "h" */
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (command->object.type == OBJECT_UNDEFINED) {
+ fprintf(stderr,
+ "Missing object specification: connection | listener | route\n");
+ return -1;
+ }
+
+ /* Parse and validate parameters for add/delete */
+ switch (command->object.type) {
+ case OBJECT_FACE:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 5) && (argc - optind != 6)) {
+ usage_face_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ /* NAME will be autogenerated (and currently not used) */
+ // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s",
+ // argv[optind++]);
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ // netdevice_set_name(&command->object.face.face.netdevice,
+ // argv[optind++]);
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ }
+
+ break;
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) &&
+ (argc - optind != 6)) {
+ usage_face_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.face.id = atoi(argv[optind++]);
+ snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ //} else if (is_symbolic_name(argv[optind])) {
+ // snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s",
+ // argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ // netdevice_set_name(&command->object.face.face.netdevice,
+ // argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_face_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 2) && (argc - optind != 3)) {
+ usage_route_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+
+ if (argc != optind) {
+ printf("parse cost\n");
+ command->object.route.cost = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if (argc - optind != 2) {
+ usage_route_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_route_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch (command->action) {
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_forwarding_strategy_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 4) && (argc - optind != 5)) {
+ usage_listener_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ command->object.listener.type = face_type_from_str(argv[optind++]);
+ if (command->object.listener.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family)) goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN,
+ "%s", argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 3) &&
+ (argc - optind != 4)) {
+ usage_listener_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.listener.id = atoi(argv[optind++]);
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) {
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.listener.type = face_type_from_str(argv[optind++]);
+ if (command->object.listener.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN,
+ "%s", argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_listener_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch (command->action) {
+ case ACTION_CREATE:
+ /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
+ if ((argc - optind != 6) && (argc - optind != 7)) {
+ usage_connection_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ command->object.connection.type = face_type_from_str(argv[optind++]);
+ if (command->object.connection.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) &&
+ (argc - optind != 6)) {
+ usage_connection_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.connection.id = atoi(argv[optind++]);
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) {
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.connection.type =
+ face_type_from_str(argv[optind++]);
+ if (command->object.connection.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_connection_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+
+ return 0;
+
+ERR_PARAM:
+ERR_COMMAND:
+ return -1;
+}
+
+int main(int argc, char *argv[]) {
+ hc_data_t *data;
+ int rc = 1;
+ hc_command_t command = {0};
+ char buf_listener[MAXSZ_HC_LISTENER];
+ char buf_connection[MAXSZ_HC_CONNECTION];
+ char buf_route[MAXSZ_HC_ROUTE];
+ char buf_strategy[MAXSZ_HC_STRATEGY];
+
+ forwarder_type_t forwarder = HICNLIGHT;
+
+ if (parse_options(argc, argv, &command, &forwarder) < 0)
+ die(OPTIONS, "Bad arguments");
+
+ hc_sock_t *s = hc_sock_create_forwarder(forwarder);
+ if (!s) die(SOCKET, "Error creating socket.");
+
+ if (hc_sock_connect(s) < 0)
+ die(CONNECT, "Error connecting to the forwarder.");
+
+ switch (command.object.type) {
+ case OBJECT_FACE:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_face_create(s, &command.object.face) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_face_delete(s, &command.object.face, 1) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_face_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Faces:\n");
+ foreach_face(f, data) {
+ if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >=
+ MAXSZ_HC_FACE)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", f->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_route_create(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_route_delete(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_route_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Routes:\n");
+ foreach_route(r, data) {
+ if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >=
+ MAXSZ_HC_ROUTE)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_route);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for route");
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch (command.action) {
+ case ACTION_LIST:
+ if (hc_strategy_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Forwarding strategies:\n");
+ foreach_strategy(st, data) {
+ if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >=
+ MAXSZ_HC_STRATEGY)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_strategy);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for strategy");
+ break;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_listener_create(s, &command.object.listener) < 0)
+ die(COMMAND, "Error creating listener");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_listener_delete(s, &command.object.listener) < 0)
+ die(COMMAND, "Error deleting listener");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_listener_list(s, &data) < 0)
+ die(COMMAND, "Error getting listeners.");
+
+ printf("Listeners:\n");
+ foreach_listener(l, data) {
+ if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >=
+ MAXSZ_HC_LISTENER)
+ die(COMMAND, "Display error");
+ printf("[%d] %s\n", l->id, buf_listener);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for listener");
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_connection_create(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_connection_delete(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_connection_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Connections:\n");
+ foreach_connection(c, data) {
+ if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION,
+ c) >= MAXSZ_HC_CONNECTION)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", c->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ default:
+ die(COMMAND, "Unsupported object");
+ break;
+ }
+
+ERR_COMMAND:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCKET:
+ERR_OPTIONS:
+ return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in
new file mode 100644
index 000000000..a27d85cde
--- /dev/null
+++ b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in
@@ -0,0 +1,8 @@
+@PACKAGE_INIT@
+
+set(Libhicnctrl_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libhicnctrl_VERSION_MINOR "@VERSION_MINOR@")
+set(Libhicnctrl_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libhicnctrl_INCLUDE_DIRS "@PACKAGE_Libhicnctrl_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libhicnctrl-targets.cmake")
diff --git a/ctrl/libhicnctrl/src/modules/CMakeLists.txt b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
index e07ab8c99..8f7916d14 100644
--- a/ctrl/libhicnctrl/src/modules/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -11,38 +11,53 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-
-list(APPEND HICNLIGHT_MODULE_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_api.c
+##############################################################
+# Hicn Light NG Module
+##############################################################
+list(APPEND HICNLIGHTNG_MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_ng_api.c
)
-build_module(hicnlightctrl_module
- SHARED
- SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+build_module(hicnlightngctrl_module
+ SOURCES ${HICNLIGHTNG_MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES}
+ INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS}
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS PRIVATE ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+
+##############################################################
+# VPP Module
+##############################################################
if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- list(APPEND HICNLIGHT_PLUGIN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c
+ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+ find_package(Safevapi ${CURRENT_VERSION} REQUIRED)
+ else()
+ list(APPEND DEPENDENCIES
+ ${SAFE_VAPI_SHARED}
+ )
+ endif()
+
+ list(APPEND HICN_PLUGIN_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c
)
build_module(vppctrl_module
- SHARED
- SOURCES ${HICNLIGHT_PLUGIN_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- LINK_LIBRARIES ${HICNPLUGIN_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
- LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs"
+ SOURCES ${HICN_PLUGIN_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ LINK_LIBRARIES
+ PRIVATE ${HICN_LIBRARIES}
+ PRIVATE ${HICNPLUGIN_LIBRARIES}
+ PRIVATE ${SAFE_VAPI_LIBRARIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES}
+ INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS}
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS} ${MARCH_COMPILER_OPTIONS}
)
-
-endif() \ No newline at end of file
+endif()
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_api.c
deleted file mode 100644
index d1a055777..000000000
--- a/ctrl/libhicnctrl/src/modules/hicn_light_api.c
+++ /dev/null
@@ -1,2278 +0,0 @@
-/*
- * 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.c
- * \brief Implementation of hICN control library API
- */
-
-#include "api_private.h"
-
-#include <assert.h> // assert
-#include <stdbool.h>
-#include <stdio.h> // snprintf
-#include <string.h> // memmove, strcasecmp
-#include <sys/socket.h> // socket
-#include <unistd.h> // close, fcntl
-#include <fcntl.h> // fcntl
-#include <sys/types.h> // getpid
-#include <unistd.h> // getpid
-#ifdef __linux__
-#include <sys/syscall.h>
-#define gettid() syscall(SYS_gettid)
-#endif /* __linux__ */
-#include <strings.h>
-
-#define PORT 9695
-
-#define BOOLSTR(x) ((x) ? "true" : "false")
-
-/*
- * Internal state associated to a pending request
- */
-typedef struct {
- int seq;
- hc_data_t * data;
- /* Information used to process results */
- int size_in;
- int (*parse)(const u8 * src, u8 * dst);
-} hc_sock_request_t;
-
-/**
- * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
- * the header_control_message structure. The forwarder simply answers back the
- * original sequence number. We maintain a map of such sequence number to
- * outgoing queries so that replied can be demultiplexed and treated
- * appropriately.
- */
-TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
-TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf);
-
-struct hc_sock_light_s {
- /* This must be the first element of the struct */
- hc_sock_t vft;
-
- char * url;
- int fd;
-
- /* 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;
-
- /* Next sequence number to be used for requests */
- int seq;
-
- /* Request being parsed (NULL if none) */
- hc_sock_request_t * cur_request;
-
- bool async;
- hc_sock_map_t * map;
-};
-
-typedef struct hc_sock_light_s hc_sock_light_t;
-
-#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t*)(s)
-
-hc_sock_request_t *
-hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse)
-{
- assert(data);
-
- hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t));
- if (!request)
- return NULL;
- request->seq = seq;
- request->data = data;
- request->parse = parse;
- return request;
-}
-
-void
-hc_sock_light_request_free(hc_sock_request_t * request)
-{
- free(request);
-}
-
-/*
- * list was working with all seq set to 0, but it seems hicnLightControl uses
- * 1, and replies with the same seqno
- */
-#define HICN_CTRL_SEND_SEQ_INIT 1
-#define HICN_CTRL_RECV_SEQ_INIT 1
-
-#define MAX(x, y) ((x > y) ? x : y)
-
-/**
- * In practise, we want to preserve enough room to store a full packet of
- * average expected size (say a header + N payload elements).
- */
-#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG)
-#define AVG_BUFLEN (sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t))
-
-/*
- * We should at least have buffer space allowing to store one processable unit
- * of data, either the header of the maximum possible payload
- */
-#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t))
-
-static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
-
-/******************************************************************************
- * Message helper types and aliases
- ******************************************************************************/
-
-#define foreach_hc_command \
- _(add_connection) \
- _(remove_connection) \
- _(list_connections) \
- _(add_listener) \
- _(remove_listener) \
- _(list_listeners) \
- _(add_route) \
- _(remove_route) \
- _(list_routes) \
- _(cache_store) \
- _(cache_serve) \
- /*_(cache_clear) */ \
- _(set_strategy) \
- _(set_wldr) \
- _(add_punting) \
- _(mapme_activator) \
- _(mapme_timing)
-
-typedef header_control_message hc_msg_header_t;
-
-typedef union {
-#define _(x) x ## _command x;
- foreach_hc_command
-#undef _
-} hc_msg_payload_t;
-
-
-typedef struct hc_msg_s {
- hc_msg_header_t hdr;
- hc_msg_payload_t payload;
-} hc_msg_t;
-
-/******************************************************************************
- * Control socket
- ******************************************************************************/
-
-/**
- * \brief Parse a connection URL into a sockaddr
- * \param [in] url - URL
- * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
- * \return 0 if parsing succeeded, a negative error value otherwise.
- */
-static int
-_hc_sock_light_parse_url(const char * url, struct sockaddr * sa)
-{
- /* FIXME URL parsing is currently not implemented */
- assert(!url);
-
-#ifdef __linux__
- srand(time(NULL) ^ getpid() ^ gettid());
-#else
- srand((unsigned int )(time(NULL) ^ getpid()));
-#endif /* __linux__ */
-
- /*
- * A temporary solution is to inspect the sa_family fields of the passed in
- * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
- * connection to localhost.
- */
- switch (sa->sa_family) {
- case AF_UNSPEC:
- case AF_INET:
- {
- struct sockaddr_in * sai = (struct sockaddr_in *)sa;
- sai->sin_family = AF_INET;
- sai->sin_port = htons(PORT);
- sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 * sai6 = (struct sockaddr_in6 *)sa;
- sai6->sin6_family = AF_INET6;
- sai6->sin6_port = htons(PORT);
- sai6->sin6_addr = loopback_addr;
- break;
- }
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int
-_hc_sock_light_reset(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- s->roff = s->woff = 0;
- s->remaining = 0;
- return 0;
-}
-
-void
-_hc_sock_light_free(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- hc_sock_request_t ** request_array = NULL;
- int n = hc_sock_map_get_value_array(s->map, &request_array);
- if (n < 0) {
- ERROR("Could not retrieve pending request array for freeing up resources");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hc_sock_request_t * request = request_array[i];
- if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
- ERROR("[hc_sock_light_process] Error removing request from map");
- hc_sock_light_request_free(request);
- }
- free(request_array);
- }
-
- hc_sock_map_free(s->map);
- if (s->url)
- free(s->url);
- close(s->fd);
- free(s);
-}
-
-static int
-_hc_sock_light_get_next_seq(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return s->seq++;
-}
-
-static int
-_hc_sock_light_set_nonblocking(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
-}
-
-static int
-_hc_sock_light_get_fd(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return s->fd;
-}
-
-static int
-_hc_sock_light_connect(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- struct sockaddr_storage ss;
- memset(&ss, 0, sizeof(struct sockaddr_storage));
-
- if (_hc_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0)
- goto ERR_PARSE;
-
- size_t size = ss.ss_family == AF_INET
- ? sizeof(struct sockaddr_in)
- : sizeof(struct sockaddr_in6);
- if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) //sizeof(struct sockaddr)) < 0)
- goto ERR_CONNECT;
-
- return 0;
-
-ERR_CONNECT:
-ERR_PARSE:
- return -1;
-}
-
-static int
-_hc_sock_light_send(hc_sock_t * socket, hc_msg_t * msg, size_t msglen, int seq)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int rc;
- msg->hdr.seqNum = seq;
- rc = (int)send(s->fd, msg, msglen, 0);
- if (rc < 0) {
- perror("hc_sock_light_send");
- return -1;
- }
- return 0;
-}
-
-static int
-_hc_sock_light_get_available(hc_sock_t * socket, u8 ** buffer, size_t * size)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- *buffer = s->buf + s->woff;
- *size = RECV_BUFLEN - s->woff;
-
- return 0;
-}
-
-static int
-_hc_sock_light_recv(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int rc;
-
- /*
- * This condition should be ensured to guarantee correct processing of
- * messages
- */
- assert(RECV_BUFLEN - s->woff > MIN_BUFLEN);
-
- rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
- if (rc == 0) {
- /* Connection has been closed */
- return 0;
- }
- if (rc < 0) {
- /*
- * Let's not return 0 which currently means the socket has been closed
- */
- if (errno == EWOULDBLOCK)
- return -1;
- perror("hc_sock_light_recv");
- return -1;
- }
- s->woff += rc;
- return rc;
-}
-
-/*
- * Returns -99 in case of internal error, -1 in case of API command failure
- */
-static int
-_hc_sock_light_process(hc_sock_t * socket, hc_data_t ** data)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int err = 0;
-
- /* We must have received at least one byte */
- size_t available = s->woff - s->roff;
-
- while(available > 0) {
-
- if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0)
- hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff);
-
- /* We expect a message header */
- if (available < sizeof(hc_msg_header_t)) {
- break;
- }
-
- hc_sock_request_t * request = NULL;
- if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) {
- ERROR("[hc_sock_light_process] Error searching for matching request");
- return -99;
- }
- if (!request) {
- ERROR("[hc_sock_light_process] No request matching received sequence number");
- return -99;
- }
-
- s->remaining = msg->hdr.length;
- switch(msg->hdr.messageType) {
- case ACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- s->cur_request = request;
- break;
- case NACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- hc_data_set_error(request->data);
- s->cur_request = request;
- err = -1;
- break;
- case RESPONSE_LIGHT:
- assert(data);
- if (s->remaining == 0) {
- hc_data_set_complete(request->data);
- *data = request->data;
- if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
- ERROR("[hc_sock_light_process] Error removing request from map");
- hc_sock_light_request_free(request);
- } else {
- /* We only remember it if there is still data to parse */
- s->cur_request = request;
- }
- break;
- default:
- ERROR("[hc_sock_light_process] Invalid response received");
- return -99;
- }
-
- available -= sizeof(hc_msg_header_t);
- s->roff += sizeof(hc_msg_header_t);
- } else {
- /* We expect the complete payload, or at least a chunk of it */
- size_t num_chunks = available / s->cur_request->data->in_element_size;
- if (num_chunks == 0)
- break;
- if (num_chunks > s->remaining)
- num_chunks = s->remaining;
-
- if (!s->cur_request->parse) {
- /* If we don't need to parse results, then we can directly push
- * all of them into the result data structure */
- hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks);
- } else {
- int rc;
- rc = hc_data_ensure_available(s->cur_request->data, num_chunks);
- if (rc < 0) {
- ERROR("[hc_sock_light_process] Error in hc_data_ensure_available");
- return -99;
- }
- for (int i = 0; i < num_chunks; i++) {
- u8 * dst = hc_data_get_next(s->cur_request->data);
- if (!dst) {
- ERROR("[hc_sock_light_process] Error in hc_data_get_next");
- return -99;
- }
-
- rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst);
- if (rc < 0) {
- ERROR("[hc_sock_light_process] Error in parse");
- err = -99; /* FIXME we let the loop complete (?) */
- }
- s->cur_request->data->size++;
- }
- }
-
- s->remaining -= num_chunks;
- available -= num_chunks * s->cur_request->data->in_element_size;
- s->roff += num_chunks * s->cur_request->data->in_element_size;
- if (s->remaining == 0) {
- if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
- ERROR("[hc_sock_light_process] Error removing request from map");
- return -99;
- }
- hc_data_set_complete(s->cur_request->data);
- if (data)
- *data = s->cur_request->data;
- hc_sock_light_request_free(s->cur_request);
- s->cur_request = NULL;
- }
-
- }
- }
-
- /* Make sure there is enough remaining space in the buffer */
- if (RECV_BUFLEN - s->woff < AVG_BUFLEN) {
- /*
- * There should be no overlap provided a sufficiently large BUFLEN, but
- * who knows.
- */
- memmove(s->buf, s->buf + s->roff, s->woff - s->roff);
- s->woff -= s->roff;
- s->roff = 0;
- }
-
- return err;
-}
-
-static int
-_hc_sock_light_callback(hc_sock_t * socket, hc_data_t ** pdata)
-{
- hc_data_t * data;
-
- for (;;) {
- int n = _hc_sock_light_recv(socket);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0) {
- switch(errno) {
- case ECONNRESET:
- case ENODEV:
- /* Forwarder restarted */
- WARN("Forwarder likely restarted: not (yet) implemented");
- goto ERR;
- case EWOULDBLOCK:
- //DEBUG("Would block... stop reading from socket");
- goto END;
- default:
- perror("hc_sock_light_recv");
- goto ERR;
- }
- }
- if (_hc_sock_light_process(socket, &data) < 0) {
- goto ERR;
- }
- }
-END:
- if (pdata)
- *pdata = data;
- else
- hc_data_free(data);
- return 0;
-
-ERR:
- hc_data_free(data);
-ERR_EOF:
- return -1;
-}
-
-/******************************************************************************
- * Command-specific structures and functions
- ******************************************************************************/
-
-typedef int (*HC_PARSE)(const u8 *, u8 *);
-
-typedef struct {
- hc_action_t cmd;
- command_id cmd_id;
- size_t size_in;
- size_t size_out;
- HC_PARSE parse;
-} hc_command_params_t;
-
-static int
-_hc_execute_command(hc_sock_t * socket, hc_msg_t * msg, size_t msg_len,
- hc_command_params_t * params, hc_data_t ** pdata, bool async)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int ret;
- if (async)
- assert(!pdata);
-
- /* Sanity check */
- switch(params->cmd) {
- case ACTION_CREATE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_DELETE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_LIST:
- assert(params->size_in != 0);
- assert(params->size_out != 0);
- assert(params->parse != NULL);
- break;
- case ACTION_SET:
- assert(params->size_in != 0);
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- default:
- return -1;
- }
-
- //hc_sock_light_reset(s);
-
- /* XXX data will at least store the result (complete) */
- hc_data_t * data = hc_data_create(params->size_in, params->size_out, NULL);
- if (!data) {
- ERROR("[_hc_execute_command] Could not create data storage");
- goto ERR_DATA;
- }
-
- int seq = _hc_sock_light_get_next_seq(socket);
-
- /* Create state used to process the request */
- hc_sock_request_t * request = NULL;
- request = hc_sock_request_create(seq, data, params->parse);
- if (!request) {
- ERROR("[_hc_execute_command] Could not create request state");
- goto ERR_REQUEST;
- }
-
- /* Add state to map */
- if (hc_sock_map_add(s->map, seq, request) < 0) {
- ERROR("[_hc_execute_command] Error adding request state to map");
- goto ERR_MAP;
- }
-
- if (_hc_sock_light_send(socket, msg, msg_len, seq) < 0) {
- ERROR("[_hc_execute_command] Error sending message");
- goto ERR_PROCESS;
- }
-
- if (async)
- return 0;
-
- while(!data->complete) {
- /*
- * As the socket is non blocking it might happen that we need to read
- * several times before success... shall we alternate between blocking
- * and non-blocking mode ?
- */
- int n = _hc_sock_light_recv(socket);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0)
- continue; //break;
- int rc = _hc_sock_light_process(socket, pdata);
- switch(rc) {
- case 0:
- break;
- case -1:
- ret = rc;
- break;
- case -99:
- ERROR("[_hc_execute_command] Error processing socket results");
- goto ERR;
- break;
- default:
- ERROR("[_hc_execute_command] Unexpected return value");
- goto ERR;
- }
- }
-
-ERR_EOF:
- ret = data->ret;
- if (!data->complete)
- return -1;
- if (!pdata)
- hc_data_free(data);
-
- return ret;
-
-ERR_PROCESS:
-ERR_MAP:
- hc_sock_light_request_free(request);
-ERR:
-ERR_REQUEST:
- hc_data_free(data);
-ERR_DATA:
- return -99;
-}
-
-/*----------------------------------------------------------------------------*
- * Listeners
- *----------------------------------------------------------------------------*/
-
-/* LISTENER CREATE */
-
-static int
-_hc_listener_create_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
-{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_create] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_create] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(listener->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return -1;
-
- struct {
- header_control_message hdr;
- add_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = listener->local_addr,
- .port = htons(listener->local_port),
- .addressType = (u8)map_to_addr_type[listener->family],
- .listenerMode = (u8)map_to_listener_mode[listener->type],
- .connectionType = (u8)map_to_connection_type[listener->type],
- }
- };
-
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of symbolic name string");
-
- rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of interface name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_LISTENER,
- .size_in = sizeof(add_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_create_internal(s, listener, false);
-}
-
-static int
-_hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_create_internal(s, listener, true);
-}
-
-/* LISTENER LIST */
-
-static int
-_hc_listener_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_LISTENERS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_LISTENERS,
- .size_in = sizeof(list_listeners_command),
- .size_out = sizeof(hc_listener_t),
- .parse = (HC_PARSE)hc_listener_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_listener_list_internal(s, pdata, false);
-}
-
-static int
-_hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_listener_list_internal(s, pdata, true);
-}
-
-/* LISTENER GET */
-
-static int
-_hc_listener_get(hc_sock_t * socket, hc_listener_t * listener,
- hc_listener_t ** listener_found)
-{
- hc_data_t * listeners;
- hc_listener_t * found;
-
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[hc_listener_get] Unexpected truncation of listener string");
- DEBUG("[hc_listener_get] listener=%s", listener_s);
-
- if (_hc_listener_list(socket, &listeners) < 0)
- return -1;
-
- /* Test */
- if (hc_listener_find(listeners, listener, &found) < 0) {
- hc_data_free(listeners);
- return -1;
- }
-
- if (found) {
- *listener_found = malloc(sizeof(hc_listener_t));
- if (!*listener_found)
- return -1;
- **listener_found = *found;
- } else {
- *listener_found = NULL;
- }
-
- hc_data_free(listeners);
-
- return 0;
-}
-
-
-/* LISTENER DELETE */
-
-static int
-_hc_listener_delete_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
-{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_delete] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_delete] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (listener->id) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else if (*listener->name) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_listener_t * listener_found;
- if (_hc_listener_get(socket, listener, &listener_found) < 0)
- return -1;
- if (!listener_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- free(listener_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_LISTENER,
- .size_in = sizeof(remove_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_delete_internal(s, listener, false);
-}
-
-static int
-_hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_delete_internal(s, listener, true);
-}
-
-/*----------------------------------------------------------------------------*
- * CONNECTION
- *----------------------------------------------------------------------------*/
-
-/* CONNECTION CREATE */
-
-static int
-_hc_connection_create_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
-{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_create] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_create] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- if (hc_connection_validate(connection) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .remoteIp = connection->remote_addr,
- .localIp = connection->local_addr,
- .remotePort = htons(connection->remote_port),
- .localPort = htons(connection->local_port),
- .ipType = (u8)map_to_addr_type[connection->family],
- .connectionType = (u8)map_to_connection_type[connection->type],
- .admin_state = connection->admin_state,
-#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
-#endif /* WITH_POLICY */
- }
- };
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_create] Unexpected truncation of symbolic name string");
- //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name);
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_CONNECTION,
- .size_in = sizeof(add_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_create_internal(s, connection, false);
-}
-
-static int
-_hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_create_internal(s, connection, true);
-}
-
-/* CONNECTION LIST */
-
-static int
-_hc_connection_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_connection_t),
- .parse = (HC_PARSE)hc_connection_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_connection_list_internal(s, pdata, false);
-}
-
-static int
-_hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_connection_list_internal(s, pdata, true);
-}
-
-/* CONNECTION GET */
-
-static int
-_hc_connection_get(hc_sock_t * socket, hc_connection_t * connection,
- hc_connection_t ** connection_found)
-{
- hc_data_t * connections;
- hc_connection_t * found;
-
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[hc_connection_get] Unexpected truncation of connection string");
- DEBUG("[hc_connection_get] connection=%s", connection_s);
-
- if (_hc_connection_list(socket, &connections) < 0)
- return -1;
-
- /* Test */
- if (hc_connection_find(connections, connection, &found) < 0) {
- hc_data_free(connections);
- return -1;
- }
-
- if (found) {
- *connection_found = malloc(sizeof(hc_connection_t));
- if (!*connection_found)
- return -1;
- **connection_found = *found;
- } else {
- *connection_found = NULL;
- }
-
- hc_data_free(connections);
-
- return 0;
-}
-
-
-/* CONNECTION DELETE */
-
-static int
-_hc_connection_delete_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
-{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_delete] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_delete] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (connection->id) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else if (*connection->name) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_connection_t * connection_found;
- if (_hc_connection_get(socket, connection, &connection_found) < 0)
- return -1;
- if (!connection_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- free(connection_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_CONNECTION,
- .size_in = sizeof(remove_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_delete_internal(s, connection, false);
-}
-
-static int
-_hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_delete_internal(s, connection, true);
-}
-
-static int
-_hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection)
-{
- // Not implemented
- return -1;
-}
-
-static int
-_hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated)
-{
- // Not implemented
- return -1;
-}
-
-/* CONNECTION SET ADMIN STATE */
-
-static int
-_hc_connection_set_admin_state_internal(hc_sock_t * socket, const char * conn_id_or_name,
- face_state_t state, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s",
- conn_id_or_name, face_state_str[state], BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_admin_state_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_ADMIN_STATE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .admin_state = state,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_admin_state] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_ADMIN_STATE,
- .size_in = sizeof(connection_set_admin_state_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
-{
- return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, false);
-}
-
-static int
-_hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
-{
- return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, true);
-}
-
-#ifdef WITH_POLICY
-
-static int
-_hc_connection_set_priority_internal(hc_sock_t * socket, const char * conn_id_or_name,
- uint32_t priority, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s",
- conn_id_or_name, priority, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_priority_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_PRIORITY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .priority = priority,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_PRIORITY,
- .size_in = sizeof(connection_set_priority_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, false);
-}
-
-static int
-_hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, true);
-}
-
-#endif // WITH_POLICY
-
-static int
-_hc_connection_set_tags_internal(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
- conn_id_or_name, tags, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_tags_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_TAGS,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .tags = tags,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_tags] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_TAGS,
- .size_in = sizeof(connection_set_tags_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, false);
-}
-
-static int
-_hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Routes
- *----------------------------------------------------------------------------*/
-
-/* ROUTE CREATE */
-
-static int
-_hc_route_create_internal(hc_sock_t * socket, hc_route_t * route, bool async)
-{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_create] Unexpected truncation of route string");
- if (rc < 0)
- WARN("[_hc_route_create] Error building route string");
- else
- DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .cost = route->cost,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
-
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_ROUTE,
- .size_in = sizeof(add_route_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_route_create(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create_internal(s, route, false);
-}
-
-static int
-_hc_route_create_async(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create_internal(s, route, true);
-}
-
-/* ROUTE DELETE */
-
-static int
-_hc_route_delete_internal(hc_sock_t * socket, hc_route_t * route, bool async)
-{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_delete] Unexpected truncation of route string");
- DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
-
- struct {
- header_control_message hdr;
- remove_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
-
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_ROUTE,
- .size_in = sizeof(remove_route_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_route_delete(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_delete_internal(s, route, false);
-}
-
-static int
-_hc_route_delete_async(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_delete_internal(s, route, true);
-}
-
-/* ROUTE LIST */
-
-static int
-_hc_route_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- //DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_ROUTES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_ROUTES,
- .size_in = sizeof(list_routes_command),
- .size_out = sizeof(hc_route_t),
- .parse = (HC_PARSE)hc_route_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_route_list_internal(s, pdata, false);
-}
-
-static int
-_hc_route_list_async(hc_sock_t * s)
-{
- return _hc_route_list_internal(s, NULL, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Face
- *
- * Face support is not directly available in hicn-light, but we can offer such
- * an interface through a combination of listeners and connections. The code
- * starts with some conversion functions between faces/listeners/connections.
- *
- * We also need to make sure that there always exist a (single) listener when a
- * connection is created, and in the hICN face case, that there is a single
- * connection attached to this listener.
- *
- *----------------------------------------------------------------------------*/
-
-/* FACE CREATE */
-
-static int
-_hc_face_create(hc_sock_t * socket, hc_face_t * face)
-{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_create] Unexpected truncation of face string");
- DEBUG("[hc_face_create] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, true) < 0) {
- ERROR("[hc_face_create] Could not convert face to connection.");
- return -1;
- }
-
- /* Ensure we have a corresponding local listener */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-
- if (_hc_listener_get(socket, &listener, &listener_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve listener");
- return -1;
- }
-
- if (!listener_found) {
- /* We need to create the listener if it does not exist */
- if (_hc_listener_create(socket, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- free(listener_found);
- return -1;
- }
- } else {
- free(listener_found);
- }
-
- /* Create corresponding connection */
- if (_hc_connection_create(socket, &connection) < 0) {
- ERROR("[hc_face_create] Could not create connection.");
- return -1;
- }
-
- /*
- * Once the connection is created, we need to list all connections
- * and compare with the current one to find the created face ID.
- */
- if (_hc_connection_get(socket, &connection, &connection_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve connection");
- return -1;
- }
-
- if (!connection_found) {
- ERROR("[hc_face_create] Could not find newly created connection.");
- return -1;
- }
-
- face->id = connection_found->id;
- free(connection_found);
-
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0) {
- ERROR("Could not convert face to listener.");
- return -1;
- }
- if (_hc_listener_create(socket, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- return -1;
- }
- return -1;
- break;
- default:
- ERROR("[hc_face_create] Unknwon face type.");
-
- return -1;
- };
-
- return 0;
-}
-
-static int
-_hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found)
-{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_get] Unexpected truncation of face string");
- DEBUG("[hc_face_get] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, false) < 0)
- return -1;
- if (_hc_connection_get(socket, &connection, &connection_found) < 0)
- return -1;
- if (!connection_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_connection_to_face(connection_found, *face_found);
- free(connection_found);
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0)
- return -1;
- if (_hc_listener_get(socket, &listener, &listener_found) < 0)
- return -1;
- if (!listener_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_listener_to_face(listener_found, *face_found);
- free(listener_found);
- break;
-
- default:
- return -1;
- }
-
- return 0;
-
-}
-
-/* FACE DELETE */
-
-static int
-_hc_face_delete(hc_sock_t * socket, hc_face_t * face)
-{
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_delete] Unexpected truncation of face string");
- DEBUG("[hc_face_delete] face=%s", face_s);
-
- hc_connection_t connection;
- if (hc_face_to_connection(face, &connection, false) < 0) {
- ERROR("[hc_face_delete] Could not convert face to connection.");
- return -1;
- }
-
- if (_hc_connection_delete(socket, &connection) < 0) {
- ERROR("[hc_face_delete] Error removing connection");
- return -1;
- }
-
- /* If this is the last connection attached to the listener, remove it */
-
- hc_data_t * connections;
- hc_listener_t listener = {{0}};
-
- /*
- * Ensure we have a corresponding local listener
- * NOTE: hc_face_to_listener is not appropriate
- */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-#if 1
- /*
- * The name is generated to prepare listener creation, we need it to be
- * empty for deletion. The id should not need to be reset though.
- */
- listener.id = 0;
- memset(listener.name, 0, sizeof(listener.name));
-#endif
- if (_hc_connection_list(socket, &connections) < 0) {
- ERROR("[hc_face_delete] Error getting the list of listeners");
- return -1;
- }
-
- bool delete = true;
- foreach_connection(c, connections) {
- if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) &&
- (c->local_port == listener.local_port) &&
- (strcmp(c->interface_name, listener.interface_name) == 0)) {
- delete = false;
- }
- }
-
- if (delete) {
- if (_hc_listener_delete(socket, &listener) < 0) {
- ERROR("[hc_face_delete] Error removing listener");
- return -1;
- }
- }
-
- hc_data_free(connections);
-
- return 0;
-
-
-}
-
-/* FACE LIST */
-
-static int
-_hc_face_list(hc_sock_t * socket, hc_data_t ** pdata)
-{
- hc_data_t * connection_data;
- hc_face_t face;
-
- //DEBUG("[hc_face_list]");
-
- if (_hc_connection_list(socket, &connection_data) < 0) {
- ERROR("[hc_face_list] Could not list connections.");
- return -1;
- }
-
- hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
- foreach_connection(c, connection_data) {
- if (hc_connection_to_face(c, &face) < 0) {
- ERROR("[hc_face_list] Could not convert connection to face.");
- goto ERR;
- }
- hc_data_push(face_data, &face);
- }
-
- *pdata = face_data;
- hc_data_free(connection_data);
- return 0;
-
-ERR:
- hc_data_free(connection_data);
- return -1;
-}
-
-static int
-_hc_face_list_async(hc_sock_t * socket)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_face_t),
- .parse = (HC_PARSE)hc_connection_parse_to_face,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, true);
-}
-
-static int
-_hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t admin_state)
-{
- return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
-}
-
-#ifdef WITH_POLICY
-static int
-_hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return hc_connection_set_priority(s, conn_id_or_name, priority);
-}
-
-static int
-_hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return hc_connection_set_tags(s, conn_id_or_name, tags);
-}
-#endif // WITH_POLICY
-
-/*----------------------------------------------------------------------------*
- * Punting
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_punting_create_internal(hc_sock_t * socket, hc_punting_t * punting, bool async)
-{
- int rc;
-
- if (hc_punting_validate(punting) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_punting_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_PUNTING,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = punting->prefix,
- .addressType = (u8)map_to_addr_type[punting->family],
- .len = punting->prefix_len,
- }
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_PUNTING,
- .size_in = sizeof(add_punting_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create_internal(s, punting, false);
-}
-
-static int
-_hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create_internal(s, punting, true);
-}
-
-static int
-_hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found)
-{
- ERROR("hc_punting_get not (yet) implemented.");
- return -1;
-}
-
-static int
-_hc_punting_delete(hc_sock_t * s, hc_punting_t * punting)
-{
- ERROR("hc_punting_delete not (yet) implemented.");
- return -1;
-}
-
-static int
-_hc_punting_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- ERROR("hc_punting_list not (yet) implemented.");
- return -1;
-}
-
-
-/*----------------------------------------------------------------------------*
- * Cache
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_cache_set_store_internal(hc_sock_t * socket, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_store_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_STORE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_STORE,
- .size_in = sizeof(cache_store_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_cache_set_store(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_store_internal(s, enabled, false);
-}
-
-static int
-_hc_cache_set_store_async(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_store_internal(s, enabled, true);
-}
-
-static int
-_hc_cache_set_serve_internal(hc_sock_t * socket, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_serve_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_SERVE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_SERVE,
- .size_in = sizeof(cache_serve_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_cache_set_serve(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve_internal(s, enabled, false);
-}
-
-static int
-_hc_cache_set_serve_async(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve_internal(s, enabled, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Strategy
- *----------------------------------------------------------------------------*/
-
-// per prefix
-static int
-_hc_strategy_set(hc_sock_t * s /* XXX */)
-{
- return 0;
-}
-
-/* How to retrieve that from the forwarder ? */
-static const char * strategies[] = {
- "random",
- "load_balancer",
-};
-
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
-
-static int
-_hc_strategy_list(hc_sock_t * s, hc_data_t ** data)
-{
- int rc;
-
- *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
-
- for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
- hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data);
- if (!strategy)
- return -1;
- rc = snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]);
- if (rc >= MAXSZ_HC_STRATEGY)
- WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
- (*data)->size++;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * WLDR
- *----------------------------------------------------------------------------*/
-
-// per connection
-static int
-_hc_wldr_set(hc_sock_t * s /* XXX */)
-{
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * MAP-Me
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_mapme_set(hc_sock_t * s, int enabled)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_discovery(hc_sock_t * s, int enabled)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_timescale(hc_sock_t * s, double timescale)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_retx(hc_sock_t * s, double timescale)
-{
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * Policy
- *----------------------------------------------------------------------------*/
-
-#ifdef WITH_POLICY
-
-/* POLICY CREATE */
-
-static int
-_hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- .policy = policy->policy,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_POLICY,
- .size_in = sizeof(add_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create_internal(s, policy, false);
-}
-
-static int
-_hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create_internal(s, policy, true);
-}
-
-/* POLICY DELETE */
-
-static int
-_hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- remove_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_POLICY,
- .size_in = sizeof(remove_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete_internal(s, policy, false);
-}
-
-static int
-_hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete_internal(s, policy, true);
-}
-
-/* POLICY LIST */
-
-static int
-_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_POLICIES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_POLICIES,
- .size_in = sizeof(list_policies_command),
- .size_out = sizeof(hc_policy_t),
- .parse = (HC_PARSE)hc_policy_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list_internal(s, pdata, false);
-}
-
-static int
-_hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list_internal(s, pdata, true);
-}
-
-#endif /* WITH_POLICY */
-
-static hc_sock_t hc_sock_light_interface = (hc_sock_t) {
- .hc_sock_get_next_seq = _hc_sock_light_get_next_seq,
- .hc_sock_set_nonblocking = _hc_sock_light_set_nonblocking,
- .hc_sock_get_fd = _hc_sock_light_get_fd,
- .hc_sock_connect = _hc_sock_light_connect,
- .hc_sock_get_available = _hc_sock_light_get_available,
- .hc_sock_send = _hc_sock_light_send,
- .hc_sock_recv = _hc_sock_light_recv,
- .hc_sock_process = _hc_sock_light_process,
- .hc_sock_callback = _hc_sock_light_callback,
- .hc_sock_reset = _hc_sock_light_reset,
- .hc_sock_free = _hc_sock_light_free,
- .hc_listener_create = _hc_listener_create,
- .hc_listener_create_async = _hc_listener_create_async,
- .hc_listener_get = _hc_listener_get,
- .hc_listener_delete = _hc_listener_delete,
- .hc_listener_delete_async = _hc_listener_delete_async,
- .hc_listener_list = _hc_listener_list,
- .hc_listener_list_async = _hc_listener_list_async,
- .hc_connection_create = _hc_connection_create,
- .hc_connection_create_async = _hc_connection_create_async,
- .hc_connection_get = _hc_connection_get,
- .hc_connection_update_by_id = _hc_connection_update_by_id,
- .hc_connection_update = _hc_connection_update,
- .hc_connection_delete = _hc_connection_delete,
- .hc_connection_delete_async = _hc_connection_delete_async,
- .hc_connection_list = _hc_connection_list,
- .hc_connection_list_async = _hc_connection_list_async,
- .hc_connection_set_admin_state = _hc_connection_set_admin_state,
- .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async,
-
-#ifdef WITH_POLICY
- .hc_connection_set_priority = _hc_connection_set_priority,
- .hc_connection_set_priority_async = _hc_connection_set_priority_async,
- .hc_connection_set_tags = _hc_connection_set_tags,
- .hc_connection_set_tags_async = _hc_connection_set_tags_async,
-#endif // WITH_POLICY
-
- .hc_face_create = _hc_face_create,
- .hc_face_get = _hc_face_get,
- .hc_face_delete = _hc_face_delete,
- .hc_face_list = _hc_face_list,
- .hc_face_list_async = _hc_face_list_async,
- .hc_face_set_admin_state = _hc_face_set_admin_state,
-
-#ifdef WITH_POLICY
- .hc_face_set_priority = _hc_face_set_priority,
- .hc_face_set_tags = _hc_face_set_tags,
-#endif // WITH_POLICY
-
- .hc_route_create = _hc_route_create,
- .hc_route_create_async = _hc_route_create_async,
- .hc_route_delete = _hc_route_delete,
- .hc_route_delete_async = _hc_route_delete_async,
- .hc_route_list = _hc_route_list,
- .hc_route_list_async = _hc_route_list_async,
-
- .hc_punting_create = _hc_punting_create,
- .hc_punting_create_async = _hc_punting_create_async,
- .hc_punting_get = _hc_punting_get,
- .hc_punting_delete = _hc_punting_delete,
- .hc_punting_list = _hc_punting_list,
-
- .hc_cache_set_store = _hc_cache_set_store,
- .hc_cache_set_store_async = _hc_cache_set_store_async,
- .hc_cache_set_serve = _hc_cache_set_serve,
- .hc_cache_set_serve_async = _hc_cache_set_serve_async,
-
- .hc_strategy_list = _hc_strategy_list,
- .hc_strategy_set = _hc_strategy_set,
- .hc_wldr_set = _hc_wldr_set,
-
- .hc_mapme_set = _hc_mapme_set,
- .hc_mapme_set_discovery = _hc_mapme_set_discovery,
- .hc_mapme_set_timescale = _hc_mapme_set_timescale,
- .hc_mapme_set_retx = _hc_mapme_set_retx,
-
-#ifdef WITH_POLICY
- .hc_policy_create = _hc_policy_create,
- .hc_policy_create_async = _hc_policy_create_async,
- .hc_policy_delete = _hc_policy_delete,
- .hc_policy_delete_async = _hc_policy_delete_async,
- .hc_policy_list = _hc_policy_list,
- .hc_policy_list_async = _hc_policy_list_async
-#endif // WITH_POLICY
-};
-
-// Public contructors
-
-hc_sock_t *
-_hc_sock_create_url(const char * url)
-{
- hc_sock_light_t * s = malloc(sizeof(hc_sock_light_t));
- if (!s)
- goto ERR_MALLOC;
-
- s->vft = hc_sock_light_interface;
- s->url = url ? strdup(url) : NULL;
-
- s->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (s->fd < 0)
- goto ERR_SOCKET;
-
- if (_hc_sock_light_reset((hc_sock_t*)s) < 0)
- goto ERR_RESET;
-
- s->seq = 0;
- s->cur_request = NULL;
-
- s->map = hc_sock_map_create();
- if (!s->map)
- goto ERR_MAP;
-
- return (hc_sock_t*)(s);
-
- //hc_sock_light_map_free(s->map);
-ERR_MAP:
-ERR_RESET:
- if (s->url)
- free(s->url);
- close(s->fd);
-ERR_SOCKET:
- free(s);
-ERR_MALLOC:
- return NULL;
-}
-
-hc_sock_t *
-_hc_sock_create(void)
-{
- return _hc_sock_create_url(NULL);
-}
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.c b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
new file mode 100644
index 000000000..bc04404bf
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 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.
+ */
+
+#include "hicn_light_common.h"
+
+TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf,
+ generic_snprintf);
+
+hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data,
+ HC_PARSE parse) {
+ assert(data);
+
+ hc_sock_request_t *request = malloc(sizeof(hc_sock_request_t));
+ if (!request) return NULL;
+ request->seq = seq;
+ request->data = data;
+ request->parse = parse;
+ return request;
+}
+
+void hc_sock_light_request_free(hc_sock_request_t *request) { free(request); }
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.h b/ctrl/libhicnctrl/src/modules/hicn_light_common.h
new file mode 100644
index 000000000..4749474c8
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021 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.
+ */
+#ifndef HICNCTRL_HICN_LIGHT_COMMON
+#define HICNCTRL_HICN_LIGHT_COMMON
+
+#include <assert.h> // assert
+
+#include "api_private.h"
+
+#define PORT 9695
+
+#define BOOLSTR(x) ((x) ? "true" : "false")
+
+/*
+ * Internal state associated to a pending request
+ */
+typedef struct {
+ int seq;
+ hc_data_t *data;
+ int (*parse)(const u8 *src, u8 *dst);
+} hc_sock_request_t;
+
+/**
+ * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
+ * the header_control_message structure. The forwarder simply answers back the
+ * original sequence number. We maintain a map of such sequence number to
+ * outgoing queries so that replied can be demultiplexed and treated
+ * appropriately.
+ */
+TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
+
+struct hc_sock_light_s {
+ /* This must be the first element of the struct */
+ hc_sock_t vft;
+
+ char *url;
+ int fd;
+
+ /* 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;
+
+ /* Next sequence number to be used for requests */
+ int seq;
+
+ /* Request being parsed (NULL if none) */
+ hc_sock_request_t *cur_request;
+
+ bool async;
+ hc_sock_map_t *map;
+};
+
+typedef struct hc_sock_light_s hc_sock_light_t;
+
+#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t *)(s)
+
+hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data,
+ HC_PARSE parse);
+
+void hc_sock_light_request_free(hc_sock_request_t *request);
+
+/*
+ * list was working with all seq set to 0, but it seems hicnLightControl uses
+ * 1, and replies with the same seqno
+ */
+#define HICN_CTRL_SEND_SEQ_INIT 1
+#define HICN_CTRL_RECV_SEQ_INIT 1
+
+#define MAX(x, y) ((x > y) ? x : y)
+
+static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
+
+#endif /* HICNCTRL_HICN_LIGHT_COMMON */
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
new file mode 100644
index 000000000..a58ee909e
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
@@ -0,0 +1,3111 @@
+/*
+ * Copyright (c) 2021 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.c
+ * \brief Implementation of hICN control library API
+ */
+
+#include <assert.h> // assert
+#include <fcntl.h> // fcntl
+#include <stdbool.h>
+#include <stdio.h> // snprintf
+#include <string.h> // memmove, strcasecmp
+#include <sys/socket.h> // socket
+#include <sys/types.h> // getpid
+#include <unistd.h> // close, fcntl
+#include <unistd.h> // getpid
+
+#include "api_private.h"
+#ifdef __linux__
+#include <sys/syscall.h>
+#define gettid() syscall(SYS_gettid)
+#endif /* __linux__ */
+#include <hicn/ctrl/hicn-light-ng.h>
+#include <strings.h>
+
+#include "hicn_light_common.h"
+#include <hicn/util/sstrncpy.h>
+
+#pragma GCC diagnostic ignored "-Warray-bounds"
+
+#if 0
+#ifdef __APPLE__
+#define RANDBYTE() (u8)(arc4random() & 0xFF)
+#else
+#define RANDBYTE() (u8)(random() & 0xFF)
+#endif
+#endif
+#define RANDBYTE() (u8)(rand() & 0xFF)
+
+/**
+ * \brief Defines the default size for the allocated data arrays holding the
+ * results of API calls.
+ *
+ * This size should not be too small to avoid wasting memoyy, but also not too
+ * big to avoid unnecessary realloc's. Later on this size is doubled at each
+ * reallocation.
+ */
+#define DEFAULT_SIZE_LOG 3
+
+#define connection_state_to_face_state(x) ((face_state_t)(x))
+#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
+
+/******************************************************************************
+ * Message helper types and aliases
+ ******************************************************************************/
+
+#define foreach_hc_command \
+ _(connection_add) \
+ _(connection_remove) \
+ _(connection_list) \
+ _(listener_add) \
+ _(listener_remove) \
+ _(listener_list) \
+ _(route_add) \
+ _(route_remove) \
+ _(route_list) \
+ _(cache_set_store) \
+ _(cache_set_serve) \
+ _(cache_clear) \
+ _(cache_list) \
+ _(strategy_set) \
+ _(strategy_add_local_prefix) \
+ _(wldr_set) \
+ _(punting_add) \
+ _(mapme_activator) \
+ _(mapme_timing) \
+ _(subscription_add) \
+ _(subscription_remove)
+
+const char *command_type_str[] = {
+#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u),
+ foreach_command_type
+#undef _
+};
+
+typedef cmd_header_t hc_msg_header_t;
+
+typedef union {
+#define _(x) cmd_##x##_t x;
+ foreach_hc_command
+#undef _
+} hc_msg_payload_t;
+
+typedef struct hc_msg_s {
+ hc_msg_header_t hdr;
+ hc_msg_payload_t payload;
+} hc_msg_t;
+
+/******************************************************************************
+ * Control socket
+ ******************************************************************************/
+
+#define AVAILABLE(s) ((s)->woff - (s)->roff)
+#define DEFAULT_SOCK_RECV_TIMEOUT_MS 100
+
+/**
+ * \brief Parse a connection URL into a sockaddr
+ * \param [in] url - URL
+ * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
+ * \return 0 if parsing succeeded, a negative error value otherwise.
+ */
+static int _hcng_sock_light_parse_url(const char *url, struct sockaddr *sa) {
+ /* FIXME URL parsing is currently not implemented */
+ assert(!url);
+
+#ifdef __linux__
+ srand(time(NULL) ^ getpid() ^ gettid());
+#else
+ srand((unsigned int)(time(NULL) ^ getpid()));
+#endif /* __linux__ */
+
+ /*
+ * A temporary solution is to inspect the sa_family fields of the passed in
+ * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
+ * connection to localhost.
+ */
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ case AF_INET: {
+ struct sockaddr_in *sai = (struct sockaddr_in *)sa;
+ sai->sin_family = AF_INET;
+ sai->sin_port = htons(PORT);
+ sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa;
+ sai6->sin6_family = AF_INET6;
+ sai6->sin6_port = htons(PORT);
+ sai6->sin6_addr = loopback_addr;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_sock_light_reset(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ s->roff = s->woff = 0;
+ s->remaining = 0;
+ return 0;
+}
+
+void _hcng_sock_light_free(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ hc_sock_request_t **request_array = NULL;
+ int n = hc_sock_map_get_value_array(s->map, &request_array);
+ if (n < 0) {
+ ERROR("Could not retrieve pending request array for freeing up resources");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hc_sock_request_t *request = request_array[i];
+ if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
+ ERROR("[hc_sock_light_process] Error removing request from map");
+ hc_sock_light_request_free(request);
+ }
+ free(request_array);
+ }
+
+ hc_sock_map_free(s->map);
+ if (s->url) free(s->url);
+ close(s->fd);
+ free(s);
+}
+
+static void _hcng_sock_increment_woff(hc_sock_t *socket, size_t bytes) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ s->woff += bytes;
+}
+
+static int _hcng_sock_light_get_next_seq(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->seq++;
+}
+
+static int _hcng_sock_light_set_nonblocking(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
+}
+
+static int _hcng_sock_light_get_fd(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->fd;
+}
+
+static int _hcng_sock_light_connect(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ struct sockaddr_storage ss;
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+
+ if (_hcng_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0)
+ goto ERR_PARSE;
+
+ size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6);
+ if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) {
+ perror("connect error");
+ goto ERR_CONNECT;
+ }
+ return 0;
+
+ERR_CONNECT:
+ERR_PARSE:
+ return -1;
+}
+
+static int _hcng_sock_light_send(hc_sock_t *socket, hc_msg_t *msg,
+ size_t msglen, uint32_t seq) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+ msg->hdr.seq_num = seq;
+ rc = (int)send(s->fd, msg, msglen, 0);
+ if (rc < 0) {
+ perror("hc_sock_light_send");
+ return -1;
+ }
+ return 0;
+}
+
+static int _hcng_sock_light_get_available(hc_sock_t *socket, u8 **buffer,
+ size_t *size) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ *buffer = s->buf + s->woff;
+ *size = RECV_BUFLEN - s->woff;
+
+ return 0;
+}
+
+static int _hcng_sock_light_recv(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+
+ /*
+ * This condition should be ensured to guarantee correct processing of
+ * messages. With TCP, we need at least a header as we will receive part of
+ * the stream. With UDP, we need the be able to receive the full datagram,
+ * otherwise the rest will be lost.
+ *
+ * Let's be sure to always be able to receive at least 1 JUMBO_MTU, which
+ * should be fine for al situations.
+ */
+ assert(RECV_BUFLEN - s->woff > JUMBO_MTU);
+
+ rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
+ if (rc == 0) {
+ /* Connection has been closed */
+ return 0;
+ }
+ if (rc < 0) {
+ /*
+ * Let's not return 0 which currently means the socket has been closed
+ */
+ if (errno == EWOULDBLOCK) return -1;
+ if (errno == EINTR) {
+ WARN("recv has been stopped by signal");
+ return -1;
+ }
+ perror("hc_sock_light_recv");
+ return -1;
+ }
+ s->woff += rc;
+ return rc;
+}
+
+static void _hcng_sock_light_mark_complete(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ hc_data_t *data = s->cur_request->data;
+
+ if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
+ ERROR("[hc_sock_light_mark_complete] Error removing request from map");
+ }
+ hc_data_set_complete(data);
+ if (pdata) *pdata = data;
+
+ /* Free current request */
+ hc_sock_light_request_free(s->cur_request);
+ s->cur_request = NULL;
+}
+
+static int _hcng_sock_light_process_notification(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ /* For now, notifications are not associated to requests */
+ assert(!s->cur_request);
+
+ /*
+ * Assumption: the whole notification data is returned in a single read and we
+ * immediately parse it.
+ *
+ * XXX This is only valid for UDP sockets.
+ */
+ size_t notification_size = AVAILABLE(s);
+
+ *pdata = hc_data_create(0, /* in_element_size, 0 = no parsing */
+ notification_size, /* out_element_size */
+ NULL); /* complete_cb */
+
+ /* Copy the packet payload as the single entry in hc_data_t */
+ hc_data_push_many(*pdata, s->buf + s->roff, 1);
+
+ return notification_size;
+}
+
+/*
+ * Notifications have no sequence number and are not linked to any request
+ */
+static hc_sock_request_t *_hcng_sock_light_get_request(hc_sock_light_t *s,
+ int seq) {
+ hc_sock_request_t *request;
+ /* Retrieve request from sock map */
+ if (hc_sock_map_get(s->map, seq, &request) < 0) {
+ ERROR("[hc_sock_light_process] Error searching for matching request");
+ return NULL;
+ }
+ if (!request) {
+ ERROR("[hc_sock_light_process] No request matching sequence number");
+ return NULL;
+ }
+ return request;
+}
+
+/*
+ * Return codes:
+ * 0 success, or not enough data yet to do something
+ * > 0 : notification type
+ * -99 invalid buffer data -> flush
+ */
+static int _hcng_sock_light_process_header(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ int rc;
+
+ /* Check we have at least a header's worth of data, and consume it */
+ if (AVAILABLE(s) < sizeof(hc_msg_header_t)) return 0;
+
+ hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff);
+
+ // INFO("Processing header header %s", command_type_str(msg->hdr.command_id));
+ s->roff += sizeof(hc_msg_header_t);
+
+ if (msg->hdr.message_type != NOTIFICATION_LIGHT) {
+ s->cur_request = _hcng_sock_light_get_request(s, msg->hdr.seq_num);
+ if (!s->cur_request) return -99;
+ }
+
+ /* How many elements are we expecting in the reply ? */
+ s->remaining = msg->hdr.length;
+ hc_data_t *request_data;
+
+ switch (msg->hdr.message_type) {
+ case ACK_LIGHT:
+ assert(s->remaining == 1); // sic
+ assert(!pdata);
+ _hcng_sock_light_mark_complete(s, pdata);
+ break;
+
+ case NACK_LIGHT:
+ assert(!pdata);
+ assert(s->remaining == 1); // sic
+ request_data = s->cur_request->data;
+ _hcng_sock_light_mark_complete(s, pdata);
+ hc_data_set_error(request_data);
+ break;
+
+ case RESPONSE_LIGHT:
+ assert(pdata);
+
+ if (s->remaining == 0) {
+ /* Empty response (i.e. containing 0 elements) */
+ _hcng_sock_light_mark_complete(s, pdata);
+ return 0;
+ }
+
+ /* Make room in hc_data_t... to avoid multiple calls */
+ rc = hc_data_ensure_available(s->cur_request->data, s->remaining);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in hc_data_ensure_available");
+ return -99;
+ }
+ break;
+
+ case NOTIFICATION_LIGHT: {
+ assert(pdata);
+ assert(s->remaining == 0);
+
+ /* This returns the notification size */
+ size_t notification_size =
+ _hcng_sock_light_process_notification(s, pdata);
+ s->roff += notification_size;
+ return msg->hdr.command_id;
+ }
+
+ default:
+ ERROR("[hc_sock_light_process] Invalid response received");
+ return -99;
+ }
+
+ return 0;
+}
+
+static int _hcng_sock_light_process_payload(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ int err = 0;
+ int rc;
+
+ hc_data_t *data = s->cur_request->data;
+
+ /* We only process full elements (size is stored in data) */
+ size_t num_chunks = AVAILABLE(s) / data->in_element_size;
+
+ /* Check whether we have enough data to process */
+ if (num_chunks == 0) return 0;
+
+ /* Safeguard: assert(num_chunks < s->remaining); */
+ if (num_chunks > s->remaining) {
+ WARN(
+ "[_hcng_sock_light_process_payload] Unexpected num_chunks > "
+ "s->remaining");
+ num_chunks = s->remaining;
+ }
+
+ if (!s->cur_request->parse) {
+ /* If we don't need to parse results, then we can directly push
+ * all of them into the result data structure */
+ hc_data_push_many(data, s->buf + s->roff, num_chunks);
+ } else {
+ /* Iterate on chunks of data */
+ for (int i = 0; i < num_chunks; i++) {
+ /* Get storage offset in hc_data_t */
+ u8 *dst = hc_data_get_next(data);
+ if (!dst) {
+ ERROR("[hc_sock_light_process] Error in hc_data_get_next");
+ err = -2;
+ break;
+ }
+
+ /* Parse element #i */
+ rc = s->cur_request->parse(s->buf + s->roff + i * data->in_element_size,
+ dst);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in parse");
+ err = -1;
+ /* In this case we let the loop complete to collect other results */
+ }
+ data->size++;
+ }
+ }
+
+ s->roff += num_chunks * data->in_element_size;
+
+ /*
+ * If we are not expecting any more data, mark the reply as complete
+ */
+ s->remaining -= num_chunks;
+ if (s->remaining == 0) _hcng_sock_light_mark_complete(s, pdata);
+
+ return err;
+}
+
+/*
+ * Process messages as they are received in the ring buffer. There can be
+ * interleaved queries and replies (they are identified by sequence number),
+ * and the assumption is that a reply can arrive over mutiple packets (in
+ * other terms, it is possible that not all data from the reply is available
+ * in the buffer at a given time). However, we assume that a full query is
+ * received at once.
+ */
+static int _hcng_sock_light_process(hc_sock_t *socket, hc_data_t **data) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc = 0;
+
+ /*
+ * We loop consuming messages until there is no more data in the buffer,
+ * or that we can find an entire message. Messages are received
+ * sequentially, and we keep track of incomplete requests in s->cur_request.
+ */
+ while (AVAILABLE(s) > 0) {
+ if (!s->cur_request) {
+ rc = _hcng_sock_light_process_header(s, data);
+ } else {
+ rc = _hcng_sock_light_process_payload(s, data);
+ }
+ if (rc < 0) break;
+ }
+
+ if ((rc == -99) || (s->roff == s->woff)) {
+ /* Flush buffer */
+ s->woff = 0;
+ } else {
+ /* Clean up read data from buffer */
+ memmove(s->buf, s->buf + s->roff, AVAILABLE(s));
+ s->woff -= s->roff;
+ }
+ s->roff = 0;
+
+ return rc;
+}
+
+static int _hcng_sock_light_callback(hc_sock_t *socket, hc_data_t **pdata) {
+ hc_data_t *data = NULL;
+ int rc = 0;
+
+ for (;;) {
+ int n = _hcng_sock_light_recv(socket);
+ if (n == 0) goto ERR_EOF;
+ if (n < 0) {
+ switch (errno) {
+ case ECONNRESET:
+ case ENODEV:
+ /* Forwarder restarted */
+ WARN("Forwarder likely restarted: not (yet) implemented");
+ goto ERR;
+ case EWOULDBLOCK:
+ // DEBUG("Would block... stop reading from socket");
+ goto END;
+ case EINTR:
+ WARN("callback has been stopped by signal");
+ goto ERR;
+ default:
+ perror("hc_sock_light_callback");
+ goto ERR;
+ }
+ }
+ rc = _hcng_sock_light_process(socket, &data);
+ if (rc < 0) goto ERR;
+ if (rc > 0) // i.e. rc = notification type
+ goto END;
+ }
+END:
+ if (pdata)
+ *pdata = data;
+ else
+ hc_data_free(data);
+ return rc;
+
+ERR:
+ hc_data_free(data);
+ERR_EOF:
+ return -1;
+}
+
+/******************************************************************************
+ * Command-specific structures and functions
+ ******************************************************************************/
+
+typedef int (*HC_PARSE)(const u8 *, u8 *);
+
+typedef struct {
+ hc_action_t cmd;
+ command_type_t cmd_id;
+ size_t size_in;
+ size_t size_out;
+ HC_PARSE parse;
+} hc_command_params_t;
+
+typedef struct hc_result_s {
+ hc_msg_t msg;
+ hc_command_params_t params;
+ bool async;
+ bool success;
+} hc_result_t;
+
+int _hcng_sock_prepare_send(hc_sock_t *socket, hc_result_t *result,
+ data_callback_t complete_cb,
+ void *complete_cb_data) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+
+ // Prepare data
+ hc_data_t *data =
+ hc_data_create(result->params.size_in, result->params.size_out, NULL);
+ if (!data) {
+ ERROR("[_hcng_execute_command] Could not create data storage");
+ goto ERR_DATA;
+ }
+ hc_data_set_callback(data, complete_cb, complete_cb_data);
+
+ // Update the sequence number
+ int seq = _hcng_sock_light_get_next_seq(socket);
+ result->msg.hdr.seq_num = seq; // Like in _hcng_sock_light_send
+
+ // Create state used to process the request
+ hc_sock_request_t *request = NULL;
+ request = hc_sock_request_create(seq, data, result->params.parse);
+ if (!request) {
+ ERROR("[_hcng_execute_command] Could not create request state");
+ goto ERR_REQUEST;
+ }
+
+ // Add state to map
+ if (hc_sock_map_add(s->map, seq, request) < 0) {
+ ERROR("[_hcng_execute_command] Error adding request state to map");
+ goto ERR_MAP;
+ }
+
+ return sizeof(result->msg);
+
+ERR_MAP:
+ hc_sock_light_request_free(request);
+ERR_REQUEST:
+ hc_data_free(data);
+ERR_DATA:
+ return -99;
+}
+
+int _hcng_sock_set_recv_timeout_ms(hc_sock_t *socket, long timeout_ms) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout_ms * 1000; // Convert ms into us
+ if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_execute_command(hc_sock_t *socket, hc_msg_t *msg,
+ size_t msg_len, hc_command_params_t *params,
+ hc_data_t **pdata, bool async) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int ret;
+ if (async) assert(!pdata);
+
+ /* Sanity check */
+ switch (params->cmd) {
+ case ACTION_CREATE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_DELETE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_LIST:
+ assert(params->size_in != 0);
+ assert(params->size_out != 0);
+ assert(params->parse != NULL);
+ break;
+ case ACTION_SET:
+ case ACTION_SERVE:
+ case ACTION_STORE:
+ case ACTION_UPDATE:
+ assert(params->size_in != 0);
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_CLEAR:
+ assert(params->size_in == 0);
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ default:
+ return -1;
+ }
+
+ // hc_sock_light_reset(s);
+
+ /* XXX data will at least store the result (complete) */
+ hc_data_t *data = hc_data_create(params->size_in, params->size_out, NULL);
+ if (!data) {
+ ERROR("[_hcng_execute_command] Could not create data storage");
+ goto ERR_DATA;
+ }
+
+ int seq = _hcng_sock_light_get_next_seq(socket);
+
+ /* Create state used to process the request */
+ hc_sock_request_t *request = NULL;
+ request = hc_sock_request_create(seq, data, params->parse);
+ if (!request) {
+ ERROR("[_hcng_execute_command] Could not create request state");
+ goto ERR_REQUEST;
+ }
+
+ /* Add state to map */
+ if (hc_sock_map_add(s->map, seq, request) < 0) {
+ ERROR("[_hcng_execute_command] Error adding request state to map");
+ goto ERR_MAP;
+ }
+
+ if (_hcng_sock_light_send(socket, msg, msg_len, seq) < 0) {
+ ERROR("[_hcng_execute_command] Error sending message");
+ goto ERR_PROCESS;
+ }
+
+ if (async) return 0;
+
+ /*
+ * Dangerous zone, we might be doing blocking operations on a non-blocking
+ * UDP socket
+ */
+ int retries = 0;
+ while (!data->complete) {
+ /*
+ * As the socket is non blocking it might happen that we need to read
+ * several times before success...
+ */
+ int n = _hcng_sock_light_recv(socket);
+ if (n == 0) goto ERR_EOF;
+ if (n < 0) {
+ if ((errno == EWOULDBLOCK) && (retries < 10)) { /* Max 500ms */
+ DEBUG("read = EWOULDBLOCK... sleeping for 50ms (max 500ms)");
+ usleep(50000); /* 50ms */
+ retries++;
+ continue;
+ }
+ break;
+ }
+ int rc = _hcng_sock_light_process(socket, pdata);
+ switch (rc) {
+ case 0:
+ case -1:
+ break;
+ case -99:
+ ERROR("[_hcng_execute_command] Error processing socket results");
+ goto ERR;
+ default:
+ ERROR("[_hcng_execute_command] Unexpected return value");
+ goto ERR;
+ }
+ }
+
+ERR_EOF:
+ ret = data->ret;
+ if (!data->complete) return -1;
+ if (!pdata) hc_data_free(data);
+
+ return ret;
+
+ERR_PROCESS:
+ERR_MAP:
+ hc_sock_light_request_free(request);
+ERR:
+ERR_REQUEST:
+ hc_data_free(data);
+ERR_DATA:
+ return -99;
+}
+
+/*----------------------------------------------------------------------------*
+ * Listeners
+ *----------------------------------------------------------------------------*/
+
+/* LISTENER CREATE */
+
+static hc_result_t *_listener_create_serialize(hc_sock_t *s,
+ hc_listener_t *listener,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hcng_listener_create] Unexpected truncation of listener string");
+ DEBUG("[_hcng_listener_create] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ if (hc_listener_validate(listener) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_listener_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = listener->local_addr,
+ .port = htons(listener->local_port),
+ .family = listener->family,
+ .type = listener->type,
+ }};
+
+ rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_create] Unexpected truncation of symbolic name "
+ "string");
+
+ rc = snprintf(msg.payload.interface_name, INTERFACE_LEN, "%s",
+ listener->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[_hc_listener_create] Unexpected truncation of interface name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_LISTENER_ADD,
+ .size_in = sizeof(cmd_listener_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.listener_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_listener_create_conf(hc_sock_t *s,
+ hc_listener_t *listener) {
+ return _listener_create_serialize(s, listener, false);
+}
+
+static int _hcng_listener_create_internal(hc_sock_t *socket,
+ hc_listener_t *listener, bool async) {
+ hc_result_t *result = _listener_create_serialize(socket, listener, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ free(result);
+ DEBUG("[_hcng_listener_create] done or error");
+ return ret;
+}
+
+static int _hcng_listener_create(hc_sock_t *s, hc_listener_t *listener) {
+ DEBUG("[_hcng_listener_create]");
+ return _hcng_listener_create_internal(s, listener, false);
+}
+
+static int _hcng_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
+ DEBUG("[_hcng_listener_create_async]");
+ return _hcng_listener_create_internal(s, listener, true);
+}
+
+/* LISTENER PARSE */
+
+static int hc_listener_parse(void *in, hc_listener_t *listener) {
+ int rc;
+ cmd_listener_list_item_t *item = (cmd_listener_list_item_t *)in;
+
+ if (!IS_VALID_ID(item->id)) {
+ ERROR("[hc_listener_parse] Invalid id received");
+ return -1;
+ }
+
+ *listener = (hc_listener_t){
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = UNION_CAST(item->address, ip_address_t),
+ .local_port = ntohs(item->port),
+ };
+ rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[hc_listener_parse] Unexpected truncation of symbolic name string");
+ rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s",
+ item->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN("[hc_listener_parse] Unexpected truncation of interface name string");
+
+ if (hc_listener_validate(listener) < 0) return -1;
+ return 0;
+}
+
+/* LISTENER LIST */
+
+static hc_result_t *_hcng_listener_list_serialize(hc_sock_t *socket,
+ hc_data_t **pdata,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
+
+ msg_listener_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_LISTENER_LIST,
+ .size_in = sizeof(cmd_listener_list_item_t),
+ .size_out = sizeof(hc_listener_t),
+ .parse = (HC_PARSE)hc_listener_parse,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.listener_list = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_listener_list_conf(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_listener_list_serialize(s, pdata, false);
+}
+
+static int _hcng_listener_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_listener_list_serialize(socket, pdata, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, pdata,
+ result->async);
+ }
+
+ hc_result_free(result);
+ DEBUG("[_hcng_listener_list] done or error");
+ return ret;
+}
+
+static int _hcng_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_listener_list]");
+ return _hcng_listener_list_internal(s, pdata, false);
+}
+
+static int _hcng_listener_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_listener_list_as-nc]");
+ return _hcng_listener_list_internal(s, pdata, true);
+}
+
+/* LISTENER GET */
+
+static int _hcng_listener_get(hc_sock_t *socket, hc_listener_t *listener,
+ hc_listener_t **listener_found) {
+ hc_data_t *listeners;
+ hc_listener_t *found;
+
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[hc_listener_get] Unexpected truncation of listener string");
+ DEBUG("[hc_listener_get] listener=%s", listener_s);
+
+ if (_hcng_listener_list(socket, &listeners) < 0) return -1;
+
+ /* Test */
+ if (hc_listener_find(listeners, listener, &found) < 0) {
+ hc_data_free(listeners);
+ return -1;
+ }
+
+ if (found) {
+ *listener_found = malloc(sizeof(hc_listener_t));
+ if (!*listener_found) return -1;
+ **listener_found = *found;
+ } else {
+ *listener_found = NULL;
+ }
+
+ hc_data_free(listeners);
+
+ return 0;
+}
+
+/* LISTENER DELETE */
+
+static int _hcng_listener_delete_internal(hc_sock_t *socket,
+ hc_listener_t *listener, bool async) {
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hcng_listener_delete] Unexpected truncation of listener string");
+ DEBUG("[_hcng_listener_delete] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ msg_listener_remove_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ }};
+
+ if (listener->id) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d",
+ listener->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else if (*listener->name) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s",
+ listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else {
+ hc_listener_t *listener_found;
+ if (_hcng_listener_get(socket, listener, &listener_found) < 0) return -1;
+ if (!listener_found) return -1;
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d",
+ listener_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ free(listener_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_LISTENER_REMOVE,
+ .size_in = sizeof(cmd_listener_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+ return _hcng_listener_delete_internal(s, listener, false);
+}
+
+static int _hcng_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
+ return _hcng_listener_delete_internal(s, listener, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * CONNECTION
+ *----------------------------------------------------------------------------*/
+
+/* CONNECTION CREATE */
+
+static hc_result_t *_connection_create_serialize(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN(
+ "[_hcng_connection_create] Unexpected truncation of connection "
+ "string");
+ DEBUG("[_hcng_connection_create] connection=%s async=%s", connection_s,
+ BOOLSTR(async));
+
+ if (hc_connection_validate(connection) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_connection_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .remote_ip = connection->remote_addr,
+ .local_ip = connection->local_addr,
+ .remote_port = htons(connection->remote_port),
+ .local_port = htons(connection->local_port),
+ .family = connection->family,
+ .type = connection->type,
+ .admin_state = connection->admin_state,
+#ifdef WITH_POLICY
+ .priority = connection->priority,
+ .tags = connection->tags,
+#endif /* WITH_POLICY */
+ }};
+ rc =
+ snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_create] Unexpected truncation of symbolic name "
+ "string");
+ // snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s",
+ // connection->interface_name);
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_CONNECTION_ADD,
+ .size_in = sizeof(cmd_connection_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.connection_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _connection_create_serialize(s, connection, false);
+}
+
+static int _hcng_connection_create_internal(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *result = _connection_create_serialize(socket, connection, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ DEBUG("[_hcng_connection_create] done or error");
+ return ret;
+}
+
+static int _hcng_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+ DEBUG("[_hcng_connection_create]");
+ return _hcng_connection_create_internal(s, connection, false);
+}
+
+static int _hcng_connection_create_async(hc_sock_t *s,
+ hc_connection_t *connection) {
+ DEBUG("[_hcng_connection_create_async]");
+ return _hcng_connection_create_internal(s, connection, true);
+}
+
+/* CONNECTION PARSE */
+
+static int hc_connection_parse(void *in, hc_connection_t *connection) {
+ int rc;
+ cmd_connection_list_item_t *item = (cmd_connection_list_item_t *)in;
+
+ if (!IS_VALID_ID(item->id)) {
+ ERROR("[hc_connection_parse] Invalid id received");
+ return -1;
+ }
+
+ *connection = (hc_connection_t){
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = item->local_addr,
+ .local_port = ntohs(item->local_port),
+ .remote_addr = item->remote_addr,
+ .remote_port = ntohs(item->remote_port),
+ .admin_state = item->admin_state,
+#ifdef WITH_POLICY
+ .priority = item->priority,
+ .tags = item->tags,
+#endif /* WITH_POLICY */
+ .state = item->state,
+ };
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_parse] Unexpected truncation of symbolic name "
+ "string");
+ rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ item->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_parse] Unexpected truncation of interface name "
+ "string");
+
+ if (hc_connection_validate(connection) < 0) return -1;
+ return 0;
+}
+
+/* CONNECTION LIST */
+
+static int _hcng_connection_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
+
+ msg_connection_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CONNECTION_LIST,
+ .size_in = sizeof(cmd_connection_list_item_t),
+ .size_out = sizeof(hc_connection_t),
+ .parse = (HC_PARSE)hc_connection_parse,
+ };
+
+ int ret = _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg),
+ &params, pdata, async);
+
+ DEBUG("[hc_connection_list] done or error");
+ return ret;
+}
+
+static int _hcng_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[hc_connection_list]");
+ return _hcng_connection_list_internal(s, pdata, false);
+}
+
+static int _hcng_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[hc_connection_list_async]");
+ return _hcng_connection_list_internal(s, pdata, true);
+}
+
+/* CONNECTION GET */
+
+static int _hcng_connection_get(hc_sock_t *socket, hc_connection_t *connection,
+ hc_connection_t **connection_found) {
+ hc_data_t *connections;
+ hc_connection_t *found;
+
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN("[hc_connection_get] Unexpected truncation of connection string");
+ DEBUG("[hc_connection_get] connection=%s", connection_s);
+
+ if (_hcng_connection_list(socket, &connections) < 0) return -1;
+
+ /* Test */
+ if (hc_connection_find(connections, connection, &found) < 0) {
+ hc_data_free(connections);
+ return -1;
+ }
+
+ if (found) {
+ *connection_found = malloc(sizeof(hc_connection_t));
+ if (!*connection_found) return -1;
+ **connection_found = *found;
+ } else {
+ *connection_found = NULL;
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+}
+
+/* CONNECTION DELETE */
+
+static hc_result_t *_hcng_connection_delete_serialize(
+ hc_sock_t *socket, hc_connection_t *connection, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ res->success = false;
+
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN(
+ "[_hcng_connection_delete] Unexpected truncation of connection "
+ "string");
+ DEBUG("[_hcng_connection_delete] connection=%s async=%s", connection_s,
+ BOOLSTR(async));
+
+ msg_connection_remove_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ if (connection->id) {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ connection->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else if (*connection->name) {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else {
+ hc_connection_t *connection_found;
+ if (hc_connection_get(socket, connection, &connection_found) < 0)
+ return res;
+ if (!connection_found) return res;
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ connection_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ free(connection_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .size_in = sizeof(cmd_connection_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.connection_remove = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_connection_delete_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _hcng_connection_delete_serialize(s, connection, false);
+}
+
+static int _hcng_connection_delete_internal(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *result =
+ _hcng_connection_delete_serialize(socket, connection, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static int _hcng_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+ return _hcng_connection_delete_internal(s, connection, false);
+}
+
+static int _hcng_connection_delete_async(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _hcng_connection_delete_internal(s, connection, true);
+}
+
+/* CONNECTION UPDATE */
+
+static int _hcng_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection) {
+ // Not implemented
+ return -1;
+}
+
+static int _hcng_connection_update(hc_sock_t *s,
+ hc_connection_t *connection_current,
+ hc_connection_t *connection_updated) {
+ // Not implemented
+ return -1;
+}
+
+/* CONNECTION SET ADMIN STATE */
+
+static int _hcng_connection_set_admin_state_internal(
+ hc_sock_t *socket, const char *conn_id_or_name, face_state_t state,
+ bool async) {
+ int rc;
+ DEBUG(
+ "[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s "
+ "async=%s",
+ conn_id_or_name, face_state_str(state), BOOLSTR(async));
+
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_admin_state_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .admin_state = state,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_admin_state] Unexpected truncation of symbolic "
+ "name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
+ .size_in = sizeof(cmd_connection_set_admin_state_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_connection_set_admin_state(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
+ return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state,
+ false);
+}
+
+static int _hcng_connection_set_admin_state_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
+ return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state,
+ true);
+}
+
+#ifdef WITH_POLICY
+
+static int _hcng_connection_set_priority_internal(hc_sock_t *socket,
+ const char *conn_id_or_name,
+ uint32_t priority,
+ bool async) {
+ int rc;
+ DEBUG(
+ "[hc_connection_set_priority] connection_id/name=%s priority=%d "
+ "async=%s",
+ conn_id_or_name, priority, BOOLSTR(async));
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_priority_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .priority = priority,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_priority] Unexpected truncation of symbolic "
+ "name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
+ .size_in = sizeof(cmd_connection_set_priority_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_connection_set_priority(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
+ return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority,
+ false);
+}
+
+static int _hcng_connection_set_priority_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
+ return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority,
+ true);
+}
+
+#endif // WITH_POLICY
+
+static int _hcng_connection_set_tags_internal(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags, bool async) {
+ int rc;
+ DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
+ conn_id_or_name, tags, BOOLSTR(async));
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_tags_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .tags = tags,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_tags] Unexpected truncation of symbolic name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_TAGS,
+ .size_in = sizeof(cmd_connection_set_tags_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), &params, NULL,
+ async);
+}
+
+static int _hcng_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, false);
+}
+
+static int _hcng_connection_set_tags_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Routes
+ *----------------------------------------------------------------------------*/
+
+/* ROUTE CREATE */
+
+static hc_result_t *_route_create_serialize(hc_sock_t *socket,
+ hc_route_t *route, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_create] Unexpected truncation of route string");
+ if (rc < 0)
+ WARN("[_hc_route_create] Error building route string");
+ else
+ DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (hc_route_validate(route) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_route_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .cost = route->cost,
+ .family = route->family,
+ .len = route->len,
+ }};
+
+ /*
+ * The route commands expects the ID or name as part of the
+ * symbolic_or_connid attribute.
+ */
+ if (route->name[0] != '\0') {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ route->name);
+ } else {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ route->face_id);
+ }
+
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_ROUTE_ADD,
+ .size_in = sizeof(cmd_route_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.route_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ return _route_create_serialize(s, route, false);
+}
+
+static int _hcng_route_create_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
+ hc_result_t *result = _route_create_serialize(socket, route, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static int _hcng_route_create(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_create_internal(s, route, false);
+}
+
+static int _hcng_route_create_async(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_create_internal(s, route, true);
+}
+
+/* ROUTE DELETE */
+
+static int _hcng_route_delete_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_delete] Unexpected truncation of route string");
+ DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (!IS_VALID_FAMILY(route->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_route_remove_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .family = route->family,
+ .len = route->len,
+ }};
+
+ /*
+ * The route commands expects the ID or name as part of the
+ * symbolic_or_connid attribute.
+ */
+ if (route->name[0] != '\0') {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ route->name);
+ } else {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ route->face_id);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_ROUTE_REMOVE,
+ .size_in = sizeof(cmd_route_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_route_delete(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_delete_internal(s, route, false);
+}
+
+static int _hcng_route_delete_async(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_delete_internal(s, route, true);
+}
+
+/* ROUTE PARSE */
+
+static int hc_route_parse(void *in, hc_route_t *route) {
+ cmd_route_list_item_t *item = (cmd_route_list_item_t *)in;
+
+ *route = (hc_route_t){
+ .name = "", /* This is not reported back */
+ .face_id = item->connection_id,
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .cost = item->cost,
+ };
+
+ if (hc_route_validate(route) < 0) return -1;
+ return 0;
+}
+
+/* ROUTE LIST */
+
+static int _hcng_route_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ // DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
+ msg_route_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_ROUTE_LIST,
+ .size_in = sizeof(cmd_route_list_item_t),
+ .size_out = sizeof(hc_route_t),
+ .parse = (HC_PARSE)hc_route_parse,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ pdata, async);
+}
+
+static int _hcng_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_route_list_internal(s, pdata, false);
+}
+
+static int _hcng_route_list_async(hc_sock_t *s) {
+ return _hcng_route_list_internal(s, NULL, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Face
+ *
+ * Face support is not directly available in hicn-light, but we can offer such
+ * an interface through a combination of listeners and connections. The code
+ * starts with some conversion functions between faces/listeners/connections.
+ *
+ * We also need to make sure that there always exist a (single) listener when
+ *a connection is created, and in the hICN face case, that there is a single
+ * connection attached to this listener.
+ *
+ *----------------------------------------------------------------------------*/
+
+/* FACE CREATE */
+
+static int _hcng_face_create(hc_sock_t *socket, hc_face_t *face) {
+ hc_listener_t listener;
+ hc_listener_t *listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t *connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_create] Unexpected truncation of face string");
+ DEBUG("[hc_face_create] face=%s", face_s);
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, true) < 0) {
+ ERROR("[hc_face_create] Could not convert face to connection.");
+ return -1;
+ }
+
+ /* Ensure we have a corresponding local listener */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+
+ if (_hcng_listener_get(socket, &listener, &listener_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve listener");
+ return -1;
+ }
+
+ if (!listener_found) {
+ /* We need to create the listener if it does not exist */
+ if (hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ free(listener_found);
+ return -1;
+ }
+ } else {
+ free(listener_found);
+ }
+
+ /* Create corresponding connection */
+ if (_hcng_connection_create(socket, &connection) < 0) {
+ ERROR("[hc_face_create] Could not create connection.");
+ return -1;
+ }
+
+ /*
+ * Once the connection is created, we need to list all connections
+ * and compare with the current one to find the created face ID.
+ */
+ if (_hcng_connection_get(socket, &connection, &connection_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve connection");
+ return -1;
+ }
+
+ if (!connection_found) {
+ ERROR("[hc_face_create] Could not find newly created connection.");
+ return -1;
+ }
+
+ face->id = connection_found->id;
+ free(connection_found);
+
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0) {
+ ERROR("Could not convert face to listener.");
+ return -1;
+ }
+ if (hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ return -1;
+ }
+ break;
+ default:
+ ERROR("[hc_face_create] Unknwon face type.");
+
+ return -1;
+ };
+
+ return 0;
+}
+
+static int _hcng_face_get(hc_sock_t *socket, hc_face_t *face,
+ hc_face_t **face_found) {
+ hc_listener_t listener;
+ hc_listener_t *listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t *connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_get] Unexpected truncation of face string");
+ DEBUG("[hc_face_get] face=%s", face_s);
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, false) < 0) return -1;
+ if (_hcng_connection_get(socket, &connection, &connection_found) < 0)
+ return -1;
+ if (!connection_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_connection_to_face(connection_found, *face_found);
+ free(connection_found);
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0) return -1;
+ if (_hcng_listener_get(socket, &listener, &listener_found) < 0) return -1;
+ if (!listener_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_listener_to_face(listener_found, *face_found);
+ free(listener_found);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* FACE DELETE */
+
+static int _hcng_face_delete(hc_sock_t *socket, hc_face_t *face,
+ uint8_t delete_listener) {
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_delete] Unexpected truncation of face string");
+ DEBUG("[hc_face_delete] face=%s", face_s);
+
+ hc_connection_t connection;
+ if (hc_face_to_connection(face, &connection, false) < 0) {
+ ERROR("[hc_face_delete] Could not convert face to connection.");
+ return -1;
+ }
+
+ if (_hcng_connection_delete(socket, &connection) < 0) {
+ ERROR("[hc_face_delete] Error removing connection");
+ return -1;
+ }
+
+ if (!delete_listener) {
+ return 0;
+ }
+
+ /* If this is the last connection attached to the listener, remove it */
+
+ hc_data_t *connections;
+ hc_listener_t listener = {{0}};
+
+ /*
+ * Ensure we have a corresponding local listener
+ * NOTE: hc_face_to_listener is not appropriate
+ */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+#if 1
+ /*
+ * The name is generated to prepare listener creation, we need it to be
+ * empty for deletion. The id should not need to be reset though.
+ */
+ listener.id = 0;
+ memset(listener.name, 0, sizeof(listener.name));
+#endif
+ if (_hcng_connection_list(socket, &connections) < 0) {
+ ERROR("[hc_face_delete] Error getting the list of listeners");
+ return -1;
+ }
+
+ bool delete = true;
+ foreach_connection(c, connections) {
+ if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) ==
+ 0) &&
+ (c->local_port == listener.local_port) &&
+ (strcmp(c->interface_name, listener.interface_name) == 0)) {
+ delete = false;
+ }
+ }
+
+ if (delete) {
+ if (_hcng_listener_delete(socket, &listener) < 0) {
+ ERROR("[hc_face_delete] Error removing listener");
+ return -1;
+ }
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+}
+
+/* FACE LIST */
+
+static int _hcng_face_list(hc_sock_t *socket, hc_data_t **pdata) {
+ hc_data_t *connection_data;
+ hc_face_t face;
+
+ DEBUG("[hc_face_list]");
+
+ if (_hcng_connection_list(socket, &connection_data) < 0) {
+ ERROR("[hc_face_list] Could not list connections.");
+ return -1;
+ }
+
+ hc_data_t *face_data =
+ hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
+ foreach_connection(c, connection_data) {
+ if (hc_connection_to_face(c, &face) < 0) {
+ ERROR("[hc_face_list] Could not convert connection to face.");
+ goto ERR;
+ }
+ hc_data_push(face_data, &face);
+ }
+
+ *pdata = face_data;
+ hc_data_free(connection_data);
+ DEBUG("[hc_face_list] done");
+ return 0;
+
+ERR:
+ hc_data_free(connection_data);
+ DEBUG("[hc_face_list] error");
+ return -1;
+}
+
+static int hc_connection_parse_to_face(void *in, hc_face_t *face) {
+ hc_connection_t connection;
+
+ if (hc_connection_parse(in, &connection) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not parse connection");
+ return -1;
+ }
+
+ if (hc_connection_to_face(&connection, face) < 0) {
+ ERROR(
+ "[hc_connection_parse_to_face] Could not convert connection to "
+ "face.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_face_list_async(hc_sock_t *socket) {
+ struct {
+ cmd_header_t hdr;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_LIST,
+ .length = 0,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CONNECTION_LIST,
+ .size_in = sizeof(cmd_connection_list_item_t),
+ .size_out = sizeof(hc_face_t),
+ .parse = (HC_PARSE)hc_connection_parse_to_face,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, true);
+}
+
+static int _hcng_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t admin_state) {
+ return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
+}
+
+#ifdef WITH_POLICY
+static int _hcng_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return hc_connection_set_priority(s, conn_id_or_name, priority);
+}
+
+static int _hcng_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return hc_connection_set_tags(s, conn_id_or_name, tags);
+}
+#endif // WITH_POLICY
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+static int _hcng_punting_create_internal(hc_sock_t *socket,
+ hc_punting_t *punting, bool async) {
+ int rc;
+
+ if (hc_punting_validate(punting) < 0) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_punting_add_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_PUNTING_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = punting->prefix,
+ .family = punting->family,
+ .len = punting->prefix_len,
+ }};
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ punting->face_id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_PUNTING_ADD,
+ .size_in = sizeof(cmd_punting_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_punting_create(hc_sock_t *s, hc_punting_t *punting) {
+ return _hcng_punting_create_internal(s, punting, false);
+}
+
+static int _hcng_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
+ return _hcng_punting_create_internal(s, punting, true);
+}
+
+static int _hcng_punting_get(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found) {
+ ERROR("hc_punting_get not (yet) implemented.");
+ return -1;
+}
+
+static int _hcng_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
+ ERROR("hc_punting_delete not (yet) implemented.");
+ return -1;
+}
+
+#if 0
+static int hc_punting_parse(void * in, hc_punting_t * punting)
+{
+ ERROR("hc_punting_parse not (yet) implemented.");
+ return -1;
+}
+#endif
+
+static int _hcng_punting_list(hc_sock_t *s, hc_data_t **pdata) {
+ ERROR("hc_punting_list not (yet) implemented.");
+ return -1;
+}
+
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
+
+/* CACHE SET STORE */
+
+static int _hcng_cache_set_store_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_set_store_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_STORE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = cache->store,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_STORE,
+ .cmd_id = COMMAND_TYPE_CACHE_SET_STORE,
+ .size_in = sizeof(cmd_cache_set_store_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_store_internal(s, cache, false);
+}
+
+static int _hcng_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_store_internal(s, cache, true);
+}
+
+/* CACHE SET SERVE */
+
+static int _hcng_cache_set_serve_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_set_serve_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_SERVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = cache->serve,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SERVE,
+ .cmd_id = COMMAND_TYPE_CACHE_SET_SERVE,
+ .size_in = sizeof(cmd_cache_set_serve_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_serve_internal(s, cache, false);
+}
+
+static int _hcng_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_serve_internal(s, cache, true);
+}
+
+/* CACHE CLEAR */
+
+static int _hcng_cache_clear_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_clear_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_CLEAR,
+ .length = 1,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CLEAR,
+ .cmd_id = COMMAND_TYPE_CACHE_CLEAR,
+ .size_in = sizeof(cmd_cache_clear_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_clear(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_clear_internal(s, cache, false);
+}
+
+/* CACHE PARSE */
+
+static int hc_cache_parse(void *in, hc_cache_info_t *cache_info) {
+ cmd_cache_list_reply_t *item = (cmd_cache_list_reply_t *)in;
+ *cache_info = (hc_cache_info_t){.store = item->store_in_cs,
+ .serve = item->serve_from_cs,
+ .cs_size = item->cs_size,
+ .num_stale_entries = item->num_stale_entries};
+
+ return 0;
+}
+
+/* CACHE LIST */
+
+static hc_result_t *_hcng_cache_list_serialize(hc_sock_t *socket,
+ hc_data_t **pdata, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_cache_list] async=%s", BOOLSTR(async));
+
+ msg_cache_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CACHE_LIST,
+ .size_in = sizeof(cmd_cache_list_reply_t),
+ .size_out = sizeof(hc_cache_info_t),
+ .parse = (HC_PARSE)hc_cache_parse,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.cache_list = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static int _hcng_cache_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_cache_list_serialize(socket, pdata, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, pdata,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static int _hcng_cache_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_cache_list_internal(s, pdata, false);
+}
+
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+// per prefix
+static hc_result_t *_strategy_set_serialize(hc_sock_t *socket,
+ hc_strategy_t *strategy) {
+ hc_result_t *res = malloc(sizeof(*res));
+
+ char strategy_s[MAXSZ_HC_STRATEGY];
+ int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME,
+ strategy_str(strategy->type));
+ if (rc != EOK) goto ERR;
+ rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy);
+ if (rc >= MAXSZ_HC_STRATEGY)
+ WARN("[_hcng_strategy_create] Unexpected truncation of strategy string");
+ DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s);
+
+ if (!IS_VALID_FAMILY(strategy->family) ||
+ !IS_VALID_STRATEGY_TYPE(strategy->type)) {
+ goto ERR;
+ }
+
+ msg_strategy_set_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_SET,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = strategy->address,
+ .family = strategy->family,
+ .len = strategy->len,
+ .type = strategy->type,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_STRATEGY_SET,
+ .size_in = sizeof(cmd_strategy_set_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.strategy_set = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+
+ERR:
+ res->success = false;
+ return res;
+}
+
+static hc_result_t *_strategy_add_local_prefix_serialize(
+ hc_sock_t *socket, hc_strategy_t *strategy) {
+ hc_result_t *res = malloc(sizeof(*res));
+
+ char strategy_s[MAXSZ_HC_STRATEGY];
+ int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME,
+ strategy_str(strategy->type));
+ if (rc != EOK) goto ERR;
+ rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy);
+ if (rc >= MAXSZ_HC_STRATEGY)
+ WARN("[_hcng_strategy_create] Unexpected truncation of strategy string");
+ DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s);
+
+ if (!IS_VALID_FAMILY(strategy->family) ||
+ !IS_VALID_STRATEGY_TYPE(strategy->type) ||
+ !IS_VALID_FAMILY(strategy->local_family)) {
+ goto ERR;
+ }
+
+ msg_strategy_add_local_prefix_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .type = strategy->type,
+ .address = strategy->address,
+ .family = strategy->family,
+ .len = strategy->len,
+ .local_address = strategy->local_address,
+ .local_family = strategy->local_family,
+ .local_len = strategy->local_len,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX,
+ .size_in = sizeof(cmd_strategy_add_local_prefix_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.strategy_add_local_prefix = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+
+ERR:
+ res->success = false;
+ return res;
+}
+
+static hc_result_t *_hcng_strategy_set_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ return _strategy_set_serialize(s, strategy);
+}
+
+static int _hcng_strategy_set(hc_sock_t *socket, hc_strategy_t *strategy) {
+ hc_result_t *result = _strategy_set_serialize(socket, strategy);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static hc_result_t *_hcng_strategy_add_local_prefix_conf(
+ hc_sock_t *s, hc_strategy_t *strategy) {
+ return _strategy_add_local_prefix_serialize(s, strategy);
+}
+
+static int _hcng_strategy_add_local_prefix(hc_sock_t *socket,
+ hc_strategy_t *strategy) {
+ hc_result_t *result = _strategy_add_local_prefix_serialize(socket, strategy);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* How to retrieve that from the forwarder ? */
+static const char *strategies[] = {
+ "random",
+ "load_balancer",
+};
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
+
+static int _hcng_strategy_list(hc_sock_t *s, hc_data_t **data) {
+ int rc;
+
+ *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
+ hc_strategy_t *strategy = (hc_strategy_t *)hc_data_get_next(*data);
+ if (!strategy) return -1;
+ rc = snprintf(strategy->name, MAXSZ_STRATEGY_NAME, "%s", strategies[i]);
+ if (rc >= MAXSZ_STRATEGY_NAME)
+ WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
+ (*data)->size++;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+// per connection
+static int _hcng_wldr_set(hc_sock_t *s /* XXX */) { return 0; }
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+static int _hcng_mapme_set(hc_sock_t *socket, int enabled) {
+ msg_mapme_enable_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_ENABLE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_ENABLE,
+ .size_in = sizeof(cmd_mapme_enable_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_discovery(hc_sock_t *socket, int enabled) {
+ msg_mapme_enable_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_DISCOVERY,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_DISCOVERY,
+ .size_in = sizeof(cmd_mapme_set_discovery_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_timescale(hc_sock_t *socket, uint32_t timescale) {
+ msg_mapme_set_timescale_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_TIMESCALE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .timePeriod = timescale,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_TIMESCALE,
+ .size_in = sizeof(cmd_mapme_set_timescale_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_retx(hc_sock_t *socket, uint32_t timescale) {
+ msg_mapme_set_retx_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_RETX,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .timePeriod = timescale,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_RETX,
+ .size_in = sizeof(msg_mapme_set_retx_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_send_update(hc_sock_t *socket, hc_mapme_t *mapme) {
+ if (!IS_VALID_FAMILY(mapme->family)) return -1;
+
+ msg_mapme_send_update_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SEND_UPDATE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_UPDATE,
+ .cmd_id = COMMAND_TYPE_MAPME_SEND_UPDATE,
+ .size_in = sizeof(msg_mapme_send_update_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
+#ifdef WITH_POLICY
+
+/* POLICY CREATE */
+
+static int _hcng_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_policy_add_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ COMMAND_TYPE_POLICY_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .family = policy->family,
+ .len = policy->len,
+ .policy = policy->policy,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_POLICY_ADD,
+ .size_in = sizeof(cmd_policy_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_policy_create(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_create_internal(s, policy, false);
+}
+
+static int _hcng_policy_create_async(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_create_internal(s, policy, true);
+}
+
+/* POLICY DELETE */
+
+static int _hcng_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_policy_remove_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .family = policy->family,
+ .len = policy->len,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_POLICY_REMOVE,
+ .size_in = sizeof(cmd_policy_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_policy_delete(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_delete_internal(s, policy, false);
+}
+
+static int _hcng_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_delete_internal(s, policy, true);
+}
+
+/* POLICY PARSE */
+
+static int hc_policy_parse(void *in, hc_policy_t *policy) {
+ cmd_policy_list_item_t *item = (cmd_policy_list_item_t *)in;
+
+ if (!IS_VALID_ADDRESS(&item->address, item->family)) {
+ ERROR("[hc_policy_parse] Invalid address");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(item->family)) {
+ ERROR("[hc_policy_parse] Invalid family");
+ return -1;
+ }
+ if (!IS_VALID_PREFIX_LEN(item->len)) {
+ ERROR("[hc_policy_parse] Invalid len");
+ return -1;
+ }
+ if (!IS_VALID_POLICY(item->policy)) {
+ ERROR("[hc_policy_parse] Invalid policy");
+ return -1;
+ }
+
+ *policy = (hc_policy_t){
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .policy = item->policy,
+ };
+ return 0;
+}
+
+/* POLICY LIST */
+
+static int _hcng_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ struct {
+ cmd_header_t hdr;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_LIST,
+ .length = 0,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_POLICY_LIST,
+ .size_in = sizeof(cmd_policy_list_item_t),
+ .size_out = sizeof(hc_policy_t),
+ .parse = (HC_PARSE)hc_policy_parse,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ pdata, async);
+}
+
+static int _hcng_policy_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_policy_list_internal(s, pdata, false);
+}
+
+static int _hcng_policy_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_policy_list_internal(s, pdata, true);
+}
+
+#endif /* WITH_POLICY */
+
+/*----------------------------------------------------------------------------*
+ * Subscriptioins
+ *----------------------------------------------------------------------------*/
+
+/* SUBSCRIPTION CREATE */
+
+static hc_result_t *_subscription_create_serialize(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ msg_subscription_add_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_SUBSCRIPTION_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {.topics = subscription->topics}};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_SUBSCRIPTION_ADD,
+ .size_in = sizeof(cmd_subscription_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ hc_result_t *res = malloc(sizeof(*res));
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.subscription_add = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_subscription_create_conf(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ return _subscription_create_serialize(s, subscription);
+}
+
+static int _hcng_subscription_create(hc_sock_t *socket,
+ hc_subscription_t *subscriiption) {
+ hc_result_t *result = _subscription_create_serialize(socket, subscriiption);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* SUBSCRIPTION DELETE */
+
+static hc_result_t *_subscription_delete_serialize(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ msg_subscription_remove_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {.topics = subscription->topics}};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE,
+ .size_in = sizeof(cmd_subscription_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ hc_result_t *res = malloc(sizeof(*res));
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.subscription_remove = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_subscription_delete_conf(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ return _subscription_delete_serialize(s, subscription);
+}
+
+static int _hcng_subscription_delete(hc_sock_t *socket,
+ hc_subscription_t *subscriiption) {
+ hc_result_t *result = _subscription_delete_serialize(socket, subscriiption);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* RESULT */
+hc_msg_t *_hcng_result_get_msg(hc_result_t *result) { return &result->msg; }
+int _hcng_result_get_cmd_id(hc_result_t *result) {
+ return result->params.cmd_id;
+}
+bool _hcng_result_get_success(hc_result_t *result) { return result->success; }
+
+static hc_sock_t hc_sock_light_ng_interface = (hc_sock_t){
+ .hc_sock_get_next_seq = _hcng_sock_light_get_next_seq,
+ .hc_sock_set_nonblocking = _hcng_sock_light_set_nonblocking,
+ .hc_sock_get_fd = _hcng_sock_light_get_fd,
+ .hc_sock_connect = _hcng_sock_light_connect,
+ .hc_sock_get_available = _hcng_sock_light_get_available,
+ .hc_sock_send = _hcng_sock_light_send,
+ .hc_sock_recv = _hcng_sock_light_recv,
+ .hc_sock_process = _hcng_sock_light_process,
+ .hc_sock_callback = _hcng_sock_light_callback,
+ .hc_sock_reset = _hcng_sock_light_reset,
+ .hc_sock_free = _hcng_sock_light_free,
+ .hc_sock_increment_woff = _hcng_sock_increment_woff,
+ .hc_sock_prepare_send = _hcng_sock_prepare_send,
+ .hc_sock_set_recv_timeout_ms = _hcng_sock_set_recv_timeout_ms,
+ .hc_listener_create = _hcng_listener_create,
+ .hc_listener_create_async = _hcng_listener_create_async,
+ .hc_listener_get = _hcng_listener_get,
+ .hc_listener_delete = _hcng_listener_delete,
+ .hc_listener_delete_async = _hcng_listener_delete_async,
+ .hc_listener_list = _hcng_listener_list,
+ .hc_listener_list_async = _hcng_listener_list_async,
+ .hc_connection_create = _hcng_connection_create,
+ .hc_connection_create_async = _hcng_connection_create_async,
+ .hc_connection_get = _hcng_connection_get,
+ .hc_connection_update_by_id = _hcng_connection_update_by_id,
+ .hc_connection_update = _hcng_connection_update,
+ .hc_connection_delete = _hcng_connection_delete,
+ .hc_connection_delete_async = _hcng_connection_delete_async,
+ .hc_connection_list = _hcng_connection_list,
+ .hc_connection_list_async = _hcng_connection_list_async,
+ .hc_connection_set_admin_state = _hcng_connection_set_admin_state,
+ .hc_connection_set_admin_state_async =
+ _hcng_connection_set_admin_state_async,
+
+#ifdef WITH_POLICY
+ .hc_connection_set_priority = _hcng_connection_set_priority,
+ .hc_connection_set_priority_async = _hcng_connection_set_priority_async,
+ .hc_connection_set_tags = _hcng_connection_set_tags,
+ .hc_connection_set_tags_async = _hcng_connection_set_tags_async,
+#endif // WITH_POLICY
+
+ .hc_face_create = _hcng_face_create,
+ .hc_face_get = _hcng_face_get,
+ .hc_face_delete = _hcng_face_delete,
+ .hc_face_list = _hcng_face_list,
+ .hc_face_list_async = _hcng_face_list_async,
+ .hc_face_set_admin_state = _hcng_face_set_admin_state,
+
+#ifdef WITH_POLICY
+ .hc_face_set_priority = _hcng_face_set_priority,
+ .hc_face_set_tags = _hcng_face_set_tags,
+#endif // WITH_POLICY
+ .hc_subscription_create = _hcng_subscription_create,
+ .hc_subscription_delete = _hcng_subscription_delete,
+
+ .hc_route_create = _hcng_route_create,
+ .hc_route_create_async = _hcng_route_create_async,
+ .hc_route_delete = _hcng_route_delete,
+ .hc_route_delete_async = _hcng_route_delete_async,
+ .hc_route_list = _hcng_route_list,
+ .hc_route_list_async = _hcng_route_list_async,
+
+ .hc_punting_create = _hcng_punting_create,
+ .hc_punting_create_async = _hcng_punting_create_async,
+ .hc_punting_get = _hcng_punting_get,
+ .hc_punting_delete = _hcng_punting_delete,
+ .hc_punting_list = _hcng_punting_list,
+
+ .hc_cache_set_store = _hcng_cache_set_store,
+ .hc_cache_set_store_async = _hcng_cache_set_store_async,
+ .hc_cache_set_serve = _hcng_cache_set_serve,
+ .hc_cache_set_serve_async = _hcng_cache_set_serve_async,
+ .hc_cache_clear = _hcng_cache_clear,
+ .hc_cache_list = _hcng_cache_list,
+
+ .hc_strategy_list = _hcng_strategy_list,
+ .hc_strategy_set = _hcng_strategy_set,
+ .hc_strategy_add_local_prefix = _hcng_strategy_add_local_prefix,
+ .hc_wldr_set = _hcng_wldr_set,
+
+ .hc_mapme_set = _hcng_mapme_set,
+ .hc_mapme_set_discovery = _hcng_mapme_set_discovery,
+ .hc_mapme_set_timescale = _hcng_mapme_set_timescale,
+ .hc_mapme_set_retx = _hcng_mapme_set_retx,
+ .hc_mapme_send_update = _hcng_mapme_send_update,
+
+#ifdef WITH_POLICY
+ .hc_policy_create = _hcng_policy_create,
+ .hc_policy_create_async = _hcng_policy_create_async,
+ .hc_policy_delete = _hcng_policy_delete,
+ .hc_policy_delete_async = _hcng_policy_delete_async,
+ .hc_policy_list = _hcng_policy_list,
+ .hc_policy_list_async = _hcng_policy_list_async,
+#endif // WITH_POLICY
+
+ .hc_listener_create_conf = _hcng_listener_create_conf,
+ .hc_listener_list_conf = _hcng_listener_list_conf,
+ .hc_connection_create_conf = _hcng_connection_create_conf,
+ .hc_connection_delete_conf = _hcng_connection_delete_conf,
+ .hc_route_create_conf = _hcng_route_create_conf,
+ .hc_strategy_set_conf = _hcng_strategy_set_conf,
+ .hc_strategy_add_local_prefix_conf = _hcng_strategy_add_local_prefix_conf,
+ .hc_subscription_create_conf = _hcng_subscription_create_conf,
+ .hc_subscription_delete_conf = _hcng_subscription_delete_conf,
+
+ .hc_result_get_msg = _hcng_result_get_msg,
+ .hc_result_get_cmd_id = _hcng_result_get_cmd_id,
+ .hc_result_get_success = _hcng_result_get_success,
+};
+
+// Public contructors
+
+hc_sock_t *_hc_sock_create_url(const char *url) {
+ hc_sock_light_t *s = malloc(sizeof(hc_sock_light_t));
+ if (!s) goto ERR_MALLOC;
+
+ s->vft = hc_sock_light_ng_interface;
+ s->url = url ? strdup(url) : NULL;
+
+ s->fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s->fd < 0) goto ERR_SOCKET;
+
+ if (_hcng_sock_set_recv_timeout_ms((hc_sock_t *)s,
+ DEFAULT_SOCK_RECV_TIMEOUT_MS) < 0)
+ goto ERR_SOCKET;
+
+ if (_hcng_sock_light_reset((hc_sock_t *)s) < 0) goto ERR_RESET;
+
+ s->seq = 0;
+ s->cur_request = NULL;
+
+ s->map = hc_sock_map_create();
+ if (!s->map) goto ERR_MAP;
+
+ return (hc_sock_t *)(s);
+
+ // hc_sock_light_map_free(s->map);
+ERR_MAP:
+ERR_RESET:
+ if (s->url) free(s->url);
+ close(s->fd);
+ERR_SOCKET:
+ free(s);
+ERR_MALLOC:
+ return NULL;
+}
diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
index e59a2e41e..6d1baa786 100644
--- a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
+++ b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -18,8 +18,6 @@
* \brief Implementation of hICN control library API
*/
-#include "api_private.h"
-
#include <assert.h> // assert
#include <fcntl.h> // fcntl
#include <math.h> // log2
@@ -29,40 +27,10 @@
#include <sys/socket.h> // socket
#include <unistd.h> // close, fcntl
#include <vapi/vapi_safe.h>
-#include <vapi/hicn.api.vapi.h>
-#include <vapi/ip.api.vapi.h>
-#include <vapi/udp.api.vapi.h>
-#include <vapi/interface.api.vapi.h>
-
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
-#endif
-
-#include <vnet/ip/ip46_address.h>
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic pop
-#endif
-
-#define APP_NAME "hicn_plugin"
-#define MAX_OUTSTANDING_REQUESTS 4
-#define RESPONSE_QUEUE_SIZE 2
-
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-DEFINE_VAPI_MSG_IDS_UDP_API_JSON
+#include <vppinfra/clib.h>
+#include <vpp_plugins/hicn/error.h>
-typedef struct {
- vapi_ctx_t g_vapi_ctx_instance;
- bool async;
-} vapi_skc_ctx_t;
-
-vapi_skc_ctx_t vapi_skc = {
- .g_vapi_ctx_instance = NULL,
- .async = false,
-};
+#include "api_private.h"
/**
* Messages to the forwarder might be multiplexed thanks to the seqNum fields in
@@ -81,7 +49,6 @@ struct hc_sock_vpp_s {
vapi_ctx_t g_vapi_ctx_instance;
char *url;
- int fd;
size_t roff; /**< Read offset */
size_t woff; /**< Write offset */
@@ -94,43 +61,42 @@ struct hc_sock_vpp_s {
typedef struct hc_sock_vpp_s hc_sock_vpp_t;
-#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t*)(s)
+#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t *)(s)
/******************************************************************************
* Message helper types and aliases
******************************************************************************/
-#define foreach_hc_command \
- _(hicn_api_node_params_set) \
- _(hicn_api_node_params_set_reply) \
- _(hicn_api_node_params_get_reply) \
- _(hicn_api_node_stats_get_reply) \
- _(hicn_api_face_get) \
- _(hicn_api_faces_details) \
- _(hicn_api_face_stats_details) \
- _(hicn_api_face_get_reply) \
- _(hicn_api_route_get) \
- _(hicn_api_route_get_reply) \
- _(hicn_api_routes_details) \
- _(hicn_api_strategies_get_reply) \
- _(hicn_api_strategy_get) \
+#define foreach_hc_command \
+ _(hicn_api_node_params_set) \
+ _(hicn_api_node_params_set_reply) \
+ _(hicn_api_node_params_get_reply) \
+ _(hicn_api_node_stats_get_reply) \
+ _(hicn_api_face_get) \
+ _(hicn_api_faces_details) \
+ _(hicn_api_face_stats_details) \
+ _(hicn_api_face_get_reply) \
+ _(hicn_api_route_get) \
+ _(hicn_api_route_get_reply) \
+ _(hicn_api_routes_details) \
+ _(hicn_api_strategies_get_reply) \
+ _(hicn_api_strategy_get) \
_(hicn_api_strategy_get_reply)
-
typedef vapi_type_msg_header2_t hc_msg_header_t;
typedef union {
-#define _(a) vapi_payload_ ## a a;
+#define _(a) vapi_payload_##a a;
foreach_hc_command
#undef _
} hc_msg_payload_t;
-typedef struct __attribute__ ((__packed__)) {
+typedef struct __attribute__((__packed__)) {
hc_msg_header_t hdr;
hc_msg_payload_t payload;
} hc_hicnp_t;
-typedef void (* NTOH)(void *msg);
+typedef void (*NTOH)(void *msg);
typedef struct __attribute__((__packed__)) {
hc_data_t *data;
@@ -138,7 +104,7 @@ typedef struct __attribute__((__packed__)) {
} callback_ctx_t;
typedef struct __attribute__((__packed__)) {
- hc_hicnp_t * hicnp_msg;
+ hc_hicnp_t *hicnp_msg;
vapi_cb_t callback;
callback_ctx_t *callback_ctx;
NTOH ntoh;
@@ -151,11 +117,9 @@ typedef struct __attribute__((__packed__)) {
static void _hc_sock_vpp_free(hc_sock_t *socket) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
if (s->url) free(s->url);
- close(s->fd);
free(s);
vapi_disconnect_safe();
- vapi_skc.g_vapi_ctx_instance = NULL;
}
static int _hc_sock_vpp_get_next_seq(hc_sock_t *socket) {
@@ -174,8 +138,7 @@ static int _hc_sock_vpp_get_fd(hc_sock_t *s) { return 1; }
static int _hc_sock_vpp_connect(hc_sock_t *socket) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_error_e rv = vapi_connect_safe(&s->g_vapi_ctx_instance, s->async);
- if (rv != VAPI_OK)
- goto ERR_CONNECT;
+ if (rv != VAPI_OK) goto ERR_CONNECT;
return 0;
@@ -184,7 +147,8 @@ ERR_CONNECT:
return -1;
}
-static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) {
+static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen,
+ uint32_t seq) {
return -1;
}
@@ -199,16 +163,16 @@ static int _hc_sock_vpp_recv(hc_sock_t *s) {
}
static int _hc_sock_vpp_process(hc_sock_t *s, hc_data_t **pdata) {
- //NOT IMPLEMENTED
+ // NOT IMPLEMENTED
return -1;
}
-static int _hc_sock_vpp_callback(hc_sock_t * socket, hc_data_t ** pdata) {
+static int _hc_sock_vpp_callback(hc_sock_t *socket, hc_data_t **pdata) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_sock_vpp_reset(hc_sock_t * socket) {
+static int _hc_sock_vpp_reset(hc_sock_t *socket) {
// NOT IMPLEMENTED
return -1;
}
@@ -217,7 +181,6 @@ static int _hc_sock_vpp_reset(hc_sock_t * socket) {
* Command-specific structures and functions
******************************************************************************/
-
/*----------------------------------------------------------------------------*
* Listeners
*----------------------------------------------------------------------------*/
@@ -236,7 +199,7 @@ static int _hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
/* LISTENER GET */
static int _hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
- hc_listener_t **listener_found) {
+ hc_listener_t **listener_found) {
// NOT IMPLEMENTED
return -1;
}
@@ -253,33 +216,32 @@ static int _hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
return -1;
}
-static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
+static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
vapi_payload_ip_address_details *reply) {
-
- if (is_last)
- return 0;
+ if (is_last) return 0;
hc_data_t *data = (hc_data_t *)callback_ctx;
if (data->size == data->current) {
- data->buffer = realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2);
+ data->buffer =
+ realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2);
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size *=2;
+ data->size *= 2;
}
- hc_listener_t * listener = (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t));
+ hc_listener_t *listener =
+ (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t));
+ memset(listener, 0, sizeof(hc_listener_t));
- if(reply->prefix.address.af == ADDRESS_IP4) {
- memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4, IPV4_ADDR_LEN);
+ if (reply->prefix.address.af == ADDRESS_IP4) {
+ memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4,
+ IPV4_ADDR_LEN);
listener->family = AF_INET;
- }
- else {
- memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6, IPV6_ADDR_LEN);
+ } else {
+ memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6,
+ IPV6_ADDR_LEN);
listener->family = AF_INET6;
}
@@ -293,31 +255,26 @@ typedef struct {
char interface_name[INTERFACE_LEN];
} hc_vapi_interface_t;
-static vapi_error_e listener_list_complete_cb (
- struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_sw_interface_details *reply) {
+static vapi_error_e listener_list_complete_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply == NULL || rv != VAPI_OK)
- return rv;
-
- if (is_last)
- return 0;
+ if (is_last) return 0;
hc_data_t *data = (hc_data_t *)callback_ctx;
if (data->size == data->current) {
- data->buffer = realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2);
+ data->buffer =
+ realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2);
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size *=2;
+ data->size *= 2;
}
- hc_vapi_interface_t *swif = &((hc_vapi_interface_t*)data->buffer)[data->current];
+ hc_vapi_interface_t *swif =
+ &((hc_vapi_interface_t *)data->buffer)[data->current];
swif[0].swif = reply->sw_if_index;
memcpy(swif[0].interface_name, reply->interface_name, INTERFACE_LEN);
@@ -327,7 +284,6 @@ static vapi_error_e listener_list_complete_cb (
return rv;
}
-
/* LISTENER LIST */
static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
@@ -344,14 +300,14 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
hicnp_msg->payload.sw_if_index = ~0;
hicnp_msg->payload.name_filter_valid = 0;
- hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t),NULL);
+ hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t), NULL);
if (!data) {
retval = -1;
goto END;
}
- hc_data_t *data2 = hc_data_create(0, 1,NULL);
+ hc_data_t *data2 = hc_data_create(0, 1, NULL);
if (!data2) {
retval = -1;
@@ -362,12 +318,13 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
data->size = 1;
if (!data->buffer) {
- free (data);
+ free(data);
retval = -1;
goto FREE_DATA;
}
- int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg, listener_list_complete_cb, data);
+ int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg,
+ listener_list_complete_cb, data);
if (ret != VAPI_OK) {
free(data->buffer);
@@ -381,28 +338,34 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
data2->out_element_size = 1;
if (!data2->buffer) {
- free (data2->buffer);
- retval =1 -1;
+ free(data2->buffer);
+ retval = -1;
goto CLEAN;
}
/* Query the forwarder for each interface */
- for(int i = 0; i < data->current; i++) {
+ for (int i = 0; i < data->current; i++) {
int index = data2->current;
- vapi_msg_ip_address_dump* msg = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
+ vapi_msg_ip_address_dump *msg =
+ vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
msg->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif;
msg->payload.is_ipv6 = 0;
- retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info, data2);
- vapi_msg_ip_address_dump* msg2 = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
+ retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info,
+ data2);
+ vapi_msg_ip_address_dump *msg2 =
+ vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
if (retval) goto CLEAN;
msg2->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif;
msg2->payload.is_ipv6 = 1;
- retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, data2);
+ retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info,
+ data2);
for (size_t j = index; j < data2->current; j++) {
- memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name, ((hc_vapi_interface_t*)(data->buffer))[i].interface_name, INTERFACE_LEN);
- ((hc_listener_t *)(data2->buffer))[j].type = CONNECTION_TYPE_HICN;
+ memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name,
+ ((hc_vapi_interface_t *)(data->buffer))[i].interface_name,
+ INTERFACE_LEN);
+ ((hc_listener_t *)(data2->buffer))[j].type = FACE_TYPE_HICN;
}
if (retval) goto CLEAN;
@@ -417,7 +380,7 @@ FREE_DATA:
data2->size = data2->current;
data2->out_element_size = sizeof(hc_listener_t);
*pdata = data2;
- END:
+END:
vapi_unlock();
return retval;
}
@@ -438,7 +401,8 @@ static int _hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
return -1;
}
-static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_create_async(hc_sock_t *s,
+ hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
@@ -446,17 +410,20 @@ static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection
/* CONNECTION GET */
static int _hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
- hc_connection_t **connection_found) {
+ hc_connection_t **connection_found) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection) {
+static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection) {
// Not implemented
return -1;
}
-static int _hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated) {
+static int _hc_connection_update(hc_sock_t *s,
+ hc_connection_t *connection_current,
+ hc_connection_t *connection_updated) {
// Not implemented
return -1;
}
@@ -468,7 +435,8 @@ static int _hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
return -1;
}
-static int _hc_connection_delete_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_delete_async(hc_sock_t *s,
+ hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
@@ -487,39 +455,47 @@ static int _hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
/* CONNECTION SET ADMIN STATE */
-static int _hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
- face_state_t state) {
+static int _hc_connection_set_admin_state(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
static int _hc_connection_set_admin_state_async(hc_sock_t *s,
- const char *conn_id_or_name,
- face_state_t state) {
+ const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
#ifdef WITH_POLICY
-static int _hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_connection_set_priority(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_connection_set_priority_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
-static int _hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_connection_set_tags_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
@@ -528,66 +504,65 @@ static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_
* Routes
*----------------------------------------------------------------------------*/
-static vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e create_udp_tunnel_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
- u32 * uei = (u32*) callback_ctx;
+ u32 *uei = (u32 *)callback_ctx;
*uei = reply->uei;
return reply->retval;
}
/* ROUTE CREATE */
-static vapi_error_e parse_route_create( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_create(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
return reply->retval;
}
-static vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_enable_disable_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e hicn_enable_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
+ face_id_t *faceid = (face_id_t *)callback_ctx;
+
+ if (reply->nfaces) {
+ *faceid = reply->faceids[0];
+ }
return reply->retval;
}
-static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
+static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
- int ret;
+ int ret = -1;
vapi_lock();
- vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
+ vapi_msg_ip_route_add_del *hicnp_msg =
+ vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
hicnp_msg->payload.is_add = 1;
if (route->family == AF_INET) {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0],
+ &route->remote_addr.v4, 4);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
- }
- else {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0],
+ &route->remote_addr.v6, 16);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
hicnp_msg->payload.route.prefix.len = route->len;
@@ -596,87 +571,101 @@ static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool
hicnp_msg->payload.route.paths[0].table_id = 0;
hc_face_t *face = &(route->face);
- switch (face->face.type) {
- case FACE_TYPE_HICN:
- {
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
- }
- else{
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
- }
-
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
-
- break;
- }
- case FACE_TYPE_UDP:
- {
- vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL;
- u32 uei = ~0;
-
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr))) &&
- ip46_address_is_ip4((ip46_address_t *)(&(face->face.local_addr)))) {
- msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
- memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4, sizeof(ip4_address_t));
- msg->payload.src_addr.af = ADDRESS_IP4;
+ face->face.netdevice.index = ~0;
+ face->id = INVALID_FACE_ID;
- memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4, sizeof(ip4_address_t));
- msg->payload.dst_addr.af = ADDRESS_IP4;
+ switch (face->face.type) {
+ case FACE_TYPE_HICN: {
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4),
+ &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6),
+ &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
- } else if (!ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.remote_addr))) &&
- !ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.local_addr)))) {
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
- memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6, sizeof(ip6_address_t));
- msg->payload.src_addr.af = ADDRESS_IP4;
+ break;
+ }
+ case FACE_TYPE_UDP: {
+ vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL;
+ u32 uei = ~0;
+
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr))) &&
+ ip_address_is_v4((ip_address_t *)(&(face->face.local_addr)))) {
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4,
+ sizeof(ip4_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP4;
+
+ memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4,
+ sizeof(ip4_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP4;
+
+ } else if (!ip_address_is_v4(
+ (ip_address_t *)(&(route->face.face.remote_addr))) &&
+ !ip_address_is_v4(
+ (ip_address_t *)(&(route->face.face.local_addr)))) {
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6,
+ sizeof(ip6_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP6;
+
+ memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6,
+ sizeof(ip6_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP6;
+ } else {
+ // NOT IMPLEMENTED
+ ret = -1;
+ goto done;
+ }
- memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6, sizeof(ip6_address_t));
- msg->payload.dst_addr.af = ADDRESS_IP6;
+ msg->payload.src_port = face->face.local_port;
+ msg->payload.dst_port = face->face.remote_port;
+ msg->payload.is_add = 1;
- } else {
- //NOT IMPLEMENTED
- ret = -1;
- goto done;
- }
+ int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg,
+ create_udp_tunnel_cb, &uei);
- msg->payload.src_port = face->face.local_port;
- msg->payload.dst_port = face->face.remote_port;
- msg->payload.is_add = 1;
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_udp_tunnel_add_del");
+ vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg);
+ goto done;
+ }
- int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg, create_udp_tunnel_cb, &uei);
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = uei;
- if(ret) {
- vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg);
- goto done;
- }
+ face->face.netdevice.index = uei;
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].nh.obj_id = uei;
- break;
- }
+ break;
+ }
default:
ret = -1;
goto done;
}
- ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_create, NULL);
+ ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg,
+ parse_route_create, NULL);
- if (ret)
+ if (ret) {
+ ERROR("Error in vapi_ip_route_add_del");
goto done;
+ }
- vapi_msg_hicn_api_enable_disable *msg = vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
+ vapi_msg_hicn_api_enable_disable *msg =
+ vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
if (route->family == AF_INET) {
memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
msg->payload.prefix.address.af = ADDRESS_IP4;
- }
- else {
+ } else {
memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
msg->payload.prefix.address.af = ADDRESS_IP6;
}
@@ -684,7 +673,13 @@ static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool
msg->payload.prefix.len = route->len;
msg->payload.enable_disable = 1;
- ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, hicn_enable_cb, NULL);
+ ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg,
+ hicn_enable_cb, &face->id);
+
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_enable_disable");
+ }
+
done:
vapi_unlock();
return ret;
@@ -699,32 +694,63 @@ static int _hc_route_create_async(hc_sock_t *s, hc_route_t *route) {
}
/* ROUTE DELETE */
-static vapi_error_e parse_route_delete( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_delete(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
+
+ return reply->retval;
+}
+
+static vapi_error_e hicn_disable_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
return reply->retval;
}
-static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
+static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_lock();
- vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
+
+ vapi_msg_hicn_api_enable_disable *msg =
+ vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
+
+ if (route->family == AF_INET) {
+ memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ msg->payload.prefix.address.af = ADDRESS_IP4;
+ } else {
+ memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ msg->payload.prefix.address.af = ADDRESS_IP6;
+ }
+
+ msg->payload.prefix.len = route->len;
+ msg->payload.enable_disable = 0;
+
+ vapi_error_e ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg,
+ hicn_disable_cb, NULL);
+
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_enable_disable in route delete");
+ goto done;
+ }
+
+ vapi_msg_ip_route_add_del *hicnp_msg =
+ vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
hicnp_msg->payload.is_add = 0;
if (route->family == AF_INET) {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0],
+ &route->remote_addr.v4, 4);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
- }
- else {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ } else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0],
+ &route->remote_addr.v6, 16);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
}
@@ -735,34 +761,41 @@ static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool
hc_face_t *face = &(route->face);
switch (face->face.type) {
- case FACE_TYPE_HICN:
- {
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
- }
- else{
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
- }
-
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
-
- break;
- }
- case FACE_TYPE_UDP:
- {
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index;
- break;
+ case FACE_TYPE_HICN: {
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4),
+ &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6),
+ &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
+
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+
+ break;
+ }
+ case FACE_TYPE_UDP: {
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index;
+ break;
+ }
default:
return -1;
}
- vapi_error_e ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_delete, NULL);
+ ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg,
+ parse_route_delete, NULL);
+
+ if (ret) {
+ ERROR("Error in vapi_ip_route_add_del in route delete");
+ goto done;
+ }
+
+done:
vapi_unlock();
return ret;
@@ -776,33 +809,31 @@ static int _hc_route_delete_async(hc_sock_t *s, hc_route_t *route) {
return _hc_route_delete_internal(s, route, true);
}
-static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_udp_encap_details *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_udp_encap_list(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_udp_encap_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- hc_face_t * face = (hc_face_t *)callback_ctx;
+ hc_face_t *face = (hc_face_t *)callback_ctx;
- if (face->face.netdevice.index == reply->udp_encap.id)
- {
- switch(reply->udp_encap.src_ip.af) {
- case ADDRESS_IP4:
- {
- memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), sizeof(ip4_address_t));
- memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), sizeof(ip4_address_t));
+ if (face->face.netdevice.index == reply->udp_encap.id) {
+ switch (reply->udp_encap.src_ip.af) {
+ case ADDRESS_IP4: {
+ memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4),
+ sizeof(ip4_address_t));
+ memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4),
+ sizeof(ip4_address_t));
break;
}
- case ADDRESS_IP6:
- {
- memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), sizeof(ip6_address_t));
- memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), sizeof(ip6_address_t));
+ case ADDRESS_IP6: {
+ memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6),
+ sizeof(ip6_address_t));
+ memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6),
+ sizeof(ip6_address_t));
break;
}
default:
- break;
+ break;
}
face->face.local_port = reply->udp_encap.src_port;
@@ -811,35 +842,35 @@ static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
return rv;
}
-static int _fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) {
- switch(path->type){
- case FIB_API_PATH_FLAG_NONE:
- {
+static int _fill_face_with_info(hc_face_t *face, vapi_type_fib_path *path,
+ hc_sock_t *s) {
+ switch (path->type) {
+ case FIB_API_PATH_FLAG_NONE: {
face->face.type = FACE_TYPE_HICN;
- switch(path->proto){
+ switch (path->proto) {
case FIB_API_PATH_NH_PROTO_IP4:
- memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4), sizeof(ip4_address_t));
- break;
+ memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4),
+ sizeof(ip4_address_t));
+ break;
case FIB_API_PATH_NH_PROTO_IP6:
- memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6), sizeof(ip6_address_t));
- break;
+ memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6),
+ sizeof(ip6_address_t));
+ break;
default:
- break;
+ break;
}
face->face.netdevice.index = path->sw_if_index;
- }
- break;
- case FIB_API_PATH_TYPE_UDP_ENCAP:
- {
+ } break;
+ case FIB_API_PATH_TYPE_UDP_ENCAP: {
face->face.type = FACE_TYPE_UDP;
face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id);
// Let's make the compiler happy
(void)parse_udp_encap_list;
- //vapi_msg_udp_encap_dump *msg;
- //msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
- //vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, face);
- }
- break;
+ // vapi_msg_udp_encap_dump *msg;
+ // msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
+ // vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list,
+ // face);
+ } break;
default:
return -1;
}
@@ -852,32 +883,33 @@ typedef struct hicn_route_socket_s {
hc_sock_t *s;
} hicn_route_socket_t;
-static vapi_error_e parse_route_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_details *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_list(vapi_ctx_t ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
hicn_route_socket_t *rs = (hicn_route_socket_t *)callback_ctx;
hc_data_t *data = rs->data;
u8 found = false;
- for (int j = 0; j < reply->route.n_paths; j++){
+ for (int j = 0; j < reply->route.n_paths; j++) {
for (int i = 0; i < data->size && !found; i++) {
- hc_route_t * route = &((hc_route_t*)(data->buffer))[i];
-
- if(ip46_address_is_ip4((ip46_address_t *)&(route->remote_addr)) &&
- memcmp(route->remote_addr.v4.as_u8, reply->route.prefix.address.un.ip4, sizeof(ip4_address_t)) == 0 &&
- route->len == reply->route.prefix.len && route->face_id == ~0) {
- _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
- found = true;
- } else if (memcmp(route->remote_addr.v6.as_u8, reply->route.prefix.address.un.ip6, sizeof(ip6_address_t)) == 0 &&
- route->len == reply->route.prefix.len && route->face_id == ~0) {
- _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
- found = true;
+ hc_route_t *route = &((hc_route_t *)(data->buffer))[i];
+
+ if (ip_address_is_v4((ip_address_t *)&(route->remote_addr)) &&
+ memcmp(route->remote_addr.v4.as_u8,
+ reply->route.prefix.address.un.ip4,
+ sizeof(ip4_address_t)) == 0 &&
+ route->len == reply->route.prefix.len && route->face_id == ~0) {
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
+ } else if (memcmp(route->remote_addr.v6.as_u8,
+ reply->route.prefix.address.un.ip6,
+ sizeof(ip6_address_t)) == 0 &&
+ route->len == reply->route.prefix.len &&
+ route->face_id == ~0) {
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
}
}
}
@@ -885,14 +917,10 @@ static vapi_error_e parse_route_list( vapi_ctx_t ctx,
return rv;
}
-static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_routes_details *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_hicn_route_list(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_routes_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
hc_data_t *data = (hc_data_t *)callback_ctx;
@@ -900,43 +928,41 @@ static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
if (empty_spots < reply->nfaces) {
int new_size = data->size + (reply->nfaces - empty_spots);
data->buffer = realloc(data->buffer, sizeof(hc_route_t) * (new_size));
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size =new_size;
+ data->size = new_size;
}
for (int i = 0; i < reply->nfaces; i++) {
- hc_route_t * route = &((hc_route_t*)(data->buffer))[data->current];
+ hc_route_t *route = &((hc_route_t *)(data->buffer))[data->current];
route->face_id = ~0;
route->cost = 1;
route->len = reply->prefix.len;
- if (reply->prefix.address.af == ADDRESS_IP6)
- {
- memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16);
- }
- else
- {
- memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4);
- }
- route->family = reply->prefix.address.af == ADDRESS_IP6? AF_INET6 : AF_INET;
+ if (reply->prefix.address.af == ADDRESS_IP6) {
+ memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16);
+ } else {
+ memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4);
+ }
+ route->family =
+ reply->prefix.address.af == ADDRESS_IP6 ? AF_INET6 : AF_INET;
data->current++;
}
return rv;
}
-static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool async) {
+static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_lock();
vapi_msg_hicn_api_routes_dump *msg;
msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance);
- hc_data_t *data = hc_data_create(0, sizeof(hc_route_t),NULL);
+ hc_data_t *data = hc_data_create(0, sizeof(hc_route_t), NULL);
int ret = VAPI_OK;
- if (!data){
+ if (!data) {
ret = -1;
goto err;
}
@@ -949,10 +975,10 @@ static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool as
goto err_free;
}
- ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, parse_hicn_route_list, data);
+ ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg,
+ parse_hicn_route_list, data);
- if (ret != VAPI_OK)
- goto err_free;
+ if (ret != VAPI_OK) goto err_free;
vapi_msg_ip_route_dump *hicnp_msg;
hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
@@ -960,29 +986,30 @@ static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool as
hicnp_msg->payload.table.is_ip6 = 1;
hicn_route_socket_t ctx = {
- .data = data,
- .s = socket,
+ .data = data,
+ .s = socket,
};
- ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list,
+ &ctx);
hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
hicnp_msg->payload.table.table_id = 0;
hicnp_msg->payload.table.is_ip6 = 0;
- ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list,
+ &ctx);
- if (ret != VAPI_OK)
- goto err_free;
+ if (ret != VAPI_OK) goto err_free;
*pdata = data;
vapi_unlock();
return ret;
- err_free:
+err_free:
free(data);
- err:
+err:
vapi_unlock();
return ret;
}
@@ -1008,17 +1035,19 @@ static int _hc_route_list_async(hc_sock_t *s) {
*
*----------------------------------------------------------------------------*/
-static int _hc_face_create(hc_sock_t *s, hc_face_t *face) {
- ERROR("Face creation implemented.");
+static int _hc_face_create(hc_sock_t *socket, hc_face_t *face) {
+ ERROR("Face creation not implemented.");
return -1;
}
-static int _hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found) {
+static int _hc_face_get(hc_sock_t *socket, hc_face_t *face,
+ hc_face_t **face_found) {
ERROR("Face deletion not implemented.");
return -1;
}
-static int _hc_face_delete(hc_sock_t *s, hc_face_t *face) {
+static int _hc_face_delete(hc_sock_t *s, hc_face_t *face,
+ uint8_t delete_listener) {
ERROR("Face deletion not implemented.");
return -1;
}
@@ -1030,9 +1059,7 @@ static int _hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
return -1;
}
-static int _hc_face_list_async(hc_sock_t *s) {
- return 0;
-}
+static int _hc_face_list_async(hc_sock_t *s) { return 0; }
static int _hc_face_set_admin_state(
hc_sock_t *s, const char *conn_id_or_name, // XXX wrong identifier
@@ -1041,22 +1068,25 @@ static int _hc_face_set_admin_state(
}
#ifdef WITH_POLICY
-static int _hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
ERROR("Face set priority not implemented.");
return -1;
}
-static int _hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
ERROR("Face set tags not implemented.");
return -1;
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
/*----------------------------------------------------------------------------*
* Punting
*----------------------------------------------------------------------------*/
-static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting, bool async) {
+static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting,
+ bool async) {
return -1;
}
@@ -1069,7 +1099,7 @@ static int _hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
}
static int _hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
- hc_punting_t **punting_found) {
+ hc_punting_t **punting_found) {
ERROR("hc_punting_get not (yet) implemented.");
return -1;
}
@@ -1088,28 +1118,30 @@ static int _hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
* Cache
*----------------------------------------------------------------------------*/
-static int _hc_cache_set_store_internal(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_store_internal(hc_sock_t *s, hc_cache_t *cache,
+ bool async) {
return 0;
}
-static int _hc_cache_set_store(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store_internal(s, enabled, false);
+static int _hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_store_internal(s, cache, false);
}
-static int _hc_cache_set_store_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store_internal(s, enabled, true);
+static int _hc_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_store_internal(s, cache, true);
}
-static int _hc_cache_set_serve_internal(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_serve_internal(hc_sock_t *s, hc_cache_t *cache,
+ bool async) {
return 0;
}
-static int _hc_cache_set_serve(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve_internal(s, enabled, false);
+static int _hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_serve_internal(s, cache, false);
}
-static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve_internal(s, enabled, true);
+static int _hc_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_serve_internal(s, cache, true);
}
/*----------------------------------------------------------------------------*
@@ -1117,12 +1149,15 @@ static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
*----------------------------------------------------------------------------*/
// per prefix
-static int _hc_strategy_set(hc_sock_t *s /* XXX */) { return 0; }
+static int _hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { return 0; }
-static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
+static int _hc_strategy_add_local_prefix(hc_sock_t *s,
+ hc_strategy_t *strategy) {
return 0;
}
+static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) { return 0; }
+
/*----------------------------------------------------------------------------*
* WLDR
*----------------------------------------------------------------------------*/
@@ -1138,9 +1173,11 @@ static int _hc_mapme_set(hc_sock_t *s, int enabled) { return 0; }
static int _hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; }
-static int _hc_mapme_set_timescale(hc_sock_t *s, double timescale) { return 0; }
+static int _hc_mapme_set_timescale(hc_sock_t *s, uint32_t timescale) {
+ return 0;
+}
-static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
+static int _hc_mapme_set_retx(hc_sock_t *s, uint32_t timescale) { return 0; }
/*----------------------------------------------------------------------------*
* Policy
@@ -1150,51 +1187,99 @@ static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
/* POLICY CREATE */
-static int _hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+static int _hc_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
return -1;
}
-static int
-_hc_policy_create(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_create(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_create_internal(s, policy, false);
}
-static int _hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_create_async(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_create_internal(s, policy, true);
}
/* POLICY DELETE */
-static int _hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+static int _hc_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
return -1;
}
-static int _hc_policy_delete(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_delete(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_delete_internal(s, policy, false);
}
-static int _hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_delete_internal(s, policy, true);
}
/* POLICY LIST */
-static int
-_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) {
+static int _hc_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
return -1;
}
-static int _hc_policy_list(hc_sock_t * s, hc_data_t ** pdata) {
+static int _hc_policy_list(hc_sock_t *s, hc_data_t **pdata) {
return _hc_policy_list_internal(s, pdata, false);
}
-static int _hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata) {
+static int _hc_policy_list_async(hc_sock_t *s, hc_data_t **pdata) {
return _hc_policy_list_internal(s, pdata, true);
}
#endif /* WITH_POLICY */
-static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
+/*----------------------------------------------------------------------------*
+ * Configuration
+ *----------------------------------------------------------------------------*/
+
+typedef struct hc_result_s {
+ void *_;
+} hc_result_t;
+
+static hc_result_t *_hc_listener_create_conf(hc_sock_t *s,
+ hc_listener_t *listener) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_strategy_set_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_strategy_add_local_prefix_conf(
+ hc_sock_t *s, hc_strategy_t *strategy) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+
+hc_msg_t *_hc_result_get_msg(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+int _hc_result_get_cmd_id(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return -1;
+}
+bool _hc_result_get_success(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return false;
+}
+void _hc_result_free(hc_result_t *result) { free(result); }
+
+static hc_sock_t hc_sock_vpp_interface = (hc_sock_t){
.hc_sock_get_next_seq = _hc_sock_vpp_get_next_seq,
.hc_sock_set_nonblocking = _hc_sock_vpp_set_nonblocking,
.hc_sock_get_fd = _hc_sock_vpp_get_fd,
@@ -1230,7 +1315,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_connection_set_priority_async = _hc_connection_set_priority_async,
.hc_connection_set_tags = _hc_connection_set_tags,
.hc_connection_set_tags_async = _hc_connection_set_tags_async,
-#endif // WITH_POLICY
+#endif // WITH_POLICY
.hc_face_create = _hc_face_create,
.hc_face_get = _hc_face_get,
@@ -1242,7 +1327,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
#ifdef WITH_POLICY
.hc_face_set_priority = _hc_face_set_priority,
.hc_face_set_tags = _hc_face_set_tags,
-#endif // WITH_POLICY
+#endif // WITH_POLICY
.hc_route_create = _hc_route_create,
.hc_route_create_async = _hc_route_create_async,
@@ -1264,6 +1349,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_strategy_list = _hc_strategy_list,
.hc_strategy_set = _hc_strategy_set,
+ .hc_strategy_add_local_prefix = _hc_strategy_add_local_prefix,
.hc_wldr_set = _hc_wldr_set,
.hc_mapme_set = _hc_mapme_set,
@@ -1277,16 +1363,27 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_policy_delete = _hc_policy_delete,
.hc_policy_delete_async = _hc_policy_delete_async,
.hc_policy_list = _hc_policy_list,
- .hc_policy_list_async = _hc_policy_list_async
-#endif // WITH_POLICY
+ .hc_policy_list_async = _hc_policy_list_async,
+#endif // WITH_POLICY
+
+ .hc_listener_create_conf = _hc_listener_create_conf,
+ .hc_connection_create_conf = _hc_connection_create_conf,
+ .hc_route_create_conf = _hc_route_create_conf,
+ .hc_strategy_set_conf = _hc_strategy_set_conf,
+ .hc_strategy_add_local_prefix_conf = _hc_strategy_add_local_prefix_conf,
+
+ .hc_result_get_msg = _hc_result_get_msg,
+ .hc_result_get_cmd_id = _hc_result_get_cmd_id,
+ .hc_result_get_success = _hc_result_get_success,
+ .hc_result_free = _hc_result_free,
};
hc_sock_t *_hc_sock_create_url(const char *url) {
- // NOT IMPLEMENTED
- return NULL;
-}
+ if (url) {
+ // NOT IMPLEMENTED
+ return NULL;
+ }
-hc_sock_t *_hc_sock_create(void) {
hc_sock_vpp_t *s = malloc(sizeof(hc_sock_vpp_t));
if (!s) goto ERR_SOCK;
@@ -1302,4 +1399,4 @@ hc_sock_t *_hc_sock_create(void) {
ERR_SOCK:
return NULL;
-} \ No newline at end of file
+}
diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c
index 703b4763f..f59dbce7c 100644
--- a/ctrl/libhicnctrl/src/route.c
+++ b/ctrl/libhicnctrl/src/route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -25,84 +25,64 @@
#define DEFAULT_HICN_ROUTE_COST 1
struct hicn_route_s {
- ip_prefix_t prefix;
- face_id_t face_id;
- route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */
+ ip_prefix_t prefix;
+ face_id_t face_id;
+ route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */
};
-hicn_route_t *
-hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost)
-{
- hicn_route_t * route = malloc(sizeof(hicn_route_t));
- if (!route)
- return NULL;
- route->prefix = *prefix;
- route->face_id = face_id;
- route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST;
+hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id,
+ route_cost_t cost) {
+ hicn_route_t* route = malloc(sizeof(hicn_route_t));
+ if (!route) return NULL;
+ route->prefix = *prefix;
+ route->face_id = face_id;
+ route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST;
- return route;
+ return route;
}
-hicn_route_t *
-hicn_route_dup(const hicn_route_t * route)
-{
- hicn_route_t * new_route = malloc(sizeof(hicn_route_t));
- if (!route)
- return NULL;
- memcpy(new_route, route, sizeof(hicn_route_t));
- return new_route;
+hicn_route_t* hicn_route_dup(const hicn_route_t* route) {
+ hicn_route_t* new_route = malloc(sizeof(hicn_route_t));
+ if (!route) return NULL;
+ memcpy(new_route, route, sizeof(hicn_route_t));
+ return new_route;
}
-void hicn_route_free(hicn_route_t * route)
-{
- free(route);
-}
+void hicn_route_free(hicn_route_t* route) { free(route); }
-int
-hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2)
-{
- int rc;
- rc = ip_prefix_cmp(&route1->prefix, &route2->prefix);
- if (rc != 0)
- return rc;
+int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2) {
+ int rc;
+ rc = ip_prefix_cmp(&route1->prefix, &route2->prefix);
+ if (rc != 0) return rc;
- return (route1->face_id > route2->face_id) ? 1 :
- (route1->face_id < route2->face_id) ? -1 : 0;
+ return (route1->face_id > route2->face_id) ? 1
+ : (route1->face_id < route2->face_id) ? -1
+ : 0;
}
-int
-hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix)
-{
- *prefix = route->prefix;
- return 0;
+int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix) {
+ *prefix = route->prefix;
+ return 0;
}
-int
-hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix)
-{
- route->prefix = prefix;
- return 0;
+int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix) {
+ route->prefix = prefix;
+ return 0;
}
-int
-hicn_route_get_cost(const hicn_route_t * route, int * cost)
-{
- *cost = route->cost;
- return 0;
+int hicn_route_get_cost(const hicn_route_t* route, int* cost) {
+ *cost = route->cost;
+ return 0;
}
-int
-hicn_route_set_cost(hicn_route_t * route, const int cost)
-{
- route->cost = cost;
- return 0;
+int hicn_route_set_cost(hicn_route_t* route, const int cost) {
+ route->cost = cost;
+ return 0;
}
/* /!\ Please update constants in header file upon changes */
-size_t
-hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route)
-{
- char prefix_s[MAXSZ_PREFIX];
- ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_PREFIX);
- return snprintf(s, size, "%s [%d]", prefix_s, route->cost);
+size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route) {
+ char prefix_s[MAXSZ_IP_PREFIX];
+ ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_IP_PREFIX);
+ return snprintf(s, size, "%s [%d]", prefix_s, route->cost);
}
diff --git a/ctrl/libhicnctrl/src/util/hash.h b/ctrl/libhicnctrl/src/util/hash.h
index 7c7bb1e3a..f3a1eedcc 100644
--- a/ctrl/libhicnctrl/src/util/hash.h
+++ b/ctrl/libhicnctrl/src/util/hash.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 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:
@@ -27,67 +27,88 @@
#ifndef UTIL_HASH_H
#define UTIL_HASH_H
-#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
- __BYTE_ORDER == __LITTLE_ENDIAN) || \
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
- defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
-# define HASH_LITTLE_ENDIAN 1
-# define HASH_BIG_ENDIAN 0
+ defined(__i586__) || defined(__i686__) || defined(vax) || \
+ defined(MIPSEL))
+#define HASH_LITTLE_ENDIAN 1
+#define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
- __BYTE_ORDER == __BIG_ENDIAN) || \
- (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
-# define HASH_LITTLE_ENDIAN 0
-# define HASH_BIG_ENDIAN 1
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 1
#else
-# define HASH_LITTLE_ENDIAN 0
-# define HASH_BIG_ENDIAN 0
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 0
#endif
-#define hashsize(n) ((uint32_t)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-
-#define mix(a,b,c) \
-{ \
- a -= c; a ^= rot(c, 4); c += b; \
- b -= a; b ^= rot(a, 6); a += c; \
- c -= b; c ^= rot(b, 8); b += a; \
- a -= c; a ^= rot(c,16); c += b; \
- b -= a; b ^= rot(a,19); a += c; \
- c -= b; c ^= rot(b, 4); b += a; \
-}
+#define hashsize(n) ((uint32_t)1 << (n))
+#define hashmask(n) (hashsize(n) - 1)
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
-#define final(a,b,c) \
-{ \
- c ^= b; c -= rot(b,14); \
- a ^= c; a -= rot(c,11); \
- b ^= a; b -= rot(a,25); \
- c ^= b; c -= rot(b,16); \
- a ^= c; a -= rot(c,4); \
- b ^= a; b -= rot(a,14); \
- c ^= b; c -= rot(b,24); \
-}
+#define mix(a, b, c) \
+ { \
+ a -= c; \
+ a ^= rot(c, 4); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 6); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 8); \
+ b += a; \
+ a -= c; \
+ a ^= rot(c, 16); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 19); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 4); \
+ b += a; \
+ }
-static inline
-uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
-{
- uint32_t a,b,c; /* internal state */
- union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot(b, 14); \
+ a ^= c; \
+ a -= rot(c, 11); \
+ b ^= a; \
+ b -= rot(a, 25); \
+ c ^= b; \
+ c -= rot(b, 16); \
+ a ^= c; \
+ a -= rot(c, 4); \
+ b ^= a; \
+ b -= rot(a, 14); \
+ c ^= b; \
+ c -= rot(b, 24); \
+ }
+
+static inline uint32_t hashlittle(const void *key, size_t length,
+ uint32_t initval) {
+ uint32_t a, b, c; /* internal state */
+ union {
+ const void *ptr;
+ size_t i;
+ } u; /* needed for Mac Powerbook G4 */
/* Set up the internal state */
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
- const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
- while (length > 12)
- {
+ while (length > 12) {
a += k[0];
b += k[1];
c += k[2];
- mix(a,b,c);
+ mix(a, b, c);
length -= 12;
k += 3;
}
@@ -104,136 +125,214 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
*/
#ifndef VALGRIND
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
- case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
- case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
- case 6 : b+=k[1]&0xffff; a+=k[0]; break;
- case 5 : b+=k[1]&0xff; a+=k[0]; break;
- case 4 : a+=k[0]; break;
- case 3 : a+=k[0]&0xffffff; break;
- case 2 : a+=k[0]&0xffff; break;
- case 1 : a+=k[0]&0xff; break;
- case 0 : return c; /* zero length strings require no mixing */
+ switch (length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += k[2] & 0xffffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 10:
+ c += k[2] & 0xffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 9:
+ c += k[2] & 0xff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += k[1] & 0xffffff;
+ a += k[0];
+ break;
+ case 6:
+ b += k[1] & 0xffff;
+ a += k[0];
+ break;
+ case 5:
+ b += k[1] & 0xff;
+ a += k[0];
+ break;
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += k[0] & 0xffffff;
+ break;
+ case 2:
+ a += k[0] & 0xffff;
+ break;
+ case 1:
+ a += k[0] & 0xff;
+ break;
+ case 0:
+ return c; /* zero length strings require no mixing */
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
- case 1 : a+=k8[0]; break;
- case 0 : return c;
+ switch (length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += ((uint32_t)k8[10]) << 16; /* fall through */
+ case 10:
+ c += ((uint32_t)k8[9]) << 8; /* fall through */
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += ((uint32_t)k8[6]) << 16; /* fall through */
+ case 6:
+ b += ((uint32_t)k8[5]) << 8; /* fall through */
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += ((uint32_t)k8[2]) << 16; /* fall through */
+ case 2:
+ a += ((uint32_t)k8[1]) << 8; /* fall through */
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
- const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
- const uint8_t *k8;
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
/*--------------- all but last block: aligned reads and different mixing */
- while (length > 12)
- {
- a += k[0] + (((uint32_t)k[1])<<16);
- b += k[2] + (((uint32_t)k[3])<<16);
- c += k[4] + (((uint32_t)k[5])<<16);
- mix(a,b,c);
+ while (length > 12) {
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ c += k[4] + (((uint32_t)k[5]) << 16);
+ mix(a, b, c);
length -= 12;
k += 6;
}
/*----------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
- switch(length)
- {
- case 12: c+=k[4]+(((uint32_t)k[5])<<16);
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=k[4];
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=k[2];
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=k[0];
- break;
- case 1 : a+=k8[0];
- break;
- case 0 : return c; /* zero length requires no mixing */
+ switch (length) {
+ case 12:
+ c += k[4] + (((uint32_t)k[5]) << 16);
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 11:
+ c += ((uint32_t)k8[10]) << 16; /* fall through */
+ case 10:
+ c += k[4];
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 7:
+ b += ((uint32_t)k8[6]) << 16; /* fall through */
+ case 6:
+ b += k[2];
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 3:
+ a += ((uint32_t)k8[2]) << 16; /* fall through */
+ case 2:
+ a += k[0];
+ break;
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c; /* zero length requires no mixing */
}
- } else { /* need to read the key one byte at a time */
+ } else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12)
- {
+ while (length > 12) {
a += k[0];
- a += ((uint32_t)k[1])<<8;
- a += ((uint32_t)k[2])<<16;
- a += ((uint32_t)k[3])<<24;
+ a += ((uint32_t)k[1]) << 8;
+ a += ((uint32_t)k[2]) << 16;
+ a += ((uint32_t)k[3]) << 24;
b += k[4];
- b += ((uint32_t)k[5])<<8;
- b += ((uint32_t)k[6])<<16;
- b += ((uint32_t)k[7])<<24;
+ b += ((uint32_t)k[5]) << 8;
+ b += ((uint32_t)k[6]) << 16;
+ b += ((uint32_t)k[7]) << 24;
c += k[8];
- c += ((uint32_t)k[9])<<8;
- c += ((uint32_t)k[10])<<16;
- c += ((uint32_t)k[11])<<24;
- mix(a,b,c);
+ c += ((uint32_t)k[9]) << 8;
+ c += ((uint32_t)k[10]) << 16;
+ c += ((uint32_t)k[11]) << 24;
+ mix(a, b, c);
length -= 12;
k += 12;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
- switch(length) /* all the case statements fall through */
+ switch (length) /* all the case statements fall through */
{
- case 12: c+=((uint32_t)k[11])<<24;
- case 11: c+=((uint32_t)k[10])<<16;
- case 10: c+=((uint32_t)k[9])<<8;
- case 9 : c+=k[8];
- case 8 : b+=((uint32_t)k[7])<<24;
- case 7 : b+=((uint32_t)k[6])<<16;
- case 6 : b+=((uint32_t)k[5])<<8;
- case 5 : b+=k[4];
- case 4 : a+=((uint32_t)k[3])<<24;
- case 3 : a+=((uint32_t)k[2])<<16;
- case 2 : a+=((uint32_t)k[1])<<8;
- case 1 : a+=k[0];
- break;
- case 0 : return c;
+ case 12:
+ c += ((uint32_t)k[11]) << 24;
+ case 11:
+ c += ((uint32_t)k[10]) << 16;
+ case 10:
+ c += ((uint32_t)k[9]) << 8;
+ case 9:
+ c += k[8];
+ case 8:
+ b += ((uint32_t)k[7]) << 24;
+ case 7:
+ b += ((uint32_t)k[6]) << 16;
+ case 6:
+ b += ((uint32_t)k[5]) << 8;
+ case 5:
+ b += k[4];
+ case 4:
+ a += ((uint32_t)k[3]) << 24;
+ case 3:
+ a += ((uint32_t)k[2]) << 16;
+ case 2:
+ a += ((uint32_t)k[1]) << 8;
+ case 1:
+ a += k[0];
+ break;
+ case 0:
+ return c;
}
}
- final(a,b,c);
+ final(a, b, c);
return c;
}
@@ -241,7 +340,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
#define HASH_INITVAL 1
//#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL)
-#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL)
+#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL)
#define hash_struct(buf) hash(buf, sizeof(buf))
#endif /* UTIL_JENKINS_HASH_H */