aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/CMakeLists.txt50
-rwxr-xr-xlib/README.md114
-rwxr-xr-xlib/doc/CMakeLists.txt23
-rwxr-xr-xlib/doc/Doxyfile.in12
-rwxr-xr-xlib/src/CMakeLists.txt81
-rwxr-xr-xlib/src/base.h136
-rwxr-xr-xlib/src/common.c165
-rwxr-xr-xlib/src/common.h231
-rwxr-xr-xlib/src/compat.c1177
-rwxr-xr-xlib/src/compat.h462
-rwxr-xr-xlib/src/error.c35
-rwxr-xr-xlib/src/error.h58
-rwxr-xr-xlib/src/header.h105
-rwxr-xr-xlib/src/hicn.h79
-rwxr-xr-xlib/src/mapme.c224
-rwxr-xr-xlib/src/mapme.h152
-rwxr-xr-xlib/src/name.c676
-rwxr-xr-xlib/src/name.h336
-rwxr-xr-xlib/src/ops.c93
-rwxr-xr-xlib/src/ops.h624
-rwxr-xr-xlib/src/protocol.h51
-rwxr-xr-xlib/src/protocol/ah.c211
-rwxr-xr-xlib/src/protocol/ah.h72
-rwxr-xr-xlib/src/protocol/icmp.c229
-rwxr-xr-xlib/src/protocol/icmp.h68
-rwxr-xr-xlib/src/protocol/icmprd.h47
-rwxr-xr-xlib/src/protocol/ipv4.c452
-rwxr-xr-xlib/src/protocol/ipv4.h91
-rwxr-xr-xlib/src/protocol/ipv6.c412
-rwxr-xr-xlib/src/protocol/ipv6.h67
-rwxr-xr-xlib/src/protocol/tcp.c370
-rwxr-xr-xlib/src/protocol/tcp.h166
-rwxr-xr-xlib/src/protocol/udp.h37
33 files changed, 7106 insertions, 0 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100755
index 000000000..1be5e67f9
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,50 @@
+# 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)
+project(Hicn C)
+include(CTest)
+
+set(CMAKE_MODULE_PATH
+ ${CMAKE_MODULE_PATH}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+)
+
+if (NOT CMAKE_BUILD_TYPE)
+ message(STATUS "No build type selected, default to Release")
+ set(CMAKE_BUILD_TYPE "Release")
+endif()
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ set(LIBHICN hicn)
+endif()
+
+set(CMAKE_VERSION_MAJOR 0)
+set(CMAKE_VERSION_MINOR 1)
+set(CMAKE_VERSION_PATCH 1)
+
+option(CMAKE_BUILD_TEST "Build unit tests" OFF)
+
+if (NOT CMAKE_BUILD_TYPE)
+ message(STATUS "No build type selected, default to Release")
+ set(CMAKE_BUILD_TYPE "Release")
+endif()
+
+set(CMAKE_C_FLAGS -Wall)
+
+if (ANDROID_API)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS} -std=c99")
+endif ()
+
+add_subdirectory (src)
diff --git a/lib/README.md b/lib/README.md
new file mode 100755
index 000000000..6dac988db
--- /dev/null
+++ b/lib/README.md
@@ -0,0 +1,114 @@
+# libhicn
+
+## Introduction
+
+libhicn provides a support library coded in C designed to help developers embed
+Hybrid ICN (hICN) functionalities in their applications (eg. forwarder, socket
+API, etc.). Its purpose is to follow the hICN specification for which it
+provides a reference implementation, abstracting the user from all internal
+mechanisms, and offering an API independent of the packet format (eg. IPv4 or
+IPv6). The library is designed to be portable across both desktop and
+mobile platforms, and we currently aim at supporting Linux, Android, OSX and
+iOS, by writing the necessary adapters to realize hICN functionality in
+userspace according to the available APIs and permissions that each system
+offers.
+
+The library consists in several layers:
+- the core library (hicn.h) provides a standard hICN packet format, as well as
+an API allowing manipulation of packet headers;
+- an hICN helper, allowing an hICN stack to be built in userspace in a portable
+way, based on TUN devices and accessible though file descriptors;
+- a network layer allow the sending an receiving of hICN packets on those file
+descriptors, implementing both source and destination address translation as
+required by the hICN mechanisms;
+- finally, a "transport" API allows the forging of dummy interest and data
+packets.
+
+A commandline interface (hicnc) is also provided that uses the library and can
+for instance be used as a test traffic generator. This interface can be run as
+either a consumer, a producer, or a simple forwarder.
+
+## Folder content
+
+CMakeLists.txt CMkake global build file
+doc Package documentation
+README.md This file
+src
+ base.h Base definitions for hICN implementation
+ CMakeLists.txt CMake library build file
+ common.{h,c} Harmonization layer across supported platforms
+ compat.{h,c} Compatibility layer for former API
+ error.{h,c} Error management files
+ header.h hICN header definitions
+ hicn.h Master include file
+ mapme.{h,c} MAP-Me : anchorless producer mobility mechanisms
+ name.{h,c} hICN naming conventions and name processing + IP helpers
+ ops.{h,c} Protocol-independent hICN operations
+ protocol/* Protocol headers + protocol-dependent implementations
+ protocol.h Common file for protocols
+
+## Using libhicn
+
+### Platforms ###
+
+libhicn has been tested in:
+
+- Ubuntu 16.04 LTS (x86_64)
+- Ubuntu 18.04 LTS (x86_64)
+- Debian Stable/Testing
+- Red Hat Enterprise Linux 7
+- CentOS 7
+- Android 8
+- iOS 12
+- macOS 10.12
+- Windows 10
+
+Other platforms and architectures may work.
+
+### Dependencies
+
+Build dependencies:
+
+- c11 ( clang / gcc )
+- CMake 3.4
+
+Basic dependencies: None
+
+## Installation
+
+You can either use released packages, or compile libhicn from sources.
+
+### Release mode
+
+mkdir build
+cd build
+cmake ..
+make
+sudo make install
+
+### Debug mode
+
+mkdir debug
+cd debug
+cmake .. -DCMAKE_BUILD_TYPE=Debug
+make
+sudo make install
+
+## License
+
+This software is distributed under the following license:
+
+```
+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.
+```
diff --git a/lib/doc/CMakeLists.txt b/lib/doc/CMakeLists.txt
new file mode 100755
index 000000000..cf022dc52
--- /dev/null
+++ b/lib/doc/CMakeLists.txt
@@ -0,0 +1,23 @@
+# add a target to generate API documentation with Doxygen
+find_package(Doxygen)
+option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND})
+
+if(BUILD_DOCUMENTATION)
+ if(NOT DOXYGEN_FOUND)
+ message(FATAL_ERROR "Doxygen is needed to build the documentation.")
+ endif()
+
+ set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
+ set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+ configure_file(${doxyfile_in} ${doxyfile} @ONLY)
+
+ add_custom_target(doc
+ COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating API documentation with Doxygen"
+ VERBATIM)
+
+# FIXME MS : wrong install path
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc)
+endif()
diff --git a/lib/doc/Doxyfile.in b/lib/doc/Doxyfile.in
new file mode 100755
index 000000000..839de9f8a
--- /dev/null
+++ b/lib/doc/Doxyfile.in
@@ -0,0 +1,12 @@
+PROJECT_NAME = "Hybrid ICN (hICN)"
+PROJECT_NUMBER = v@CMAKE_VERSION_MAJOR@.@CMAKE_VERSION_MINOR@.@CMAKE_VERSION_PATCH@
+STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ \
+ @PROJECT_BINARY_DIR@
+INPUT = @doxy_main_page@ \
+ @PROJECT_SOURCE_DIR@ \
+ @PROJECT_BINARY_DIR@
+FILE_PATTERNS = *.md \
+ *.h \
+ *.cc
+RECURSIVE = YES
+USE_MDFILE_AS_MAINPAGE = ../README.md
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
new file mode 100755
index 000000000..0137a16c7
--- /dev/null
+++ b/lib/src/CMakeLists.txt
@@ -0,0 +1,81 @@
+# 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 LIBHICN_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/compat.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/header.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/name.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ops.h
+)
+
+list(APPEND LIBHICN_HEADER_FILES_PROTOCOL
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ah.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmprd.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv4.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/udp.h
+)
+
+list(APPEND LIBHICN_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/compat.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/name.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/ops.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ah.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv4.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.c
+)
+
+set (COMPILER_DEFINITIONS "-DWITH_MAPME -DWITH_MAPME_FIXES")
+
+include(BuildMacros)
+build_library(${LIBHICN}
+ SHARED STATIC
+ SOURCES ${LIBHICN_SOURCE_FILES}
+ COMPONENT libhicn
+ INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ INSTALL_ROOT_DIR hicn
+ INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL}
+)
+
+add_custom_command(TARGET hicn PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${PROJECT_BINARY_DIR}/hicn
+)
+
+add_custom_command(TARGET hicn POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/hicn/
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBHICN_HEADER_FILES} ${PROJECT_BINARY_DIR}/hicn/
+)
+
+add_custom_command(TARGET hicn POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/hicn/protocol
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBHICN_HEADER_FILES_PROTOCOL} ${PROJECT_BINARY_DIR}/hicn/protocol
+)
+
+# install(FILES ${LIBHICN_HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/hicn COMPONENT libhicn)
+# install(FILES ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/hicn/protocol COMPONENT libhicn)
diff --git a/lib/src/base.h b/lib/src/base.h
new file mode 100755
index 000000000..c1bd23aeb
--- /dev/null
+++ b/lib/src/base.h
@@ -0,0 +1,136 @@
+/*
+ * 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 base.h
+ * @brief Base hICN definitions.
+ */
+
+#ifndef HICN_BASE_H
+#define HICN_BASE_H
+
+#include "common.h"
+
+/* Default header fields */
+#define HICN_DEFAULT_TTL 254
+
+typedef u32 hicn_faceid_t;
+typedef u8 hicn_pathlabel_t;
+typedef u32 hicn_lifetime_t;
+
+#define HICN_MAX_LIFETIME HICN_MAX_LIFETIME_SCALED << HICN_MAX_LIFETIME_MULTIPLIER
+#define HICN_MAX_LIFETIME_SCALED 0xFFFF
+#define HICN_MAX_LIFETIME_MULTIPLIER 0xF /* 4 bits */
+
+/**
+ * @brief hICN packet format type
+ *
+ * The hICN type represents the sequence of protocols that we can find in packet
+ * headers. They are represented as a quartet of u8 values, correponding to
+ * IANA protocol assignment, and read from right to left. This is done to
+ * faciliate decapsulation of packet header by simple shift/mask operations.
+ *
+ * For instance, an IPv6/TCP packet will be identified as :
+ * [IPPROTO_NONE, IPPROTO_NONE, IPPROTO_TCP, IPPROTO_IPV6]
+ *
+ * We expect four elements to be sufficient for most uses, the max being
+ * currently used by an hypothetical signed MAP-Me update :
+ * [IPPROTO_ICMPRD, IPPROTO_AH, IPPROTO_ICMP, IPPROTO_IPV6]
+ */
+typedef union
+{
+ /** protocol layers representation */
+ struct
+ {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ u8 l1; /**< First layer */
+ u8 l2; /**< Second layer */
+ u8 l3; /**< Third layer */
+ u8 l4; /**< Fourth layer */
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ u8 l4; /**< Fourth layer */
+ u8 l3; /**< Third layer */
+ u8 l2; /**< Second layer */
+ u8 l1; /**< First layer */
+#else
+#error "Unsupported endianness"
+#endif
+ };
+ /** u32 representation */
+ u32 as_u32;
+} hicn_type_t;
+
+/* Common protocol layers */
+#define HICN_TYPE_IPV4_TCP (hicn_type_t) {{ .l4 = IPPROTO_NONE, .l3 = IPPROTO_NONE, .l2 = IPPROTO_TCP, .l1 = IPPROTO_IP }}
+#define HICN_TYPE_IPV4_ICMP (hicn_type_t) {{ .l4 = IPPROTO_NONE, .l3 = IPPROTO_NONE, .l2 = IPPROTO_ICMP, .l1 = IPPROTO_IP }}
+#define HICN_TYPE_IPV6_TCP (hicn_type_t) {{ .l4 = IPPROTO_NONE, .l3 = IPPROTO_NONE, .l2 = IPPROTO_TCP, .l1 = IPPROTO_IPV6 }}
+#define HICN_TYPE_IPV6_ICMP (hicn_type_t) {{ .l4 = IPPROTO_NONE, .l3 = IPPROTO_NONE, .l2 = IPPROTO_ICMPV6, .l1 = IPPROTO_IPV6 }}
+
+
+/**
+ * @brief hICN Payload type
+ *
+ * This type distinguishes several types of data packet, which can either carry
+ * content data, or Manifest
+ */
+typedef enum
+{
+ HPT_DATA = 0,
+ HPT_MANIFEST = 1,
+ HPT_UNSPEC = 999
+} hicn_payload_type_t;
+
+/**
+ * @brief Path label computations
+ *
+ * Path label is computed by accumulating the identifiers of successive output
+ * faces as a Data packet is traveling from its producer back to the consumer
+ * originating the Interest.
+ *
+ * NOTE: this computation is not (yet) part of the hICN specification.
+ */
+
+#define HICN_PATH_LABEL_MASK 0xF000 /* 1000 0000 0000 0000 */
+#define HICN_PATH_LABEL_SIZE 8
+
+/**
+ * @brief Path label update
+ * @param [in] current_label Current pathlabel
+ * @param [in] face_id The face identifier to combine into the path label
+ * @param [out] new_label Computed pathlabel
+ *
+ * This function updates the current_label based on the new face_id, and returns
+ */
+always_inline void
+update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id,
+ hicn_pathlabel_t * new_label)
+{
+ hicn_pathlabel_t pl_face_id =
+ (hicn_pathlabel_t) ((face_id & HICN_PATH_LABEL_MASK) >>
+ (16 - HICN_PATH_LABEL_SIZE));
+ *new_label =
+ ((current_label << 1) | (current_label >> (HICN_PATH_LABEL_SIZE - 1))) ^
+ pl_face_id;
+}
+
+#endif /* HICN_BASE_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/common.c b/lib/src/common.c
new file mode 100755
index 000000000..4b7c4a2a7
--- /dev/null
+++ b/lib/src/common.c
@@ -0,0 +1,165 @@
+/*
+ * 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 common.c
+ * @brief Implementation of common interfaces abstracting low-level platform.
+ * details.
+ */
+
+#include <stdlib.h>
+#include <string.h> // memset
+#include <sys/types.h> // getaddrinfo
+#include <sys/socket.h> // ''
+#include <netdb.h> // ''
+#include <stdio.h>
+
+#include "common.h"
+
+
+int
+get_addr_family (const char *ip_address)
+{
+ struct addrinfo hint, *res = NULL;
+ int rc;
+
+ memset (&hint, '\0', sizeof hint);
+
+ hint.ai_family = PF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+
+ rc = getaddrinfo (ip_address, NULL, &hint, &res);
+ if (rc)
+ {
+ return -1;
+ }
+ rc = res->ai_family;
+ freeaddrinfo (res);
+ return rc;
+}
+
+/* hashes */
+
+u32
+cumulative_hash32 (const void *data, size_t len, u32 lastValue)
+{
+ // Standard FNV 32-bit prime: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ const u32 fnv1a_prime = 0x01000193;
+ u32 hash = lastValue;
+ size_t i;
+
+ const char *chardata = data;
+
+ for (i = 0; i < len; i++)
+ {
+ hash = hash ^ chardata[i];
+ hash = hash * fnv1a_prime;
+ }
+
+ return hash;
+}
+
+u32
+hash32 (const void *data, size_t len)
+{
+ // Standard FNV 32-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ const u32 fnv1a_offset = 0x811C9DC5;
+ return cumulative_hash32 (data, len, fnv1a_offset);
+}
+
+u64
+cumulative_hash64 (const void *data, size_t len, u64 lastValue)
+{
+ // Standard FNV 64-bit prime: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ const u64 fnv1a_prime = 0x00000100000001B3ULL;
+ u64 hash = lastValue;
+ const char *chardata = data;
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ {
+ hash = hash ^ chardata[i];
+ hash = hash * fnv1a_prime;
+ }
+
+ return hash;
+}
+
+u64
+hash64 (const void *data, size_t len)
+{
+ // Standard FNV 64-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ const u64 fnv1a_offset = 0xCBF29CE484222325ULL;
+ return cumulative_hash64 (data, len, fnv1a_offset);
+}
+
+void
+hicn_packet_dump (uint8_t * buffer, size_t len)
+{
+ int i;
+ unsigned char buff[17];
+ unsigned char *pc = (unsigned char *) buffer;
+
+ // Output description if given.
+ if (len == 0)
+ {
+ printf (" ZERO LENGTH\n");
+ return;
+ }
+
+ // Process every byte in the data.
+ for (i = 0; i < len; i++)
+ {
+ // Multiple of 16 means new line (with line offset).
+
+ if ((i % 16) == 0)
+ {
+ // Just don't print ASCII for the zeroth line.
+ if (i != 0)
+ printf (" %s\n", buff);
+
+ // Output the offset.
+ printf (" %04x ", i);
+ }
+
+ // Now the hex code for the specific character.
+ printf (" %02x", pc[i]);
+
+ // And store a printable ASCII character for later.
+ if ((pc[i] < 0x20) || (pc[i] > 0x7e))
+ buff[i % 16] = '.';
+ else
+ buff[i % 16] = pc[i];
+ buff[(i % 16) + 1] = '\0';
+ }
+
+ // Pad out last line if not exactly 16 characters.
+ while ((i % 16) != 0)
+ {
+ printf (" ");
+ i++;
+ }
+
+ // And print the final ASCII bit.
+ printf (" %s\n", buff);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/common.h b/lib/src/common.h
new file mode 100755
index 000000000..9ddbdeb09
--- /dev/null
+++ b/lib/src/common.h
@@ -0,0 +1,231 @@
+/*
+ * 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 common.c
+ * @brief Common interfaces abstracting low-level platform.
+ * details.
+ *
+ * The role of this header file is to provide an uniform interface to the
+ * different platform on top of which we build the hICN interface:
+ * - syntax helpers
+ * - IP address management
+ * - protocol definition
+ * - ...
+ *
+ * The rationale is to leverage as much as possible platform-specific code,
+ * however some level of harmonization is needed to build code on top. Whenever
+ * possible, we align to VPP structure and naming.
+ */
+
+#ifndef HICN_COMMON_H
+#define HICN_COMMON_H
+
+#include <stdint.h>
+#include <assert.h>
+
+/* Concise type definitions */
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+
+/*
+ * Code annotations
+ *
+ * NOTE: these are defined by default in VPP.
+ */
+
+#ifndef HICN_VPP_PLUGIN
+
+#define PREDICT_FALSE(x) (x)
+#define PREDICT_TRUE(x) (x)
+#define always_inline static inline
+#define static_always_inline static inline
+#define STRUCT_SIZE_OF(type, member) sizeof(((type *)0)->member)
+#define ASSERT
+
+#define STATIC_ASSERT(x)
+
+#endif /* ! HICN_VPP_PLUGIN */
+
+/*
+ * IP address types
+ */
+
+#ifdef HICN_VPP_PLUGIN
+
+#include <vnet/ip/ip4_packet.h> // ip4_address_t
+#include <vnet/ip/ip6_packet.h> // ip6_address_t
+
+#else
+
+#include <netinet/in.h>
+
+typedef union
+{
+ u32 as_u32;
+ struct in_addr as_inaddr;
+} ip4_address_t;
+
+typedef union
+{
+ u64 as_u64[2];
+ u32 as_u32[4];
+ u8 as_u8[16];
+ struct in6_addr as_in6addr;
+} ip6_address_t;
+
+typedef union
+{
+ struct
+ {
+ u32 pad[3];
+ ip4_address_t ip4;
+ };
+ ip6_address_t ip6;
+} ip46_address_t;
+
+#define ip46_address_is_ip4(ip46) (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0)
+
+#endif /* ! HICN_VPP_PLUGIN */
+
+/**
+ * @brief Returns the family of an IP address
+ * @param [in] ip_address - IP address in presentation format
+ * @return AF_INET or AF_INET6 if successful, -1 otherwise
+ */
+int get_addr_family (const char *ip_address);
+
+/*
+ * Checksum computation
+ *
+ * NOTE: VPP provides efficient (incremental) checksum computations
+ * that we reuse, and provide alternative implementation otherwise.
+ */
+
+#ifndef HICN_VPP_PLUGIN
+
+typedef u16 ip_csum_t;
+
+/*
+ * Checksum update (incremental and non-incremental)
+ *
+ * Those functions are already defined in VPP in vnet/ip/ip_packet.h, and we
+ * borrow this code here.
+ */
+
+static_always_inline u16
+ip_csum_fold (ip_csum_t c)
+{
+ /* Reduce to 16 bits. */
+#if 0 // uword_bits == 64
+ c = (c & (ip_csum_t) 0xffffffff) + (c >> (ip_csum_t) 32);
+ c = (c & 0xffff) + (c >> 16);
+#endif
+
+ c = (c & 0xffff) + (c >> 16);
+ c = (c & 0xffff) + (c >> 16);
+
+ return c;
+}
+
+static_always_inline ip_csum_t
+ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
+{
+ ip_csum_t t = sum + x;
+ return t + (t < x);
+}
+
+/* Update checksum changing field at even byte offset from x -> 0. */
+static_always_inline ip_csum_t
+ip_csum_add_even (ip_csum_t c, ip_csum_t x)
+{
+ ip_csum_t d;
+
+ d = c - x;
+
+ /* Fold in carry from high bit. */
+ d -= d > c;
+
+ return d;
+}
+
+/* Update checksum changing field at even byte offset from 0 -> x. */
+static_always_inline ip_csum_t
+ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
+{
+ return ip_csum_with_carry (c, x);
+}
+
+u32 cumulative_hash32 (const void *data, size_t len, u32 lastValue);
+u32 hash32 (const void *data, size_t len);
+u64 cumulative_hash64 (const void *data, size_t len, u64 lastValue);
+u64 hash64 (const void *data, size_t len);
+void hicn_packet_dump (uint8_t * buffer, size_t len);
+
+#endif /* ! HICN_VPP_PLUGIN */
+
+/**
+ * @brief Computes buffer checksum
+ * @param [in] addr - Pointer to buffer start
+ * @param [in] size - Size of buffer
+ * @param [in] init - Checksum initial value
+ * @return Checksum of specified buffer
+ */
+always_inline u16
+csum (const void *addr, size_t size, u16 init)
+{
+ u32 sum = init;
+ const u16 *bytes = (u16 *) addr;
+
+ while (size > 1)
+ {
+ sum += *bytes++;
+ size -= sizeof (u16);
+ }
+ if (size)
+ {
+ sum += *(const u8 *) bytes;
+ }
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ return (u16) ~ sum;
+}
+
+/*
+ * Useful aliases
+ */
+
+/* Symmetry with IPPROTO_ICMPV6 */
+#define IPPROTO_ICMPV4 IPPROTO_ICMP
+
+/*
+ * Query IP version from packet (either 4 or 6)
+ * (version is located as same offsets in both protocol headers)
+ */
+#define HICN_IP_VERSION(packet) ((hicn_header_t *)packet)->v4.ip.version
+
+#endif /* HICN_COMMON_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/compat.c b/lib/src/compat.c
new file mode 100755
index 000000000..7d9eef025
--- /dev/null
+++ b/lib/src/compat.c
@@ -0,0 +1,1177 @@
+/*
+ * 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 compat.c
+ * @brief Implementation of the compatibility layer.
+ */
+
+#include <netinet/in.h>
+#include <string.h> // memset
+#include <stddef.h> // offsetof
+
+#include "common.h"
+#include "compat.h"
+#include "error.h"
+#include "header.h"
+#include "name.h"
+#include "ops.h"
+
+#define member_size(type, member) sizeof(((type *)0)->member)
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+#define HICN_NAME_COMPONENT_SIZE 2
+
+int
+hicn_packet_get_format (const hicn_header_t * h, hicn_format_t * format)
+{
+ *format = HF_UNSPEC;
+
+ switch (HICN_IP_VERSION (h))
+ {
+ case 4:
+ switch (h->v4.ip.protocol)
+ {
+ case IPPROTO_TCP:
+ if (h->v4.tcp.flags & AH_FLAG)
+ *format = HF_INET_TCP_AH;
+ else
+ *format = HF_INET_TCP;
+ break;
+ case IPPROTO_ICMP:
+ *format = HF_INET_ICMP;
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_HICN;
+ }
+ break;
+ case 6:
+ switch (h->v6.ip.nxt)
+ {
+ case IPPROTO_TCP:
+ if (h->v6.tcp.flags & AH_FLAG)
+ *format = HF_INET6_TCP_AH;
+ else
+ *format = HF_INET6_TCP;
+ break;
+ case IPPROTO_ICMPV6:
+ *format = HF_INET6_ICMP;
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_HICN;
+ }
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_HICN;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+/**
+ * @brief Convert (former) hICN format into (newer) hICN type
+ * @param [in] format - hICN format
+ * @return hICN type, all zero'ed if type is unknown
+ */
+hicn_type_t
+hicn_format_to_type (hicn_format_t format)
+{
+ switch (format)
+ {
+ case HF_INET_TCP:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_NONE,.l2 = IPPROTO_TCP,.l1 =
+ IPPROTO_IP};
+ case HF_INET6_TCP:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_NONE,.l2 = IPPROTO_TCP,.l1 =
+ IPPROTO_IPV6};
+ case HF_INET_ICMP:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_NONE,.l2 = IPPROTO_ICMP,.l1 =
+ IPPROTO_IP};
+ case HF_INET6_ICMP:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_NONE,.l2 = IPPROTO_ICMPV6,.l1 =
+ IPPROTO_IPV6};
+ case HF_INET_TCP_AH:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_AH,.l2 = IPPROTO_TCP,.l1 = IPPROTO_IP};
+ case HF_INET6_TCP_AH:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_AH,.l2 = IPPROTO_TCP,.l1 =
+ IPPROTO_IPV6};
+ case HF_INET_ICMP_AH:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_AH,.l2 = IPPROTO_ICMP,.l1 =
+ IPPROTO_IP};
+ case HF_INET6_ICMP_AH:
+ return (hicn_type_t)
+ {
+ .l4 = IPPROTO_NONE,.l3 = IPPROTO_AH,.l2 = IPPROTO_ICMPV6,.l1 =
+ IPPROTO_IPV6};
+ default:
+ break;
+ }
+ return (hicn_type_t)
+ {
+ {
+ IPPROTO_NONE}
+ };
+}
+
+/**
+ * @brief Parse hICN header and return hICN type
+ * @param [in] h - hICN header
+ * @param [out] format - hICN type
+ * @return hICN error code
+ *
+ * This function is used to wrap old API calls to new ones
+ */
+hicn_type_t
+hicn_header_to_type (const hicn_header_t * h)
+{
+ hicn_format_t format;
+ hicn_packet_get_format (h, &format);
+ return hicn_format_to_type (format);
+}
+
+int
+hicn_packet_init_header (hicn_format_t format, hicn_header_t * packet)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->init_packet_header (type, &packet->protocol);
+}
+
+int
+hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t * h)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, 0, 0);
+}
+
+int
+hicn_packet_compute_header_checksum (hicn_format_t format, hicn_header_t * h,
+ u16 init_sum)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ /* payload_length == ~0: ignore payload */
+ return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol,
+ init_sum, ~0);
+}
+
+int
+hicn_packet_check_integrity (hicn_format_t format, hicn_header_t * h)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->verify_checksums (type, &h->protocol, 0, 0);
+}
+
+int
+hicn_packet_get_header_length_from_format (hicn_format_t format,
+ size_t * header_length)
+{
+ *header_length = _is_ipv4 (format) * IPV4_HDRLEN;
+ *header_length += _is_ipv6 (format) * IPV6_HDRLEN;
+ *header_length += _is_icmp (format) * ICMP_HDRLEN;
+ *header_length += _is_tcp (format) * TCP_HDRLEN;
+ *header_length += _is_ah (format) * AH_HDRLEN;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t * h,
+ size_t * header_length)
+{
+ hicn_packet_get_header_length_from_format (format, header_length);
+ int is_ah = _is_ah (format);
+ int is_ipv4 = _is_ipv4 (format);
+ int is_ipv6 = _is_ipv6 (format);
+ // The signature payload is expressed as number of 32 bits words
+ *header_length += (is_ah * is_ipv4) * (h->v4ah.ah.payloadlen) << 2;
+ *header_length += (is_ah * is_ipv6) * (h->v6ah.ah.payloadlen) << 2;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t * h,
+ size_t * payload_length)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
+ payload_length);
+}
+
+int
+hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t * h,
+ size_t payload_length)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol,
+ payload_length);
+}
+
+int
+hicn_packet_compare (const hicn_header_t * packet1,
+ const hicn_header_t * packet2)
+{
+ hicn_type_t type1 = hicn_header_to_type (packet1);
+ hicn_type_t type2 = hicn_header_to_type (packet2);
+
+ size_t len1, len2;
+ int rc;
+
+ if (type1.as_u32 != type2.as_u32)
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ rc = hicn_ops_vft[type1.l1]->get_length (type1, &packet1->protocol, &len1);
+ if (PREDICT_FALSE (rc < 0))
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ rc = hicn_ops_vft[type2.l1]->get_length (type2, &packet2->protocol, &len2);
+ if (PREDICT_FALSE (rc < 0))
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ if (len1 != len2)
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ return memcmp ((u8 *) packet1, (u8 *) packet2, len1);
+
+}
+
+int
+hicn_packet_get_name (hicn_format_t format, const hicn_header_t * h,
+ hicn_name_t * name, u8 is_interest)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+
+ if (is_interest)
+ return hicn_ops_vft[type.l1]->get_interest_name (type, &h->protocol,
+ name);
+ else
+ return hicn_ops_vft[type.l1]->get_data_name (type, &h->protocol, name);
+}
+
+int
+hicn_packet_set_name (hicn_format_t format, hicn_header_t * h,
+ const hicn_name_t * name, u8 is_interest)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+
+#ifndef HICN_VPP_PLUGIN
+ if (name->type & HNT_IOV)
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+#endif /* HICN_VPP_PLUGIN */
+
+ if (is_interest)
+ return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol,
+ name);
+ else
+ return hicn_ops_vft[type.l1]->set_data_name (type, &h->protocol, name);
+}
+
+int
+hicn_packet_set_payload (hicn_format_t format, hicn_header_t * h,
+ const u8 * payload, u16 payload_length)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ size_t header_length;
+ int rc;
+
+ rc =
+ hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
+ &header_length);
+ if (rc < 0)
+ return rc;
+
+ memcpy ((u8 *) h + header_length, payload, payload_length);
+
+ return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol,
+ payload_length);
+}
+
+int
+hicn_packet_get_payload (hicn_format_t format, const hicn_header_t * h,
+ u8 ** payload, size_t * payload_size, bool hard_copy)
+{
+ size_t header_length, payload_length;
+ int rc;
+ hicn_type_t type = hicn_format_to_type (format);
+
+ rc =
+ hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
+ &header_length);
+ if (rc < 0)
+ return rc;
+
+ rc =
+ hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
+ &payload_length);
+ if (rc < 0)
+ return rc;
+
+ if (hard_copy)
+ {
+ memcpy (payload, (u8 *) h + header_length, payload_length);
+ }
+ else
+ {
+ *payload = (u8 *) h + header_length;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h,
+ ip_address_t * ip_address, bool is_interest)
+{
+ const void *locator;
+ int is_ipv4 = (format & HFO_INET);
+ int is_ipv6 = (format & HFO_INET6) >> 1;
+
+ if (is_ipv4)
+ {
+ locator = is_interest ? &h->v4.ip.saddr : &h->v4.ip.daddr;
+ ip_address->family = AF_INET;
+ ip_address->prefix_len = IPV4_ADDR_LEN_BITS;
+ }
+ else if (is_ipv6)
+ {
+ locator = is_interest ? &h->v6.ip.saddr : &h->v6.ip.daddr;
+ ip_address->family = AF_INET6;
+ ip_address->prefix_len = IPV6_ADDR_LEN_BITS;
+ }
+ else
+ {
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ memcpy (ip_address->buffer, locator, ip_address_len (ip_address));
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h,
+ const ip_address_t * ip_address, bool is_interest)
+{
+ void *locator;
+ int is_ipv4 = (format & HFO_INET);
+ int is_ipv6 = (format & HFO_INET6) >> 1;
+
+ if (is_ipv6)
+ {
+ locator = is_interest ? &h->v6.ip.saddr : &h->v6.ip.daddr;
+ }
+ else if (is_ipv4)
+ {
+ locator = is_interest ? &h->v4.ip.saddr : &h->v4.ip.daddr;
+ }
+ else
+ {
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+ }
+
+ memcpy (locator, ip_address->buffer, ip_address_len (ip_address));
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_signature_size (hicn_format_t format, const hicn_header_t * h,
+ size_t * bytes)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_signature_size (type, &h->protocol,
+ bytes);
+}
+
+int
+hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t * h,
+ size_t bytes)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_signature_size (type, &h->protocol,
+ bytes);
+}
+
+int
+hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t * h,
+ uint64_t signature_timestamp)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_signature_timestamp (type, &h->protocol,
+ signature_timestamp);
+}
+
+int
+hicn_packet_get_signature_timestamp (hicn_format_t format, const hicn_header_t * h,
+ uint64_t *signature_timestamp)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_signature_timestamp (type, &h->protocol,
+ signature_timestamp);
+}
+
+int
+hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t * h,
+ uint8_t validation_algorithm)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_validation_algorithm (type, &h->protocol,
+ validation_algorithm);
+}
+
+int
+hicn_packet_get_validation_algorithm (hicn_format_t format, const hicn_header_t * h,
+ uint8_t * validation_algorithm)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_validation_algorithm (type, &h->protocol,
+ validation_algorithm);
+}
+
+int
+hicn_packet_set_key_id (hicn_format_t format, hicn_header_t * h,
+ uint8_t *key_id)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_key_id (type, &h->protocol,
+ key_id);
+}
+
+int
+hicn_packet_get_key_id (hicn_format_t format, hicn_header_t * h,
+ uint8_t ** key_id, uint8_t *key_id_length)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_key_id (type, &h->protocol,
+ key_id, key_id_length);
+}
+
+int
+hicn_packet_get_hoplimit (const hicn_header_t * h, u8 * hops)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *hops = h->v6.ip.hlim;
+ break;
+ case 4:
+ *hops = h->v4.ip.ttl;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_hoplimit (hicn_header_t * h, u8 hops)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.ip.hlim = hops;
+ break;
+ case 4:
+ h->v4.ip.ttl = hops;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+
+int
+hicn_packet_get_lifetime (const hicn_header_t * h, u32 * lifetime)
+{
+ hicn_type_t type = hicn_header_to_type (h);
+ return hicn_ops_vft[type.l1]->get_lifetime (type, &h->protocol,
+ (hicn_lifetime_t *) lifetime);
+}
+
+int
+hicn_packet_set_lifetime (hicn_header_t * h, u32 lifetime)
+{
+ hicn_type_t type = hicn_header_to_type (h);
+ return hicn_ops_vft[type.l1]->set_lifetime (type, &h->protocol,
+ (hicn_lifetime_t) lifetime);
+}
+
+int
+hicn_packet_get_reserved_bits (const hicn_header_t * h, u8 * reserved_bits)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *reserved_bits = h->v6.tcp.reserved;
+ break;
+ case 4:
+ *reserved_bits = h->v4.tcp.reserved;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_reserved_bits (hicn_header_t * h, u8 reserved_bits)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.reserved = reserved_bits;
+ break;
+ case 4:
+ h->v4.tcp.reserved = reserved_bits;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_payload_type (const hicn_header_t * h,
+ hicn_payload_type_t * payload_type)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *payload_type = ((h->v6.tcp.flags & TCP_FLAG_URG) == TCP_FLAG_URG);
+ break;
+ case 4:
+ *payload_type = ((h->v4.tcp.flags & TCP_FLAG_URG) == TCP_FLAG_URG);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ if (*payload_type == HPT_UNSPEC)
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_payload_type (hicn_header_t * h,
+ hicn_payload_type_t payload_type)
+{
+ if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ if (payload_type)
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_URG;
+ else
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_URG;
+ break;
+ case 4:
+ if (payload_type)
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_URG;
+ else
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_URG;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_syn (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_SYN;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_SYN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_reset_syn (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_SYN;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_SYN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_test_syn (const hicn_header_t * h, bool * flag)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *flag = h->v6.tcp.flags & TCP_FLAG_SYN;
+ break;
+ case 4:
+ *flag = h->v4.tcp.flags & TCP_FLAG_SYN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_ack (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_ACK;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_ACK;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_reset_ack (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_ACK;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_ACK;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_test_ack (const hicn_header_t * h, bool * flag)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *flag = h->v6.tcp.flags & TCP_FLAG_ACK;
+ break;
+ case 4:
+ *flag = h->v4.tcp.flags & TCP_FLAG_ACK;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_rst (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_RST;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_RST;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_reset_rst (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_RST;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_RST;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_test_rst (const hicn_header_t * h, bool * flag)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *flag = h->v6.tcp.flags & TCP_FLAG_RST;
+ break;
+ case 4:
+ *flag = h->v4.tcp.flags & TCP_FLAG_RST;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_fin (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_FIN;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_FIN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_reset_fin (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_FIN;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_FIN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_test_fin (const hicn_header_t * h, bool * flag)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *flag = h->v6.tcp.flags & TCP_FLAG_FIN;
+ break;
+ case 4:
+ *flag = h->v4.tcp.flags & TCP_FLAG_FIN;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_ece (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags | TCP_FLAG_ECE;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags | TCP_FLAG_ECE;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_reset_ece (hicn_header_t * h)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.flags = h->v6.tcp.flags & ~TCP_FLAG_ECE;
+ break;
+ case 4:
+ h->v4.tcp.flags = h->v4.tcp.flags & ~TCP_FLAG_ECE;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_test_ece (const hicn_header_t * h, bool * flag)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *flag = h->v6.tcp.flags & TCP_FLAG_ECE;
+ break;
+ case 4:
+ *flag = h->v4.tcp.flags & TCP_FLAG_ECE;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_src_port (hicn_header_t * h, u16 src_port)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.sport = htons (src_port);
+ break;
+ case 4:
+ h->v4.tcp.sport = htons (src_port);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_src_port (const hicn_header_t * h, u16 * src_port)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *src_port = ntohs (h->v6.tcp.sport);
+ break;
+ case 4:
+ *src_port = ntohs (h->v4.tcp.sport);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_set_dst_port (hicn_header_t * h, u16 dst_port)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ h->v6.tcp.dport = htons (dst_port);
+ break;
+ case 4:
+ h->v4.tcp.dport = htons (dst_port);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_dst_port (const hicn_header_t * h, u16 * dst_port)
+{
+ switch (HICN_IP_VERSION (h))
+ {
+ case 6:
+ *dst_port = ntohs (h->v6.tcp.dport);
+ break;
+ case 4:
+ *dst_port = ntohs (h->v4.tcp.dport);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_copy_header (hicn_format_t format, const hicn_header_t * packet,
+ hicn_header_t * destination, bool copy_ah)
+{
+ size_t header_length = _is_ipv4 (format) * IPV4_HDRLEN;
+ header_length += _is_ipv6 (format) * IPV6_HDRLEN;
+ header_length += _is_icmp (format) * ICMP_HDRLEN;
+ header_length += _is_tcp (format) * TCP_HDRLEN;
+ header_length += _is_ah (format) * copy_ah * AH_HDRLEN;
+
+ memcpy (destination, packet, header_length);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+#define _INTEREST 1
+#define _DATA 0
+
+/* Interest */
+
+int
+hicn_interest_get_name (hicn_format_t format, const hicn_header_t * interest,
+ hicn_name_t * name)
+{
+ return hicn_packet_get_name (format, interest, name, _INTEREST);
+}
+
+int
+hicn_interest_set_name (hicn_format_t format, hicn_header_t * interest,
+ const hicn_name_t * name)
+{
+ int ret_err = hicn_packet_reset_ece (interest); //interest packet -> ece flag unset
+ if (ret_err < 0)
+ return HICN_LIB_ERROR_UNEXPECTED;
+ return hicn_packet_set_name (format, interest, name, _INTEREST);
+}
+
+int
+hicn_interest_get_locator (hicn_format_t format,
+ const hicn_header_t * interest,
+ ip_address_t * ip_address)
+{
+ return hicn_packet_get_locator (format, interest, ip_address, _INTEREST);
+}
+
+int
+hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
+ const ip_address_t * ip_address)
+{
+ return hicn_packet_set_locator (format, interest, ip_address, _INTEREST);
+}
+
+int
+hicn_interest_compare (const hicn_header_t * interest_1,
+ const hicn_header_t * interest_2)
+{
+ return hicn_packet_compare (interest_1, interest_2);
+}
+
+int
+hicn_interest_get_lifetime (const hicn_header_t * interest, u32 * lifetime)
+{
+ return hicn_packet_get_lifetime (interest, lifetime);
+}
+
+int
+hicn_interest_set_lifetime (hicn_header_t * interest, u32 lifetime)
+{
+ return hicn_packet_set_lifetime (interest, lifetime);
+}
+
+int
+hicn_interest_get_header_length (hicn_format_t format,
+ const hicn_header_t * interest,
+ size_t * header_length)
+{
+ return hicn_packet_get_header_length (format, interest, header_length);
+}
+
+int
+hicn_interest_get_payload_length (hicn_format_t format,
+ const hicn_header_t * interest,
+ size_t * payload_length)
+{
+ return hicn_packet_get_payload_length (format, interest, payload_length);
+}
+
+int
+hicn_interest_get_payload (hicn_format_t format,
+ const hicn_header_t * interest, u8 ** payload,
+ size_t * payload_size, bool hard_copy)
+{
+ return hicn_packet_get_payload (format, interest, payload, payload_size,
+ hard_copy);
+}
+
+int
+hicn_interest_set_payload (hicn_format_t format, hicn_header_t * interest,
+ const u8 * payload, size_t payload_length)
+{
+ return hicn_packet_set_payload (format, interest, payload, payload_length);
+}
+
+int
+hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t * packet)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->reset_interest_for_hash (type,
+ &packet->protocol);
+}
+
+/* Data */
+
+int
+hicn_data_get_name (hicn_format_t format, const hicn_header_t * data,
+ hicn_name_t * name)
+{
+ return hicn_packet_get_name (format, data, name, _DATA);
+}
+
+int
+hicn_data_set_name (hicn_format_t format, hicn_header_t * data,
+ hicn_name_t * name)
+{
+ int ret_err = hicn_packet_set_ece (data); //data packet -> ece flag set
+ if (ret_err < 0)
+ return HICN_LIB_ERROR_UNEXPECTED;
+ return hicn_packet_set_name (format, data, name, _DATA);
+}
+
+int
+hicn_data_get_locator (hicn_format_t format, const hicn_header_t * data,
+ ip_address_t * ip_address)
+{
+ return hicn_packet_get_locator (format, data, ip_address, _DATA);
+}
+
+int
+hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
+ const ip_address_t * ip_address)
+{
+ return hicn_packet_set_locator (format, data, ip_address, _DATA);
+}
+
+int
+hicn_data_compare (const hicn_header_t * data_1, const hicn_header_t * data_2)
+{
+ return hicn_packet_compare (data_1, data_2);
+}
+
+int
+hicn_data_get_expiry_time (const hicn_header_t * data, u32 * expiry_time)
+{
+ return hicn_packet_get_lifetime (data, expiry_time);
+}
+
+int
+hicn_data_set_expiry_time (hicn_header_t * data, u32 expiry_time)
+{
+ return hicn_packet_set_lifetime (data, (hicn_lifetime_t) expiry_time);
+}
+
+int
+hicn_data_get_header_length (hicn_format_t format, hicn_header_t * data,
+ size_t * header_length)
+{
+ return hicn_packet_get_header_length (format, data, header_length);
+}
+
+int
+hicn_data_get_payload_length (hicn_format_t format,
+ const hicn_header_t * data,
+ size_t * payload_length)
+{
+ return hicn_packet_get_payload_length (format, data, payload_length);
+}
+
+int
+hicn_data_set_payload_type (hicn_header_t * data,
+ hicn_payload_type_t payload_type)
+{
+ return hicn_packet_set_payload_type (data, payload_type);
+}
+
+int
+hicn_data_get_payload_type (const hicn_header_t * data,
+ hicn_payload_type_t * payload_type)
+{
+ return hicn_packet_get_payload_type (data, payload_type);
+}
+
+int
+hicn_data_get_path_label (const hicn_header_t * data, u32 * path_label)
+{
+ hicn_type_t type = hicn_header_to_type (data);
+ return hicn_ops_vft[type.l1]->get_data_pathlabel (type, &data->protocol,
+ path_label);
+}
+
+int
+hicn_data_set_path_label (hicn_header_t * data, u32 path_label)
+{
+ hicn_type_t type = hicn_header_to_type (data);
+ return hicn_ops_vft[type.l1]->set_data_pathlabel (type, &data->protocol,
+ path_label);
+}
+
+int
+hicn_data_set_payload (hicn_format_t format, hicn_header_t * data,
+ const u8 * payload, size_t payload_length)
+{
+ return hicn_packet_set_payload (format, data, payload, payload_length);
+}
+
+int
+hicn_data_get_payload (hicn_format_t format, const hicn_header_t * data,
+ u8 ** payload, size_t * payload_size, bool hard_copy)
+{
+ return hicn_packet_get_payload (format, data, payload, payload_size,
+ hard_copy);
+}
+
+int
+hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t * packet)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->reset_interest_for_hash (type,
+ &packet->protocol);
+
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/compat.h b/lib/src/compat.h
new file mode 100755
index 000000000..1a1743de2
--- /dev/null
+++ b/lib/src/compat.h
@@ -0,0 +1,462 @@
+/*
+ * 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 compat.h
+ * @brief Implementation of the compatibility layer.
+ *
+ * The structure of the core API has evolved to support operations of a variety
+ * of packet formats in addition to IPv4/TCP and IPv6/TCP, namely with the use
+ * of ICMP for signalization and AH headers for integrity. The new API format
+ * has been designed to scale better with the multiplicity of packet formats,
+ * and provide a unified interface on top. We maintain an interface for the
+ * former API in this file, which mainly acts as a wrapper on top of new calls.
+ */
+#ifndef HICN_COMPAT_H
+#define HICN_COMPAT_H
+
+#include "common.h"
+#include "header.h"
+#include "name.h"
+
+/* HICN format options */
+#define HFO_INET 1 << 0
+#define HFO_INET6 1 << 1
+#define HFO_TCP 1 << 2
+#define HFO_ICMP 1 << 3
+#define HFO_AH 1 << 4
+
+#define _is_ipv4(format) ((format & HFO_INET))
+#define _is_ipv6(format) ((format & HFO_INET6) >> 1)
+#define _is_tcp(format) ((format & HFO_TCP) >> 2)
+#define _is_icmp(format) ((format & HFO_ICMP) >> 3)
+#define _is_ah(format) ((format & HFO_AH) >> 4)
+
+typedef enum
+{
+ HF_UNSPEC = 0,
+ HF_INET_TCP = HFO_INET | HFO_TCP,
+ HF_INET6_TCP = HFO_INET6 | HFO_TCP,
+ HF_INET_ICMP = HFO_INET | HFO_ICMP,
+ HF_INET6_ICMP = HFO_INET6 | HFO_ICMP,
+ HF_INET_TCP_AH = HFO_INET | HFO_TCP | HFO_AH,
+ HF_INET6_TCP_AH = HFO_INET6 | HFO_TCP | HFO_AH,
+ HF_INET_ICMP_AH = HFO_INET | HFO_ICMP | HFO_AH,
+ HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH
+} hicn_format_t;
+
+/**
+ * Maximum Size of the hICN header (the effective size will depend on the
+ * underlying IP version)
+ */
+#define HICN_HDR_LEN sizeof(hicn_header_t)
+
+/**
+ * Minimum required header length to determine the type and length of a supposed
+ * hICN packet.
+ * This should be equal to the maximum value over all possible hICN packet
+ * formats, and less than the minimum possible IP packet size.
+ */
+#define HICN_V6_MIN_HDR_LEN 6 /* bytes */
+#define HICN_V4_MIN_HDR_LEN 4 /* bytes */
+
+// #define HICN_MIN_HDR_LEN ((HICN_V6_MIN_HDR_LEN > HICN_V4_MIN_HDR_LEN) ? HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN)
+#define HICN_MIN_HDR_LEN HICN_V6_MIN_HDR_LEN
+
+/**
+ * @brief Parse packet headers and return hICN format
+ * @param [in] format - hICN Format
+ * @param [in, out] packet - Buffer containing the hICN header to be initialized
+ * @return hICN error code
+ */
+int hicn_packet_init_header (hicn_format_t format, hicn_header_t * packet);
+
+/**
+ * @brief Parse packet headers and return hICN format
+ * @param [in] h - hICN header
+ * @param [out] format - hICN format
+ * @return hICN error code
+ */
+int hicn_packet_get_format (const hicn_header_t * packet,
+ hicn_format_t * format);
+
+/**
+ * @brief Update checksums in packet headers
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @return hICN error code
+ */
+int hicn_packet_compute_checksum (hicn_format_t format,
+ hicn_header_t * packet);
+
+/**
+ * @brief compute the checksum of the packet header, adding init_sum to the final value
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @param [in] init_sum - value to add to the final checksum
+ * @return hICN error code
+ */
+int hicn_packet_compute_header_checksum (hicn_format_t format,
+ hicn_header_t * packet,
+ u16 init_sum);
+
+/**
+ * @brief Verify checksums in packet headers
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @return hICN error code
+ */
+int hicn_packet_check_integrity (hicn_format_t format,
+ hicn_header_t * packet);
+
+// this is not accounted here
+/**
+ * @brief Return total length of hicn headers (but signature payload)
+ * @param [in] format - hICN format
+ * @param [out] header_length - Total length of headers
+ * @return hICN error code
+ */
+int hicn_packet_get_header_length_from_format (hicn_format_t format,
+ size_t * header_length);
+
+/**
+ * @brief Return total length of hicn headers (before payload)
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] header_length - Total length of headers
+ * @return hICN error code
+ */
+int hicn_packet_get_header_length (hicn_format_t format,
+ const hicn_header_t * packet,
+ size_t * header_length);
+
+/**
+ * @brief Return payload length
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] payload_length - payload length
+ * @return hICN error code
+ */
+int hicn_packet_get_payload_length (hicn_format_t format,
+ const hicn_header_t * packet,
+ size_t * payload_length);
+
+/**
+ * @brief Sets payload length
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @param [in] payload_length - payload length
+ * @return hICN error code
+ */
+int hicn_packet_set_payload_length (hicn_format_t format,
+ hicn_header_t * packet,
+ const size_t payload_length);
+
+/**
+ * @brief Compare two hICN packets
+ * @param [in] packet_1 - First packet
+ * @param [in] packet_2 - Second packet
+ * @return 0 if both packets are considered equal, any other value otherwise.
+ */
+int hicn_packet_compare (const hicn_header_t * packet1,
+ const hicn_header_t * packet2);
+
+/**
+ * @brief Retrieve the name of an interest/data packet
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] name - name holding the result
+ * @param [in] is_interest - Flag to determine whether it is an interest (1) or
+ * data packet (0)
+ * @return hICN error code
+ */
+int hicn_packet_get_name (hicn_format_t format, const hicn_header_t * packet,
+ hicn_name_t * name, u8 is_interest);
+
+/**
+ * @brief Sets the name of an interest/data packet
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @param [in] name - name to set into packet
+ * @param [in] is_interest - Flag to determine whether it is an interest (1) or
+ * data packet (0)
+ * @return hICN error code
+ */
+int hicn_packet_set_name (hicn_format_t format, hicn_header_t * packet,
+ const hicn_name_t * name, u8 is_interest);
+
+/**
+ * @brief Sets the payload of a packet
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @param [in] payload - payload to set
+ * @param [in] payload_length - size of the payload to set
+ * @return hICN error code
+ *
+ * NOTE:
+ * - The buffer holding payload is assumed sufficiently large
+ * - This function updates header fields with the new length, but no checksum.
+ */
+int hicn_packet_set_payload (hicn_format_t format, hicn_header_t * packet,
+ const u8 * payload, u16 payload_length);
+
+/**
+ * @brief Retrieves the payload of a packet
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] payload - pointer to buffer for storing the result
+ * @param [out] payload_length - size of the retreived payload
+ * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is made
+ * into the payload buffer, otherwise (0) the pointer is changed to point to the payload offset in the packet.
+ * @return hICN error code
+ *
+ * NOTE:
+ * - The buffer holding payload is assumed sufficiently large
+ */
+int hicn_packet_get_payload (hicn_format_t format,
+ const hicn_header_t * packet, u8 ** payload,
+ size_t * payload_size, bool hard_copy);
+
+/**
+ * @brief Retrieve the locator of an interest / data packet
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] ip_address - retrieved locator
+ * @param [in] is_interest - Flag to determine whether it is an interest (1) or
+ * data packet (0)
+ * @return hICN error code
+ */
+int hicn_packet_get_locator (hicn_format_t format,
+ const hicn_header_t * packet,
+ ip_address_t * ip_address, bool is_interest);
+
+/**
+ * @brief Sets the locator of an interest / data packet
+ * @param [in] format - hICN format
+ * @param [in,out] packet - packet header
+ * @param [out] ip_address - retrieved locator
+ * @param [in] is_interest - Flag to determine whether it is an interest (1) or
+ * data packet (0)
+ * @return hICN error code
+ */
+int hicn_packet_set_locator (hicn_format_t format, hicn_header_t * packet,
+ const ip_address_t * ip_address,
+ bool is_interest);
+
+/**
+ * @brief Retrieves the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] bytes - Retrieved signature size
+ * @return hICN error code
+ */
+int hicn_packet_get_signature_size (hicn_format_t format,
+ const hicn_header_t * packet,
+ size_t * bytes);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [in] bytes - Retrieved signature size
+ * @return hICN error code
+ */
+int hicn_packet_set_signature_size (hicn_format_t format,
+ hicn_header_t * packet, size_t bytes);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [in] signature_timestamp - Signature timestamp to set
+ * @return hICN error code
+ */
+int hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t * h,
+ uint64_t signature_timestamp);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] signature_timestamp - Retrieved signature timestamp
+ * @return hICN error code
+ */
+int hicn_packet_get_signature_timestamp (hicn_format_t format, const hicn_header_t * h,
+ uint64_t *signature_timestamp);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [in] validation_algorithm - Validation algorithm to set
+ * @return hICN error code
+ */
+int hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t * h,
+ uint8_t validation_algorithm);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] validation_algorithm - Retrieved validation algorithm
+ * @return hICN error code
+ */
+int hicn_packet_get_validation_algorithm (hicn_format_t format, const hicn_header_t * h,
+ uint8_t * validation_algorithm);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [in] key_id - Key id to set
+ * @return hICN error code
+ */
+int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t * h,
+ uint8_t *key_id);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] format - hICN format
+ * @param [in] packet - packet header
+ * @param [out] key_id - Retrieved key id
+ * @return hICN error code
+ */
+int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t * h,
+ uint8_t ** key_id, uint8_t *key_id_length);
+
+/**
+ * @brief Retrieves the packet hop limit
+ * @param [in] packet - packet header
+ * @param [out] hops - Retrieved hop limit
+ * @return hICN error code
+ */
+int hicn_packet_get_hoplimit (const hicn_header_t * packet, u8 * hops);
+
+/**
+ * @brief Sets the packet hop limit
+ * @param [in] packet - packet header
+ * @param [in] hops - Hop limit to set
+ * @return hICN error code
+ */
+int hicn_packet_set_hoplimit (hicn_header_t * packet, u8 hops);
+
+int hicn_packet_copy_header (hicn_format_t format,
+ const hicn_header_t * packet,
+ hicn_header_t * destination, bool copy_ah);
+
+int hicn_packet_get_lifetime (const hicn_header_t * packet, u32 * lifetime);
+int hicn_packet_set_lifetime (hicn_header_t * packet, u32 lifetime);
+int hicn_packet_get_reserved_bits (const hicn_header_t * packet,
+ u8 * reserved_bits);
+int hicn_packet_set_reserved_bits (hicn_header_t * packet,
+ const u8 reserved_bits);
+int hicn_packet_get_payload_type (const hicn_header_t * packet,
+ hicn_payload_type_t * payload_type);
+int hicn_packet_set_payload_type (hicn_header_t * packet,
+ const hicn_payload_type_t payload_type);
+
+int hicn_packet_set_syn (hicn_header_t * packet);
+int hicn_packet_reset_syn (hicn_header_t * packet);
+int hicn_packet_test_syn (const hicn_header_t * packet, bool * flag);
+int hicn_packet_set_ack (hicn_header_t * packet);
+int hicn_packet_reset_ack (hicn_header_t * packet);
+int hicn_packet_test_ack (const hicn_header_t * packet, bool * flag);
+int hicn_packet_set_rst (hicn_header_t * packet);
+int hicn_packet_reset_rst (hicn_header_t * packet);
+int hicn_packet_test_rst (const hicn_header_t * packet, bool * flag);
+int hicn_packet_set_fin (hicn_header_t * packet);
+int hicn_packet_reset_fin (hicn_header_t * packet);
+int hicn_packet_test_fin (const hicn_header_t * packet, bool * flag);
+int hicn_packet_set_ece (hicn_header_t * packet);
+int hicn_packet_reset_ece (hicn_header_t * packet);
+int hicn_packet_test_ece (const hicn_header_t * packet, bool * flag);
+
+int hicn_packet_set_src_port (hicn_header_t * packet, u16 src_port);
+int hicn_packet_get_src_port (const hicn_header_t * packet, u16 * src_port);
+int hicn_packet_set_dst_port (hicn_header_t * packet, u16 dst_port);
+int hicn_packet_get_dst_port (const hicn_header_t * packet, u16 * dst_port);
+
+/* Interest */
+
+int hicn_interest_get_name (hicn_format_t format,
+ const hicn_header_t * interest,
+ hicn_name_t * name);
+int hicn_interest_set_name (hicn_format_t format, hicn_header_t * interest,
+ const hicn_name_t * name);
+int hicn_interest_get_locator (hicn_format_t format,
+ const hicn_header_t * interest,
+ ip_address_t * ip_address);
+int hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
+ const ip_address_t * ip_address);
+int hicn_interest_compare (const hicn_header_t * interest_1,
+ const hicn_header_t * interest_2);
+int hicn_interest_set_lifetime (hicn_header_t * interest, u32 lifetime);
+int hicn_interest_get_lifetime (const hicn_header_t * interest,
+ u32 * lifetime);
+int hicn_interest_get_header_length (hicn_format_t format,
+ const hicn_header_t * interest,
+ size_t * header_length);
+int hicn_interest_get_payload_length (hicn_format_t format,
+ const hicn_header_t * interest,
+ size_t * payload_length);
+int hicn_interest_set_payload (hicn_format_t format, hicn_header_t * interest,
+ const u8 * payload, size_t payload_length);
+int hicn_interest_get_payload (hicn_format_t format,
+ const hicn_header_t * interest, u8 ** payload,
+ size_t * payload_size, bool hard_copy);
+int hicn_interest_reset_for_hash (hicn_format_t format,
+ hicn_header_t * packet);
+
+/* Data */
+
+int hicn_data_get_name (hicn_format_t format, const hicn_header_t * data,
+ hicn_name_t * name);
+int hicn_data_set_name (hicn_format_t format, hicn_header_t * data,
+ hicn_name_t * name);
+int hicn_data_get_locator (hicn_format_t format, const hicn_header_t * data,
+ ip_address_t * ip_address);
+int hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
+ const ip_address_t * ip_address);
+int hicn_data_compare (const hicn_header_t * data_1,
+ const hicn_header_t * data_2);
+int hicn_data_get_expiry_time (const hicn_header_t * data, u32 * expiry_time);
+int hicn_data_set_expiry_time (hicn_header_t * data, u32 expiry_time);
+int hicn_data_get_header_length (hicn_format_t format, hicn_header_t * data,
+ size_t * header_length);
+int hicn_data_get_payload_length (hicn_format_t format,
+ const hicn_header_t * data,
+ size_t * payload_length);
+int hicn_data_get_path_label (const hicn_header_t * data, u32 * path_label);
+int hicn_data_set_path_label (hicn_header_t * data, u32 path_label);
+int hicn_data_get_payload (hicn_format_t format, const hicn_header_t * data,
+ u8 ** payload, size_t * payload_size,
+ bool hard_copy);
+int hicn_data_set_payload (hicn_format_t format, hicn_header_t * data,
+ const u8 * payload, size_t payload_length);
+int hicn_data_get_payload_type (const hicn_header_t * data,
+ hicn_payload_type_t * payload_type);
+int hicn_data_set_payload_type (hicn_header_t * data,
+ hicn_payload_type_t payload_type);
+int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t * packet);
+
+#endif /* HICN_COMPAT_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/error.c b/lib/src/error.c
new file mode 100755
index 000000000..865e2b47d
--- /dev/null
+++ b/lib/src/error.c
@@ -0,0 +1,35 @@
+/*
+ * 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 error.c
+ * @brief Implementation of error management functions.
+ */
+
+#include "error.h"
+
+const char *HICN_LIB_ERROR_STRING[] = {
+#define _(a,b,c) [b] = c,
+ foreach_libhicn_error
+#undef _
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/error.h b/lib/src/error.h
new file mode 100755
index 000000000..3e027c4e5
--- /dev/null
+++ b/lib/src/error.h
@@ -0,0 +1,58 @@
+/*
+ * 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 error.h
+ * @brief Error management functions.
+ */
+#ifndef HICN_ERROR_H
+#define HICN_ERROR_H
+
+/******************************************************************************
+ * Error definitions
+ ******************************************************************************/
+
+#define foreach_libhicn_error \
+_(NONE, 0, "OK") \
+_(UNSPECIFIED, 128, "Unspecified Error") \
+_(NOT_IMPLEMENTED, 180, "Function not yet implemented") \
+_(NOT_HICN, 202, "Non hICN packet") \
+_(UNKNOWN_ADDRESS, 210, "Unknown address") \
+_(INVALID_PARAMETER, 220, "Invalid parameter") \
+_(INVALID_IP_ADDRESS, 221, "Invalid IP address") \
+_(CORRUPTED_PACKET, 222, "Corrupted packet ") \
+_(UNEXPECTED, 298, "Unexpected error")
+
+typedef enum
+{
+#define _(a,b,c) HICN_LIB_ERROR_##a = (-b),
+ foreach_libhicn_error
+#undef _
+ HICN_LIB_N_ERROR,
+} hicn_lib_error_t;
+
+extern const char *HICN_LIB_ERROR_STRING[];
+
+#define hicn_strerror(errno) (char *)(HICN_LIB_ERROR_STRING[-errno])
+
+#endif /* HICN_ERROR_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/header.h b/lib/src/header.h
new file mode 100755
index 000000000..3864064f2
--- /dev/null
+++ b/lib/src/header.h
@@ -0,0 +1,105 @@
+/*
+ * 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 header.h
+ * @brief hICN header data structures.
+ * details.
+ */
+#ifndef HICN_HEADER_H
+#define HICN_HEADER_H
+
+#include "common.h"
+#include "protocol.h"
+
+
+typedef struct
+{
+ _ipv6_header_t ip;
+ union
+ {
+ _tcp_header_t tcp;
+ _icmp_header_t icmp;
+ _icmp_wldr_header_t wldr;
+ };
+} hicn_v6_hdr_t;
+
+typedef struct
+{
+ _ipv6_header_t ip;
+ union
+ {
+ struct
+ {
+ _tcp_header_t tcp;
+ _ah_header_t ah;
+ };
+ struct
+ {
+ _icmp_header_t icmp;
+ _ah_header_t icmp_ah;
+ };
+ };
+} hicn_v6ah_hdr_t;
+
+typedef struct
+{
+ _ipv4_header_t ip;
+ union
+ {
+ _tcp_header_t tcp;
+ _icmp_header_t icmp;
+ _icmp_wldr_header_t wldr;
+ };
+} hicn_v4_hdr_t;
+
+typedef struct
+{
+ _ipv4_header_t ip;
+ union
+ {
+ struct
+ {
+ _tcp_header_t tcp;
+ _ah_header_t ah;
+ };
+ struct
+ {
+ _icmp_header_t icmp;
+ _ah_header_t icmp_ah;
+ };
+ };
+} hicn_v4ah_hdr_t;
+
+typedef union
+{
+ /* To deprecate as redundant with hicn_type_t */
+ hicn_v6_hdr_t v6;
+ hicn_v6ah_hdr_t v6ah;
+ hicn_v4_hdr_t v4;
+ hicn_v4ah_hdr_t v4ah;
+
+ hicn_protocol_t protocol;
+} hicn_header_t;
+
+#endif /* HICN_HEADER_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/hicn.h b/lib/src/hicn.h
new file mode 100755
index 000000000..749fd4247
--- /dev/null
+++ b/lib/src/hicn.h
@@ -0,0 +1,79 @@
+/*
+ * 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 hicn.h
+ * @brief hICN master include file.
+ *
+ * Reference: https://tools.ietf.org/html/draft-muscariello-intarea-hicn
+ *
+ * This file is the entry point for projects to libhicn, which provides a
+ * reference implementation for hICN specifications [1], including:
+ * - naming
+ * - packet headers
+ * - protocol mappings (IPv4, IPv6, TCP, ICMP, AH)
+ * - protocol independent packet operations
+ * - helpers for additional features such as Wireless Loss Detection and
+ * Recovery (WLDR) [2], Anchorless Mobility Management (hICN-AMM) [3],
+ * including MAP-Me producer mobility mechanisms [4].
+ *
+ * [1] Hybrid Information-Centric Networking
+ * L. Muscariello, G. Carofiglio, J. Augé, M. Papalini
+ * IETF draft (intarea) @ https://tools.ietf.org/html/draft-muscariello-intarea-hicn
+ *
+ * [2] Leveraging ICN in-network control for loss detection and recovery in wireless mobile networks
+ * G. Carofiglio, L. Muscariello, M. Papalini, N. Rozhnova, X. Zeng
+ * In proc. ICN'2016, Kyoto, JP
+ *
+ * [3] Anchorless mobility through hICN
+ * J. Augé, G. Carofiglio, L. Muscariello, M. Papalini
+ * IETF draft (DMM) @ https://tools.ietf.org/html/draft-auge-dmm-hicn-mobility
+ *
+ *
+ * [4] MAP-Me : Managing Anchorless Mobility in Content Centric Networking
+ * J. Augé, G. Carofiglio, L. Muscariello, M. Papalini
+ * IRTF draft (ICNRG) @ https://tools.ietf.org/html/draft-irtf-icnrg-mapme
+ */
+
+#ifndef HICN__H
+#define HICN__H
+
+#ifdef HICN_VPP_PLUGIN
+
+#include <hicn/header.h>
+#include <hicn/name.h>
+#include <hicn/ops.h>
+#include <hicn/mapme.h>
+
+#else
+
+#include <hicn/error.h>
+#include <hicn/header.h>
+#include <hicn/name.h>
+#include <hicn/ops.h>
+#include <hicn/mapme.h>
+#include <hicn/compat.h>
+
+#endif
+
+#endif /* HICN__H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/mapme.c b/lib/src/mapme.c
new file mode 100755
index 000000000..e4c5ee1f2
--- /dev/null
+++ b/lib/src/mapme.c
@@ -0,0 +1,224 @@
+/*
+ * 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 mapme.c
+ * @brief Implementation of MAP-Me anchorless producer mobility management.
+ */
+
+#include "mapme.h"
+#include "common.h"
+#include "error.h"
+
+#include "protocol/ipv4.h"
+#include "protocol/ipv6.h"
+
+size_t
+hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
+ const mapme_params_t * params)
+{
+ hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
+ /* *INDENT-OFF* */
+ *mh = (hicn_mapme_v4_header_t) {
+ .ip = {
+ .version_ihl = (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL),
+ .tos = IPV4_DEFAULT_TOS,
+ .len = HICN_MAPME_V4_HDRLEN,
+ .id = htons(IPV4_DEFAULT_ID),
+ .frag_off = htons(IPV4_DEFAULT_FRAG_OFF),
+ .ttl = HICN_MAPME_TTL,
+ .protocol = IPPROTO_ICMP,
+ .csum = 0,
+ .saddr.as_u32 = 0,
+ .daddr = prefix->name.ip4,
+ },
+ .icmp = {
+ .type = ((params->type == UPDATE) || (params->type == NOTIFICATION))
+ ? HICN_MAPME_ICMP_TYPE_IPV4
+ : HICN_MAPME_ICMP_TYPE_ACK_IPV4,
+ .code = HICN_MAPME_ICMP_CODE,
+ .csum = 0,
+ },
+ .icmp_rd = {
+ .ip = prefix->name.ip4,
+ },
+ .seq = htonl(params->seq),
+ .len = prefix->len,
+ };
+ /* *INDENT-ON* */
+
+ return HICN_MAPME_V4_HDRLEN;
+}
+
+size_t
+hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
+ const mapme_params_t * params)
+{
+ hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
+ /* *INDENT-OFF* */
+ *mh = (hicn_mapme_v6_header_t) {
+ .ip = {
+ .saddr = {{0}},
+ .daddr = prefix->name.ip6,
+ .version_class_flow = htonl(
+ (IPV6_DEFAULT_VERSION << 28) |
+ (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
+ (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
+ .len = htons(HICN_MAPME_V6_HDRLEN - IPV6_HDRLEN),
+ .nxt = IPPROTO_ICMPV6,
+ .hlim = HICN_MAPME_TTL,
+ },
+ .icmp = {
+ .type = ((params->type == UPDATE) || (params->type == NOTIFICATION))
+ ? HICN_MAPME_ICMP_TYPE_IPV6
+ : HICN_MAPME_ICMP_TYPE_ACK_IPV6,
+ .code = HICN_MAPME_ICMP_CODE,
+ .csum = 0,
+ },
+ .icmp_rd = {
+ .res = 0,
+ .tgt = prefix->name.ip6,
+ .dst = prefix->name.ip6,
+ },
+ .seq = htonl(params->seq),
+ .len = prefix->len,
+ };
+ /* *INDENT-ON* */
+ return HICN_MAPME_V6_HDRLEN;
+}
+
+size_t
+hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
+ const mapme_params_t * params)
+{
+ /* We currently ignore subsequent protocol definitions */
+ if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
+ return hicn_mapme_v6_create_packet (buf, prefix, params);
+ else
+ return hicn_mapme_v4_create_packet (buf, prefix, params);
+}
+
+size_t
+hicn_mapme_v4_create_ack (u8 * buf, const mapme_params_t * params)
+{
+ ip4_address_t tmp; // tmp storage for swapping IP addresses for ACK
+
+ hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
+ tmp = mh->ip.daddr;
+ mh->ip.daddr = mh->ip.saddr;
+ mh->ip.saddr = tmp;
+ mh->ip.ttl = HICN_MAPME_TTL;
+ mh->icmp.type = (params->type == UPDATE) ? UPDATE_ACK : NOTIFICATION_ACK;
+ mh->icmp.csum = 0;
+
+ return HICN_MAPME_V4_HDRLEN;
+}
+
+size_t
+hicn_mapme_v6_create_ack (u8 * buf, const mapme_params_t * params)
+{
+ ip6_address_t tmp; // tmp storage for swapping IP addresses for ACK
+
+ hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
+ tmp = mh->ip.daddr;
+ mh->ip.daddr = mh->ip.saddr;
+ mh->ip.saddr = tmp;
+ mh->ip.hlim = HICN_MAPME_TTL;
+ mh->icmp.type = (params->type == UPDATE) ? UPDATE_ACK : NOTIFICATION_ACK;
+ mh->icmp.csum = 0;
+
+ return HICN_MAPME_V6_HDRLEN;
+}
+
+size_t
+hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params)
+{
+ /* We currently ignore subsequent protocol definitions */
+ if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
+ return hicn_mapme_v6_create_ack (buf, params);
+ else
+ return hicn_mapme_v4_create_ack (buf, params);
+}
+
+int
+hicn_mapme_v4_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
+ mapme_params_t * params)
+{
+ hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) packet;
+
+ /* *INDENT-OFF* */
+ *prefix = (hicn_prefix_t) {
+ .name = {
+ .ip4 = HICN_MAPME_TYPE_IS_IU (mh->icmp.type) ? mh->ip.daddr : mh->ip.saddr,
+ },
+ .len = mh->len,
+ };
+
+ *params = (mapme_params_t) {
+ .protocol = IPPROTO_IP,
+ .type = (mh->icmp.type == HICN_MAPME_ICMP_TYPE_IPV4) ? UPDATE : UPDATE_ACK,
+ .seq = ntohl (mh->seq),
+ };
+ /* *INDENT-ON* */
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_mapme_v6_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
+ mapme_params_t * params)
+{
+ hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) packet;
+
+ /* *INDENT-OFF* */
+ *prefix = (hicn_prefix_t) {
+ .name = {
+ .ip6 = HICN_MAPME_TYPE_IS_IU (mh->icmp.type) ? mh->ip.daddr : mh->ip.saddr,
+ },
+ .len = mh->len,
+ };
+
+ *params = (mapme_params_t) {
+ .protocol = IPPROTO_IPV6,
+ .type = (mh->icmp.type == HICN_MAPME_ICMP_TYPE_IPV6) ? UPDATE : UPDATE_ACK,
+ .seq = ntohl (mh->seq),
+ };
+ /* *INDENT-ON* */
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
+ mapme_params_t * params)
+{
+ switch (HICN_IP_VERSION (packet))
+ {
+ case 4:
+ return hicn_mapme_v4_parse_packet (packet, prefix, params);
+ case 6:
+ return hicn_mapme_v6_parse_packet (packet, prefix, params);
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/mapme.h b/lib/src/mapme.h
new file mode 100755
index 000000000..460c15282
--- /dev/null
+++ b/lib/src/mapme.h
@@ -0,0 +1,152 @@
+/*
+ * 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 mapme.h
+ * @brief MAP-Me anchorless producer mobility management.
+ */
+#ifndef HICN_MAPME_H
+#define HICN_MAPME_H
+
+#include <stdint.h> // u32
+#include <stdbool.h>
+
+#include "common.h"
+#include "protocol.h"
+#include "ops.h"
+
+/**
+ * @brief MAP-Me configuration options
+ */
+typedef struct
+{
+ /** MAP-Me enabled flag (default: false) */
+ bool enabled;
+ /** timescale (T_U parameter) in ms (default: 0 for no notifications) */
+ u32 timescale;
+ /** retransmission timer in ms (default: 50) */
+ u32 retx;
+ /**
+ * Discovery enabled flag (default: true, should be true if mandatory is
+ * notifications are enabled)
+ */
+ bool discovery;
+} hicn_mapme_conf_t;
+
+/** @brief Default MAP-Me configuration */
+static const hicn_mapme_conf_t hicn_mapme_conf = {
+ .enabled = false,
+ .timescale = 0,
+ .retx = 50,
+ .discovery = true,
+};
+
+/** @brief MAP-Me update sequence number */
+typedef u32 seq_t;
+
+/** @brief MAP-Me packet types */
+typedef enum
+{
+ UNKNOWN,
+ UPDATE,
+ UPDATE_ACK,
+ NOTIFICATION,
+ NOTIFICATION_ACK,
+} hicn_mapme_type_t;
+
+/** @brief MAP-Me parameters (excluding those contained in * hicn_prefix_t) */
+typedef struct
+{
+ int protocol;
+ hicn_mapme_type_t type;
+ seq_t seq;
+} mapme_params_t;
+
+
+/* MAP-Me API */
+size_t hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
+ const mapme_params_t * params);
+size_t hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params);
+int hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
+ mapme_params_t * params);
+
+/* Implementation & parsing : ICMP Redirect */
+
+#define HEADER_TYPE_MAPME4 (hicn_type_t) {0, IPPROTO_ICMPRD, IPPROTO_ICMP, IPPROTO_IP}
+#define HEADER_TYPE_MAPME6 (hicn_type_t) {0, IPPROTO_ICMPRD, IPPROTO_ICMP, IPPROTO_IPV6}
+
+#define HICN_MAPME_ACK_FLAG (0x20 | 0x60)
+
+#define HICN_MAPME_ICMP_TYPE_IPV4 5
+#define HICN_MAPME_ICMP_TYPE_IPV6 137
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV4 (HICN_MAPME_ICMP_TYPE_IPV4 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV6 (HICN_MAPME_ICMP_TYPE_IPV6 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_CODE 0 /* Redirect Datagrams for the Network (or subnet) */
+
+#define HICN_MAPME_TYPE_IS_IU(type) ((type == HICN_MAPME_ICMP_TYPE_IPV4) || (type == HICN_MAPME_ICMP_TYPE_IPV6))
+#define HICN_MAPME_TYPE_IS_IU_ACK(type) ((type == HICN_MAPME_ICMP_TYPE_ACK_IPV4) || (type == HICN_MAPME_ICMP_TYPE_ACK_IPV6))
+
+#define HICN_MAPME_IS_IU(type, code) (HICN_MAPME_TYPE_IS_IU(type) && (code == HICN_MAPME_ICMP_CODE))
+#define HICN_MAPME_IS_ACK(type, code) (HICN_MAPME_TYPE_IS_IU_ACK(type) && (code == HICN_MAPME_ICMP_CODE))
+
+#define HICN_IS_MAPME(type, code) (HICN_MAPME_IS_IU(type, code) || HICN_MAPME_IS_ACK(type, code))
+
+/* Fast check for ACK flag */
+#define HICN_MAPME_IS_ACK_FAST(icmp_type) (icmp_type & HICN_MAPME_ACK_FLAG)
+
+/* Default TTL */
+#define HICN_MAPME_TTL 255 // typical for redirect (ref?)
+
+/** @brief MAP-Me packet header for IPv4 */
+typedef struct __attribute__ ((packed))
+{
+ _ipv4_header_t ip;
+ _icmp_header_t icmp;
+ _icmprd4_header_t icmp_rd;
+ seq_t seq;
+ u8 len;
+ u8 _pad[3];
+} hicn_mapme_v4_header_t;
+
+/** @brief MAP-Me packet header for IPv6 */
+typedef struct __attribute__ ((packed))
+{
+ _ipv6_header_t ip;
+ _icmp_header_t icmp;
+ _icmprd_header_t icmp_rd;
+ seq_t seq;
+ u8 len;
+ u8 _pad[3];
+} hicn_mapme_v6_header_t;
+
+/** @brief MAP-Me packet header (IP version agnostic) */
+typedef union
+{
+ hicn_mapme_v4_header_t v4;
+ hicn_mapme_v6_header_t v6;
+} hicn_mapme_header_t;
+
+#define HICN_MAPME_V4_HDRLEN sizeof(hicn_mapme_v4_header_t)
+#define HICN_MAPME_V6_HDRLEN sizeof(hicn_mapme_v6_header_t)
+
+#endif /* HICN_MAPME_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/name.c b/lib/src/name.c
new file mode 100755
index 000000000..6e5711252
--- /dev/null
+++ b/lib/src/name.c
@@ -0,0 +1,676 @@
+/*
+ * 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 name.c
+ * @brief Implementation of hICN name helpers.
+ */
+
+#include <arpa/inet.h> // inet_ptin
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h> // strtoul
+#include <string.h> // memcpy
+
+#include "common.h"
+#include "error.h"
+#include "name.h"
+
+#define DUMMY_PORT ntohs(1234)
+
+#if ! HICN_VPP_PLUGIN
+int
+hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name)
+{
+ int af, rc;
+
+ af = get_addr_family (ip_address);
+
+ switch (af)
+ {
+ case AF_INET:
+ if (name->type == HNT_UNSPEC)
+ {
+ name->type = HNT_CONTIGUOUS_V4;
+ }
+ name->len = IPV4_ADDR_LEN;
+ break;
+ case AF_INET6:
+ if (name->type == HNT_UNSPEC)
+ {
+ name->type = HNT_CONTIGUOUS_V6;
+ }
+ name->len = IPV6_ADDR_LEN;
+ break;
+ default:
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ }
+
+ if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
+ {
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ rc = inet_pton (af, ip_address, name->buffer);
+ if (rc <= 0)
+ {
+ return HICN_LIB_ERROR_UNKNOWN_ADDRESS;
+ }
+ *(u32 *) (name->buffer + name->len) = id;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_create_from_ip_address (const ip_address_t * ip_address, u32 id,
+ hicn_name_t * name)
+{
+ switch (ip_address->family)
+ {
+ case AF_INET:
+ if (name->type == HNT_UNSPEC)
+ {
+ name->type = HNT_CONTIGUOUS_V4;
+ }
+ break;
+ case AF_INET6:
+ if (name->type == HNT_UNSPEC)
+ {
+ name->type = HNT_CONTIGUOUS_V6;
+ }
+ break;
+ default:
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ }
+
+ name->len = ip_address->prefix_len;
+ if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
+ {
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ memcpy (name->buffer, ip_address->buffer, ip_address_len (ip_address));
+ *(u32 *) (name->buffer + name->len) = id;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+u8
+hicn_name_get_length (const hicn_name_t * name)
+{
+ return name->len;
+}
+
+int
+hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
+ bool consider_segment)
+{
+ hicn_name_t *name1 = (hicn_name_t *) name_1;
+ hicn_name_t *name2 = (hicn_name_t *) name_2;
+
+ if ((name1->type == HNT_CONTIGUOUS_V4 && name2->type == HNT_CONTIGUOUS_V6)
+ || (name1->type == HNT_CONTIGUOUS_V6
+ && name2->type == HNT_CONTIGUOUS_V4))
+ {
+ return -1;
+ }
+
+ if ((name1->type == HNT_IOV_V4 && name2->type == HNT_IOV_V6) ||
+ (name1->type == HNT_IOV_V6 && name2->type == HNT_IOV_V4))
+ {
+ return -1;
+ }
+
+ if ((name1->type == HNT_IOV_V4 && name2->type == HNT_CONTIGUOUS_V6) ||
+ (name1->type == HNT_IOV_V6 && name2->type == HNT_CONTIGUOUS_V4))
+ {
+ return -1;
+ }
+
+ if (name1->type == HNT_UNSPEC || name2->type == HNT_UNSPEC)
+ {
+ return -1;
+ }
+
+ size_t len1 = 0, len2 = 0;
+
+ u8 *buffer11, *buffer12, *buffer21, *buffer22;
+
+ switch (name1->type)
+ {
+ case HNT_CONTIGUOUS_V4:
+ buffer11 = name1->buffer;
+ buffer12 = name1->buffer + IPV4_ADDR_LEN;
+ len1 = IPV4_ADDR_LEN;
+ break;
+ case HNT_CONTIGUOUS_V6:
+ buffer11 = name1->buffer;
+ buffer12 = name1->buffer + IPV6_ADDR_LEN;
+ len1 = IPV6_ADDR_LEN;
+ break;
+ case HNT_IOV_V4:
+ buffer11 = name1->iov.buffers[0].iov_base;
+ buffer12 = name1->iov.buffers[1].iov_base;
+ len1 = IPV4_ADDR_LEN;
+ break;
+ case HNT_IOV_V6:
+ buffer11 = name1->iov.buffers[0].iov_base;
+ buffer12 = name1->iov.buffers[1].iov_base;
+ len1 = IPV6_ADDR_LEN;
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ switch (name2->type)
+ {
+ case HNT_CONTIGUOUS_V4:
+ buffer21 = name2->buffer;
+ buffer22 = name2->buffer + IPV4_ADDR_LEN;
+ len2 = IPV4_ADDR_LEN;
+ break;
+ case HNT_CONTIGUOUS_V6:
+ buffer21 = name2->buffer;
+ buffer22 = name2->buffer + IPV6_ADDR_LEN;
+ len2 = IPV6_ADDR_LEN;
+ break;
+ case HNT_IOV_V4:
+ buffer21 = name2->iov.buffers[0].iov_base;
+ buffer22 = name2->iov.buffers[1].iov_base;
+ len2 = IPV4_ADDR_LEN;
+ break;
+ case HNT_IOV_V6:
+ buffer21 = name2->iov.buffers[0].iov_base;
+ buffer22 = name2->iov.buffers[1].iov_base;
+ len2 = IPV6_ADDR_LEN;
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ // Sanity check
+ if (len1 != len2)
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ int ret1 = memcmp ((u8 *) buffer11, (u8 *) buffer21, len1);
+
+ if (!consider_segment)
+ {
+ return ret1;
+ }
+
+ int ret2 = memcmp ((u8 *) buffer12, (u8 *) buffer22, HICN_SEGMENT_LEN);
+
+ return ret1 || ret2;
+}
+
+int
+hicn_name_hash (const hicn_name_t * name, u32 * hash)
+{
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V4:
+ *hash = hash32 (name->buffer, HICN_V4_NAME_LEN);
+ break;
+ case HNT_CONTIGUOUS_V6:
+ *hash = hash32 (name->buffer, HICN_V6_NAME_LEN);
+ break;
+ case HNT_IOV_V4:
+ case HNT_IOV_V6:
+ *hash =
+ hash32 (name->iov.buffers[0].iov_base, name->iov.buffers[0].iov_len);
+ *hash =
+ cumulative_hash32 (name->iov.buffers[1].iov_base,
+ name->iov.buffers[1].iov_len, *hash);
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_empty (hicn_name_t * name)
+{
+ return name->type == HNT_UNSPEC ? HICN_LIB_ERROR_NONE : 1;
+}
+
+int
+hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src)
+{
+ switch (src->type)
+ {
+ case HNT_CONTIGUOUS_V4:
+ case HNT_CONTIGUOUS_V6:
+ *dst = *src;
+ break;
+ case HNT_IOV_V4:
+ case HNT_IOV_V6:
+ dst->type =
+ src->type == HNT_IOV_V4 ? HNT_CONTIGUOUS_V4 : HNT_CONTIGUOUS_V6;
+ memcpy (dst->buffer, src->iov.buffers[0].iov_base,
+ src->iov.buffers[0].iov_len);
+ memcpy (dst->buffer + src->iov.buffers[0].iov_len,
+ src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
+ bool copy_suffix)
+{
+ size_t length;
+
+ switch (src->type)
+ {
+ case HNT_CONTIGUOUS_V4:
+ if (copy_suffix)
+ {
+ length = HICN_V4_NAME_LEN;
+ }
+ else
+ {
+ length = IPV4_ADDR_LEN;
+ }
+ memcpy (dst, src->buffer, length);
+ break;
+ case HNT_CONTIGUOUS_V6:
+ if (copy_suffix)
+ {
+ length = HICN_V6_NAME_LEN;
+ }
+ else
+ {
+ length = IPV6_ADDR_LEN;
+ }
+ memcpy (dst, src->buffer, length);
+ break;
+ case HNT_IOV_V4:
+ case HNT_IOV_V6:
+ memcpy (dst, src->iov.buffers[0].iov_base, src->iov.buffers[0].iov_len);
+ if (copy_suffix)
+ {
+ memcpy (dst + src->iov.buffers[0].iov_len,
+ src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
+ }
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number)
+{
+ u8 *sequence_number = NULL;
+
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ sequence_number = name->buffer + IPV6_ADDR_LEN;
+ break;
+ case HNT_CONTIGUOUS_V4:
+ sequence_number = name->buffer + IPV4_ADDR_LEN;
+ break;
+ case HNT_IOV_V6:
+ case HNT_IOV_V4:
+ sequence_number = name->iov.buffers[1].iov_base;
+ break;
+ case HNT_UNSPEC:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ if (sequence_number)
+ {
+ *(u32 *) sequence_number = seq_number;
+ }
+ else
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_to_sockaddr_address (const hicn_name_t * name,
+ struct sockaddr *ip_address)
+{
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
+ struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
+
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ tmp6->sin6_family = AF_INET6;
+ tmp6->sin6_scope_id = 0;
+ tmp6->sin6_port = DUMMY_PORT;
+ memcpy (&tmp6->sin6_addr, name->buffer, IPV6_ADDR_LEN);
+ break;
+ case HNT_IOV_V6:
+ tmp6->sin6_family = AF_INET6;
+ tmp6->sin6_scope_id = 0;
+ tmp6->sin6_port = DUMMY_PORT;
+ memcpy (&tmp6->sin6_addr, name->iov.buffers[0].iov_base,
+ name->iov.buffers[0].iov_len);
+ break;
+ case HNT_CONTIGUOUS_V4:
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, name->buffer, IPV4_ADDR_LEN);
+ break;
+ case HNT_IOV_V4:
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, name->iov.buffers[0].iov_base,
+ name->iov.buffers[0].iov_len);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_to_ip_address (const hicn_name_t * name, ip_address_t * ip_address)
+{
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ memcpy (&ip_address->buffer, name->buffer, IPV6_ADDR_LEN);
+ ip_address->family = AF_INET6;
+ break;
+ case HNT_IOV_V6:
+ memcpy (&ip_address->buffer, name->iov.buffers[0].iov_base,
+ name->iov.buffers[0].iov_len);
+ ip_address->family = AF_INET6;
+ break;
+ case HNT_CONTIGUOUS_V4:
+ memcpy (&ip_address->buffer, name->buffer, IPV4_ADDR_LEN);
+ ip_address->family = AF_INET;
+ break;
+ case HNT_IOV_V4:
+ memcpy (&ip_address->buffer, name->iov.buffers[0].iov_base,
+ name->iov.buffers[0].iov_len);
+ ip_address->family = AF_INET;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number)
+{
+ const u8 *sequence_number = NULL;
+
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ sequence_number = name->buffer + IPV6_ADDR_LEN;
+ break;
+ case HNT_CONTIGUOUS_V4:
+ sequence_number = name->buffer + IPV4_ADDR_LEN;
+ break;
+ case HNT_IOV_V6:
+ case HNT_IOV_V4:
+ sequence_number = name->iov.buffers[1].iov_base;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ if (sequence_number)
+ {
+ *seq_number = *(u32 *) sequence_number;
+ }
+ else
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len)
+{
+ int offset;
+ const char *rc;
+ void *seg_number = NULL;
+
+ switch (src->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ rc = inet_ntop (AF_INET6, src->buffer, dst, len);
+ seg_number = (u8 *) src->buffer + IPV6_ADDR_LEN;
+ break;
+ case HNT_CONTIGUOUS_V4:
+ rc = inet_ntop (AF_INET, src->buffer, dst, len);
+ seg_number = (u8 *) src->buffer + IPV4_ADDR_LEN;
+ break;
+ case HNT_IOV_V6:
+ rc = inet_ntop (AF_INET6, src->iov.buffers[0].iov_base, dst, len);
+ seg_number = src->iov.buffers[1].iov_base;
+ break;
+ case HNT_IOV_V4:
+ rc = inet_ntop (AF_INET, src->iov.buffers[0].iov_base, dst, len);
+ seg_number = src->iov.buffers[1].iov_base;
+ break;
+ default:
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (!rc)
+ {
+ goto ERR;
+ }
+
+ offset = strlen (dst);
+ dst[offset] = '|';
+
+ sprintf (dst + offset + 1, "%lu", (unsigned long) (*(u32 *) seg_number));
+
+ return HICN_LIB_ERROR_NONE;
+
+ERR:
+ return HICN_LIB_ERROR_UNSPECIFIED;
+}
+
+int
+hicn_name_pton (const char *src, hicn_name_t * dst)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+}
+
+int
+hicn_name_get_family (const hicn_name_t * name, int *family)
+{
+ switch (name->type)
+ {
+ case HNT_CONTIGUOUS_V6:
+ case HNT_IOV_V6:
+ *family = AF_INET6;
+ break;
+ case HNT_CONTIGUOUS_V4:
+ case HNT_IOV_V4:
+ *family = AF_INET;
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_prefix_create_from_ip_address (const ip_address_t * ip_address,
+ hicn_prefix_t * prefix)
+{
+ switch (ip_address->family)
+ {
+ case AF_INET:
+ prefix->name.ip4.as_u32 = ip_address->as_u32[0];
+ break;
+ case AF_INET6:
+ prefix->name.ip6.as_u64[0] = ip_address->as_u64[0];
+ prefix->name.ip6.as_u64[1] = ip_address->as_u64[1];
+ break;
+ default:
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ }
+ prefix->len = ip_address->prefix_len;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+#endif /* ! HICN_VPP_PLUGIN */
+
+/********
+ * IP
+ */
+
+inline int
+ip_address_len (const ip_address_t * ip_address)
+{
+ return (ip_address->family == AF_INET6) ? IPV6_ADDR_LEN :
+ (ip_address->family == AF_INET) ? IPV4_ADDR_LEN : 0;
+}
+
+bool
+ip_address_empty (const ip_address_t * ip_address)
+{
+ return ip_address->prefix_len == 0;
+}
+
+int
+hicn_ip_ntop (const ip_address_t * ip_address, char *dst, const size_t len)
+{
+ const char *rc;
+
+ rc = inet_ntop (ip_address->family, ip_address->buffer, dst, len);
+ if (!rc)
+ {
+ printf ("error ntop: %d %s\n", errno, strerror (errno));
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+/*
+ * Parse ip addresses in presentation format, or prefixes (in bits, separated by a slash)
+ */
+int
+hicn_ip_pton (const char *ip_address_str, ip_address_t * ip_address)
+{
+ int pton_fd;
+ char *p;
+ char *eptr;
+ u32 dst_len;
+ char *addr = strdup (ip_address_str);
+
+ p = strchr (addr, '/');
+ if (!p)
+ {
+ dst_len = 0; // until we get the ip address family
+ }
+ else
+ {
+ dst_len = strtoul (p + 1, &eptr, 10);
+ *p = 0;
+ }
+
+ ip_address->family = get_addr_family (addr);
+
+ switch (ip_address->family)
+ {
+ case AF_INET6:
+ if (dst_len > IPV6_ADDR_LEN_BITS)
+ goto ERR;
+ pton_fd = inet_pton (AF_INET6, addr, &ip_address->buffer);
+ ip_address->prefix_len = dst_len ? : IPV6_ADDR_LEN_BITS;
+ break;
+ case AF_INET:
+ if (dst_len > IPV4_ADDR_LEN_BITS)
+ goto ERR;
+ pton_fd = inet_pton (AF_INET, addr, &ip_address->buffer);
+ ip_address->prefix_len = dst_len ? : IPV4_ADDR_LEN_BITS;
+ break;
+ default:
+ goto ERR;
+ }
+
+ // 0 = not in presentation format
+ // < 0 = other error (use perror)
+ if (pton_fd <= 0)
+ {
+ goto ERR;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+ERR:
+ free (addr);
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+}
+
+int
+hicn_ip_to_sockaddr_address (const ip_address_t * ip_address,
+ struct sockaddr *sockaddr_address)
+{
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sockaddr_address;
+ struct sockaddr_in *tmp4 = (struct sockaddr_in *) sockaddr_address;
+
+ switch (ip_address->family)
+ {
+ case AF_INET6:
+ tmp6->sin6_family = AF_INET6;
+ tmp6->sin6_port = DUMMY_PORT;
+ tmp6->sin6_scope_id = 0;
+ memcpy (&tmp6->sin6_addr, ip_address->buffer, IPV6_ADDR_LEN);
+ break;
+ case AF_INET:
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, ip_address->buffer, IPV4_ADDR_LEN);
+ break;
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/name.h b/lib/src/name.h
new file mode 100755
index 000000000..0a55fedc6
--- /dev/null
+++ b/lib/src/name.h
@@ -0,0 +1,336 @@
+/*
+ * 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 name.h
+ * @brief hICN name helpers.
+ *
+ * The purpose of the file is to offer an efficient, platform- and protocol-
+ * independent way to manipulate hICN names.
+ */
+
+#ifndef HICN_NAME_H
+#define HICN_NAME_H
+
+#include <stdbool.h>
+#include <netinet/in.h> // struct sockadd
+
+#include "common.h"
+
+/******************************************************************************
+ * IP address helpers
+ ******************************************************************************/
+
+/* Presentation format */
+#define INET_ADDRSTRLEN 16
+#define INET6_ADDRSTRLEN 46
+//#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN
+
+/* Address size */
+#define bytes_to_bits(x) (x * 8)
+#define IPV6_ADDR_LEN 16 /* bytes */
+#define IPV4_ADDR_LEN 4 /* bytes */
+#define IPV6_ADDR_LEN_BITS bytes_to_bits(IPV6_ADDR_LEN)
+#define IPV4_ADDR_LEN_BITS bytes_to_bits(IPV4_ADDR_LEN)
+
+#define IP_MAX_ADDR_LEN IPV6_ADDR_LEN
+#define TCP_SEQNO_LEN 4 /* bytes */
+
+typedef struct
+{
+ union
+ {
+ u8 buffer[IP_MAX_ADDR_LEN];
+ u8 as_u8[IP_MAX_ADDR_LEN];
+ u16 as_u16[IP_MAX_ADDR_LEN >> 1];
+ u32 as_u32[IP_MAX_ADDR_LEN >> 2];
+ u64 as_u64[IP_MAX_ADDR_LEN >> 3];
+ ip4_address_t as_ip4;
+ ip6_address_t as_ip6;
+ };
+ int family;
+ unsigned short prefix_len;
+} ip_address_t;
+
+int ip_address_len (const ip_address_t * ip_address);
+bool ip_address_empty (const ip_address_t * ip_address);
+
+int hicn_ip_ntop (const ip_address_t * ip_address, char *dst,
+ const size_t len);
+int hicn_ip_pton (const char *ip_address_str, ip_address_t * ip_address);
+int hicn_ip_to_sockaddr_address (const ip_address_t * ip_address,
+ struct sockaddr *sockaddr_address);
+
+/******************************************************************************
+ * hICN names
+ ******************************************************************************/
+
+#define HICN_V4_PREFIX_LEN IPV4_ADDR_LEN
+#define HICN_V6_PREFIX_LEN IPV6_ADDR_LEN
+#define HICN_SEGMENT_LEN TCP_SEQNO_LEN
+#define HICN_V6_NAME_LEN (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes */
+#define HICN_V4_NAME_LEN (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes */
+
+/* Prefix */
+
+typedef u32 hicn_name_suffix_t;
+
+typedef struct
+{
+ ip46_address_t name;
+ u8 len;
+} hicn_prefix_t;
+
+/*
+ * Name
+ *
+ * A name is a prefix + a segment name (suffix)
+ */
+
+typedef union
+{
+ struct
+ {
+ union
+ {
+ u32 prefix;
+ u8 prefix_as_u8[4];
+ ip4_address_t prefix_as_ip4;
+ };
+ hicn_name_suffix_t suffix;
+ };
+ u8 buffer[HICN_V4_NAME_LEN];
+} hicn_v4_name_t;
+
+typedef union
+{
+ struct
+ {
+ union
+ {
+ u64 prefix[2];
+ u8 prefix_as_u8[16];
+ ip6_address_t prefix_as_ip6;
+ };
+ hicn_name_suffix_t suffix;
+ };
+ u8 buffer[HICN_V6_NAME_LEN];
+} hicn_v6_name_t;
+
+typedef struct
+{
+ u8 buffer[0];
+} hicn_v46_name_t;
+
+#ifndef HICN_VPP_PLUGIN
+#define HICN_NAME_COMPONENT_SIZE 2
+
+typedef struct
+{
+ struct iovec buffers[HICN_NAME_COMPONENT_SIZE];
+} hicn_iov_name_t;
+
+#define UNSPEC 1 << 0
+#define HNT_CONTIGUOUS 1 << 1
+#define HNT_IOV 1 << 2
+#define HNT_INET 1 << 3
+#define HNT_INET6 1 << 4
+
+typedef enum
+{
+ HNT_UNSPEC = UNSPEC,
+ HNT_CONTIGUOUS_V4 = HNT_CONTIGUOUS | HNT_INET,
+ HNT_CONTIGUOUS_V6 = HNT_CONTIGUOUS | HNT_INET6,
+ HNT_IOV_V4 = HNT_IOV | HNT_INET,
+ HNT_IOV_V6 = HNT_IOV | HNT_INET6,
+} hicn_name_type_t;
+#endif /* HICN_VPP_PLUGIN */
+
+typedef struct
+{
+#ifndef HICN_VPP_PLUGIN
+ hicn_name_type_t type;
+ u8 len;
+#endif /* HICN_VPP_PLUGIN */
+ union
+ {
+ hicn_v4_name_t ip4;
+ hicn_v6_name_t ip6;
+ ip46_address_t ip46;
+#ifndef HICN_VPP_PLUGIN
+ hicn_iov_name_t iov;
+ u8 buffer[0];
+#endif /* HICN_VPP_PLUGIN */
+ };
+} hicn_name_t;
+
+#ifndef HICN_VPP_PLUGIN
+#define _is_unspec(name) ((name->type & UNSPEC))
+#define _is_contiguous(name) ((name->type & HNT_CONTIGUOUS) >> 1)
+#define _is_iov(name) ((name->type & HNT_IOV) >> 2)
+#define _is_inet4(name) ((name->type & HNT_INET) >> 3)
+#define _is_inet6(name) ((name->type & HNT_INET6) >> 4)
+#endif /* HICN_VPP_PLUGIN */
+
+/**
+ * @brief Create an hICN name from IP address in presentation format
+ * @param [in] ip_address - IP address
+ * @param [in] id - Segment identifier
+ * @param [out] Resulting hICN name
+ * @return hICN error code
+ */
+int hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name);
+
+/**
+ * @brief Create an hICN name from IP address
+ * @param [in] ip_address - IP address
+ * @param [in] id Segment - identifier
+ * @param [out] Resulting - hICN name
+ * @return hICN error code
+ */
+int hicn_name_create_from_ip_address (const ip_address_t * ip_address, u32 id,
+ hicn_name_t * name);
+
+/**
+ * @brief Returns the length of an hICN name
+ * @param [in] name - hICN name
+ * @return Name length
+ */
+u8 hicn_name_get_length (const hicn_name_t * name);
+
+/**
+ * @brief Compare two hICN names
+ * @param [in] name_1 - First name to compare
+ * @param [in] name_2 - Second name to compare
+ * @param [in] consider_segment - Flag indicating whether the segment part has to be
+ * considered
+ * @return An integer less than, equal to, or greater than zero if name_1 is
+ * found, respectively, to be lest than, to match, or be greater than name_2
+ * based on numeric order.
+ */
+int hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
+ bool consider_segment);
+
+/**
+ * @brief Provides a 32-bit hash of an hICN name
+ * @param [in] name - Name to hash
+ * @param [out] hash - Resulting hash
+ * @return hICN error code
+ */
+int hicn_name_hash (const hicn_name_t * name, u32 * hash);
+
+/**
+ * @brief Test whether an hICN name is empty
+ * @param [in] name - Name to test
+ * @return 0 if the name is empty, any other value otherwise (implementation
+ * returns 1)
+ */
+int hicn_name_empty (hicn_name_t * name);
+
+/**
+ * @brief Copy an hICN name
+ * @param [out] dst - Destination name
+ * @param [in] src - Source name to copy
+ * @return hICN error code
+ */
+int hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src);
+
+/**
+ * @brief Copy an hICN name to a buffer
+ * @param [out] dst - Destination buffer
+ * @param [in] src - Source name to copy
+ * @param [in] copy_suffix - Flag indicating whether the suffix has to be
+ * considered
+ */
+int hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
+ bool copy_suffix);
+
+/**
+ * @brief Sets the segment part of an hICN name
+ * @param [in,out] name - hICN name to modify
+ * @param [in] seq_number - Segment identifier
+ * @return hICN error code
+ */
+int hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number);
+
+/**
+ * @brief Retrieves the segment part of an hICN name
+ * @param [in,out] name - hICN name
+ * @param [in] seq_number - Segment identifier
+ * @return hICN error code
+ */
+int hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number);
+
+/**
+ * @brief Convert an hICN name to a socket address
+ * @param [in] name - Name to convert
+ * @param [out] ip_address - Resulting socket address
+ * @return hICN error code
+ */
+int hicn_name_to_sockaddr_address (const hicn_name_t * name,
+ struct sockaddr *ip_address);
+
+/**
+ * @brief Convert an hICN name to an IP address
+ * @param [in] name - Name to convert
+ * @param [out] ip_address - Resulting IP address
+ * @return hICN error code
+ */
+int hicn_name_to_ip_address (const hicn_name_t * name,
+ ip_address_t * ip_address);
+
+/**
+ * @brief Convert an hICN name to presentation format
+ * @param [in] src - Name to convert
+ * @param [out] dst - Buffer to receive the name in presentation format
+ * @param [in] len - Number of bytes available in the buffer
+ * @return hICN error code
+ */
+int hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len);
+
+/**
+ * @brief Convert an hICN name from presentation format
+ * @param [in] src - Name in presentation format to parse
+ * @param [out] dst - Resulting name
+ * @return hICN error code
+ */
+int hicn_name_pton (const char *src, hicn_name_t * dst);
+
+/**
+ * @brief Returns the IP address family of an hICN name
+ * @param [in] name - Name to lookup
+ * @param [out] family - Resulting IP address family (AF_INET or AF_INET6)
+ * @return hICN error code
+ */
+int hicn_name_get_family (const hicn_name_t * name, int *family);
+
+/**
+ * @brief Creates an hICN prefix from an IP address
+ * @param [in] ip_address - Input IP address
+ * @param [out] prefix - Resulting prefix
+ * @return hICN error code
+ */
+int hicn_prefix_create_from_ip_address (const ip_address_t * ip_address,
+ hicn_prefix_t * prefix);
+
+#endif /* HICN_NAME_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/ops.c b/lib/src/ops.c
new file mode 100755
index 000000000..ad45a13a5
--- /dev/null
+++ b/lib/src/ops.c
@@ -0,0 +1,93 @@
+/*
+ * 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 ops.c
+ * @brief Initializers for protocol-independent packet operations
+ */
+
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "ops.h"
+
+#include "header.h"
+
+extern const hicn_ops_t hicn_ops_ipv4;
+extern const hicn_ops_t hicn_ops_icmp;
+extern const hicn_ops_t hicn_ops_tcp;
+extern const hicn_ops_t hicn_ops_ipv6;
+extern const hicn_ops_t hicn_ops_ah;
+
+/* Declare empty operations (terminates recursion on protocol layers) */
+DECLARE_init_packet_header (none, NONE);
+DECLARE_get_interest_locator (none, NONE);
+DECLARE_set_interest_locator (none, NONE);
+DECLARE_get_interest_name (none, NONE);
+DECLARE_set_interest_name (none, NONE);
+DECLARE_get_interest_name_suffix (none, NONE);
+DECLARE_set_interest_name_suffix (none, NONE);
+DECLARE_reset_interest_for_hash (none, NONE);
+DECLARE_get_data_locator (none, NONE);
+DECLARE_set_data_locator (none, NONE);
+DECLARE_get_data_name (none, NONE);
+DECLARE_set_data_name (none, NONE);
+DECLARE_get_data_name_suffix (none, NONE);
+DECLARE_set_data_name_suffix (none, NONE);
+DECLARE_get_data_pathlabel (none, NONE);
+DECLARE_set_data_pathlabel (none, NONE);
+DECLARE_update_data_pathlabel (none, NONE);
+DECLARE_reset_data_for_hash (none, NONE);
+DECLARE_get_lifetime (none, NONE);
+DECLARE_set_lifetime (none, NONE);
+DECLARE_update_checksums (none, NONE);
+DECLARE_verify_checksums (none, NONE);
+DECLARE_rewrite_interest (none, NONE);
+DECLARE_rewrite_data (none, NONE);
+DECLARE_get_length (none, NONE);
+DECLARE_get_header_length (none, NONE);
+DECLARE_get_current_header_length (none, NONE);
+DECLARE_get_payload_length (none, NONE);
+DECLARE_set_payload_length (none, NONE);
+DECLARE_get_signature_size (none, NONE);
+DECLARE_set_signature_size (none, NONE);
+DECLARE_set_signature_timestamp (none, NONE);
+DECLARE_get_signature_timestamp (none, NONE);
+DECLARE_set_validation_algorithm (none, NONE);
+DECLARE_get_validation_algorithm (none, NONE);
+DECLARE_set_key_id (none, NONE);
+DECLARE_get_key_id (none, NONE);
+DECLARE_HICN_OPS (none);
+
+/**
+ * @brief Virtual function table for packet operations
+ * NOTE: protocol numbers have to be kept in order
+ */
+const hicn_ops_t *const hicn_ops_vft[] = {
+ /* 0 */ [IPPROTO_IP] = &hicn_ops_ipv4,
+ /* 1 */ [IPPROTO_ICMP] = &hicn_ops_icmp,
+ /* 6 */ [IPPROTO_TCP] = &hicn_ops_tcp,
+ /* 41 */ [IPPROTO_IPV6] = &hicn_ops_ipv6,
+ /* 51 */ [IPPROTO_AH] = &hicn_ops_ah,
+ /* 58 */ [IPPROTO_ICMPV6] = &hicn_ops_icmp,
+ [IPPROTO_NONE] = &hicn_ops_none,
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/ops.h b/lib/src/ops.h
new file mode 100755
index 000000000..d56e6ae4a
--- /dev/null
+++ b/lib/src/ops.h
@@ -0,0 +1,624 @@
+/*
+ * 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 base.h
+ * @brief Protocol-independent packet operations
+ */
+
+#ifndef HICN_OPS_H
+#define HICN_OPS_H
+
+#include <stdlib.h>
+
+#include "error.h"
+#include "header.h"
+#include "name.h"
+
+/*
+ * hICN operations on packets
+ *
+ * All prototypes take an hicn_type_t parameter as their first argument, as this
+ * decides the sequence of protocols that are being used by the different
+ * operations.
+ */
+
+typedef struct hicn_ops_s
+{
+ /** Protocol name */
+ const char *name;
+
+ /**
+ * @brief Initialize the headers of the hicn packet
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the packet
+ */
+ int (*init_packet_header) (hicn_type_t type, hicn_protocol_t * h);
+
+ /**
+ * @brief Retrieves an Interest locator
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest packet
+ * @param [out] ip_address - Retrieved locator
+ * @return hICN error code
+ */
+ int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address);
+
+ /**
+ * @brief Sets an Interest locator
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @param [in] ip_address - Locator to set
+ * @return hICN error code
+ */
+ int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address);
+
+ /**
+ * @brief Retrieves an Interest name
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest packet
+ * @param [out] name - Retrieved name
+ * @return hICN error code
+ */
+ int (*get_interest_name) (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name);
+
+ /**
+ * @brief Sets an Interest name
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @param [in] name - Name to set
+ * @return hICN error code
+ */
+ int (*set_interest_name) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name);
+
+ /**
+ * @brief Retrieves an Interest name suffix
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest packet
+ * @param [out] suffix - Retrieved name suffix
+ * @return hICN error code
+ */
+ int (*get_interest_name_suffix) (hicn_type_t type,
+ const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix);
+
+ /**
+ * @brief Sets an Interest name suffix
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @param [in] suffix - Name suffix to set
+ * @return hICN error code
+ */
+ int (*set_interest_name_suffix) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix);
+
+ /**
+ * @brief Clear the necessary Interest fields in order to hash it
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @return hICN error code
+ */
+ int (*reset_interest_for_hash) (hicn_type_t type, hicn_protocol_t * h);
+
+ /**
+ * @brief Retrieves a Data locator
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Data packet
+ * @param [out] ip_address - Retrieved locator
+ * @return hICN error code
+ */
+ int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address);
+
+ /**
+ * @brief Sets a Data locator
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @param [in] ip_address - Locator to set
+ * @return hICN error code
+ */
+ int (*set_data_locator) (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address);
+
+ /**
+ * @brief Retrieves a Data name
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Data packet
+ * @param [out] name - Retrieved name
+ * @return hICN error code
+ */
+ int (*get_data_name) (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name);
+
+ /**
+ * @brief Sets a Data name
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @param [in] name - Name to set
+ * @return hICN error code
+ */
+ int (*set_data_name) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name);
+
+ /**
+ * @brief Retrieves a Data name suffix
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Data packet
+ * @param [out] suffix - Retrieved name suffix
+ * @return hICN error code
+ */
+ int (*get_data_name_suffix) (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix);
+
+ /**
+ * @brief Sets a Data name suffix
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @param [in] suffix - Name suffix to set
+ * @return hICN error code
+ */
+ int (*set_data_name_suffix) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix);
+
+ /**
+ * @brief Retrieves a Data pathlabel
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Data packet
+ * @param [out] pathlabel - Retrieved pathlabel
+ * @return hICN error code
+ */
+ int (*get_data_pathlabel) (hicn_type_t type, const hicn_protocol_t * h,
+ u32 * pathlabel);
+
+ /**
+ * @brief Sets a Data pathlabel
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @param [in] pathlabel - Pathlabel to set
+ * @return hICN error code
+ */
+ int (*set_data_pathlabel) (hicn_type_t type, hicn_protocol_t * h,
+ const u32 pathlabel);
+
+ /**
+ * @brief Update a Data pathlabel with a new face identifier
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @param [in] pathlabel - Face identifier used to update pathlabel
+ * @return hICN error code
+ */
+ int (*update_data_pathlabel) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_faceid_t face_id);
+
+ /**
+ * @brief Clear the necessary Data fields in order to hash it
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Data packet
+ * @return hICN error code
+ */
+ int (*reset_data_for_hash) (hicn_type_t type, hicn_protocol_t * h);
+
+ /**
+ * @brief Retrieves an Interest or Data lifetime
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] pathlabel - Retrieved lifetime
+ * @return hICN error code
+ */
+ int (*get_lifetime) (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_lifetime_t * lifetime);
+
+ /**
+ * @brief Sets an Interest or Data lifetime
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] pathlabel - Lifetime to set
+ * @return hICN error code
+ */
+ int (*set_lifetime) (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_lifetime_t lifetime);
+
+ /**
+ * @brief Update all checksums in packet headers
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the packet
+ * @param [in] partial_csum - Partial checksum (set to 0, used internally to
+ * carry intermediate values from IP pseudo-header)
+ * @param [in] payload_length - Payload length (can be set to 0, retrieved
+ * and used internally to carry payload length across protocol headers)
+ * @return hICN error code
+ */
+ int (*update_checksums) (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length);
+
+ /**
+ * @brief Validate all checksums in packet headers
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the packet
+ * @param [in] partial_csum - Partial checksum (set to 0, used internally to
+ * carry intermediate values from IP pseudo-header)
+ * @param [in] payload_length - Payload length (can be set to 0, retrieved
+ * and used internally to carry payload length across protocol headers)
+ * @return hICN error code
+ */
+ int (*verify_checksums) (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length);
+
+ /**
+ * @brief Rewrite an Interest packet header (locator)
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest packet
+ * @param [in] addr_new - New locator
+ * @param [in] addr_old - Old locator (set to NULL, used internally to
+ * compute incremental checksums)
+ * @return hICN error code
+ */
+ int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old);
+
+ /**
+ * @brief Rewrite a Data packet header (locator + pathlabel)
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Data packet
+ * @param [in] addr_new - New locator
+ * @param [in] addr_old - Old locator (set to NULL, used internally to
+ * compute incremental checksums)
+ * @param [in] face_id - Face identifier used to update pathlabel
+ * @return hICN error code
+ */
+ int (*rewrite_data) (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old,
+ const hicn_faceid_t face_id);
+
+ /**
+ * @brief Return the packet length
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the packet
+ * @parma [out] length - Returned packet length
+ * @return hICN error code
+ */
+ int (*get_length) (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * length);
+
+ /**
+ * @brief Return the current packet header length
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the packet
+ * @parma [out] header_length - Returned packet current header length
+ * @return hICN error code
+ */
+ int (*get_current_header_length) (hicn_type_t type,
+ const hicn_protocol_t * h,
+ size_t * header_length);
+
+ /**
+ * @brief Return the packet header length
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the packet
+ * @parma [out] header_length - Returned packet header length
+ * @return hICN error code
+ */
+ int (*get_header_length) (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length);
+
+ /**
+ * @brief Return the packet payload length
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the packet
+ * @parma [out] payload_length - Returned packet payload length
+ * @return hICN error code
+ */
+ int (*get_payload_length) (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * payload_length);
+
+ /**
+ * @brief Sets the packet paylaod length
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the packet
+ * @parma [out] payload_length - Payload length to set
+ * @return hICN error code
+ */
+ int (*set_payload_length) (hicn_type_t type, hicn_protocol_t * h,
+ size_t payload_length);
+
+ /**
+ * @brief Retrieves an Interest or Data signature size
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] signature_size - Retrieved signature size
+ * @return hICN error code
+ */
+ int (*get_signature_size) (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size);
+
+ /**
+ * @brief Sets an Interest or Data signature size
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] signature_size - Signature size to set
+ * @return hICN error code
+ */
+ int (*set_signature_size) (hicn_type_t type, hicn_protocol_t * h,
+ size_t signature_size);
+
+ /**
+ * @brief Sets the signature timestamp
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] signature_timestamp - Signature timestamp to set
+ * @return hICN error code
+ */
+ int (*set_signature_timestamp) (hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp);
+
+ /**
+ * @brief Gets the signature timestamp
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [out] signature_timestamp - Retrieved signature timestamp
+ * @return hICN error code
+ */
+ int (*get_signature_timestamp) (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t *signature_timestamp);
+
+ /**
+ * @brief Sets the signature validation algorithm
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] validation_algorithm - Validation algorithm enumeration
+ * @return hICN error code
+ */
+ int (*set_validation_algorithm) (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm);
+
+ /**
+ * @brief Gets the signature validation algorithm
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [out] validation_algorithm - Retrieved validation_algorithm
+ * @return hICN error code
+ */
+ int (*get_validation_algorithm) (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t *validation_algorithm);
+
+ /**
+ * @brief Sets the key id
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] key_id - Key id first byte address
+ * @return hICN error code
+ */
+ int (*set_key_id) (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id);
+
+ /**
+ * @brief Gets the key id
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [out] key_id - Retrieved key id first byte address
+ * @return hICN error code
+ */
+ int (*get_key_id) (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size);
+
+} hicn_ops_t;
+
+#define DECLARE_HICN_OPS(protocol) \
+ const hicn_ops_t hicn_ops_ ## protocol = { \
+ .init_packet_header = protocol ## _init_packet_header, \
+ .get_interest_locator = protocol ## _get_interest_locator, \
+ .set_interest_locator = protocol ## _set_interest_locator, \
+ .get_interest_name = protocol ## _get_interest_name, \
+ .set_interest_name = protocol ## _set_interest_name, \
+ .get_interest_name_suffix = protocol ## _get_interest_name_suffix, \
+ .set_interest_name_suffix = protocol ## _set_interest_name_suffix, \
+ .reset_interest_for_hash = protocol ## _reset_interest_for_hash, \
+ .get_data_locator = protocol ## _get_data_locator, \
+ .set_data_locator = protocol ## _set_data_locator, \
+ .get_data_name = protocol ## _get_data_name, \
+ .set_data_name = protocol ## _set_data_name, \
+ .get_data_name_suffix = protocol ## _get_data_name_suffix, \
+ .set_data_name_suffix = protocol ## _set_data_name_suffix, \
+ .get_data_pathlabel = protocol ## _get_data_pathlabel, \
+ .set_data_pathlabel = protocol ## _set_data_pathlabel, \
+ .update_data_pathlabel = protocol ## _update_data_pathlabel, \
+ .reset_data_for_hash = protocol ## _reset_data_for_hash, \
+ .get_lifetime = protocol ## _get_lifetime, \
+ .set_lifetime = protocol ## _set_lifetime, \
+ .update_checksums = protocol ## _update_checksums, \
+ .verify_checksums = protocol ## _verify_checksums, \
+ .rewrite_interest = protocol ## _rewrite_interest, \
+ .rewrite_data = protocol ## _rewrite_data, \
+ .get_length = protocol ## _get_length, \
+ .get_current_header_length= protocol ## _get_current_header_length, \
+ .get_header_length = protocol ## _get_header_length, \
+ .get_payload_length = protocol ## _get_payload_length, \
+ .set_payload_length = protocol ## _set_payload_length, \
+ .get_signature_size = protocol ## _get_signature_size, \
+ .set_signature_size = protocol ## _set_signature_size, \
+ .set_signature_timestamp = protocol ## _set_signature_timestamp, \
+ .get_signature_timestamp = protocol ## _get_signature_timestamp, \
+ .set_validation_algorithm = protocol ## _set_validation_algorithm, \
+ .get_validation_algorithm = protocol ## _get_validation_algorithm, \
+ .set_key_id = protocol ## _set_key_id, \
+ .get_key_id = protocol ## _get_key_id, \
+ }
+
+/**
+ * @brief Protocol-independent packet operations VFT
+ * NOTE: The following declarations should be kept in order
+ */
+extern const hicn_ops_t *const hicn_ops_vft[];
+
+/*
+ * Helpers for writing recursive protocol operations on packet headers
+ *
+ * NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is IPv4...)
+ */
+always_inline hicn_type_t
+TYPE_POP (hicn_type_t type)
+{
+ return (hicn_type_t)
+ {
+ {
+ .l1 = type.l2,.l2 = type.l3,.l3 = type.l4,.l4 = IPPROTO_NONE,}
+ };
+}
+
+always_inline hicn_protocol_t *
+PAYLOAD (hicn_type_t type, const hicn_protocol_t * h)
+{
+ size_t header_length;
+ int rc = hicn_ops_vft[type.l1]->get_current_header_length (type, h,
+ &header_length);
+ if (rc < 0)
+ return NULL;
+ return (hicn_protocol_t *) ((u8 *) h + header_length);
+}
+
+#define CHILD_OPS(f, type, h, ...) (hicn_ops_vft[type.l2]->f(TYPE_POP(type), PAYLOAD(type, h), ## __VA_ARGS__))
+
+/** Shortcuts to entry points in VFT */
+#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP]
+#define HICN_OPS6 hicn_ops_vft[IPPROTO_IPV6]
+
+/* Helpers for simple declarations */
+
+#define DECLARE_init_packet_header(protocol, error) \
+ int protocol ## _init_packet_header(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_interest_locator(protocol, error) \
+ int protocol ## _get_interest_locator(hicn_type_t type, const hicn_protocol_t * h, ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_interest_locator(protocol, error) \
+ int protocol ## _set_interest_locator(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_interest_name(protocol, error) \
+ int protocol ## _get_interest_name(hicn_type_t type, const hicn_protocol_t * h, hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_interest_name(protocol, error) \
+ int protocol ## _set_interest_name(hicn_type_t type, hicn_protocol_t * h, const hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_interest_name_suffix(protocol, error) \
+ int protocol ## _get_interest_name_suffix(hicn_type_t type, const hicn_protocol_t * h, hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_interest_name_suffix(protocol, error) \
+ int protocol ## _set_interest_name_suffix(hicn_type_t type, hicn_protocol_t * h, const hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_reset_interest_for_hash(protocol, error) \
+ int protocol ## _reset_interest_for_hash(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_data_locator(protocol, error) \
+ int protocol ## _get_data_locator(hicn_type_t type, const hicn_protocol_t * h, ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_data_locator(protocol, error) \
+ int protocol ## _set_data_locator(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_data_name(protocol, error) \
+ int protocol ## _get_data_name(hicn_type_t type, const hicn_protocol_t * h, hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_data_name(protocol, error) \
+ int protocol ## _set_data_name(hicn_type_t type, hicn_protocol_t * h, const hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_data_name_suffix(protocol, error) \
+ int protocol ## _get_data_name_suffix(hicn_type_t type, const hicn_protocol_t * h, hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_data_name_suffix(protocol, error) \
+ int protocol ## _set_data_name_suffix(hicn_type_t type, hicn_protocol_t * h, const hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_data_pathlabel(protocol, error) \
+ int protocol ## _get_data_pathlabel(hicn_type_t type, const hicn_protocol_t * h, u32 * pathlabel) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_data_pathlabel(protocol, error) \
+ int protocol ## _set_data_pathlabel(hicn_type_t type, hicn_protocol_t * h, const u32 pathlabel) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_update_data_pathlabel(protocol, error) \
+ int protocol ## _update_data_pathlabel(hicn_type_t type, hicn_protocol_t * h, const hicn_faceid_t face_id) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_reset_data_for_hash(protocol, error) \
+ int protocol ## _reset_data_for_hash(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_lifetime(protocol, error) \
+ int protocol ## _get_lifetime(hicn_type_t type, const hicn_protocol_t * h, hicn_lifetime_t * lifetime) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_lifetime(protocol, error) \
+ int protocol ## _set_lifetime(hicn_type_t type, hicn_protocol_t * h, const hicn_lifetime_t lifetime) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_update_checksums(protocol, error) \
+ int protocol ## _update_checksums(hicn_type_t type, hicn_protocol_t * h, u16 partial_csum, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_verify_checksums(protocol, error) \
+ int protocol ## _verify_checksums(hicn_type_t type, hicn_protocol_t * h, u16 partial_csum, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_rewrite_interest(protocol, error) \
+ int protocol ## _rewrite_interest(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_rewrite_data(protocol, error) \
+ int protocol ## _rewrite_data(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old, const hicn_faceid_t face_id) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_length(protocol, error) \
+ int protocol ## _get_length(hicn_type_t type, const hicn_protocol_t * h, size_t * length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_current_header_length(protocol, error) \
+ int protocol ## _get_current_header_length(hicn_type_t type, const hicn_protocol_t * h, size_t * header_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_header_length(protocol, error) \
+ int protocol ## _get_header_length(hicn_type_t type, const hicn_protocol_t * h, size_t * header_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_payload_length(protocol, error) \
+ int protocol ## _get_payload_length(hicn_type_t type, const hicn_protocol_t * h, size_t * payload_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_payload_length(protocol, error) \
+ int protocol ## _set_payload_length(hicn_type_t type, hicn_protocol_t * h, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_signature_size(protocol, error) \
+ int protocol ## _get_signature_size(hicn_type_t type, const hicn_protocol_t * h, size_t * signature_size) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_signature_size(protocol, error) \
+ int protocol ## _set_signature_size(hicn_type_t type, hicn_protocol_t * h, size_t signature_size) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_signature_timestamp(protocol, error) \
+ int protocol ## _set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h, uint64_t signature_timestamp) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_signature_timestamp(protocol, error) \
+ int protocol ## _get_signature_timestamp(hicn_type_t type, const hicn_protocol_t * h, uint64_t * signature_timestamp) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_validation_algorithm(protocol, error) \
+ int protocol ## _set_validation_algorithm(hicn_type_t type, hicn_protocol_t * h, uint8_t validation_algorithm) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_validation_algorithm(protocol, error) \
+ int protocol ## _get_validation_algorithm(hicn_type_t type, const hicn_protocol_t * h, uint8_t * validation_algorithm) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_set_key_id(protocol, error) \
+ int protocol ## _set_key_id(hicn_type_t type, hicn_protocol_t * h, uint8_t * key_id) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_get_key_id(protocol, error) \
+ int protocol ## _get_key_id(hicn_type_t type, hicn_protocol_t * h, uint8_t ** key_id, uint8_t *key_id_size) { return HICN_LIB_ERROR_ ## error ; }
+
+#endif /* HICN_OPS_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol.h b/lib/src/protocol.h
new file mode 100755
index 000000000..a97cc99cf
--- /dev/null
+++ b/lib/src/protocol.h
@@ -0,0 +1,51 @@
+/*
+ * 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 protocol.h
+ * @brief Protocol header definitions
+ */
+#ifndef HICN_PROTOCOL_H
+#define HICN_PROTOCOL_H
+
+#include "protocol/ah.h"
+#include "protocol/ipv4.h"
+#include "protocol/ipv6.h"
+#include "protocol/icmp.h"
+#include "protocol/icmprd.h"
+#include "protocol/tcp.h"
+#include "protocol/udp.h"
+
+typedef union
+{
+ _ipv4_header_t ipv4;
+ _ipv6_header_t ipv6;
+ _tcp_header_t tcp;
+ _udp_header_t udp;
+ _icmp_header_t icmp;
+ _icmprd_header_t icmprd;
+ _ah_header_t ah;
+ void *bytes;
+} hicn_protocol_t;
+
+#endif /* HICN_PROTOCOL_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
new file mode 100755
index 000000000..f9ddf7775
--- /dev/null
+++ b/lib/src/protocol/ah.c
@@ -0,0 +1,211 @@
+/*
+ * 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 protocol/ah.c
+ * @brief hICN operations for AH header
+ */
+
+#include <string.h> // memcpy
+#include "../common.h"
+#include "../error.h"
+#include "../header.h"
+#include "../ops.h"
+#include "ah.h"
+
+DECLARE_get_interest_locator (ah, UNEXPECTED);
+DECLARE_set_interest_locator (ah, UNEXPECTED);
+DECLARE_get_interest_name (ah, UNEXPECTED);
+DECLARE_set_interest_name (ah, UNEXPECTED);
+DECLARE_get_interest_name_suffix (ah, UNEXPECTED);
+DECLARE_set_interest_name_suffix (ah, UNEXPECTED);
+DECLARE_get_data_locator (ah, UNEXPECTED);
+DECLARE_set_data_locator (ah, UNEXPECTED);
+DECLARE_get_data_name (ah, UNEXPECTED);
+DECLARE_set_data_name (ah, UNEXPECTED);
+DECLARE_get_data_name_suffix (ah, UNEXPECTED);
+DECLARE_set_data_name_suffix (ah, UNEXPECTED);
+DECLARE_get_data_pathlabel (ah, UNEXPECTED);
+DECLARE_set_data_pathlabel (ah, UNEXPECTED);
+DECLARE_update_data_pathlabel (ah, UNEXPECTED);
+DECLARE_get_lifetime (ah, UNEXPECTED);
+DECLARE_set_lifetime (ah, UNEXPECTED);
+DECLARE_get_payload_length (ah, UNEXPECTED);
+DECLARE_set_payload_length (ah, UNEXPECTED);
+
+int
+ah_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+}
+
+int
+ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ size_t signature_size;
+ int rc =
+ hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size);
+ if (rc < 0)
+ return rc;
+ memset (&(h->ah.validationPayload), 0, signature_size);
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ size_t signature_size;
+ int rc =
+ hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size);
+ if (rc < 0)
+ return rc;
+ memset (&(h->ah.validationPayload), 0, signature_size);
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+ah_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ size_t payload_length)
+{
+ /* Nothing to do as there is no checksum in AH */
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ size_t payload_length)
+{
+ /* Nothing to do as there is no checksum in AH */
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old)
+{
+ /* Nothing to do on signature */
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ const hicn_faceid_t face_id)
+{
+ /* Nothing to do on signature */
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_length (hicn_type_t type, const hicn_protocol_t * h, size_t * length)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+}
+
+int
+ah_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = AH_HDRLEN + (h->ah.payloadlen << 2);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *header_length = AH_HDRLEN + (h->ah.payloadlen << 2) + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size)
+{
+ *signature_size = h->ah.payloadlen << 2;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ const size_t signature_size)
+{
+ h->ah.payloadlen = signature_size >> 2;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp)
+{
+ h->ah.timestamp_as_u64 = signature_timestamp;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t * signature_timestamp)
+{
+ *signature_timestamp = h->ah.timestamp_as_u64;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm)
+{
+ h->ah.validationAlgorithm = validation_algorithm;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t * validation_algorithm)
+{
+ *validation_algorithm = h->ah.validationAlgorithm;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_set_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id)
+{
+ memcpy(h->ah.keyId, key_id, sizeof(h->ah.keyId));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ *key_id = h->ah.keyId;
+ *key_id_size = sizeof(h->ah.keyId);
+ return HICN_LIB_ERROR_NONE;
+}
+
+DECLARE_HICN_OPS (ah);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ah.h b/lib/src/protocol/ah.h
new file mode 100755
index 000000000..0b4171135
--- /dev/null
+++ b/lib/src/protocol/ah.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.
+ */
+
+/**
+ * @file protocol/ah.h
+ * @brief AH packet header
+ */
+#ifndef HICN_PROTOCOL_AH_H
+#define HICN_PROTOCOL_AH_H
+
+/*
+ * The TCP PSH flag is set to indicate TCP payload in fact contains a AH header
+ * with signature information for the packet
+ */
+#define AH_FLAG 0x10
+
+typedef struct
+{
+ u8 nh; // (to match with reserved in IPSEC AH)
+ u8 payloadlen; // Len of signature/HMAC in 4-bytes words
+ union
+ {
+ u16 reserved;
+ struct
+ {
+ u8 validationAlgorithm; // As defined in parc_SignerAlgorithm.h
+ u8 unused; // Unused (to match with reserved in IPSEC AH)
+ };
+ };
+ union
+ {
+ struct
+ {
+ u32 spi;
+ u32 seq;
+ };
+ union
+ {
+ u8 timestamp_as_u8[8];
+ u64 timestamp_as_u64;
+ }; // Unix timestamp indicating when the signature has been calculated
+
+ };
+ // ICV would follow
+ u8 keyId[32]; // Hash of the pub key
+ /* 44 B + validationPayload */
+ u8 validationPayload[0]; // Holds the signature
+} _ah_header_t;
+
+#define AH_HDRLEN sizeof(_ah_header_t)
+
+#endif /* HICN_PROTOCOL_AH_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
new file mode 100755
index 000000000..44b646fb2
--- /dev/null
+++ b/lib/src/protocol/icmp.c
@@ -0,0 +1,229 @@
+/*
+ * 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 <string.h>
+#include "icmp.h"
+
+#include "../error.h"
+#include "../ops.h"
+
+DECLARE_get_interest_locator (icmp, UNEXPECTED)
+DECLARE_set_interest_locator (icmp, UNEXPECTED)
+DECLARE_get_interest_name (icmp, UNEXPECTED)
+DECLARE_set_interest_name (icmp, UNEXPECTED)
+DECLARE_get_interest_name_suffix (icmp, UNEXPECTED)
+DECLARE_set_interest_name_suffix (icmp, UNEXPECTED)
+DECLARE_get_data_locator (icmp, UNEXPECTED)
+DECLARE_set_data_locator (icmp, UNEXPECTED)
+DECLARE_get_data_name (icmp, UNEXPECTED)
+DECLARE_set_data_name (icmp, UNEXPECTED)
+DECLARE_get_data_name_suffix (icmp, UNEXPECTED)
+DECLARE_set_data_name_suffix (icmp, UNEXPECTED)
+DECLARE_get_data_pathlabel (icmp, UNEXPECTED)
+DECLARE_set_data_pathlabel (icmp, UNEXPECTED)
+DECLARE_update_data_pathlabel (icmp, UNEXPECTED)
+DECLARE_get_lifetime (icmp, UNEXPECTED)
+DECLARE_set_lifetime (icmp, UNEXPECTED)
+DECLARE_get_length (icmp, UNEXPECTED)
+DECLARE_get_payload_length (icmp, UNEXPECTED)
+DECLARE_set_payload_length (icmp, UNEXPECTED)
+ int icmp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->icmp = (_icmp_header_t)
+ {
+ .type = 0,.code = 0,.csum = 0,};
+
+ return HICN_LIB_ERROR_NONE; // CHILD_OPS(init_packet_header, type, h->icmp);
+}
+
+int
+icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->icmp.csum = 0;
+
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->icmp.csum = 0;
+
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+int
+icmp_update_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+// h->icmp.csum = 0;
+// h->icmp.csum = csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum);
+//
+// return CHILD_OPS(update_checksums, type, h->icmp, 0, payload_length);
+}
+
+int
+icmp_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+// if (csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
+// return HICN_LIB_ERROR_CORRUPTED_PACKET;
+// return CHILD_OPS(verify_checksums, type, h->icmp, 0, payload_length);
+}
+
+int
+icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+// u16 *icmp_checksum = &(h->icmp.csum);
+//
+// /*
+// * Padding fields are set to zero so we can apply checksum on the
+// * whole struct by interpreting it as IPv6 in all cases
+// *
+// * v4 code would be:
+// * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
+// * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+// */
+// u16 csum = ip_csum_sub_even (*icmp_checksum, h->ipv6.saddr.as_u64[0]);
+// csum = ip_csum_sub_even (csum, h->ipv6.saddr.as_u64[1]);
+// csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[0]);
+// csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[1]);
+//
+// *icmp_checksum = ip_csum_fold (csum);
+//
+// return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ const hicn_faceid_t face_id)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+// u16 *icmp_checksum = &(h->icmp.csum);
+//
+// /*
+// * Padding fields are set to zero so we can apply checksum on the
+// * whole struct by interpreting it as IPv6 in all cases
+// *
+// * v4 code would be:
+// * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
+// * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+// */
+// u16 csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[0]);
+// csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[1]);
+// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]);
+// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]);
+//
+// csum = ip_csum_sub_even (csum, h->icmp.pathlabel);
+// icmp_update_data_pathlabel(type, h, face_id);
+// csum = ip_csum_add_even (csum, h->icmp.pathlabel);
+//
+// *icmp_checksum = ip_csum_fold (csum);
+//
+// return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = ICMP_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+
+ *header_length = ICMP_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+icmp_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+icmp_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+icmp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t * signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+icmp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+icmp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t * validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+icmp_set_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+icmp_get_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+DECLARE_HICN_OPS (icmp);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/icmp.h b/lib/src/protocol/icmp.h
new file mode 100755
index 000000000..5a84995b6
--- /dev/null
+++ b/lib/src/protocol/icmp.h
@@ -0,0 +1,68 @@
+/*
+ * 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 protocol/icmp.h
+ * @brief ICMP packet header
+ */
+#ifndef HICN_PROTOCOL_ICMP_H
+#define HICN_PROTOCOL_ICMP_H
+
+#include "../common.h"
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+} _icmp_header_t;
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+ union
+ {
+ struct
+ {
+ u16 id;
+ u16 sequence;
+ } echo; /* echo datagram */
+ u32 gateway; /* gateway address */
+ struct
+ {
+ u16 _unused;
+ u16 mtu;
+ } frag; /* path mtu discovery */
+ struct
+ {
+ u16 expected_lbl;
+ u16 received_lbl;
+ } wldr_notification_lbl;
+ };
+} _icmp_wldr_header_t;
+
+#define ICMP_HDRLEN sizeof(_icmp_header_t)
+
+#endif /* HICN_PROTOCOL_ICMP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/icmprd.h b/lib/src/protocol/icmprd.h
new file mode 100755
index 000000000..c2f27d673
--- /dev/null
+++ b/lib/src/protocol/icmprd.h
@@ -0,0 +1,47 @@
+/*
+ * 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 protocol/icmp-rd.c
+ * @brief hICN operations for ICMP Redirect header
+ */
+#ifndef HICN_PROTOCOL_ICMPRD_H
+#define HICN_PROTOCOL_ICMPRD_H
+
+#include "../common.h"
+
+typedef struct __attribute__ ((__packed__))
+{
+ ip4_address_t ip;
+ _ipv4_header_t iph;
+ u8 data[64];
+} _icmprd4_header_t;
+
+typedef struct __attribute__ ((__packed__))
+{
+ u32 res;
+ ip6_address_t tgt;
+ ip6_address_t dst;
+} _icmprd_header_t;
+
+#endif /* HICN_PROTOCOL_ICMPRD_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
new file mode 100755
index 000000000..7c6af127d
--- /dev/null
+++ b/lib/src/protocol/ipv4.c
@@ -0,0 +1,452 @@
+/*
+ * 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 protocol/ipv4.c
+ * @brief hICN operations for IPv4 header
+ *
+ * NOTE: IPv4 options (affecting the header size) are currently not supported.
+ */
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../error.h"
+#include "../ops.h"
+#include "../common.h"
+#include "../header.h"
+
+#include "ipv4.h"
+
+int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * payload_length);
+
+int
+ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+{
+ size_t total_header_length;
+ int rc =
+ hicn_ops_vft[type.l1]->get_header_length (type, h, &total_header_length);
+ if (rc < 0)
+ return rc;
+
+ h->ipv4 = (_ipv4_header_t)
+ {
+ .version_ihl =
+ (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL),.tos =
+ IPV4_DEFAULT_TOS,.len = htons ((u16) total_header_length),.id =
+ htons (IPV4_DEFAULT_ID),.frag_off =
+ htons (IPV4_DEFAULT_FRAG_OFF),.ttl = HICN_DEFAULT_TTL,.protocol =
+ type.l2,.csum = 0,.saddr.as_u32 = 0,.daddr.as_u32 = 0,};
+
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address)
+{
+ ip_address->ip4 = h->ipv4.saddr;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address)
+{
+ h->ipv4.saddr = ip_address->ip4;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name)
+{
+ name->ip4.prefix_as_ip4 = h->ipv4.daddr;
+#ifndef HICN_VPP_PLUGIN
+ name->type = HNT_CONTIGUOUS_V4;
+ name->len = HICN_V4_NAME_LEN;
+#endif /* HICN_VPP_PLUGIN */
+ return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip4.suffix));
+}
+
+int
+ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name)
+{
+ h->ipv4.daddr = name->ip4.prefix_as_ip4;
+ return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip4.suffix));
+}
+
+int
+ipv4_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+}
+
+int
+ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+}
+
+int
+ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ /* Sets everything to 0 up to IP destination address */
+ memset (&(h->ipv4), 0, 16);
+
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address)
+{
+ ip_address->ip4 = h->ipv4.daddr;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address)
+{
+ h->ipv4.daddr = ip_address->ip4;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name)
+{
+ name->ip4.prefix_as_ip4 = h->ipv4.saddr;
+#ifndef HICN_VPP_PLUGIN
+ name->type = HNT_CONTIGUOUS_V4;
+ name->len = HICN_V4_NAME_LEN;
+#endif /* HICN_VPP_PLUGIN */
+ return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip4.suffix));
+}
+
+int
+ipv4_set_data_name (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name)
+{
+ h->ipv4.saddr = name->ip4.prefix_as_ip4;
+ return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip4.suffix));
+}
+
+int
+ipv4_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (get_data_name_suffix, type, h, suffix);
+}
+
+int
+ipv4_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (set_data_name_suffix, type, h, suffix);
+}
+
+int
+ipv4_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
+ u32 * pathlabel)
+{
+ return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
+}
+
+int
+ipv4_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const u32 pathlabel)
+{
+ return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
+}
+
+int
+ipv4_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_faceid_t face_id)
+{
+ return CHILD_OPS (update_data_pathlabel, type, h, face_id);
+}
+
+int
+ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ /* Sets everything to 0 up to source address */
+ memset (&h->ipv4, 0, 12);
+ /* Clears destination address */
+ memset (&(h->ipv4.daddr), 0, 4);
+
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+int
+ipv4_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_lifetime_t * lifetime)
+{
+ return CHILD_OPS (get_lifetime, type, h, lifetime);
+}
+
+int
+ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_lifetime_t lifetime)
+{
+ return CHILD_OPS (set_lifetime, type, h, lifetime);
+}
+
+int
+ipv4_update_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ /*
+ * Checksum field is not accounted for in lower layers, so we can compute
+ * them in any order. Note that it is only a header checksum.
+ */
+ h->ipv4.csum = 0;
+ h->ipv4.csum = csum (h, IPV4_HDRLEN, 0);
+
+ /* Retrieve payload length if not specified, as it is not available later */
+ if (payload_length == 0)
+ {
+ int rc = ipv4_get_payload_length (type, h, &payload_length);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Ignore the payload if payload_length = ~0 */
+ if (payload_length == ~0)
+ {
+ payload_length = 0;
+ }
+
+ /* Build pseudo-header */
+ ipv4_pseudo_header_t psh;
+ psh.ip_src = h->ipv4.saddr;
+ psh.ip_dst = h->ipv4.daddr;
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
+ psh.zero = 0;
+ psh.protocol = (u8) h->ipv4.protocol;
+
+ /* Compute partial checksum based on pseudo-header */
+ if (partial_csum != 0)
+ {
+ partial_csum = ~partial_csum;
+ }
+ partial_csum = csum (&psh, IPV4_PSHDRLEN, partial_csum);
+
+ return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ /*
+ * Checksum field is not accounted for in lower layers, so we can compute
+ * them in any order. Note that it is only a header checksum.
+ */
+ if (csum (h, IPV4_HDRLEN, 0) != 0)
+ return HICN_LIB_ERROR_CORRUPTED_PACKET;
+
+ /* Retrieve payload length if not specified, as it is not available later */
+ if (payload_length == 0)
+ {
+ int rc = ipv4_get_payload_length (type, h, &payload_length);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Build pseudo-header */
+ ipv4_pseudo_header_t psh;
+ psh.ip_src = h->ipv4.saddr;
+ psh.ip_dst = h->ipv4.daddr;
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
+ psh.zero = 0;
+ psh.protocol = (u8) h->ipv4.protocol;
+
+ /* Compute partial checksum based on pseudo-header */
+ partial_csum = csum (&psh, IPV4_PSHDRLEN, 0);
+
+ return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old)
+{
+ // ASSERT(addr_old == NULL);
+ addr_old->ip4 = h->ipv4.saddr;
+ addr_old->pad[0] = 0;
+ addr_old->pad[1] = 0;
+ addr_old->pad[2] = 0;
+
+ h->ipv4.saddr = addr_new->ip4;
+ h->ipv4.csum = 0;
+ h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
+
+ return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
+}
+
+int
+ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ const hicn_faceid_t face_id)
+{
+ // ASSERT(addr_old == NULL);
+ addr_old->ip4 = h->ipv4.daddr;
+ addr_old->pad[0] = 0;
+ addr_old->pad[1] = 0;
+ addr_old->pad[2] = 0;
+
+ h->ipv4.daddr = addr_new->ip4;
+ h->ipv4.csum = 0;
+ h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
+
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id);
+}
+
+int
+ipv4_get_current_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = IPV4_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = h->ipv4.len;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = IPV4_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *header_length = IPV4_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * payload_length)
+{
+ size_t child_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *payload_length = htons (h->ipv4.len) - IPV4_HDRLEN - child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t * h,
+ size_t payload_length)
+{
+ size_t child_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ h->ipv4.len = htons (payload_length + IPV4_HDRLEN + child_header_length);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+ipv4_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+ipv4_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t * signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+ipv4_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+ipv4_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t * validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+ipv4_set_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+ipv4_get_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+DECLARE_HICN_OPS (ipv4);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv4.h b/lib/src/protocol/ipv4.h
new file mode 100755
index 000000000..c57485b6c
--- /dev/null
+++ b/lib/src/protocol/ipv4.h
@@ -0,0 +1,91 @@
+/*
+ * 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 HICN_PROTOCOL_IPV4
+#define HICN_PROTOCOL_IPV4
+
+#include "../base.h"
+#include "../common.h"
+#include "../protocol.h"
+
+/* Headers were adapted from linux' definitions in netinet/ip.h */
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ u8 ihl:4;
+ u8 version:4;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ u8 version:4;
+ u8 ihl:4;
+#else
+#error "Unsupported endianness"
+#endif
+ };
+
+ u8 version_ihl;
+ };
+ u8 tos;
+ u16 len;
+ u16 id;
+ u16 frag_off;
+ u8 ttl;
+ u8 protocol;
+ u16 csum;
+ ip4_address_t saddr;
+ ip4_address_t daddr;
+} _ipv4_header_t;
+
+#define ipv4_header_bytes(ipv4_header) (sizeof(u32) * (ipv4_header->version_ihl & 0xf))
+
+#define IPV4_HDRLEN sizeof(_ipv4_header_t)
+
+typedef struct
+{
+ ip4_address_t ip_src;
+ ip4_address_t ip_dst;
+ u8 zero;
+ u8 protocol;
+ u16 size;
+} ipv4_pseudo_header_t;
+
+#define IPV4_PSHDRLEN sizeof(ipv4_pseudo_header_t)
+
+/* Default field values */
+#define IPV4_DEFAULT_VERSION 4
+#define IPV4_DEFAULT_IHL 5
+#define IPV4_DEFAULT_TOS 0
+#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV4_DEFAULT_ID 300
+#define IPV4_DEFAULT_FRAG_OFF 0x000
+#define IPV4_DEFAULT_TTL 64
+#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
+#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
+#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
+
+
+#endif /* HICN_PROTOCOL_IPV4 */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
new file mode 100755
index 000000000..41b00ec92
--- /dev/null
+++ b/lib/src/protocol/ipv6.c
@@ -0,0 +1,412 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "../common.h"
+#include "../error.h"
+#include "../ops.h"
+
+int
+ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * payload_length);
+
+int
+ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+{
+ size_t total_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &total_header_length);
+ if (rc < 0)
+ return rc;
+
+ /* *INDENT-OFF* */
+ h->ipv6 = (_ipv6_header_t)
+ {
+ .saddr = {{ 0 }}
+ ,.daddr = {{ 0 }}
+ ,.version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) |
+ (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
+ (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
+ .len = htons ((u16) total_header_length),
+ .nxt = type.l2,
+ .hlim = HICN_DEFAULT_TTL,
+ };
+ /* *INDENT-ON* */
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address)
+{
+ ip_address->ip6 = h->ipv6.saddr;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address)
+{
+ h->ipv6.saddr = ip_address->ip6;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name)
+{
+ name->ip6.prefix_as_ip6 = h->ipv6.daddr;
+#ifndef HICN_VPP_PLUGIN
+ name->type = HNT_CONTIGUOUS_V6;
+ name->len = HICN_V6_NAME_LEN;
+#endif /* HICN_VPP_PLUGIN */
+ return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip6.suffix));
+}
+
+int
+ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name)
+{
+ h->ipv6.daddr = name->ip6.prefix_as_ip6;
+ return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip6.suffix));
+}
+
+int
+ipv6_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
+}
+
+int
+ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+}
+
+int
+ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ /* Sets everything to 0 up to IP destination address */
+ memset (&(h->ipv6), 0, 24);
+
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t * h,
+ ip46_address_t * ip_address)
+{
+ ip_address->ip6 = h->ipv6.daddr;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * ip_address)
+{
+ h->ipv6.daddr = ip_address->ip6;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_t * name)
+{
+ name->ip6.prefix_as_ip6 = h->ipv6.saddr;
+#ifndef HICN_VPP_PLUGIN
+ name->type = HNT_CONTIGUOUS_V6;
+ name->len = HICN_V6_NAME_LEN;
+#endif /* HICN_VPP_PLUGIN */
+ return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip6.suffix));
+}
+
+int
+ipv6_set_data_name (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_t * name)
+{
+ h->ipv6.saddr = name->ip6.prefix_as_ip6;
+ return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip6.suffix));
+}
+
+int
+ipv6_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (get_data_name_suffix, type, h, suffix);
+}
+
+int
+ipv6_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ return CHILD_OPS (set_data_name_suffix, type, h, suffix);
+}
+
+int
+ipv6_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
+ u32 * pathlabel)
+{
+ return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
+}
+
+int
+ipv6_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const u32 pathlabel)
+{
+ return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
+}
+
+int
+ipv6_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_faceid_t face_id)
+{
+ return CHILD_OPS (update_data_pathlabel, type, h, face_id);
+}
+
+int
+ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ /* IP: Set everithing to 0 up to destination address */
+ memset (&h->ipv6, 0, 8);
+ /* Clears destination address */
+ memset (&(h->ipv6.daddr), 0, 16);
+
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+int
+ipv6_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_lifetime_t * lifetime)
+{
+ return CHILD_OPS (get_lifetime, type, h, lifetime);
+}
+
+int
+ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_lifetime_t lifetime)
+{
+ return CHILD_OPS (set_lifetime, type, h, lifetime);
+}
+
+int
+ipv6_update_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ /* Retrieve payload length if not specified */
+ if (payload_length == 0)
+ {
+ int rc = ipv6_get_payload_length (type, h, &payload_length);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Ignore the payload if payload_length = ~0 */
+ if (payload_length == ~0)
+ {
+ payload_length = 0;
+ }
+
+ /* Build pseudo-header */
+ ipv6_pseudo_header_t psh;
+ psh.ip_src = h->ipv6.saddr;
+ psh.ip_dst = h->ipv6.daddr;
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ psh.size = htonl (ntohs (h->ipv6.len));
+ psh.zeros = 0;
+ psh.zero = 0;
+ psh.protocol = h->ipv6.nxt;
+
+ /* Compute partial checksum based on pseudo-header */
+ if (partial_csum != 0)
+ {
+ partial_csum = ~partial_csum;
+ }
+ partial_csum = csum (&psh, IPV6_PSHDRLEN, partial_csum);
+
+ return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
+ u16 partial_csum, size_t payload_length)
+{
+ /* Retrieve payload length if not specified */
+ if (payload_length == 0)
+ {
+ int rc = ipv6_get_payload_length (type, h, &payload_length);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Build pseudo-header */
+ ipv6_pseudo_header_t pseudo;
+ pseudo.ip_src = h->ipv6.saddr;
+ pseudo.ip_dst = h->ipv6.daddr;
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ pseudo.size = htonl (ntohs (h->ipv6.len));
+ pseudo.zeros = 0;
+ pseudo.zero = 0;
+ pseudo.protocol = h->ipv6.nxt;
+
+ /* Compute partial checksum based on pseudo-header */
+ partial_csum = csum (&pseudo, IPV6_PSHDRLEN, 0);
+
+ return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old)
+{
+ // ASSERT(addr_old == NULL);
+ addr_old->ip6 = h->ipv6.saddr;
+ h->ipv6.saddr = addr_new->ip6;
+
+ return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
+}
+
+int
+ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ const hicn_faceid_t face_id)
+{
+ // ASSERT(addr_old == NULL);
+ addr_old->ip6 = h->ipv6.daddr;
+ h->ipv6.daddr = addr_new->ip6;
+
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id);
+}
+
+int
+ipv6_get_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = IPV6_HDRLEN + ntohs (h->ipv6.len);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = IPV6_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *header_length = IPV6_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * payload_length)
+{
+ size_t child_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *payload_length = ntohs (h->ipv6.len) - child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t * h,
+ size_t payload_length)
+{
+ size_t child_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ h->ipv6.len = htons (payload_length + child_header_length);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+ipv6_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+ipv6_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t * signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+ipv6_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+ipv6_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t * validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+ipv6_set_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+ipv6_get_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+DECLARE_HICN_OPS (ipv6);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv6.h b/lib/src/protocol/ipv6.h
new file mode 100755
index 000000000..28a1aa47f
--- /dev/null
+++ b/lib/src/protocol/ipv6.h
@@ -0,0 +1,67 @@
+/*
+ * 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 HICN_PROTOCOL_IPV6_H
+#define HICN_PROTOCOL_IPV6_H
+
+#include "../common.h"
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+ u16 len; /* payload length */
+ u8 nxt; /* next header */
+ u8 hlim; /* hop limit */
+ };
+ u8 vfc; /* 4 bits version, top 4 bits class */
+ };
+ ip6_address_t saddr; /* source address */
+ ip6_address_t daddr; /* destination address */
+} _ipv6_header_t;
+
+
+#define IPV6_HDRLEN sizeof(_ipv6_header_t)
+
+typedef struct
+{
+ ip6_address_t ip_src;
+ ip6_address_t ip_dst;
+ u32 size;
+ u16 zeros;
+ u8 zero;
+ u8 protocol;
+} ipv6_pseudo_header_t;
+
+#define IPV6_PSHDRLEN sizeof(ipv6_pseudo_header_t)
+
+/* Default field values */
+#define IPV6_DEFAULT_VERSION 6
+#define IPV6_DEFAULT_TRAFFIC_CLASS 0
+#define IPV6_DEFAULT_FLOW_LABEL 0
+#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
+
+#endif
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
new file mode 100755
index 000000000..2afc4f6f4
--- /dev/null
+++ b/lib/src/protocol/tcp.c
@@ -0,0 +1,370 @@
+/*
+ * 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 <string.h>
+#include "tcp.h"
+
+#include "../error.h"
+#include "../ops.h"
+
+#define TCP_DEFAULT_SRC_PORT 0x8000
+#define TCP_DEFAULT_DST_PORT 0x0080
+#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
+#define TCP_DEFAULT_HLEN 20
+#define TCP_DEFAULT_DATA_OFFSET_RES (TCP_DEFAULT_HLEN >> 2) << 4
+#define TCP_DEFAULT_CWR 0
+#define TCP_DEFAULT_ECE 0
+#define TCP_DEFAULT_URG 0
+#define TCP_DEFAULT_ACK 0
+#define TCP_DEFAULT_PSH 0
+#define TCP_DEFAULT_RST 0
+#define TCP_DEFAULT_SYN 1
+#define TCP_DEFAULT_FIN 0
+
+DECLARE_get_interest_locator (tcp, UNEXPECTED);
+DECLARE_set_interest_locator (tcp, UNEXPECTED);
+DECLARE_get_interest_name (tcp, UNEXPECTED);
+DECLARE_set_interest_name (tcp, UNEXPECTED);
+DECLARE_get_data_locator (tcp, UNEXPECTED);
+DECLARE_set_data_locator (tcp, UNEXPECTED);
+DECLARE_get_data_name (tcp, UNEXPECTED);
+DECLARE_set_data_name (tcp, UNEXPECTED);
+DECLARE_get_length (tcp, UNEXPECTED);
+DECLARE_get_payload_length (tcp, UNEXPECTED);
+DECLARE_set_payload_length (tcp, UNEXPECTED);
+
+int
+tcp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->tcp = (_tcp_header_t)
+ {
+ .sport = htons (TCP_DEFAULT_SRC_PORT),.dport =
+ htons (TCP_DEFAULT_DST_PORT),.seq = 0,.seq_ack =
+ 0,.data_offset_and_reserved = TCP_DEFAULT_DATA_OFFSET_RES,.flags =
+ TCP_DEFAULT_CWR << 7 | TCP_DEFAULT_ECE << 6 | TCP_DEFAULT_URG << 5 |
+ TCP_DEFAULT_ACK << 4 | TCP_DEFAULT_PSH << 3 | TCP_DEFAULT_RST << 2 |
+ TCP_DEFAULT_SYN << 1 | TCP_DEFAULT_FIN << 0,.window =
+ htons (TCP_DEFAULT_WINDOW_SIZE),.csum = 0,.urg_ptr = 65000,};
+
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ *suffix = ntohl (h->tcp.name_suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ h->tcp.name_suffix = htonl (*suffix);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ memset (&(h->tcp), 0, 4);
+ memset (&(h->tcp.seq_ack), 0, 12);
+
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+
+int
+tcp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_name_suffix_t * suffix)
+{
+ *suffix = ntohl (h->tcp.name_suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_name_suffix_t * suffix)
+{
+ h->tcp.name_suffix = htonl (*suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
+ u32 * pathlabel)
+{
+ *pathlabel = h->tcp.seq_ack;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const u32 pathlabel)
+{
+ h->tcp.seq_ack = pathlabel;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_faceid_t face_id)
+{
+ hicn_pathlabel_t pl =
+ (hicn_pathlabel_t) ((h->tcp.pathlabel & HICN_PATH_LABEL_MASK) >> (32 -
+ HICN_PATH_LABEL_SIZE));
+ hicn_pathlabel_t new_pl;
+
+ update_pathlabel (pl, face_id, &new_pl);
+ h->tcp.pathlabel = new_pl;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+{
+ memset (&(h->tcp), 0, 4);
+ memset (&(h->tcp.seq_ack), 0, 12);
+
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+
+int
+tcp_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
+ hicn_lifetime_t * lifetime)
+{
+ *lifetime =
+ ntohs (h->tcp.urg_ptr) << (h->tcp.data_offset_and_reserved & 0xF);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+ const hicn_lifetime_t lifetime)
+{
+ u8 multiplier = 0;
+ u32 lifetime_scaled = lifetime;
+
+ if (PREDICT_FALSE (lifetime >= HICN_MAX_LIFETIME))
+ {
+ h->tcp.urg_ptr = htons (HICN_MAX_LIFETIME_SCALED);
+ h->tcp.data_offset_and_reserved =
+ (h->
+ tcp.data_offset_and_reserved & ~0xF) | HICN_MAX_LIFETIME_MULTIPLIER;
+ return HICN_LIB_ERROR_NONE;
+ }
+
+ while (lifetime_scaled > HICN_MAX_LIFETIME_SCALED
+ && multiplier <= HICN_MAX_LIFETIME_MULTIPLIER)
+ {
+ multiplier++;
+ lifetime_scaled = lifetime_scaled >> 1;
+ }
+
+ h->tcp.urg_ptr = htons (lifetime_scaled);
+ h->tcp.data_offset_and_reserved =
+ (h->tcp.data_offset_and_reserved & ~0xF) | multiplier;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ size_t payload_length)
+{
+ h->tcp.csum = 0;
+
+ if (PREDICT_TRUE (partial_csum != 0))
+ {
+ partial_csum = ~partial_csum;
+ }
+
+ h->tcp.csum = csum (h, TCP_HDRLEN + payload_length, partial_csum);
+
+ return CHILD_OPS (update_checksums, type, h, 0, payload_length);
+}
+
+int
+tcp_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ size_t payload_length)
+{
+ if (csum (h, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
+ return HICN_LIB_ERROR_CORRUPTED_PACKET;
+ return CHILD_OPS (verify_checksums, type, h, 0, payload_length);
+}
+
+#define TCP_OFFSET_MASK 13
+#define TCP_OFFSET_DATA_OFFSET 12
+#define TCP_OFFSET_IN_BITS_DATA_OFFSET 0
+#define TCP_OFFSET_IN_BITS_RESERVED 4
+#define TCP_OFFSET_IN_BITS_NS 7
+
+#define TCP_DEFAULT_SRC_PORT 0x8000
+#define TCP_DEFAULT_DST_PORT 0x0080
+#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
+#define TCP_DEFAULT_DATA_OFFSET 5 // Size of the TCP header in words (= 4 bytes). Must be greater or equal than 5.
+#define TCP_DEFAULT_CWR 0
+#define TCP_DEFAULT_ECE 0
+#define TCP_DEFAULT_URG 0
+#define TCP_DEFAULT_ACK 0
+#define TCP_DEFAULT_PSH 0
+#define TCP_DEFAULT_RST 0
+#define TCP_DEFAULT_SYN 1
+#define TCP_DEFAULT_FIN 0
+
+int
+tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new,
+ ip46_address_t * addr_old)
+{
+ u16 *tcp_checksum = &(h->tcp.csum);
+
+ /*
+ * Padding fields are set to zero so we can apply checksum on the
+ * whole struct by interpreting it as IPv6 in all cases
+ *
+ * v4 code would be:
+ * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
+ * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ */
+ u16 csum = ip_csum_sub_even (*tcp_checksum, h->ipv6.saddr.as_u64[0]);
+ csum = ip_csum_sub_even (csum, h->ipv6.saddr.as_u64[1]);
+ csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[0]);
+ csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[1]);
+
+ *tcp_checksum = ip_csum_fold (csum);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
+ const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ const hicn_faceid_t face_id)
+{
+ u16 *tcp_checksum = &(h->tcp.csum);
+
+ /*
+ * Padding fields are set to zero so we can apply checksum on the
+ * whole struct by interpreting it as IPv6 in all cases
+ *
+ * v4 code would be:
+ * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
+ * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ */
+ u16 csum = ip_csum_sub_even (*tcp_checksum, addr_old->ip6.as_u64[0]);
+ csum = ip_csum_sub_even (*tcp_checksum, addr_old->ip6.as_u64[1]);
+ csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]);
+ csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]);
+
+ csum = ip_csum_sub_even (csum, h->tcp.pathlabel);
+ tcp_update_data_pathlabel (type, h, face_id);
+ csum = ip_csum_add_even (csum, h->tcp.pathlabel);
+
+ *tcp_checksum = ip_csum_fold (csum);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ *header_length = TCP_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+
+ *header_length = TCP_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
+ size_t * signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+tcp_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+tcp_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+tcp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
+ uint64_t * signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+tcp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+tcp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
+ uint8_t * validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+tcp_set_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+tcp_get_key_id (hicn_type_t type, hicn_protocol_t * h,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+DECLARE_HICN_OPS (tcp);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/tcp.h b/lib/src/protocol/tcp.h
new file mode 100755
index 000000000..68f4bf8f9
--- /dev/null
+++ b/lib/src/protocol/tcp.h
@@ -0,0 +1,166 @@
+/*
+ * 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 HICN_PROTOCOL_TCP_H
+#define HICN_PROTOCOL_TCP_H
+
+#include "../base.h"
+#include "../common.h"
+#include "../name.h"
+
+/*
+ * NOTE: bitfields are problematic for portability reasons. There are provided
+ * here for reference and documentation purposes, we might just provide a macro
+ * to disable and use it instead of __BYTE_ORDER__.
+ */
+typedef struct __attribute__ ((packed))
+{
+ u16 sport;
+ u16 dport;
+ union
+ {
+ u32 seq;
+ hicn_name_suffix_t name_suffix;
+ };
+ union
+ {
+ u32 seq_ack;
+ struct
+ {
+ hicn_pathlabel_t pathlabel;
+ u8 pad[3];
+ };
+ };
+
+ union
+ {
+ struct
+ {
+ u8 data_offset_and_reserved;
+ u8 flags;
+ };
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ struct
+ {
+ u16 reserved:4;
+ u16 doff:4;
+ u16 fin:1;
+ u16 syn:1;
+ u16 rst:1;
+ u16 psh:1;
+ u16 ack:1;
+ u16 urg:1;
+ u16 ece:1;
+ u16 cwr:1;
+ };
+ struct
+ { /* __ denotes unchanged bitfields */
+ u16 timescale:4;
+ u16 __doff:4;
+ u16 __fin:1;
+ u16 __syn:1;
+ u16 __rst:1;
+ u16 sig:1;
+ u16 __ack:1;
+ u16 man:1;
+ u16 id:1;
+ u16 __cwr:1;
+ };
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ struct
+ {
+ u16 doff:4;
+ u16 reserved:4;
+ u16 cwr:1;
+ u16 ece:1;
+ u16 urg:1;
+ u16 ack:1;
+ u16 psh:1;
+ u16 rst:1;
+ u16 syn:1;
+ u16 fin:1;
+ };
+ struct
+ {
+ u16 __doff:4;
+ u16 timescale:4;
+ u16 __cwr:1;
+ u16 id:1 u16 man:1;
+ u16 __ack:1;
+ u16 sig:1;
+ u16 __rst:1;
+ u16 __syn:1;
+ u16 __fin:1;
+ };
+#endif
+ };
+ union
+ {
+ u16 window;
+ u16 ldr;
+ };
+ u16 csum;
+ union
+ {
+ u16 urg_ptr;
+ u16 lifetime;
+ };
+} _tcp_header_t;
+
+#define TCP_HDRLEN sizeof(_tcp_header_t)
+
+#ifndef HICN_VPP_PLUGIN
+
+/* TCP flags bit 0 first. */
+#define foreach_tcp_flag \
+ _ (FIN) /**< No more data from sender. */ \
+ _ (SYN) /**< Synchronize sequence numbers. */ \
+ _ (RST) /**< Reset the connection. */ \
+ _ (PSH) /**< Push function. */ \
+ _ (ACK) /**< Ack field significant. */ \
+ _ (URG) /**< Urgent pointer field significant. */ \
+ _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
+ _ (CWR) /**< Sender reduced congestion window */
+
+enum
+{
+#define _(f) TCP_FLAG_BIT_##f,
+ foreach_tcp_flag
+#undef _
+ TCP_N_FLAG_BITS,
+};
+
+enum
+{
+#define _(f) TCP_FLAG_##f = 1 << TCP_FLAG_BIT_##f,
+ foreach_tcp_flag
+#undef _
+};
+
+#endif /* HICN_VPP_PLUGIN */
+
+// get_data_name_suffix
+// name->ip4.suffix = h->v4.tcp.seq;
+
+
+#endif /* HICN_PROTOCOL_TCP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/udp.h b/lib/src/protocol/udp.h
new file mode 100755
index 000000000..58cd65095
--- /dev/null
+++ b/lib/src/protocol/udp.h
@@ -0,0 +1,37 @@
+/*
+ * 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 HICN_PROTOCOL_UDP_H
+#define HICN_PROTOCOL_UDP_H
+
+typedef struct
+{
+ u16 src_port;
+ u16 dst_port;
+ u16 length;
+ u16 checksum;
+} _udp_header_t;
+
+#define UDP_HDRLEN sizeof(_udp_header_t)
+
+#endif /* HICN_PROTOCOL_UDP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */