summaryrefslogtreecommitdiffstats
path: root/hicn-light/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/utils')
-rwxr-xr-xhicn-light/src/utils/CMakeLists.txt36
-rwxr-xr-xhicn-light/src/utils/address.c419
-rwxr-xr-xhicn-light/src/utils/address.h498
-rwxr-xr-xhicn-light/src/utils/addressList.c133
-rwxr-xr-xhicn-light/src/utils/addressList.h196
-rwxr-xr-xhicn-light/src/utils/commands.h282
-rwxr-xr-xhicn-light/src/utils/interface.c168
-rwxr-xr-xhicn-light/src/utils/interface.h208
-rwxr-xr-xhicn-light/src/utils/interfaceSet.c149
-rwxr-xr-xhicn-light/src/utils/interfaceSet.h198
-rwxr-xr-xhicn-light/src/utils/punting.c98
-rwxr-xr-xhicn-light/src/utils/punting.h72
-rwxr-xr-xhicn-light/src/utils/utils.c258
-rwxr-xr-xhicn-light/src/utils/utils.h82
14 files changed, 2797 insertions, 0 deletions
diff --git a/hicn-light/src/utils/CMakeLists.txt b/hicn-light/src/utils/CMakeLists.txt
new file mode 100755
index 000000000..7d438d157
--- /dev/null
+++ b/hicn-light/src/utils/CMakeLists.txt
@@ -0,0 +1,36 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/addressList.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interface.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/punting.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/utils.h
+)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/addressList.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interface.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/punting.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/hicn-light/src/utils/address.c b/hicn-light/src/utils/address.c
new file mode 100755
index 000000000..3f6fe2591
--- /dev/null
+++ b/hicn-light/src/utils/address.c
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <src/config.h>
+#include <stdio.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <src/utils/address.h>
+
+#include <parc/algol/parc_Base64.h>
+#include <parc/algol/parc_BufferComposer.h>
+#include <parc/algol/parc_Hash.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Network.h>
+#include <parc/algol/parc_Object.h>
+
+#include <parc/assert/parc_Assert.h>
+
+struct address {
+ address_type addressType;
+ PARCBuffer *blob;
+};
+
+static struct address_type_str {
+ address_type type;
+ const char *str;
+} addressTypeString[] = {
+ {.type = ADDR_INET, .str = "INET"}, {.type = ADDR_INET6, .str = "INET6"},
+ {.type = ADDR_LINK, .str = "LINK"}, {.type = ADDR_IFACE, .str = "IFACE"},
+ {.type = ADDR_UNIX, .str = "UNIX"}, {.type = 0, .str = NULL}};
+
+void addressDestroy(Address **addressPtr) {
+ parcAssertNotNull(addressPtr, "Parameter must be non-null double pointer");
+ parcAssertNotNull(*addressPtr,
+ "Parameter must dereference to non-null pointer");
+
+ Address *address = *addressPtr;
+ parcBuffer_Release(&address->blob);
+ parcMemory_Deallocate((void **)&address);
+ *addressPtr = NULL;
+}
+
+void addressAssertValid(const Address *address) {
+ parcAssertNotNull(address, "Parameter must be non-null Address *");
+}
+
+const char *addressTypeToString(address_type type) {
+ for (int i = 0; addressTypeString[i].str != NULL; i++) {
+ if (addressTypeString[i].type == type) {
+ return addressTypeString[i].str;
+ }
+ }
+ parcTrapIllegalValue(type, "Unknown value: %d", type);
+ const char *result = NULL;
+ return result;
+}
+
+address_type addressStringToType(const char *str) {
+ for (int i = 0; addressTypeString[i].str != NULL; i++) {
+ if (strcasecmp(addressTypeString[i].str, str) == 0) {
+ return addressTypeString[i].type;
+ }
+ }
+ parcTrapIllegalValue(str, "Unknown type '%s'", str);
+ return 0;
+}
+
+static Address *_addressCreate(address_type addressType, PARCBuffer *buffer) {
+ Address *result = parcMemory_AllocateAndClear(sizeof(Address));
+
+ parcAssertNotNull(result, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(Address));
+ if (result != NULL) {
+ result->addressType = addressType;
+ result->blob = buffer;
+ }
+ return result;
+}
+
+Address *addressCreateFromInet(struct sockaddr_in *addr_in) {
+ parcAssertNotNull(addr_in, "Parameter must be non-null");
+
+ addr_in->sin_family = AF_INET;
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in));
+ parcBuffer_PutArray(buffer, sizeof(struct sockaddr_in), (uint8_t *)addr_in);
+ parcBuffer_Flip(buffer);
+
+ Address *result = _addressCreate(ADDR_INET, buffer);
+
+ return result;
+}
+
+Address *addressCreateFromInet6(struct sockaddr_in6 *addr_in6) {
+ parcAssertNotNull(addr_in6, "Parameter must be non-null");
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in6));
+ parcBuffer_PutArray(buffer, sizeof(struct sockaddr_in6), (uint8_t *)addr_in6);
+ parcBuffer_Flip(buffer);
+
+ Address *result = _addressCreate(ADDR_INET6, buffer);
+
+ return result;
+}
+
+Address *addressCreateFromLink(const uint8_t *linkaddr, size_t length) {
+ parcAssertNotNull(linkaddr, "Parameter must be non-null");
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in6));
+ parcBuffer_PutArray(buffer, length, linkaddr);
+ parcBuffer_Flip(buffer);
+
+ Address *result = _addressCreate(ADDR_LINK, buffer);
+ return result;
+}
+
+Address *addressCreateFromInterface(unsigned interfaceIndex) {
+ unsigned netbyteorder = htonl(interfaceIndex);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(netbyteorder));
+ parcBuffer_PutArray(buffer, sizeof(netbyteorder), (uint8_t *)&netbyteorder);
+ parcBuffer_Flip(buffer);
+
+ Address *result = _addressCreate(ADDR_IFACE, buffer);
+ return result;
+}
+
+Address *addressCreateFromUnix(struct sockaddr_un *addr_un) {
+ parcAssertNotNull(addr_un, "Parameter must be non-null");
+
+ PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_un));
+ parcBuffer_PutArray(buffer, sizeof(struct sockaddr_un), (uint8_t *)addr_un);
+ parcBuffer_Flip(buffer);
+
+ Address *result = _addressCreate(ADDR_UNIX, buffer);
+ return result;
+}
+
+Address *addressCopy(const Address *original) {
+ addressAssertValid(original);
+
+ Address *result =
+ _addressCreate(original->addressType, parcBuffer_Copy(original->blob));
+ return result;
+}
+
+bool addressEquals(const Address *a, const Address *b) {
+ if (a == b) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ if (a->addressType == b->addressType) {
+ if (parcBuffer_Equals(a->blob, b->blob)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+address_type addressGetType(const Address *address) {
+ addressAssertValid(address);
+
+ return address->addressType;
+}
+
+// The Get functions need better names, what they do (Get from what? Put to
+// what?) is not clear from their names. Case 1028
+bool addressGetInet(const Address *address, struct sockaddr_in *addr_in) {
+ addressAssertValid(address);
+ parcAssertNotNull(addr_in, "Parameter addr_in must be non-null");
+
+ if (address->addressType == ADDR_INET) {
+ parcAssertTrue(
+ parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_in),
+ "Address corrupted. Expected length %zu, actual length %zu",
+ sizeof(struct sockaddr_in), parcBuffer_Remaining(address->blob));
+
+ memcpy(addr_in, parcBuffer_Overlay(address->blob, 0),
+ sizeof(struct sockaddr_in));
+ return true;
+ }
+ return false;
+}
+
+bool addressGetInet6(const Address *address, struct sockaddr_in6 *addr_in6) {
+ addressAssertValid(address);
+ parcAssertNotNull(addr_in6, "Parameter addr_in6 must be non-null");
+
+ if (address->addressType == ADDR_INET6) {
+ parcAssertTrue(
+ parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_in6),
+ "Address corrupted. Expected length %zu, actual length %zu",
+ sizeof(struct sockaddr_in6), parcBuffer_Remaining(address->blob));
+
+ memcpy(addr_in6, parcBuffer_Overlay(address->blob, 0),
+ sizeof(struct sockaddr_in6));
+ return true;
+ }
+ return false;
+}
+
+bool addressGetUnix(const Address *address, struct sockaddr_un *addr_un) {
+ addressAssertValid(address);
+ parcAssertNotNull(addr_un, "Parameter addr_in6 must be non-null");
+
+ if (address->addressType == ADDR_UNIX) {
+ parcAssertTrue(
+ parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_un),
+ "Address corrupted. Expected length %zu, actual length %zu",
+ sizeof(struct sockaddr_un), parcBuffer_Remaining(address->blob));
+
+ memcpy(addr_un, parcBuffer_Overlay(address->blob, 0),
+ sizeof(struct sockaddr_un));
+ return true;
+ }
+ return false;
+}
+
+bool addressGetInterfaceIndex(const Address *address, uint32_t *ifidx) {
+ addressAssertValid(address);
+ parcAssertNotNull(ifidx, "Parameter ifidx must be non-null");
+
+ if (address->addressType == ADDR_IFACE) {
+ parcAssertTrue(parcBuffer_Remaining(address->blob) == sizeof(uint32_t),
+ "Address corrupted. Expected length %zu, actual length %zu",
+ sizeof(uint32_t), parcBuffer_Remaining(address->blob));
+
+ uint32_t netbyteorder;
+ memcpy(&netbyteorder, parcBuffer_Overlay(address->blob, 0),
+ sizeof(uint32_t));
+ *ifidx = ntohl(netbyteorder);
+ return true;
+ }
+ return false;
+}
+
+PARCBuffer *addressGetLinkAddress(const Address *address) {
+ addressAssertValid(address);
+ if (address->addressType == ADDR_LINK) {
+ return address->blob;
+ }
+ return NULL;
+}
+
+static PARCBufferComposer *_Inet_BuildString(const Address *address,
+ PARCBufferComposer *composer) {
+ addressAssertValid(address);
+
+ struct sockaddr_in *saddr =
+ (struct sockaddr_in *)parcBuffer_Overlay(address->blob, 0);
+ return parcNetwork_SockInet4Address_BuildString(saddr, composer);
+}
+
+static PARCBufferComposer *_Inet6_BuildString(const Address *address,
+ PARCBufferComposer *composer) {
+ addressAssertValid(address);
+
+ struct sockaddr_in6 *saddr =
+ (struct sockaddr_in6 *)parcBuffer_Overlay(address->blob, 0);
+ return parcNetwork_SockInet6Address_BuildString(saddr, composer);
+}
+
+static PARCBufferComposer *_Link_BuildString(const Address *address,
+ PARCBufferComposer *composer) {
+ addressAssertValid(address);
+
+ const unsigned char *addr = parcBuffer_Overlay(address->blob, 0);
+
+ size_t length = parcBuffer_Remaining(address->blob);
+
+ return parcNetwork_LinkAddress_BuildString(addr, length, composer);
+}
+
+static ssize_t _UnixToString(char *output, size_t remaining_size,
+ const PARCBuffer *addr) {
+ parcAssertNotNull(output, "parameter output must be non-null");
+ parcBuffer_AssertValid(addr);
+
+ parcAssertTrue(parcBuffer_Remaining(addr) == sizeof(struct sockaddr_un),
+ "Address corrupted. Expected %zu actual %zu",
+ sizeof(struct sockaddr_un), parcBuffer_Remaining(addr));
+
+ // sockaddr length for the path, 16 for the ascii stuff, 3 for the length
+ // number
+ struct sockaddr_un *saddr =
+ (struct sockaddr_un *)parcBuffer_Overlay((PARCBuffer *)addr, 0);
+ size_t min_remaining = strlen(saddr->sun_path) + 16 + 3;
+ parcAssertTrue(remaining_size >= min_remaining,
+ "Remaining size too small, need at least %zu", min_remaining);
+
+ ssize_t output_length = sprintf(output, "{ .path=%s, .len=%zu }",
+ saddr->sun_path, strlen(saddr->sun_path));
+ return output_length;
+}
+
+static ssize_t _IfaceToString(char *output, size_t remaining_size,
+ const PARCBuffer *addr) {
+ parcAssertNotNull(output, "parameter output must be non-null");
+ parcBuffer_AssertValid(addr);
+
+ parcAssertTrue(parcBuffer_Remaining(addr) == sizeof(uint32_t),
+ "Address corrupted. Expected %zu actual %zu", sizeof(uint32_t),
+ parcBuffer_Remaining(addr));
+
+ uint32_t *ifidx = (uint32_t *)parcBuffer_Overlay((PARCBuffer *)addr, 0);
+
+ ssize_t output_length = sprintf(output, "{ .ifidx=%u }", ntohl(*ifidx));
+
+ return output_length;
+}
+
+PARCBufferComposer *addressBuildString(const Address *address,
+ PARCBufferComposer *composer) {
+ if (address != NULL) {
+ char *str = addressToString(address);
+ parcBufferComposer_PutString(composer, str);
+ parcMemory_Deallocate((void **)&str);
+ }
+ return composer;
+}
+
+char *addressToString(const Address *address) {
+ addressAssertValid(address);
+
+ char addrstr[256];
+
+ switch (address->addressType) {
+ case ADDR_INET: {
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
+ _Inet_BuildString(address, composer));
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+ return result;
+ } break;
+
+ case ADDR_INET6: {
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
+ _Inet6_BuildString(address, composer));
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ parcBufferComposer_Release(&composer);
+ return result;
+ } break;
+
+ case ADDR_LINK:
+ _UnixToString(addrstr, 256, address->blob);
+ break;
+
+ case ADDR_IFACE: {
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
+ _Link_BuildString(address, composer));
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ parcBufferComposer_Release(&composer);
+ return result;
+ } break;
+
+ case ADDR_UNIX:
+ _IfaceToString(addrstr, 256, address->blob);
+ break;
+
+ default:
+ sprintf(addrstr, "UNKNOWN type = %d", address->addressType);
+ break;
+ }
+
+ ssize_t alloc_size = 1024;
+ char *output = parcMemory_Allocate(alloc_size);
+ parcAssertNotNull(output, "parcMemory_Allocate(%zu) returned NULL",
+ alloc_size);
+ ssize_t output_length =
+ snprintf(output, alloc_size, "{ .type=%s, .data=%s }",
+ addressTypeToString(address->addressType), addrstr);
+
+ parcAssertTrue(output_length < alloc_size,
+ "allocated size too small, needed %zd", output_length);
+ parcAssertFalse(output_length < 0, "snprintf error: (%d) %s", errno,
+ strerror(errno));
+
+ return output;
+}
+
+PARCHashCode addressHashCode(const Address *address) {
+ addressAssertValid(address);
+
+ PARCHashCode hash = parcBuffer_HashCode(address->blob);
+ hash = parcHashCode_HashImpl((uint8_t *)&address->addressType,
+ sizeof(address->addressType), hash);
+
+ return hash;
+}
diff --git a/hicn-light/src/utils/address.h b/hicn-light/src/utils/address.h
new file mode 100755
index 000000000..a98d15084
--- /dev/null
+++ b/hicn-light/src/utils/address.h
@@ -0,0 +1,498 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief Represents an endpoint address.
+ *
+ * Represents an endpoint address. May be INET, INET6, or a multi-byte LINK,
+ * or an Interface Index.
+ *
+ * INET and INET6 must contain the .sa_addr member, and other members as needed
+ * by the use of the address.
+ *
+ * The Interface Index address is essentially a pointer to a device.
+ *
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+#ifndef address_h
+#define address_h
+
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <sys/un.h>
+
+#include <parc/algol/parc_Buffer.h>
+#include <parc/algol/parc_BufferComposer.h>
+#include <src/utils/commands.h>
+
+/**
+ * Return a string representation of the given `address_type`
+ *
+ * @param [in] type A valid address_type value.
+ *
+ * @return NULL An error occurred
+ * @return non-NULL A pointer to a static string representation of the
+ * `address_type`.
+ *
+ * Example:
+ * @code
+ * {
+ * const char *typeAsString = addressTypeToString(commandAddrType_INET);
+ * }
+ * @endcode
+ *
+ * @see addressStringToType
+ */
+const char *addressTypeToString(address_type type);
+
+/**
+ * Return a `address_type` from the given nul-terminated C string.
+ *
+ * @param [in] typeAsString A nul-terminated, C string representation of a
+ * `address_type`.
+ *
+ * @return A address_type
+ *
+ * Example:
+ * @code
+ * {
+ * address_type type = addressTypeToString("INET");
+ * }
+ * @endcode
+ *
+ * @see addressTypeToString
+ */
+address_type addressStringToType(const char *typeAsString);
+
+struct address;
+typedef struct address Address;
+
+/**
+ * Create a new `Address` instance from an IPv4 IP address, the port is
+ * optional.
+ *
+ * The sockaddr_in should be filled in network byte order. The newly created
+ * instance must eventually be destroyed by calling {@link addressDestroy}().
+ *
+ * @param [in] addr_in The `sockaddr_in` representing the IPv4 IP address with
+ * which to initialize the new `Address` instance.
+ * @return A new instance of `Address` that must eventually be destroyed by
+ * calling {@link addressDestroy}().
+ *
+ * Example:
+ * @code
+ * {
+ * Address *dest = addressCreateFromInet(
+ * &(struct sockaddr_in) {
+ * .sa_addr =
+ * inet_addr("foo.bar.com"), .sa_port = htons(9695) } ); addressDestroy(&dest);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCreateFromInet(struct sockaddr_in *addr_in);
+
+/**
+ * Create a new `Address` instance from an IPv6 IP address, the port is
+ * optional.
+ *
+ *
+ * The sockaddr_in should be filled in network byte order. The newly created
+ * instance must eventually be destroyed by calling {@link addressDestroy}().
+ *
+ * @param [in] addr_in6 A `sockaddr_in6` from which to initialize a new instance
+ * of Address
+ * @return A new instance of `Address` that must eventually be destroyed by
+ * calling {@link addressDestroy}()
+ *
+ * Example:
+ * @code
+ * {
+ * struct sockaddr_in6 addr_in6;
+ * memset(&addr_in6, 0, sizeof(struct sockaddr_in6));
+ *
+ * inet_pton(AF_INET6, "2001:720:1500:1::a100", &(addr_in6.sin6_addr));
+ * addr_in6.sin6_family = AF_INET6;
+ * addr_in6.sin6_port = 0x0A0B;
+ * addr_in6.sin6_flowinfo = 0x01020304;
+ *
+ * Address *address = addressCreateFromInet6(&addr_in6);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCreateFromInet6(struct sockaddr_in6 *addr_in6);
+
+/**
+ * Create a new `Address` instance, initialized from a Link address.
+ *
+ * User must know the link address format (i.e. token ring vs ethernet) and have
+ * the address in a byte array. The array is encoded in left-to-right order. The
+ * newly created instance must eventually be destroyed by calling {@link
+ * addressDestroy}().
+ *
+ * @param [in] linkaddr A byte array containing the link address
+ * @param [in] length The length of the link address byte array
+ * @return A new instance of `Address` that must eventually be destroyed by
+ * calling {@link addressDestroy}()
+ *
+ * Example:
+ * @code
+ * {
+ * uint8_t mac[] = { 0x14, 0x10, 0x9f, 0xd7, 0x0b, 0x89 };
+ * Address *address = addressCreateFromLink(mac, sizeof(mac));
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCreateFromLink(const uint8_t *linkaddr, size_t length);
+
+/**
+ * Create a new `Address` instance from a network interface index.
+ *
+ * The interfaceIndex should be in host byte order. The newly created instance
+ * must eventually be destroyed by calling {@link addressDestroy}().
+ *
+ * @param [in] interfaceIndex The index of the interface to encode
+ * @return A new instance of `Address` that must eventually be destroyed by
+ * calling {@link addressDestroy}()
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(2);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCreateFromInterface(uint32_t interfaceIndex);
+
+/**
+ * Create a new Address instance from a PF_UNIX address domain.
+ *
+ * The newly created instance must eventually be destroyed by calling {@link
+ * addressDestroy}().
+ *
+ * @param [in] addr_un The `struct sockaddr_un` specifying the local PF_UNIX
+ * socket address
+ * @return A new instance of `Address` that must eventually be destroyed by
+ * calling {@link addressDestroy}()
+ *
+ * Example:
+ * @code
+ * {
+ * struct sockaddr_un addr_unix;
+ * memset(&addr_unix, 0, sizeof(struct sockaddr_un));
+ * char path[] = "/Hello/Cruel/World";
+ * strcpy(addr_un.sun_path, path);
+ * addr_un.sun_family = AF_UNIX;
+ *
+ * Address *address = addressCreateFromUnix(&addr_un);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCreateFromUnix(struct sockaddr_un *addr_un);
+
+/**
+ * Create a deep copy of an instance of a `Address`. A completely new,
+ * indedependent instance is created.
+ *
+ * The newly created instance must eventually be destroyed by calling {@link
+ * addressDestroy}().
+ *
+ * @param [in] original A pointer to a `Address` instance to be copied.
+ * @return A new instance of a Address, deep copied from the `original`
+ * instance.
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(2);
+ *
+ * Address *copy = addressCopy(address);
+ *
+ * addressDestroy(&address);
+ * addressDestroy(&copy);
+ * }
+ * @endcode
+ * @see addressDestroy
+ */
+Address *addressCopy(const Address *original);
+
+/**
+ * Deallocate an instance of a Address.
+ *
+ * The Address instance is deallocated, and any referenced data is also
+ * deallocated. The referenced pointer is set to NULL upon return.
+ *
+ * @param [in] addressPtr A pointer to a pointer to an instance of Address.
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(2);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ */
+void addressDestroy(Address **addressPtr);
+
+/**
+ * Determine if two Address instances are equal.
+ *
+ *
+ * The following equivalence relations on non-null `Address` instances are
+ * maintained:
+ *
+ * * It is reflexive: for any non-null reference value x, `addressEquals(x, x)`
+ * must return true.
+ *
+ * * It is symmetric: for any non-null reference values x and y,
+ * `addressEquals(x, y)` must return true if and only if
+ * `addressEquals(y, x)` returns true.
+ *
+ * * It is transitive: for any non-null reference values x, y, and z, if
+ * `addressEquals(x, y)` returns true and
+ * `addressEquals(y, z)` returns true,
+ * then `addressEquals(x, z)` must return true.
+ *
+ * * It is consistent: for any non-null reference values x and y, multiple
+ * invocations of `addressEquals(x, y)` consistently return true or
+ * consistently return false.
+ *
+ * * For any non-null reference value x, `addressEquals(x, NULL)` must
+ * return false.
+ *
+ * If one address specifies more information than other,
+ * e.g. a is INET with a port and b is not, they are not equal.
+ *
+ * `a` and `b` may be NULL, and NULL == NULL.
+ *
+ * @param a A pointer to a Address instance
+ * @param b A pointer to a Address instance
+ * @return true if the two instances are equal
+ * @return false if the two instances are not equal
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(2);
+ * Address *copy = addressCopy(address);
+ *
+ * if (addressEquals(address, copy)) {
+ * // true
+ * } else {
+ * // false
+ * }
+ *
+ * addressDestroy(&address);
+ * addressDestroy(&copy);
+ * }
+ * @endcode
+ */
+bool addressEquals(const Address *a, const Address *b);
+
+/**
+ * Return the {@link address_type} from a specified Address.
+ *
+ * @param [in] A pointer to a Address instance
+ *
+ * @return the {@link address_type} of the specified Address instance
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(2);
+ *
+ * address_type type = addressGetType(address);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ *
+ * @see address_type
+ */
+address_type addressGetType(const Address *address);
+
+/**
+ * Fills in the output parameter with an INET address.
+ *
+ * @param addr_in must be non-NULL
+ * @return true if INET address and output filled in, false otherwise.
+ *
+ */
+bool addressGetInet(const Address *address, struct sockaddr_in *addr_in);
+
+/**
+ * Retrieve the INET6 address associated with a `Address` instance.
+ *
+ * If the specified Address instance is of type {@link commandAddrType_INET6},
+ * then populate the supplied `struct sockaddr_in6` from the Address and return
+ * true. If the Address is not of type `commandAddrType_INET6`, this function
+ * returns false.
+ *
+ * @param [in] address A pointer to a `Address` instance of type {@link
+ * commandAddrType_INET6}.
+ * @param [in] addr_in6 A pointer to a `struct sockaddr_in6`. Must be non-NULL.
+ * @return true If the Address instance is of type `commandAddrType_INET6` and
+ * `addr_in6` was filled in
+ * @return false If the Address instance was not of type `commandAddrType_INET6`
+ * or `addr_in6` could not be filled in.
+ *
+ * @see addressGetType
+ */
+bool addressGetInet6(const Address *address, struct sockaddr_in6 *addr_in6);
+
+/**
+ * Retrieve the interface index associated with a `Address` instance.
+ *
+ * If the specified `Address` instance is of type {@link commandAddrType_IFACE},
+ * then populate the supplied `uint32_t` from the Address and return true. If
+ * the `Address` is not of type `commandAddrType_INET6`, this function returns
+ * false.
+ *
+ * @param [in] address A pointer to a `Address` instance of type {@link
+ * commandAddrType_IFACE}.
+ * @param [in] interfaceIndex A pointer to a `uint32_t` to fill in. Must be
+ * non-NULL.
+ * @return true If the Address instance is of type `commandAddrType_IFACE` and
+ * `interfaceIndex` was filled in.
+ * @return false If the Address instance was not of type `commandAddrType_IFACE`
+ * or `interfaceIndex` could not be filled in.
+ *
+ * @see addressGetType
+ */
+bool addressGetInterfaceIndex(const Address *address, uint32_t *interfaceIndex);
+
+/**
+ * Retrieve the link address associated with a `Address` instance.
+ *
+ * If the specified `Address` instance is of type {@link commandAddrType_LINK},
+ * then return a pointer to the {@link PARCBuffer} containing the link address.
+ * If the `Address` is not of type {@link commandAddrType_LINK}, then return
+ * NULL. The returned PARCBuffer pointer points to memory managed by the Address
+ * instance, and does not need to be destroyed or released on its own.
+ *
+ * @param [in] address A pointer to a `Address` instance of type {@link
+ * commandAddrType_LINK}.
+ * @return A pointer to the {@link PARCBuffer} containing the link address.
+ *
+ * Example:
+ * @code
+ * {
+ * uint8_t mac[] = { 0x14, 0x10, 0x9f, 0xd7, 0x0b, 0x89 };
+ * Address *address = addressCreateFromLink(mac, sizeof(mac));
+ *
+ * PARCBuffer *macBuffer = addressGetLinkAddress(address);
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see addressGetType
+ */
+PARCBuffer *addressGetLinkAddress(const Address *address);
+
+/**
+ * Append the string representation of a `Address` to a specified
+ * `PARCBufferComposer`.
+ *
+ * @param [in] address A pointer to a `Address` instance.
+ * @param [in] composer A pointer to a `PARCBufferComposer` instance to which to
+ * append the string.
+ *
+ * @return The `PARCBufferComposer` instance that was passed in.
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(1);
+ * PARCBufferComposer *composer = addressBuildString(address,
+ * parcBufferComposer_Create()); parcBufferComposer_Release(&composer);
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ *
+ * @see PARCBufferComposer
+ */
+PARCBufferComposer *addressBuildString(const Address *address,
+ PARCBufferComposer *composer);
+
+/**
+ * Produce a nil-terminated string representation of the specified instance.
+ *
+ * The result must be freed by the caller via {@link parcMemory_Deallocate}.
+ *
+ * @param [in] interest A pointer to the instance.
+ *
+ * @return NULL Cannot allocate memory.
+ * @return non-NULL A pointer to an allocated, nul-terminated C string that must
+ * be deallocated via {@link parcMemory_Deallocate}().
+ *
+ * Example:
+ * @code
+ * {
+ * Address *address = addressCreateFromInterface(1);
+ *
+ * char *string = addressToString(address);
+ *
+ * if (string != NULL) {
+ * printf("Address looks like: %s\n", string);
+ * parcMemory_Deallocate(string);
+ * } else {
+ * printf("Cannot allocate memory\n");
+ * }
+ *
+ * addressDestroy(&address);
+ * }
+ * @endcode
+ * @see parcMemory_Deallocate
+ * @see addressBuildString
+ */
+char *addressToString(const Address *address);
+
+/**
+ * Return a non-cryptographic hash code consistent with Equals
+ *
+ * If commandAddrA == commandAddrB, then addressHashCode(commandAddrA) ==
+ * addressHashCode(commandAddrB)
+ *
+ * @param [in] address A pointer to a Address instance.
+ * @return A 32-bit hashcode for the specified Address instance.
+ *
+ * Example:
+ * @code
+ * Address *address = addressCreateFromInterface(1);
+ *
+ * uint32_t hashCode = addressHashCode(address);
+ *
+ * addressDestroy(&address);
+ * @endcode
+ */
+PARCHashCode addressHashCode(const Address *address);
+#endif // address_h
diff --git a/hicn-light/src/utils/addressList.c b/hicn-light/src/utils/addressList.c
new file mode 100755
index 000000000..4f51a11bf
--- /dev/null
+++ b/hicn-light/src/utils/addressList.c
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#include <src/config.h>
+#include <stdio.h>
+
+#include <parc/assert/parc_Assert.h>
+
+#include <src/utils/addressList.h>
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_Buffer.h>
+#include <parc/algol/parc_Memory.h>
+
+struct address_list {
+ PARCArrayList *listOfAddress;
+};
+
+static void _addressListFreeAddress(void **addressVoidPtr) {
+ Address **addressPtr = (Address **)addressVoidPtr;
+ addressDestroy(addressPtr);
+}
+
+AddressList *addressListCreate() {
+ AddressList *list = parcMemory_AllocateAndClear(sizeof(AddressList));
+ parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(AddressList));
+ list->listOfAddress = parcArrayList_Create(_addressListFreeAddress);
+ parcAssertNotNull(list->listOfAddress, "Got null from parcArrayList_Create");
+
+ return list;
+}
+
+void addressListDestroy(AddressList **addressListPtr) {
+ parcAssertNotNull(addressListPtr,
+ "Parameter must be non-null double pointer");
+ parcAssertNotNull(*addressListPtr,
+ "Parameter must dereference to non-null pointer");
+ AddressList *list = *addressListPtr;
+
+ parcArrayList_Destroy(&list->listOfAddress);
+ parcMemory_Deallocate((void **)&list);
+ *addressListPtr = NULL;
+}
+
+AddressList *addressListAppend(AddressList *list, Address *address) {
+ parcAssertNotNull(list, "Parameter list must be non-null");
+ parcAssertNotNull(address, "Parameter address must be non-null");
+
+ parcArrayList_Add(list->listOfAddress, (PARCObject *)address);
+ return list;
+}
+
+AddressList *addressListCopy(const AddressList *original) {
+ parcAssertNotNull(original, "Parameter must be non-null");
+
+ AddressList *copy = addressListCreate();
+ for (int i = 0; i < parcArrayList_Size(original->listOfAddress); i++) {
+ Address *address = (Address *)parcArrayList_Get(original->listOfAddress, i);
+ parcArrayList_Add(copy->listOfAddress, (PARCObject *)addressCopy(address));
+ }
+
+ return copy;
+}
+
+bool addressListEquals(const AddressList *a, const AddressList *b) {
+ parcAssertNotNull(a, "Parameter a must be non-null");
+ parcAssertNotNull(b, "Parameter b must be non-null");
+
+ if (a == b) {
+ return true;
+ }
+
+ if (parcArrayList_Size(a->listOfAddress) !=
+ parcArrayList_Size(b->listOfAddress)) {
+ return false;
+ }
+
+ for (size_t i = 0; i < parcArrayList_Size(a->listOfAddress); i++) {
+ const Address *addr_a = (Address *)parcArrayList_Get(a->listOfAddress, i);
+ const Address *addr_b = (Address *)parcArrayList_Get(b->listOfAddress, i);
+ if (!addressEquals(addr_a, addr_b)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+size_t addressListLength(const AddressList *list) {
+ parcAssertNotNull(list, "Parameter must be non-null");
+ return parcArrayList_Size(list->listOfAddress);
+}
+
+const Address *addressListGetItem(const AddressList *list, size_t item) {
+ parcAssertNotNull(list, "Parameter must be non-null");
+ parcAssertTrue(item < addressListLength(list),
+ "Asked for item %zu beyond end of list %zu", item,
+ addressListLength(list));
+
+ return (Address *)parcArrayList_Get(list->listOfAddress, item);
+}
+
+char *addressListToString(const AddressList *list) {
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ for (size_t i = 0; i < addressListLength(list); i++) {
+ char *addressString = addressToString(addressListGetItem(list, i));
+ parcBufferComposer_PutString(composer, addressString);
+ if (i < (addressListLength(list) - 1)) {
+ parcBufferComposer_PutString(composer, " ");
+ }
+ parcMemory_Deallocate((void **)&addressString);
+ }
+
+ PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
+ char *result = parcBuffer_ToString(buffer);
+ parcBuffer_Release(&buffer);
+ parcBufferComposer_Release(&composer);
+
+ return result;
+}
diff --git a/hicn-light/src/utils/addressList.h b/hicn-light/src/utils/addressList.h
new file mode 100755
index 000000000..bcb312c14
--- /dev/null
+++ b/hicn-light/src/utils/addressList.h
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief A list of Address instances.
+ *
+ * An AddressList is a list of addresses.
+ * It wraps a PARCLinkedList for type saftey with Address.
+ *
+ */
+#ifndef address_list_h
+#define address_list_h
+
+#include <src/utils/address.h>
+
+struct address_list;
+/**
+ * @typedef AddressList
+ * @abstract A list of Address instance pointers.
+ */
+typedef struct address_list AddressList;
+
+/**
+ * Create an instance of {@link AddressList}
+ *
+ * @return NULL An error occurred
+ * @return non-NULL A pointer to a valid AddressList instance.
+ *
+ * Example:
+ * @code
+ * {
+ * AddressList *list = addressListCreate();
+ *
+ * }
+ * @endcode
+ *
+ * @see addressListDestroy
+ */
+AddressList *addressListCreate(void);
+
+/**
+ * Dellocate and destroy a AddressList instance.
+ *
+ * @param [in] addressListPtr A pointer to a pointer to a valid {@link
+ * AddressList}.
+ *
+ *
+ * Example:
+ * @code
+ * {
+ * AddressList *list = addressListCreate(void);
+ * addressListDestroy(&list);
+ * }
+ * @endcode
+ *
+ * @see addressListCreate
+ */
+void addressListDestroy(AddressList **addressListPtr);
+
+/**
+ * Appends the address, taking ownership of the memory
+ *
+ * @param list A pointer to a AddressList.
+ * @param address must be non-null
+ * @return The input list
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+AddressList *addressListAppend(AddressList *list, Address *address);
+
+/**
+ * Creates a reference counted copy
+ *
+ * @param list A pointer to a valid {@link AddressList}.
+ *
+ * @return An allocated list, you must destroy it.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+AddressList *addressListCopy(const AddressList *list);
+
+/**
+ * Determine if two AddressList instances are equal.
+ *
+ * Two AddressList instances are equal if, and only if, they have the same
+ * length, with the same elements in the same order.
+ *
+ *
+ * The following equivalence relations on non-null `AddressList` instances are
+ * maintained:
+ *
+ * * It is reflexive: for any non-null reference value x,
+ * `AddressList_Equals(x, x)` must return true.
+ *
+ * * It is symmetric: for any non-null reference values x and y,
+ * `AddressList_Equals(x, y)` must return true if and only if
+ * `addressListEquals(y, x)` returns true.
+ *
+ * * It is transitive: for any non-null reference values x, y, and z, if
+ * `addressListEquals(x, y)` returns true and
+ * `addressListEquals(y, z)` returns true,
+ * then `addressListEquals(x, z)` must return true.
+ *
+ * * It is consistent: for any non-null reference values x and y, multiple
+ * invocations of `addressListEquals(x, y)` consistently return true or
+ * consistently return false.
+ *
+ * * For any non-null reference value x, `addressListEquals(x, NULL)` must
+ * return false.
+ *
+ * @param a A pointer to a `AddressList` instance.
+ * @param b A pointer to a `AddressList` instance.
+ * @return true if the two `AddressList` instances are equal.
+ *
+ * Example:
+ * @code
+ * {
+ * AddressList *a = addressListCreate();
+ * AddressList *b = addressListCreate();
+ *
+ * if (addressListEquals(a, b)) {
+ * // true
+ * } else {
+ * // false
+ * }
+ * }
+ * @endcode
+ */
+bool addressListEquals(const AddressList *a, const AddressList *b);
+
+/**
+ * Get the number of items in the list
+ *
+ * @param list A pointer to a {@link AddressList}.
+ * @return The number of items in the list.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t addressListLength(const AddressList *list);
+
+/**
+ * Returns a const reference to an item.
+ * Use addressCopy if needed.
+ *
+ * Do not free or modify the returned value.
+ * Use addressCopy if you need a mutable instance.
+ *
+ * @param list A pointer to a AddressList.
+ * @param item A value less than the number of items in the given {@link
+ * AddressList}.
+ * @return Asserts if item off end of list.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+const Address *addressListGetItem(const AddressList *list, size_t item);
+
+/**
+ * Get a nul-terminated, C-string representation of the given {@link
+ * AddressList}.
+ *
+ * @param list A pointer to a valid {@link AddressList} instance.
+ *
+ * @return An allocate string representation of the {@link AddressList} that
+ * must be freed via `parcMemory_Deallocate()`.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+char *addressListToString(const AddressList *list);
+#endif // address_list_h
diff --git a/hicn-light/src/utils/commands.h b/hicn-light/src/utils/commands.h
new file mode 100755
index 000000000..2f8ebcbfe
--- /dev/null
+++ b/hicn-light/src/utils/commands.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file commands.h
+ * @brief All hicn-light commands: 14 in total.
+ *
+ * Header and payload in binary format.
+ */
+
+#ifndef commands_h
+#define commands_h
+
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+typedef struct in6_addr ipv6_addr_t;
+typedef uint32_t ipv4_addr_t;
+
+union commandAddr {
+ ipv4_addr_t ipv4;
+ ipv6_addr_t ipv6;
+};
+
+typedef enum {
+ REQUEST_LIGHT = 100,
+ RESPONSE_LIGHT,
+ ACK_LIGHT,
+ NACK_LIGHT,
+ LAST_MSG_TYPE_VALUE
+} message_type;
+
+typedef enum {
+ ADD_LISTENER,
+ ADD_CONNECTION,
+ LIST_CONNECTIONS,
+ ADD_ROUTE,
+ LIST_ROUTES,
+ REMOVE_CONNECTION,
+ REMOVE_ROUTE,
+ CACHE_STORE,
+ CACHE_SERVE,
+ CACHE_CLEAR,
+ SET_STRATEGY,
+ SET_WLDR,
+ ADD_PUNTING,
+ LIST_LISTENERS,
+ MAPME_ENABLE,
+ MAPME_DISCOVERY,
+ MAPME_TIMESCALE,
+ MAPME_RETX,
+ LAST_COMMAND_VALUE
+} command_id;
+
+typedef enum {
+ ADDR_INET = 1,
+ ADDR_INET6,
+ ADDR_LINK,
+ ADDR_IFACE,
+ ADDR_UNIX /* PF_UNIX */
+} address_type;
+
+typedef enum {
+ UDP_CONN,
+ TCP_CONN,
+ GRE_CONN, // not implemented
+ HICN_CONN
+} connection_type;
+
+typedef enum { ACTIVATE_ON, ACTIVATE_OFF } activate_type;
+
+//========== HEADER ==========
+
+typedef struct {
+ uint8_t messageType;
+ uint8_t commandID;
+ uint16_t length; // tells the number of structures in the payload
+ uint32_t seqNum;
+} header_control_message;
+// for the moment has to be at least 8 bytes
+
+// SIZE=8
+
+//========== [00] ADD LISTENER ==========
+
+typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
+
+typedef struct {
+ char symbolic[16];
+ // char interfaceName[16];
+ union commandAddr address;
+ uint16_t port;
+ // uint16_t etherType;
+ uint8_t addressType;
+ uint8_t listenerMode;
+ uint8_t connectionType;
+} add_listener_command;
+
+// SIZE=40
+
+//========== [01] ADD CONNECTION ==========
+
+typedef struct {
+ char symbolic[16];
+ union commandAddr remoteIp;
+ union commandAddr localIp;
+ uint16_t remotePort;
+ uint16_t localPort;
+ uint8_t ipType;
+ uint8_t connectionType;
+} add_connection_command;
+
+// SIZE=56
+
+//========== [02] LIST CONNECTIONS ==========
+
+typedef enum {
+ CONN_GRE,
+ CONN_TCP,
+ CONN_UDP,
+ CONN_MULTICAST,
+ CONN_L2,
+ CONN_HICN
+} list_connections_type;
+
+typedef enum {
+ IFACE_UP = 0,
+ IFACE_DOWN = 1,
+ IFACE_UNKNOWN = 2 // not used actually
+} connection_state;
+
+typedef struct {
+ add_connection_command connectionData;
+ uint32_t connid;
+ uint8_t state;
+} list_connections_command;
+
+// SIZE=64
+
+//========== [03] ADD ROUTE ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+} add_route_command;
+
+// SIZE=36
+
+//========== [04] LIST ROUTE ==========
+
+typedef struct {
+ union commandAddr address;
+ uint32_t connid;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+} list_routes_command;
+
+// SIZE=24
+
+//========== [05] REMOVE CONNECTION ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+} remove_connection_command;
+
+// SIZE=16
+
+//========== [06] REMOVE ROUTE ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+} remove_route_command;
+
+// SIZE=36
+
+//========== [07] CACHE STORE ==========
+
+typedef struct {
+ uint8_t activate;
+} cache_store_command;
+
+// SIZE=1
+
+//========== [08] CACHE SERVE ==========
+
+typedef struct {
+ uint8_t activate;
+} cache_serve_command;
+
+// SIZE=1
+
+//========== [09] SET STRATEGY ==========
+
+typedef enum {
+ SET_STRATEGY_LOADBALANCER,
+ SET_STRATEGY_RANDOM,
+ SET_STRATEGY_RANDOM_PER_DASH_SEGMENT,
+ SET_STRATEGY_LOADBALANCER_WITH_DELAY,
+ SET_STRATEGY_LOADBALANCER_BY_RATE,
+ SET_STRATEGY_LOADBALANCER_BEST_ROUTE,
+ LAST_STRATEGY_VALUE
+} strategy_type;
+
+typedef struct {
+ union commandAddr address;
+ uint8_t strategyType;
+ uint8_t addressType;
+ uint8_t len;
+} set_strategy_command;
+
+// SIZE=20
+
+//========== [11] SET WLDR ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ uint8_t activate;
+} set_wldr_command;
+
+// SIZE=17
+
+//========== [12] ADD PUNTING ==========
+
+typedef struct {
+ char symbolicOrConnid[16];
+ union commandAddr address;
+ uint8_t addressType;
+ uint8_t len;
+} add_punting_command;
+
+// SIZE=36
+
+//========== [13] LIST LISTENER ==========
+
+typedef struct {
+ union commandAddr address;
+ uint32_t connid;
+ uint16_t port;
+ uint8_t addressType;
+ uint8_t encapType;
+} list_listeners_command;
+
+// SIZE=24
+
+//========== [14] MAPME ==========
+
+// (enable/discovery/timescale/retx)
+
+typedef struct {
+ uint8_t activate;
+} mapme_activator_command;
+
+// SIZE=1
+
+typedef struct {
+ uint32_t timePeriod;
+} mapme_timing_command;
+
+// SIZE=1
+
+#endif
diff --git a/hicn-light/src/utils/interface.c b/hicn-light/src/utils/interface.c
new file mode 100755
index 000000000..ab7a88f0f
--- /dev/null
+++ b/hicn-light/src/utils/interface.c
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#include <src/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_BufferComposer.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <src/utils/addressList.h>
+#include <src/utils/interface.h>
+
+#include <parc/assert/parc_Assert.h>
+#include <src/utils/commands.h>
+
+struct interface {
+ char *name;
+ unsigned interfaceIndex;
+ bool loopback;
+ bool supportMulticast;
+ unsigned mtu;
+
+ AddressList *addressList;
+};
+
+char *interfaceToString(const Interface *interface) {
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ parcBufferComposer_Format(
+ composer, "%3u %10s %1s%1s %8u ", interface->interfaceIndex,
+ interface->name, interface->loopback ? "l" : " ",
+ interface->supportMulticast ? "m" : " ", interface->mtu);
+
+ for (size_t i = 0; i < addressListLength(interface->addressList); i++) {
+ addressBuildString(addressListGetItem(interface->addressList, i), composer);
+ if (i < (addressListLength(interface->addressList) - 1)) {
+ parcBufferComposer_PutStrings(composer, "\n", NULL);
+ }
+ }
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+ return result;
+}
+
+Interface *interfaceCreate(const char *name, unsigned interfaceIndex,
+ bool loopback, bool supportMulticast, unsigned mtu) {
+ Interface *iface = parcMemory_AllocateAndClear(sizeof(Interface));
+
+ parcAssertNotNull(iface, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(Interface));
+ iface->name = parcMemory_StringDuplicate(name, 64);
+ iface->interfaceIndex = interfaceIndex;
+ iface->loopback = loopback;
+ iface->supportMulticast = supportMulticast;
+ iface->mtu = mtu;
+ iface->addressList = addressListCreate();
+
+ return iface;
+}
+
+void interfaceDestroy(Interface **interfacePtr) {
+ parcAssertNotNull(interfacePtr, "Parameter must be non-null double pointer");
+ parcAssertNotNull(*interfacePtr,
+ "Parameter must dereference to non-null pointer");
+
+ Interface *iface = *interfacePtr;
+ parcMemory_Deallocate((void **)&iface->name);
+ addressListDestroy(&iface->addressList);
+ parcMemory_Deallocate((void **)&iface);
+ interfacePtr = NULL;
+}
+
+void interfaceAddAddress(Interface *iface, Address *address) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+
+ size_t length = addressListLength(iface->addressList);
+ for (size_t i = 0; i < length; i++) {
+ const Address *a = addressListGetItem(iface->addressList, i);
+ if (addressEquals(a, address)) {
+ return;
+ }
+ }
+
+ addressListAppend(iface->addressList, address);
+}
+
+const AddressList *interfaceGetAddresses(const Interface *iface) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+ return iface->addressList;
+}
+
+unsigned interfaceGetInterfaceIndex(const Interface *iface) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+ return iface->interfaceIndex;
+}
+
+bool interfaceNameEquals(const Interface *iface, const char *name) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+
+ if (strcasecmp(iface->name, name) == 0) {
+ return true;
+ }
+ return false;
+}
+
+bool interfaceEquals(const Interface *a, const Interface *b) {
+ if (a == NULL && b == NULL) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ if (a->interfaceIndex == b->interfaceIndex) {
+ if (a->loopback == b->loopback) {
+ if (a->supportMulticast == b->supportMulticast) {
+ if (a->mtu == b->mtu) {
+ if (strcasecmp(a->name, b->name) == 0) {
+ if (addressListEquals(a->addressList, b->addressList)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// static const char light_Iface[] = "Interface";
+// static const char light_IfName[] = "Name";
+// static const char light_IFIDX[] = "Index";
+// static const char light_IsLoopback[] = "Loopback";
+// static const char light_Multicast[] = "Multicast";
+// static const char light_MTU[] = "MTU";
+
+// static const char light_True[] = "true";
+// static const char light_False[] = "false";
+// static const char light_Addrs[] = "Addrs";
+
+const char *interfaceGetName(const Interface *iface) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+ return iface->name;
+}
+
+unsigned interfaceGetMTU(const Interface *iface) {
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+ return iface->mtu;
+}
diff --git a/hicn-light/src/utils/interface.h b/hicn-light/src/utils/interface.h
new file mode 100755
index 000000000..0810ec053
--- /dev/null
+++ b/hicn-light/src/utils/interface.h
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief <#Brief Description#>
+ *
+ * <#Detailed Description#>
+ *
+ */
+#ifndef interface_h
+#define interface_h
+
+#include <src/utils/address.h>
+#include <src/utils/addressList.h>
+
+struct interface;
+typedef struct interface Interface;
+
+/**
+ * Creates a representation of an interface
+ *
+ * The name is copied. Creates a representation of a system interface.
+ *
+ * @param <#param1#>
+ * @return An allocated object, you must call <code>interfaceDestroy()</code>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+Interface *interfaceCreate(const char *name, unsigned interfaceIndex,
+ bool loopback, bool supportMulticast, unsigned mtu);
+
+void interfaceDestroy(Interface **interfacePtr);
+
+/**
+ * Adds an address to an interface
+ *
+ * Does not allow duplicates, if already exists is not added again
+ *
+ * @param <#param1#>
+ * @return <#return#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void interfaceAddAddress(Interface *iface, Address *address);
+
+/**
+ * Retrieves a list of interface addresses
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return Will not be NULL, but may be empty
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+const AddressList *interfaceGetAddresses(const Interface *iface);
+
+/**
+ * The interface index
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return <#return#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+unsigned interfaceGetInterfaceIndex(const Interface *iface);
+
+/**
+ * Returns the interface name, e.g. "eth0"
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] iface An allocated Interface
+ *
+ * @return non-null The interface Name as a C-string
+ * @return null An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+const char *interfaceGetName(const Interface *iface);
+
+/**
+ * Returns the Maximum Transmission Unit (MTU) of the interface
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] iface An allocated Interface
+ *
+ * @return number The MTU as reported by the kernel
+ *
+ * Example:
+ * @code
+ * {
+ * <#example#>
+ * }
+ * @endcode
+ */
+unsigned interfaceGetMTU(const Interface *iface);
+
+/**
+ * Determine if two InterfaceName instances are equal.
+ *
+ *
+ * The following equivalence relations on non-null `InterfaceName` instances are
+ * maintained:
+ *
+ * * It is reflexive: for any non-null reference value x,
+ * `InterfaceName_Equals(x, x)` must return true.
+ *
+ * * It is symmetric: for any non-null reference values x and y,
+ * `InterfaceName_Equals(x, y)` must return true if and only if
+ * `InterfaceName_Equals(y, x)` returns true.
+ *
+ * * It is transitive: for any non-null reference values x, y, and z, if
+ * `InterfaceName_Equals(x, y)` returns true and
+ * `InterfaceName_Equals(y, z)` returns true,
+ * then `InterfaceName_Equals(x, z)` must return true.
+ *
+ * * It is consistent: for any non-null reference values x and y, multiple
+ * invocations of `InterfaceName_Equals(x, y)` consistently return true or
+ * consistently return false.
+ *
+ * * For any non-null reference value x, `InterfaceName_Equals(x, NULL)` must
+ * return false.
+ *
+ * @param a A pointer to a `InterfaceName` instance.
+ * @param b A pointer to a `InterfaceName` instance.
+ * @return true if the two `InterfaceName` instances are equal.
+ *
+ * Example:
+ * @code
+ * {
+ * InterfaceName *a = InterfaceName_Create();
+ * InterfaceName *b = InterfaceName_Create();
+ *
+ * if (InterfaceName_Equals(a, b)) {
+ * // true
+ * } else {
+ * // false
+ * }
+ * }
+ * @endcode
+ */
+bool interfaceNameEquals(const Interface *iface, const char *name);
+
+/**
+ * Two Interfaces are idential
+ *
+ * All properties must be the same. The order of addresses matters, and
+ * they must have been added to the address list in the same order.
+ *
+ * The interface name match is case in-sensitive.
+ *
+ * @param <#param1#>
+ * @return <#return#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool interfaceEquals(const Interface *a, const Interface *b);
+
+/**
+ * <#OneLineDescription#>
+ *
+ * <#Discussion#>
+ *
+ * @param interface A Interface structure pointer.
+ * @return An allocate string representation of the Interface that must be freed
+ * via parcMemory_Deallocate().
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+char *interfaceToString(const Interface *interface);
+#endif // interface_h
diff --git a/hicn-light/src/utils/interfaceSet.c b/hicn-light/src/utils/interfaceSet.c
new file mode 100755
index 000000000..3f56ec167
--- /dev/null
+++ b/hicn-light/src/utils/interfaceSet.c
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#include <src/config.h>
+#include <stdio.h>
+
+#include <src/utils/interfaceSet.h>
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_Memory.h>
+
+#include <parc/assert/parc_Assert.h>
+
+struct interfaceSet {
+ PARCArrayList *listOfInterfaces;
+};
+
+static void _destroyInterface(void **ifaceVoidPtr) {
+ interfaceDestroy((Interface **)ifaceVoidPtr);
+}
+
+InterfaceSet *interfaceSetCreate(void) {
+ InterfaceSet *set = parcMemory_AllocateAndClear(sizeof(InterfaceSet));
+ parcAssertNotNull(set, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(InterfaceSet));
+ set->listOfInterfaces = parcArrayList_Create(_destroyInterface);
+ return set;
+}
+
+void interfaceSetDestroy(InterfaceSet **setPtr) {
+ parcAssertNotNull(setPtr, "Parameter must be non-null double pointer");
+ parcAssertNotNull(*setPtr, "Parameter must dereference to non-null pointer");
+
+ InterfaceSet *set = *setPtr;
+ parcArrayList_Destroy(&set->listOfInterfaces);
+ parcMemory_Deallocate((void **)&set);
+ *setPtr = NULL;
+}
+
+bool interfaceSetAdd(InterfaceSet *set, Interface *iface) {
+ parcAssertNotNull(set, "Parameter set must be non-null");
+ parcAssertNotNull(iface, "Parameter iface must be non-null");
+
+ unsigned ifaceIndex = interfaceGetInterfaceIndex(iface);
+ size_t length = parcArrayList_Size(set->listOfInterfaces);
+ for (size_t i = 0; i < length; i++) {
+ Interface *listEntry =
+ (Interface *)parcArrayList_Get(set->listOfInterfaces, i);
+ unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry);
+ if (entryInterfaceIndex == ifaceIndex) {
+ return false;
+ }
+ }
+
+ parcArrayList_Add(set->listOfInterfaces, (PARCObject *)iface);
+ return true;
+}
+
+size_t interfaceSetLength(const InterfaceSet *set) {
+ parcAssertNotNull(set, "Parameter set must be non-null");
+ return parcArrayList_Size(set->listOfInterfaces);
+}
+
+Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set,
+ size_t ordinalIndex) {
+ parcAssertNotNull(set, "Parameter set must be non-null");
+ return (Interface *)parcArrayList_Get(set->listOfInterfaces, ordinalIndex);
+}
+
+Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set,
+ unsigned interfaceIndex) {
+ size_t length = parcArrayList_Size(set->listOfInterfaces);
+ for (size_t i = 0; i < length; i++) {
+ Interface *listEntry =
+ (Interface *)parcArrayList_Get(set->listOfInterfaces, i);
+ unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry);
+ if (entryInterfaceIndex == interfaceIndex) {
+ return listEntry;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Uses the system name (e.g. "en0")
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return NULL if not found
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+Interface *interfaceSetGetByName(InterfaceSet *set, const char *name) {
+ size_t length = parcArrayList_Size(set->listOfInterfaces);
+ for (size_t i = 0; i < length; i++) {
+ Interface *listEntry =
+ (Interface *)parcArrayList_Get(set->listOfInterfaces, i);
+ if (interfaceNameEquals(listEntry, name)) {
+ return listEntry;
+ }
+ }
+ return NULL;
+}
+
+bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b) {
+ if (a == NULL && b == NULL) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ size_t length_a = parcArrayList_Size(a->listOfInterfaces);
+ size_t length_b = parcArrayList_Size(b->listOfInterfaces);
+
+ if (length_a == length_b) {
+ for (size_t i = 0; i < length_a; i++) {
+ Interface *iface_a =
+ (Interface *)parcArrayList_Get(a->listOfInterfaces, i);
+
+ // the set is unique by interface id, so if it exists in set b, it
+ // exists there by interface id
+ Interface *iface_b = interfaceSetGetByInterfaceIndex(
+ b, interfaceGetInterfaceIndex(iface_a));
+ if (!interfaceEquals(iface_b, iface_b)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/hicn-light/src/utils/interfaceSet.h b/hicn-light/src/utils/interfaceSet.h
new file mode 100755
index 000000000..8eb8397fb
--- /dev/null
+++ b/hicn-light/src/utils/interfaceSet.h
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief <#Brief Description#>
+ *
+ * <#Detailed Description#>
+ *
+ */
+#ifndef InterfaceSet_h
+#define InterfaceSet_h
+
+#include <src/utils/interface.h>
+
+struct interfaceSet;
+/**
+ *
+ * @see interfaceSetCreate
+ */
+typedef struct interfaceSet InterfaceSet;
+
+/**
+ * <#One Line Description#>
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ *
+ * @see <#references#>
+ */
+InterfaceSet *interfaceSetCreate(void);
+
+/**
+ * <#One Line Description#>
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ *
+ * @see <#references#>
+ */
+void interfaceSetDestroy(InterfaceSet **setPtr);
+
+/**
+ * Adds interface to set, does not allow duplicates
+ *
+ * Takes ownership of the iface memory if added
+ *
+ * Duplicates are two entries with the same interface index
+ *
+ * @param <#param1#>
+ * @return true if added, false if not (likely a duplicate)
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool interfaceSetAdd(InterfaceSet *set, Interface *iface);
+
+/**
+ * The number of interfaces in the set
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return <#return#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t interfaceSetLength(const InterfaceSet *set);
+
+/**
+ * Uses the ordinal index of the interface in the Set
+ *
+ * Ranges from 0 .. <code>interfaceSetLength()-1</code>.
+ *
+ * @param <#param1#>
+ * @return NULL if not found
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set,
+ size_t ordinalIndex);
+
+/**
+ * Retreives by the assigned interface index
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return NULL if not found
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set,
+ unsigned interfaceIndex);
+
+/**
+ * Uses the system name (e.g. "en0")
+ *
+ * <#Discussion#>
+ *
+ * @param <#param1#>
+ * @return NULL if not found
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+Interface *interfaceSetGetByName(InterfaceSet *set, const char *name);
+
+/**
+ * Determine if two InterfaceSet instances are equal.
+ *
+ * Two InterfaceSet instances are equal if, and only if, the sets contain the
+ * same elements
+ * - order independent.
+ * Each element is compared via <code>interfaceEquals()</code>
+ *
+ * The following equivalence relations on non-null `InterfaceSet` instances are
+ * maintained:
+ *
+ * * It is reflexive: for any non-null reference value x,
+ * `InterfaceSet_Equals(x, x)` must return true.
+ *
+ * * It is symmetric: for any non-null reference values x and y,
+ * `InterfaceSet_Equals(x, y)` must return true if and only if
+ * `interfaceSetEquals(y, x)` returns true.
+ *
+ * * It is transitive: for any non-null reference values x, y, and z, if
+ * `interfaceSetEquals(x, y)` returns true and
+ * `interfaceSetEquals(y, z)` returns true,
+ * then `interfaceSetEquals(x, z)` must return true.
+ *
+ * * It is consistent: for any non-null reference values x and y, multiple
+ * invocations of `interfaceSetEquals(x, y)` consistently return true or
+ * consistently return false.
+ *
+ * * For any non-null reference value x, `interfaceSetEquals(x, NULL)` must
+ * return false.
+ *
+ * @param a A pointer to a `InterfaceSet` instance.
+ * @param b A pointer to a `InterfaceSet` instance.
+ * @return true if the two `InterfaceSet` instances are equal.
+ *
+ * Example:
+ * @code
+ * {
+ * InterfaceSet *a = interfaceSetCreate();
+ * InterfaceSet *b = interfaceSetCreate();
+ *
+ * if (interfaceSetEquals(a, b)) {
+ * // true
+ * } else {
+ * // false
+ * }
+ * }
+ * @endcode
+ */
+bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b);
+#endif // InterfaceSet_h
diff --git a/hicn-light/src/utils/punting.c b/hicn-light/src/utils/punting.c
new file mode 100755
index 000000000..9352732fe
--- /dev/null
+++ b/hicn-light/src/utils/punting.c
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include <src/config.h>
+#include <stdio.h>
+
+#include <parc/assert/parc_Assert.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <src/utils/punting.h>
+
+struct punting {
+ char *symbolic;
+ Address *prefix;
+ uint32_t len;
+};
+
+Punting *puntingCreate(const char *listenerName, Address *prefix,
+ uint32_t len) {
+ parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
+ parcAssertNotNull(prefix, "Parameter prefix must be non-null");
+
+ Punting *punting = parcMemory_AllocateAndClear(sizeof(Punting));
+ if (punting) {
+ punting->symbolic =
+ parcMemory_StringDuplicate(listenerName, strlen(listenerName));
+ punting->prefix = addressCopy(prefix);
+ punting->len = len;
+ }
+
+ return punting;
+}
+
+void puntingRelease(Punting **puntingPtr) {
+ parcAssertNotNull(puntingPtr,
+ "Parameter puntingPtr must be non-null double pointer");
+ parcAssertNotNull(*puntingPtr,
+ "Parameter puntingPtr dereference to non-null pointer");
+
+ Punting *punting = *puntingPtr;
+
+ if (punting->symbolic) {
+ parcMemory_Deallocate((void **)&punting->symbolic);
+ }
+
+ if (punting->prefix) {
+ addressDestroy(&punting->prefix);
+ }
+
+ parcMemory_Deallocate((void **)&punting);
+ *puntingPtr = NULL;
+}
+
+bool puntingEquals(const Punting *a, const Punting *b) {
+ if ((a == NULL && b == NULL) || a == b) {
+ // both null or identically equal
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ // only one is null
+ return false;
+ }
+
+ if ((strcmp(a->symbolic, b->symbolic) == 0) &&
+ (addressEquals(a->prefix, b->prefix)) && (a->len == b->len)) {
+ return true;
+ }
+
+ return false;
+}
+
+const char *puntingGetSymbolicName(const Punting *punting) {
+ parcAssertNotNull(punting, "Parameter listener must be non-null");
+ return punting->symbolic;
+}
+
+Address *puntingGetAddress(const Punting *punting) {
+ parcAssertNotNull(punting, "Parameter listener must be non-null");
+ return punting->prefix;
+}
+
+uint32_t puntingPrefixLen(const Punting *punting) {
+ parcAssertNotNull(punting, "Parameter listener must be non-null");
+ return punting->len;
+}
diff --git a/hicn-light/src/utils/punting.h b/hicn-light/src/utils/punting.h
new file mode 100755
index 000000000..03841c5ad
--- /dev/null
+++ b/hicn-light/src/utils/punting.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef punting_h
+#define punting_h
+
+struct punting;
+typedef struct punting Punting;
+
+#include <src/utils/address.h>
+
+/**
+ * Creates a Punting object
+ *
+ * The symbolic name represents this listener and may be used by other commands.
+ * It must be unique, otherwise the command will fail when sent to the
+ * forwarder.
+ *
+ * @param [in] symbolic name of the listener
+ * @param [in] prefix address to add to the punting rule
+ * @param [in] len prefix length
+ *
+ * @return non-null An Allocated object
+ * @return null An error
+ *
+ */
+Punting *puntingCreate(const char *symbolic, Address *prefix, uint32_t len);
+
+/**
+ * Releases a reference count to the object
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in,out] etherConnPtr A pointer to an etherConn object, will be
+ * null'd.
+ *
+ */
+void puntingRelease(Punting **puntingPtr);
+
+/**
+ * Determine if two light Punting are equal.
+ *
+ */
+
+bool puntingEquals(const Punting *a, const Punting *b);
+
+/**
+ * Returns the symbolic name
+ *
+ */
+const char *puntingGetSymbolicName(const Punting *punting);
+
+/**
+ * Returns the address (INET or INET6 ip address)
+ *
+ */
+Address *puntingGetAddress(const Punting *punting);
+
+uint32_t puntingPrefixLen(const Punting *punting);
+#endif // punting_h
diff --git a/hicn-light/src/utils/utils.c b/hicn-light/src/utils/utils.c
new file mode 100755
index 000000000..a41478a4b
--- /dev/null
+++ b/hicn-light/src/utils/utils.c
@@ -0,0 +1,258 @@
+// Utility function for commands
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Network.h>
+#include <parc/assert/parc_Assert.h>
+#include <src/utils/utils.h>
+
+// This is the unique sequence number used by all messages and its thread locks
+static pthread_mutex_t nextSequenceNumberMutex = PTHREAD_MUTEX_INITIALIZER;
+static uint32_t nextSequenceNumber = 1;
+
+uint32_t utils_GetNextSequenceNumber(void) {
+ uint32_t seqnum;
+
+ int result = pthread_mutex_lock(&nextSequenceNumberMutex);
+ parcAssertTrue(result == 0, "Got error from pthread_mutex_lock: %d", result);
+
+ seqnum = nextSequenceNumber++;
+
+ result = pthread_mutex_unlock(&nextSequenceNumberMutex);
+ parcAssertTrue(result == 0, "Got error from pthread_mutex_unlock: %d",
+ result);
+
+ return seqnum;
+}
+
+/**
+ * Return true if string is purely an integer
+ */
+bool utils_IsNumber(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.
+ */
+bool utils_ValidateSymbolicName(const char *symbolic) {
+ bool success = false;
+ size_t len = strlen(symbolic);
+ if (len > 0) {
+ if (isalpha(symbolic[0])) {
+ success = true;
+ for (size_t i = 1; i < len; i++) {
+ if (!isalnum(symbolic[i])) {
+ success = false;
+ break;
+ }
+ }
+ }
+ }
+ return success;
+}
+
+Address *utils_AddressFromInet(in_addr_t *addr4, in_port_t *port) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = *port;
+ addr.sin_addr.s_addr = *addr4;
+
+ Address *result = addressCreateFromInet(&addr);
+ return result;
+}
+
+Address *utils_AddressFromInet6(struct in6_addr *addr6, in_port_t *port) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = *port;
+ addr.sin6_addr = *addr6;
+ addr.sin6_scope_id = 0;
+ // Other 2 fields: scope_id and flowinfo, do not know what to put inside.
+
+ Address *result = addressCreateFromInet6(&addr);
+ return result;
+}
+
+struct iovec *utils_CreateAck(header_control_message *header, void *payload,
+ size_t payloadLen) {
+ struct iovec *response =
+ parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+
+ header->messageType = ACK_LIGHT;
+
+ response[0].iov_base = header;
+ response[0].iov_len = sizeof(header_control_message);
+ response[1].iov_base = payload;
+ response[1].iov_len = payloadLen;
+
+ return response;
+}
+
+struct iovec *utils_CreateNack(header_control_message *header, void *payload,
+ size_t payloadLen) {
+ struct iovec *response =
+ parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+
+ header->messageType = NACK_LIGHT;
+
+ response[0].iov_base = header;
+ response[0].iov_len = sizeof(header_control_message);
+ response[1].iov_base = payload;
+ response[1].iov_len = payloadLen;
+
+ return response;
+}
+
+char *utils_BuildStringFromInet(in_addr_t *addr4, in_port_t *port) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = *port;
+ addr.sin_addr.s_addr = *addr4;
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
+ parcNetwork_SockInet4Address_BuildString(&addr, composer));
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+ return result;
+}
+
+char *utils_BuildStringFromInet6(struct in6_addr *addr6, in_port_t *port) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = *port;
+ addr.sin6_addr = *addr6;
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
+ parcNetwork_SockInet6Address_BuildString(&addr, composer));
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+ return result;
+}
+
+char *utils_CommandAddressToString(address_type addressType,
+ union commandAddr *address,
+ in_port_t *port) {
+ char *result;
+
+ switch (addressType) {
+ case ADDR_INET: {
+ result = utils_BuildStringFromInet(&address->ipv4, port);
+ break;
+ }
+
+ case ADDR_INET6: {
+ result = utils_BuildStringFromInet6(&address->ipv6, port);
+ break;
+ }
+
+ default: {
+ char *addrStr = (char *)parcMemory_Allocate(sizeof(char) * 32);
+ sprintf(addrStr, "Error: UNKNOWN address type = %d", addressType);
+ result = addrStr;
+ break;
+ }
+ }
+ return result;
+}
+
+struct iovec *utils_SendRequest(ControlState *state, command_id command,
+ void *payload, size_t payloadLen) {
+ bool success = false;
+
+ // get sequence number for the header
+ uint32_t currentSeqNum = utils_GetNextSequenceNumber();
+
+ // Allocate and fill the header
+ header_control_message *headerControlMessage =
+ parcMemory_AllocateAndClear(sizeof(header_control_message));
+ headerControlMessage->messageType = REQUEST_LIGHT;
+ headerControlMessage->commandID = command;
+ headerControlMessage->seqNum = currentSeqNum;
+ if (payloadLen > 0) {
+ headerControlMessage->length = 1;
+ }
+
+ struct iovec msg[2];
+ msg[0].iov_base = headerControlMessage;
+ msg[0].iov_len = sizeof(header_control_message);
+ msg[1].iov_base = payload;
+ msg[1].iov_len = payloadLen;
+
+ struct iovec *response = controlState_WriteRead(state, msg);
+
+ header_control_message *receivedHeader =
+ (header_control_message *)response[0].iov_base;
+ if (receivedHeader->seqNum != currentSeqNum) {
+ printf("Seq number is NOT correct: expected %d got %d \n", currentSeqNum,
+ receivedHeader->seqNum);
+ // failure
+ } else {
+ if (receivedHeader->messageType == RESPONSE_LIGHT) {
+ return response; // command needs both payload and header
+ } else {
+ if (receivedHeader->messageType == ACK_LIGHT) {
+ success = true;
+ } else if (receivedHeader->messageType == NACK_LIGHT) {
+ success = true;
+ } else {
+ printf("Error: unrecognized message type"); // failure
+ }
+ }
+ }
+
+ // deallocate when payload & header of the response are not needed
+ if (receivedHeader->length > 0) {
+ parcMemory_Deallocate(&response[1].iov_base); // free received payload
+ }
+ parcMemory_Deallocate(&response[0].iov_base); // free receivedHeader
+
+ // return response
+ if (success) {
+ return response;
+ } else {
+ parcMemory_Deallocate(&response); // free iovec pointer
+ return NULL; // will generate a failure
+ }
+}
+
+const char *utils_PrefixLenToString(address_type addressType,
+ union commandAddr *address,
+ uint8_t *prefixLen) {
+ char len[4]; // max size + 1
+ sprintf(len, "%u", (unsigned)*prefixLen);
+ in_port_t port = htons(1234); // this is a random port number that is ignored
+
+ char *prefix = utils_CommandAddressToString(addressType, address, &port);
+ char *prefixStr = malloc(strlen(prefix) + strlen(len) + 2);
+ strcpy(prefixStr, prefix);
+ strcat(prefixStr, "/");
+ strcat(prefixStr, len);
+
+ free(prefix);
+
+ return prefixStr;
+}
diff --git a/hicn-light/src/utils/utils.h b/hicn-light/src/utils/utils.h
new file mode 100755
index 000000000..1d2616941
--- /dev/null
+++ b/hicn-light/src/utils/utils.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef utils_h
+#define utils_h
+
+#include <src/config/controlState.h>
+#include <src/utils/address.h>
+#include <src/utils/commands.h>
+
+/**
+ * Return true if string is purely an integer
+ */
+bool utils_IsNumber(const char *string);
+
+/**
+ * A symbolic name must be at least 1 character and must begin with an alpha.
+ * The remainder must be an alphanum.
+ */
+bool utils_ValidateSymbolicName(const char *symbolic);
+
+/**
+ * Convert an internet address family (IPv4) to the address format used by the
+ * Fwd
+ */
+Address *utils_AddressFromInet(in_addr_t *addr4, in_port_t *port);
+
+/**
+ * Convert an internet address family (IPv6) to the address format used by the
+ * Fwd
+ */
+Address *utils_AddressFromInet6(struct in6_addr *addr6, in_port_t *port);
+
+/**
+ *Create an Ack message instance as a response of a control successfully
+ *completed.
+ */
+struct iovec *utils_CreateAck(header_control_message *header, void *payload,
+ size_t payloadLen);
+
+/**
+ *Create a Nack message instance as a response of a control unsuccessfully
+ *completed.
+ */
+struct iovec *utils_CreateNack(header_control_message *header, void *payload,
+ size_t payloadLen);
+
+/**
+ *Convert IPv4/IPv6 address from binary to text string. `uint8_t *ipAddress` has
+ *to be a `in_addr_t * or `a struct in6_addr *.
+ */
+char *utils_CommandAddressToString(address_type addressType,
+ union commandAddr *address, in_port_t *port);
+
+/**
+ *Given a command payload, it generates the header and send the request to the
+ *deamon.
+ */
+struct iovec *utils_SendRequest(ControlState *state, command_id command,
+ void *payload, size_t payloadLen);
+
+/**
+ *Convert a IPv4/IPv6 address plus Netmask len from binary to text string in the
+ *form [add]:[port]/[len].
+ */
+const char *utils_PrefixLenToString(address_type addressType,
+ union commandAddr *address,
+ uint8_t *prefixLen);
+
+#endif \ No newline at end of file