aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/libhicnctrl/src/objects
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/libhicnctrl/src/objects')
-rw-r--r--ctrl/libhicnctrl/src/objects/active_interface.c86
-rw-r--r--ctrl/libhicnctrl/src/objects/active_interface.h28
-rw-r--r--ctrl/libhicnctrl/src/objects/base.c34
-rw-r--r--ctrl/libhicnctrl/src/objects/base.h27
-rw-r--r--ctrl/libhicnctrl/src/objects/connection.c298
-rw-r--r--ctrl/libhicnctrl/src/objects/connection.h32
-rw-r--r--ctrl/libhicnctrl/src/objects/face.c187
-rw-r--r--ctrl/libhicnctrl/src/objects/face.h30
-rw-r--r--ctrl/libhicnctrl/src/objects/listener.c208
-rw-r--r--ctrl/libhicnctrl/src/objects/listener.h30
-rw-r--r--ctrl/libhicnctrl/src/objects/mapme.c95
-rw-r--r--ctrl/libhicnctrl/src/objects/mapme.h30
-rw-r--r--ctrl/libhicnctrl/src/objects/route.c176
-rw-r--r--ctrl/libhicnctrl/src/objects/route.h30
-rw-r--r--ctrl/libhicnctrl/src/objects/stats.c108
-rw-r--r--ctrl/libhicnctrl/src/objects/stats.h29
-rw-r--r--ctrl/libhicnctrl/src/objects/strategy.c92
-rw-r--r--ctrl/libhicnctrl/src/objects/strategy.h29
-rw-r--r--ctrl/libhicnctrl/src/objects/subscription.c94
-rw-r--r--ctrl/libhicnctrl/src/objects/subscription.h28
20 files changed, 1671 insertions, 0 deletions
diff --git a/ctrl/libhicnctrl/src/objects/active_interface.c b/ctrl/libhicnctrl/src/objects/active_interface.c
new file mode 100644
index 000000000..796123963
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/active_interface.c
@@ -0,0 +1,86 @@
+/*
+ * 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:
+ *
+ * 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 active_interface.c
+ * \brief Implementation of active_interface object.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/active_interface.h>
+#include <hicn/util/log.h>
+#include <hicn/util/ip_address.h>
+
+#include "../object_private.h"
+#include "../object_vft.h"
+
+/* ACTIVE_INTERFACE VALIDATE */
+
+int hc_active_interface_validate(const hc_active_interface_t *active_interface,
+ bool allow_partial) {
+ return 0; // XXX TODO
+}
+
+int _hc_active_interface_validate(const hc_object_t *object,
+ bool allow_partial) {
+ return hc_active_interface_validate(&object->active_interface, allow_partial);
+}
+
+/* ACTIVE_INTERFACE CMP */
+
+// XXX TODO
+int hc_active_interface_cmp(const hc_active_interface_t *active_interface1,
+ const hc_active_interface_t *active_interface2) {
+ return -1;
+}
+
+int _hc_active_interface_cmp(const hc_object_t *object1,
+ const hc_object_t *object2) {
+ return hc_active_interface_cmp(&object1->active_interface,
+ &object2->active_interface);
+}
+
+/* ACTIVE_INTERFACE SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_active_interface_snprintf(
+ char *s, size_t size, const hc_active_interface_t *active_interface) {
+ int rc;
+ char *pos = s;
+
+ rc = hicn_ip_prefix_snprintf(pos, size, &active_interface->prefix);
+ if ((rc < 0) || (rc >= size)) return rc;
+ pos += rc;
+ size -= rc;
+
+ for (netdevice_type_t type = NETDEVICE_TYPE_UNDEFINED + 1;
+ type < NETDEVICE_TYPE_N; type++) {
+ if (!netdevice_flags_has(active_interface->interface_types, type)) continue;
+ rc = snprintf(pos, size, " %s", netdevice_type_str(type));
+ if ((rc < 0) || (rc >= size)) return (int)(pos - s + rc);
+
+ pos += rc;
+ size -= rc;
+ }
+ return (int)(pos - s);
+}
+
+int _hc_active_interface_snprintf(char *s, size_t size,
+ const hc_object_t *object) {
+ return hc_active_interface_snprintf(s, size, &object->active_interface);
+}
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface);
diff --git a/ctrl/libhicnctrl/src/objects/active_interface.h b/ctrl/libhicnctrl/src/objects/active_interface.h
new file mode 100644
index 000000000..973b08e40
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/active_interface.h
@@ -0,0 +1,28 @@
+/*
+ * 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:
+ *
+ * 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 active_interface.h
+ * \brief Route.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H
+#define HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H
+
+#include "../object_vft.h"
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H */
diff --git a/ctrl/libhicnctrl/src/objects/base.c b/ctrl/libhicnctrl/src/objects/base.c
new file mode 100644
index 000000000..86e4bfb72
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/base.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 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:
+ *
+ * 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 base.c
+ * \brief Implementation of base functions for object APIs.
+ */
+
+#include <stdbool.h>
+
+#include "base.h"
+
+#include <hicn/util/log.h>
+
+bool iszero(const void *ptr, int bytes) {
+ char *bptr = (char *)ptr;
+ while (bytes--)
+ if (*bptr++) return false;
+ return true;
+}
+
+bool isempty(const char *str) { return str[0] == '\0'; }
diff --git a/ctrl/libhicnctrl/src/objects/base.h b/ctrl/libhicnctrl/src/objects/base.h
new file mode 100644
index 000000000..eb85483e9
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/base.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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:
+ *
+ * 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 base.h
+ * \brief Base functions for object APIs.
+ */
+
+#ifndef HICNCTRL_OBJECTS_BASE_H
+#define HICNCTRL_OBJECTS_BASE_H
+
+bool iszero(const void *ptr, int bytes);
+bool isempty(const char *str);
+
+#endif /* HICNCTRL_OBJECTS_BASE_H */
diff --git a/ctrl/libhicnctrl/src/objects/connection.c b/ctrl/libhicnctrl/src/objects/connection.c
new file mode 100644
index 000000000..ca09d9a54
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/connection.c
@@ -0,0 +1,298 @@
+/*
+ * 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:
+ *
+ * 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 connection.c
+ * \brief Implementation of connection object.
+ */
+
+#include <assert.h>
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/connection.h>
+#include <hicn/util/log.h>
+
+#include "../object_private.h"
+#include "../object_vft.h"
+#include "base.h"
+
+bool hc_connection_is_local(const hc_connection_t *connection) {
+ return (strncmp(connection->interface_name, "lo", INTERFACE_LEN) == 0);
+}
+
+bool hc_connection_has_local(const hc_connection_t *connection) {
+ assert(connection);
+ return IS_VALID_PORT(connection->local_port) &&
+ IS_VALID_ADDRESS(connection->local_addr);
+}
+
+/* CONNECTION VALIDATE */
+
+int hc_connection_validate(const hc_connection_t *connection,
+ bool allow_partial) {
+ int has_id = 0;
+ int has_name = 0;
+#if 0
+ int has_interface_name = 0;
+#endif
+ int has_netdevice_type = 0;
+ int has_type = 0;
+ int has_family = 0;
+ int has_local_addr = 0;
+ int has_local_port = 0;
+ int has_remote_addr = 0;
+ int has_remote_port = 0;
+ int has_admin_state = 0;
+ int has_priority = 0;
+ int has_tags = 0;
+ int has_state = 0;
+
+ if (connection->id == ~0) {
+ ERROR("[hc_listener_validate] Invalid id specified");
+ return -1;
+ }
+ has_id = 1;
+
+ if (!isempty(connection->name)) {
+ if (!IS_VALID_NAME(connection->name)) {
+ ERROR("[hc_connection_validate] Invalid name specified");
+ return -1;
+ }
+ has_name = 1;
+ }
+
+#if 0
+ if (!isempty(connection->interface_name)) {
+ if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) {
+ ERROR("[hc_connection_validate] Invalid interface_name specified");
+ return -1;
+ }
+ has_interface_name = 1;
+ }
+#endif
+
+ if (connection->type != FACE_TYPE_UNDEFINED) {
+ if (!IS_VALID_TYPE(connection->type)) {
+ ERROR("[hc_connection_validate] Invalid type specified");
+ return -1;
+ }
+ has_type = 1;
+ }
+
+ if (connection->family != AF_UNSPEC) {
+ if (!IS_VALID_FAMILY(connection->family)) {
+ ERROR("[hc_connection_validate] Invalid family specified");
+ return -1;
+ }
+ has_family = 1;
+ }
+
+ if (!hicn_ip_address_empty(&connection->local_addr)) {
+ if (!IS_VALID_ADDRESS(connection->local_addr)) {
+ ERROR("[hc_connection_validate] Invalid local_addr specified");
+ return -1;
+ }
+ has_local_addr = 1;
+ }
+
+ if (connection->local_port != 0) {
+ if (!IS_VALID_PORT(connection->local_port)) {
+ ERROR("[hc_connection_validate] Invalid local_port specified");
+ return -1;
+ }
+ has_local_port = 1;
+ }
+
+ if (!hicn_ip_address_empty(&connection->remote_addr)) {
+ if (!IS_VALID_ADDRESS(connection->remote_addr)) {
+ ERROR("[hc_connection_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ has_remote_addr = 1;
+ }
+
+ if (connection->remote_port != 0) {
+ if (!IS_VALID_PORT(connection->remote_port)) {
+ ERROR("[hc_connection_validate] Invalid remote_port specified");
+ return -1;
+ }
+ has_remote_port = 1;
+ }
+
+ /* Interface name is optional */
+ int has_key = has_id || has_name;
+ int has_mandatory_attributes = has_type && has_family && has_local_addr &&
+ has_local_port && has_remote_addr &&
+ has_remote_port;
+ int has_optional_attributes =
+ has_netdevice_type && has_admin_state && has_state;
+ has_optional_attributes = has_optional_attributes && has_priority && has_tags;
+
+ if (allow_partial) {
+ if (has_key && !has_mandatory_attributes && !has_optional_attributes)
+ return 0;
+ else if (has_mandatory_attributes)
+ return 0;
+ else
+ return -1;
+ } else {
+ if (has_key && has_mandatory_attributes) return 0;
+ return -1;
+ }
+}
+
+int _hc_connection_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_connection_validate(&object->connection, allow_partial);
+}
+
+/* CONNECTION CMP */
+
+/*
+ * hICN light uses ports even for hICN connections, but their value is
+ * ignored. 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;
+
+ rc = INT_CMP(c1->type, c2->type);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(c1->family, c2->family);
+ if (rc != 0) return rc;
+
+ if (!isempty(c1->interface_name) && !isempty(c2->interface_name)) {
+ rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
+ }
+
+ rc = hicn_ip_address_cmp(&c1->local_addr, &c2->local_addr);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(c1->local_port, c2->local_port);
+ if (rc != 0) return rc;
+
+ rc = hicn_ip_address_cmp(&c1->remote_addr, &c2->remote_addr);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(c1->remote_port, c2->remote_port);
+
+ return rc;
+}
+
+int _hc_connection_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return hc_connection_cmp(&object1->connection, &object2->connection);
+}
+
+int hc_connection_has_valid_id(const hc_connection_t *connection) {
+ return connection->id != INVALID_FACE_ID;
+}
+
+/* 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)
+ if (strcmp(connection->name, "SELF") == 0) {
+ return snprintf(s, size, "%s", connection->name);
+ }
+
+ rc = url_snprintf(local, MAXSZ_URL, &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->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_connection_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_connection_snprintf(s, size, &object->connection);
+}
+
+int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.connection = *connection;
+ return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_CONNECTION, &object, NULL);
+}
+
+int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
+ hc_data_t **pdata) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.connection = *connection;
+ return hc_execute(s, ACTION_GET, OBJECT_TYPE_CONNECTION, &object, pdata);
+}
+
+int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.connection = *connection;
+ return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_CONNECTION, &object, NULL);
+}
+
+int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_CONNECTION, NULL, pdata);
+}
+
+int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1;
+ object.connection.admin_state = state;
+ return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL);
+}
+
+int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1;
+ object.connection.priority = priority;
+ return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL);
+}
+
+int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1;
+ object.connection.tags = tags;
+ return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL);
+}
+
+GENERATE_FIND(connection);
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_CONNECTION, connection);
diff --git a/ctrl/libhicnctrl/src/objects/connection.h b/ctrl/libhicnctrl/src/objects/connection.h
new file mode 100644
index 000000000..1e9bf0376
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/connection.h
@@ -0,0 +1,32 @@
+/*
+ * 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:
+ *
+ * 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 connection.h
+ * \brief Connection.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_CONNECTION_H
+#define HICNCTRL_IMPL_OBJECTS_CONNECTION_H
+
+#include "../object_vft.h"
+
+bool hc_connection_is_local(const hc_connection_t *connection);
+bool hc_connection_has_local(const hc_connection_t *connection);
+bool hc_connection_has_valid_id(const hc_connection_t *connection);
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_CONNECTION, connection);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_CONNECTION_H */
diff --git a/ctrl/libhicnctrl/src/objects/face.c b/ctrl/libhicnctrl/src/objects/face.c
new file mode 100644
index 000000000..5dbe1c8dc
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/face.c
@@ -0,0 +1,187 @@
+/*
+ * 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:
+ *
+ * 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 object.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/face.h>
+#include <hicn/util/log.h>
+
+#include "../object_private.h"
+#include "../object_vft.h"
+
+bool hc_face_has_netdevice(const hc_face_t *face) {
+ return netdevice_is_empty(&face->netdevice);
+}
+
+/* FACE VALIDATE */
+
+int hc_face_validate(const hc_face_t *face, bool allow_partial) {
+ if ((!allow_partial || !hc_face_has_netdevice(face)) &&
+ !IS_VALID_INTERFACE_NAME(face->interface_name)) {
+ ERROR("[hc_face_validate] Invalid interface_name specified");
+ return -1;
+ }
+ if (!IS_VALID_TYPE(face->type)) {
+ ERROR("[hc_face_validate] Invalid type specified");
+ return -1;
+ }
+ if ((!allow_partial || face->family != AF_UNSPEC) &&
+ !IS_VALID_FAMILY(face->family)) {
+ ERROR("[hc_face_validate] Invalid family specified");
+ return -1;
+ }
+ if ((!allow_partial || !hicn_ip_address_empty(&face->local_addr)) &&
+ !IS_VALID_ADDRESS(face->local_addr)) {
+ ERROR("[hc_face_validate] Invalid local_addr specified");
+ return -1;
+ }
+ if ((!allow_partial || !(face->local_port == 0)) &&
+ !IS_VALID_PORT(face->local_port)) {
+ ERROR("[hc_face_validate] Invalid local_port specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(face->remote_addr)) {
+ ERROR("[hc_face_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(face->remote_port)) {
+ ERROR("[hc_face_validate] Invalid remote_port specified");
+ return -1;
+ }
+ return 0;
+}
+
+int _hc_face_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_face_validate(&object->face, allow_partial);
+}
+
+/* FACE CMP */
+
+int hc_face_cmp(const hc_face_t *c1, const hc_face_t *c2) {
+ return -99; // Not implemented
+}
+
+int _hc_face_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return hc_face_cmp(&object1->face, &object2->face);
+}
+
+/* FACE SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_face_snprintf(char *s, size_t size, const 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];
+ char tags[MAXSZ_POLICY_TAGS];
+ int rc;
+
+ switch (face->type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ rc = hicn_ip_address_snprintf(local, MAXSZ_URL, &face->local_addr);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = hicn_ip_address_snprintf(remote, MAXSZ_URL, &face->remote_addr);
+ 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->local_addr, 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->remote_addr,
+ 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)
+ rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, 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->netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->netdevice.name
+ : "*",
+ face_type_str(face->type), local, remote, face_state_str(face->state),
+ face_state_str(face->admin_state), face->priority, tags);
+}
+
+int _hc_face_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_face_snprintf(s, size, &object->face);
+}
+
+int hc_face_create(hc_sock_t *s, hc_face_t *face) {
+ int rc;
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.face = *face;
+ rc = hc_execute(s, ACTION_CREATE, OBJECT_TYPE_FACE, &object, NULL);
+ face->id = object.face.id;
+ return rc;
+}
+
+int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_data_t **pdata) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.face = *face;
+ return hc_execute(s, ACTION_GET, OBJECT_TYPE_FACE, &object, pdata);
+}
+
+int hc_face_delete(hc_sock_t *s, hc_face_t *face) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.face = *face;
+ return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_FACE, &object, NULL);
+}
+
+int hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, pdata);
+}
+
+int hc_face_list_async(hc_sock_t *s) {
+ return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, NULL, NULL);
+}
+
+int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return -1; // Not implemented
+#if 0
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_FACE, &object, NULL);
+#endif
+}
+
+GENERATE_FIND(face);
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_FACE, face);
diff --git a/ctrl/libhicnctrl/src/objects/face.h b/ctrl/libhicnctrl/src/objects/face.h
new file mode 100644
index 000000000..08f90f195
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/face.h
@@ -0,0 +1,30 @@
+/*
+ * 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:
+ *
+ * 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.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_FACE_H
+#define HICNCTRL_IMPL_OBJECTS_FACE_H
+
+#include "../object_vft.h"
+
+int hc_face_validate(const hc_face_t *face, bool allow_partial);
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_FACE, face);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_FACE_H */
diff --git a/ctrl/libhicnctrl/src/objects/listener.c b/ctrl/libhicnctrl/src/objects/listener.c
new file mode 100644
index 000000000..97a2430d8
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/listener.c
@@ -0,0 +1,208 @@
+/*
+ * 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:
+ *
+ * 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 listener.c
+ * \brief Implementation of listener.
+ */
+
+#include <string.h>
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/listener.h>
+#include <hicn/util/log.h>
+
+#include "../object_vft.h"
+#include "../object_private.h"
+#include "base.h"
+
+bool hc_listener_is_local(const hc_listener_t *listener) {
+ return (strncmp(listener->interface_name, "lo", INTERFACE_LEN) == 0);
+}
+
+/* LISTENER VALIDATE */
+
+int hc_listener_validate(const hc_listener_t *listener, bool allow_partial) {
+ // if a field is specified it should be valid
+ // then we allow different specification, by key or by attributes, if
+ // allow_partial
+
+ int has_id = 0;
+ int has_name = 0;
+#if 0
+ int has_interface_name = 0;
+#endif
+ int has_type = 0;
+ int has_family = 0;
+ int has_local_addr = 0;
+ int has_local_port = 0;
+
+ if (listener->id == ~0) {
+ ERROR("[hc_listener_validate] Invalid id specified");
+ return -1;
+ }
+ has_id = 1;
+
+ if (!isempty(listener->name)) {
+ if (!IS_VALID_NAME(listener->name)) {
+ ERROR("[hc_listener_validate] Invalid name specified");
+ return -1;
+ }
+ has_name = 1;
+ }
+
+#if 0
+ if (!isempty(listener->interface_name)) {
+ if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) {
+ ERROR("[hc_listener_validate] Invalid interface_name specified");
+ return -1;
+ }
+ has_interface_name = 1;
+ }
+#endif
+
+ if (listener->type != FACE_TYPE_UNDEFINED) {
+ if (!IS_VALID_TYPE(listener->type)) {
+ ERROR("[hc_listener_validate] Invalid type specified");
+ return -1;
+ }
+ has_type = 1;
+ }
+
+ if (listener->family != AF_UNSPEC) {
+ if (!IS_VALID_FAMILY(listener->family)) {
+ ERROR("[hc_listener_validat] Invalid family specified");
+ return -1;
+ }
+ has_family = 1;
+ }
+
+ if (!hicn_ip_address_empty(&listener->local_addr)) {
+ if (!IS_VALID_ADDRESS(listener->local_addr)) {
+ ERROR("[hc_listener_validate] Invalid local_addr specified");
+ return -1;
+ }
+ has_local_addr = 1;
+ }
+
+ if (listener->local_port != 0) {
+ if (!IS_VALID_PORT(listener->local_port)) {
+ ERROR("[hc_listener_validate] Invalid local_port specified");
+ return -1;
+ }
+ has_local_port = 1;
+ }
+
+ if (allow_partial) {
+ if ((has_id || has_name) && !has_type && !has_family && !has_local_port &&
+ !has_local_port)
+ return 0;
+ else if (has_name && has_type && has_family && has_local_addr &&
+ has_local_port)
+ return 0;
+ else
+ return -1;
+ } else {
+ /* name and interface are optional */
+ if (has_id && has_type && has_family && has_local_addr && has_local_port)
+ return 0;
+ return -1;
+ }
+}
+
+int _hc_listener_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_listener_validate(&object->listener, allow_partial);
+}
+
+/* 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;
+
+ if (!isempty(l1->interface_name) && !isempty(l2->interface_name)) {
+ rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
+ }
+
+ rc = hicn_ip_address_cmp(&l1->local_addr, &l2->local_addr);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(l1->local_port, l2->local_port);
+ if (rc != 0) return rc;
+
+ return 0;
+}
+
+int _hc_listener_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return hc_listener_cmp(&object1->listener, &object2->listener);
+}
+
+/* LISTENER SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_listener_snprintf(char *s, size_t size, const hc_listener_t *listener) {
+ char local[MAXSZ_URL];
+ int rc;
+ rc = url_snprintf(local, MAXSZ_URL, &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 interface=%s", listener->name, local,
+ face_type_str(listener->type), listener->interface_name);
+}
+
+int _hc_listener_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_listener_snprintf(s, size, &object->listener);
+}
+
+/* OPERATIONS */
+
+int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.listener = *listener;
+ return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_LISTENER, &object, NULL);
+}
+
+int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_data_t **pdata) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.listener = *listener;
+ return hc_execute(s, ACTION_GET, OBJECT_TYPE_LISTENER, &object, pdata);
+}
+
+int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.listener = *listener;
+ return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_LISTENER, &object, NULL);
+}
+
+int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_LISTENER, NULL, pdata);
+}
+
+GENERATE_FIND(listener);
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_LISTENER, listener);
diff --git a/ctrl/libhicnctrl/src/objects/listener.h b/ctrl/libhicnctrl/src/objects/listener.h
new file mode 100644
index 000000000..515c8f0ad
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/listener.h
@@ -0,0 +1,30 @@
+/*
+ * 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:
+ *
+ * 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 listener.h
+ * \brief Listener.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_LISTENER_H
+#define HICNCTRL_IMPL_OBJECTS_LISTENER_H
+
+#include "../object_vft.h"
+
+bool hc_listener_is_local(const hc_listener_t *listener);
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_LISTENER, listener);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_LISTENER_H */
diff --git a/ctrl/libhicnctrl/src/objects/mapme.c b/ctrl/libhicnctrl/src/objects/mapme.c
new file mode 100644
index 000000000..1acdcb35a
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/mapme.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021-2023 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 mapme.c
+ * \brief Implementation of mapme object.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/mapme.h>
+#include <hicn/util/log.h>
+
+#include "../object_private.h"
+#include "../object_vft.h"
+#include "face.h"
+#include "base.h"
+
+/* MAPME VALIDATE */
+
+int hc_mapme_validate(const hc_mapme_t *mapme, bool allow_partial) {
+ int has_family = 0;
+ int has_address = 0;
+ int has_len = 0;
+
+ if (allow_partial) return 0;
+
+ if (mapme->family != AF_UNSPEC) {
+ if (!IS_VALID_FAMILY(mapme->family)) {
+ ERROR("[hc_mapme_validate] Invalid family specified");
+ return -1;
+ }
+ has_family = 1;
+ }
+
+ if (!hicn_ip_address_empty(&mapme->address)) {
+ if (!IS_VALID_ADDRESS(mapme->address)) {
+ ERROR("[hc_mapme_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ has_address = 1;
+ }
+
+ if (!IS_VALID_PREFIX_LEN(mapme->len)) {
+ ERROR("[hc_mapme_validate] Invalid len");
+ return -1;
+ }
+ has_len = 1;
+ return has_family && has_address && has_len;
+}
+
+int _hc_mapme_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_mapme_validate(&object->mapme, allow_partial);
+}
+
+/* MAPME CMP */
+
+int hc_mapme_cmp(const hc_mapme_t *mapme1, const hc_mapme_t *mapme2) {
+ return -1;
+}
+
+int _hc_mapme_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return -1;
+}
+
+/* MAPME SNPRINTF */
+
+int hc_mapme_snprintf(char *s, size_t size, const hc_mapme_t *mapme) {
+ return -1;
+}
+
+int _hc_mapme_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return -1;
+}
+
+int hc_mapme_create(hc_sock_t *s, hc_mapme_t *mapme) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.mapme = *mapme;
+ return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_MAPME, &object, NULL);
+}
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_MAPME, mapme);
diff --git a/ctrl/libhicnctrl/src/objects/mapme.h b/ctrl/libhicnctrl/src/objects/mapme.h
new file mode 100644
index 000000000..488f97cd5
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/mapme.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021-2023 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 mapme.h
+ * \brief Route.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_MAPME_H
+#define HICNCTRL_IMPL_OBJECTS_MAPME_H
+
+#include "../object_vft.h"
+
+bool hc_mapme_has_face(const hc_mapme_t* mapme);
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_MAPME, mapme);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_MAPME_H */
diff --git a/ctrl/libhicnctrl/src/objects/route.c b/ctrl/libhicnctrl/src/objects/route.c
new file mode 100644
index 000000000..4bdaa0afb
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/route.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021-2023 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 route.c
+ * \brief Implementation of route object.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/route.h>
+#include <hicn/util/log.h>
+
+#include "../object_private.h"
+#include "../object_vft.h"
+#include "face.h"
+#include "base.h"
+
+bool hc_route_has_face(const hc_route_t *route) {
+ return !iszero(&route->face, sizeof(hc_face_t));
+}
+
+/* ROUTE VALIDATE */
+
+int hc_route_validate(const hc_route_t *route, bool allow_partial) {
+ int has_id = 0;
+ int has_name = 0;
+ int has_face = 0;
+
+ int has_family = 0;
+ int has_remote_addr = 0;
+
+ if (IS_VALID_CONNECTION_ID(route->face_id)) {
+ has_id = 1;
+ }
+
+ if (!isempty(route->face_name)) {
+ if (!IS_VALID_NAME(route->face_name)) {
+ ERROR("[hc_route_validate] Invalid name specified");
+ return -1;
+ }
+ has_name = 1;
+ }
+
+ if (route->family != AF_UNSPEC) {
+ if (!IS_VALID_FAMILY(route->family)) {
+ ERROR("[hc_route_validate] Invalid family specified");
+ return -1;
+ }
+ has_family = 1;
+ }
+
+ //::/0 is a valid remote addr
+#if 0
+ if (!hicn_ip_address_empty(&route->remote_addr)) {
+ if (!IS_VALID_ADDRESS(route->remote_addr)) {
+ ERROR("[hc_route_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ has_remote_addr = 1;
+ }
+#else
+ has_remote_addr = 1;
+#endif
+
+ if (!IS_VALID_ROUTE_COST(route->cost)) {
+ ERROR("[hc_route_validate] Invalid cost");
+ return -1;
+ }
+
+#if 0
+ if (!IS_VALID_PREFIX_LEN(route->len)) {
+ ERROR("[hc_route_validate] Invalid len");
+ return -1;
+ }
+#endif
+
+ if (hc_route_has_face(route)) {
+ if (hc_face_validate(&route->face, allow_partial) < 0) {
+ ERROR("[hc_route_validate] Invalid face");
+ return -1;
+ }
+ has_face = 1;
+ }
+
+ /* We also allow routes without faces, hence the '>' sign */
+ if (allow_partial && (has_id + has_name + has_face > 1)) return -1;
+ // if (has_face_info && has_family && has_remote_addr) return 0;
+ if (has_family && has_remote_addr) return 0;
+
+ return -1;
+}
+
+int _hc_route_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_route_validate(&object->route, allow_partial);
+}
+
+/* ROUTE CMP */
+
+// XXX TODO
+int hc_route_cmp(const hc_route_t *route1, const hc_route_t *route2) {
+ return -1;
+}
+
+int _hc_route_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return hc_route_cmp(&object1->route, &object2->route);
+}
+
+/* ROUTE SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_route_snprintf(char *s, size_t size, const hc_route_t *route) {
+ /* interface cost prefix length */
+
+ char prefix[MAXSZ_IP_ADDRESS];
+ int rc;
+
+ rc = hicn_ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr);
+ if (rc >= MAXSZ_IP_ADDRESS)
+ ;
+ if (rc < 0) return rc;
+
+ return snprintf(s, size, "%d (%s) %*d %s %*d", route->face_id,
+ route->face_name, MAXSZ_COST, route->cost, prefix, MAXSZ_LEN,
+ route->len);
+}
+
+int _hc_route_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_route_snprintf(s, size, &object->route);
+}
+
+int hc_route_create(hc_sock_t *s, hc_route_t *route) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.route = *route;
+ return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_ROUTE, &object, NULL);
+}
+
+int hc_route_get(hc_sock_t *s, hc_route_t *route, hc_data_t **pdata) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.route = *route;
+ return hc_execute(s, ACTION_GET, OBJECT_TYPE_ROUTE, &object, pdata);
+}
+
+int hc_route_delete(hc_sock_t *s, hc_route_t *route) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.route = *route;
+ return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_ROUTE, &object, NULL);
+}
+
+int hc_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, pdata);
+}
+
+int hc_route_list_async(hc_sock_t *s) {
+ return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, NULL, NULL);
+}
+
+// XXX difference between GET and FIND
+GENERATE_FIND(route);
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_ROUTE, route);
diff --git a/ctrl/libhicnctrl/src/objects/route.h b/ctrl/libhicnctrl/src/objects/route.h
new file mode 100644
index 000000000..854bd70a6
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/route.h
@@ -0,0 +1,30 @@
+/*
+ * 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:
+ *
+ * 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 route.h
+ * \brief Route.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_ROUTE_H
+#define HICNCTRL_IMPL_OBJECTS_ROUTE_H
+
+#include "../object_vft.h"
+
+bool hc_route_has_face(const hc_route_t* route);
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ROUTE, route);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_ROUTE_H */
diff --git a/ctrl/libhicnctrl/src/objects/stats.c b/ctrl/libhicnctrl/src/objects/stats.c
new file mode 100644
index 000000000..f9d0e1de7
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/stats.c
@@ -0,0 +1,108 @@
+/*
+ * 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:
+ *
+ * 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 stats.c
+ * \brief Implementation of stats.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/util/log.h>
+
+#include "../object_vft.h"
+
+/* GENERAL STATS */
+
+int _hc_stats_validate(const hc_object_t *object, bool allow_partial) {
+ // Nothing to validate
+ return 0;
+}
+
+int _hc_stats_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ ERROR("[_hc_stats_cmp] Not implemented");
+ return -1;
+}
+
+int _hc_stats_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_stats_snprintf(s, size, &object->stats);
+}
+
+int hc_stats_snprintf(char *s, size_t size, const hc_stats_t *stats) {
+ return snprintf(
+ s, size,
+ "*** STATS ***\nreceived = %u (interest = %u, data = %u)\ndropped = %u "
+ "(interest = %u, data = %u, other = %u)\nforwarded = { interests = "
+ "%u, data = %u }\ndropped_reason = { connection_not_found = %u, "
+ "send_failure = %u, no_route_in_fib = %u }\ninterest processing = { "
+ "aggregated = %u, retransmitted = %u, satisfied_from_cs = %u, "
+ "expired_interests = %u, expired_data = %u }\ndata processing = { "
+ "no_reverse_path = %u }\npacket cache = {PIT size = %u, CS size = %u, "
+ "eviction = %u}",
+ stats->forwarder.countReceived, stats->forwarder.countInterestsReceived,
+ stats->forwarder.countObjectsReceived, stats->forwarder.countDropped,
+ stats->forwarder.countInterestsDropped,
+ stats->forwarder.countObjectsDropped, stats->forwarder.countOtherDropped,
+ stats->forwarder.countInterestForwarded,
+ stats->forwarder.countObjectsForwarded,
+ stats->forwarder.countDroppedConnectionNotFound,
+ stats->forwarder.countSendFailures, stats->forwarder.countDroppedNoRoute,
+ stats->forwarder.countInterestsAggregated,
+ stats->forwarder.countInterestsRetransmitted,
+ stats->forwarder.countInterestsSatisfiedFromStore,
+ stats->forwarder.countInterestsExpired, stats->forwarder.countDataExpired,
+ stats->forwarder.countDroppedNoReversePath,
+ stats->pkt_cache.n_pit_entries, stats->pkt_cache.n_cs_entries,
+ stats->pkt_cache.n_lru_evictions);
+}
+
+int hc_stats_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STATS, NULL, pdata);
+}
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_STATS, stats);
+
+/* PER-FACE STATS */
+
+int _hc_face_stats_validate(const hc_object_t *object, bool allow_partial) {
+ // Nothing to validate
+ return 0;
+}
+
+int _hc_face_stats_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ ERROR("[_hc_stats_cmp] Not implemented");
+ return -1;
+}
+
+int _hc_face_stats_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_face_stats_snprintf(s, size, &object->face_stats);
+}
+
+int hc_face_stats_snprintf(char *s, size_t size, const hc_face_stats_t *stats) {
+ return snprintf(
+ s, size,
+ "conn #%u:\tinterests =\t{ rx packets = %u, rx bytes = %u, "
+ "tx packets = %u, tx bytes = %u }\n\t\tdata =\t\t{ rx packets "
+ "= %u, rx bytes = %u, "
+ "tx packets = %u, tx bytes = %u }",
+ stats->conn_id, stats->interests.rx_pkts, stats->interests.rx_bytes,
+ stats->interests.tx_pkts, stats->interests.tx_bytes, stats->data.rx_pkts,
+ stats->data.rx_bytes, stats->data.tx_pkts, stats->data.tx_bytes);
+}
+
+int hc_face_stats_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_FACE_STATS, NULL, pdata);
+}
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_FACE_STATS, face_stats); \ No newline at end of file
diff --git a/ctrl/libhicnctrl/src/objects/stats.h b/ctrl/libhicnctrl/src/objects/stats.h
new file mode 100644
index 000000000..3a4f04b2e
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/stats.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 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:
+ *
+ * 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 stats.h
+ * \brief Stats.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_STATS_H
+#define HICNCTRL_IMPL_OBJECTS_STATS_H
+
+#include "../object_vft.h"
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_STATS, stats);
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_FACE_STATS, face_stats);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_STATS_H */ \ No newline at end of file
diff --git a/ctrl/libhicnctrl/src/objects/strategy.c b/ctrl/libhicnctrl/src/objects/strategy.c
new file mode 100644
index 000000000..0e7a5787e
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/strategy.c
@@ -0,0 +1,92 @@
+/*
+ * 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:
+ *
+ * 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 strategy.c
+ * \brief Implementation of strategy.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/strategy.h>
+#include <hicn/util/log.h>
+
+#include "../object_vft.h"
+#include "../object_private.h"
+
+/* STREATEGY VALIDATE */
+
+int hc_strategy_validate(const hc_strategy_t *strategy, bool allow_partial) {
+ // TODO verify name
+ return 0;
+}
+
+int _hc_strategy_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_strategy_validate(&object->strategy, allow_partial);
+}
+
+/* STRATEGY CMP */
+
+int hc_strategy_cmp(const hc_strategy_t *s1, const hc_strategy_t *s2) {
+ return strcmp(s1->name, s2->name);
+}
+
+int _hc_strategy_cmp(const hc_object_t *object1, const hc_object_t *object2) {
+ return hc_strategy_cmp(&object1->strategy, &object2->strategy);
+}
+
+/* STRATEGY SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_strategy_snprintf(char *s, size_t size, const hc_strategy_t *strategy) {
+ return snprintf(s, size, "%s", strategy->name);
+}
+
+int _hc_strategy_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_strategy_snprintf(s, size, &object->strategy);
+}
+
+/* OPERATIONS */
+
+int hc_strategy_create(hc_sock_t *s, hc_strategy_t *strategy) { return -1; }
+
+int hc_strategy_get(hc_sock_t *s, hc_strategy_t *strategy, hc_data_t **pdata) {
+ return -1;
+}
+
+int hc_strategy_delete(hc_sock_t *s, hc_strategy_t *strategy) { return -1; }
+
+int hc_strategy_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STRATEGY, NULL, pdata);
+}
+
+/* new api */
+
+int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.strategy = *strategy;
+ return hc_execute(s, ACTION_SET, OBJECT_TYPE_STRATEGY, &object, NULL);
+}
+
+#if 0
+int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_add_local_prefix(s, strategy);
+}
+#endif
+
+GENERATE_FIND(strategy);
+
+DECLARE_OBJECT_OPS(OBJECT_TYPE_STRATEGY, strategy);
diff --git a/ctrl/libhicnctrl/src/objects/strategy.h b/ctrl/libhicnctrl/src/objects/strategy.h
new file mode 100644
index 000000000..0cc4f525d
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/strategy.h
@@ -0,0 +1,29 @@
+
+/*
+ * 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:
+ *
+ * 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 listener.h
+ * \brief Listener.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_STRATEGY_H
+#define HICNCTRL_IMPL_OBJECTS_STRATEGY_H
+
+#include "../object_vft.h"
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_STRATEGY, strategy);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_STRATEGY_H */
diff --git a/ctrl/libhicnctrl/src/objects/subscription.c b/ctrl/libhicnctrl/src/objects/subscription.c
new file mode 100644
index 000000000..8db55660d
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/subscription.c
@@ -0,0 +1,94 @@
+/*
+ * 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:
+ *
+ * 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 subscription.c
+ * \brief Implementation of subscription.
+ */
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/object.h>
+#include <hicn/ctrl/objects/subscription.h>
+#include <hicn/util/log.h>
+
+#include "../object_vft.h"
+#include "../object_private.h"
+
+/* SUBSCRIPTION VALIDATE */
+
+int hc_subscription_validate(const hc_subscription_t *subscription,
+ bool allow_partial) {
+ /* Any topic is considered valid */
+ return 0;
+}
+
+int _hc_subscription_validate(const hc_object_t *object, bool allow_partial) {
+ return hc_subscription_validate(&object->subscription, allow_partial);
+}
+
+/* LISTENER CMP */
+
+int hc_subscription_cmp(const hc_subscription_t *l1,
+ const hc_subscription_t *l2) {
+ return -1;
+}
+
+int _hc_subscription_cmp(const hc_object_t *object1,
+ const hc_object_t *object2) {
+ return hc_subscription_cmp(&object1->subscription, &object2->subscription);
+}
+
+/* SUBSCRIPTION SNPRINTF */
+
+/* /!\ Please update constants in header file upon changes */
+int hc_subscription_snprintf(char *s, size_t size,
+ const hc_subscription_t *subscription) {
+ return -99; /* Not implemented */
+}
+
+int _hc_subscription_snprintf(char *s, size_t size, const hc_object_t *object) {
+ return hc_subscription_snprintf(s, size, &object->subscription);
+}
+
+/* OPERATIONS */
+
+int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.subscription = *subscription;
+ return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL);
+}
+
+int hc_subscription_get(hc_sock_t *s, hc_subscription_t *subscription,
+ hc_data_t **pdata) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.subscription = *subscription;
+ return hc_execute(s, ACTION_GET, OBJECT_TYPE_SUBSCRIPTION, &object, pdata);
+}
+
+int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) {
+ hc_object_t object;
+ memset(&object, 0, sizeof(hc_object_t));
+ object.subscription = *subscription;
+ return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL);
+}
+
+int hc_subscription_list(hc_sock_t *s, hc_data_t **pdata) {
+ return hc_execute(s, ACTION_LIST, OBJECT_TYPE_SUBSCRIPTION, NULL, pdata);
+}
+
+GENERATE_FIND(subscription);
+DECLARE_OBJECT_OPS(OBJECT_TYPE_SUBSCRIPTION, subscription);
diff --git a/ctrl/libhicnctrl/src/objects/subscription.h b/ctrl/libhicnctrl/src/objects/subscription.h
new file mode 100644
index 000000000..6eb7583c6
--- /dev/null
+++ b/ctrl/libhicnctrl/src/objects/subscription.h
@@ -0,0 +1,28 @@
+/*
+ * 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:
+ *
+ * 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 subscription.h
+ * \brief Listener.
+ */
+
+#ifndef HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H
+#define HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H
+
+#include "../object_vft.h"
+
+DECLARE_OBJECT_OPS_H(OBJECT_TYPE_SUBSCRIPTION, subscription);
+
+#endif /* HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H */