summaryrefslogtreecommitdiffstats
path: root/hicn-light/src/core/messageHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/core/messageHandler.h')
-rwxr-xr-xhicn-light/src/core/messageHandler.h580
1 files changed, 580 insertions, 0 deletions
diff --git a/hicn-light/src/core/messageHandler.h b/hicn-light/src/core/messageHandler.h
new file mode 100755
index 000000000..d63656461
--- /dev/null
+++ b/hicn-light/src/core/messageHandler.h
@@ -0,0 +1,580 @@
+/*
+ * 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 messageHandler
+#define messageHandler
+
+#include <stdlib.h>
+
+#include <hicn/hicn.h>
+#include <src/core/messagePacketType.h>
+
+#define H(packet) ((hicn_header_t *)packet)
+#define H6(packet) (H(packet)->v6.ip)
+#define H6T(packet) (H(packet)->v6.tcp)
+#define H4(packet) (H(packet)->v4.ip)
+#define H4T(packet) (H(packet)->v4.tcp)
+
+#define HICN_V6_LEN(packet) (H6(packet).len)
+#define HICN_V4_LEN(packet) (H4(packet).len)
+
+/*** codes and types ***/
+#define IPv6_TYPE 6
+#define IPv4_TYPE 4
+#define ICMP_WLDR_TYPE 42
+#define ICMP_WLDR_CODE 0
+#define ICMP_LB_TYPE 43
+
+/*** masks and constants ***/
+#define PATH_LABEL_MASK 0x8000 // 1000 0000 0000 0000
+#define NOT_PATH_LABEL_MASK 0x7fff // 0111 0000 0000 0000
+#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111
+#define NEVER_EXPIRE \
+ 16777216 // 2^16 (max urgent pointer) * 2^8 (max reserved + NS bits)
+
+/*** HICN ALLOWED PORTS ***/
+#define CONTROL_PORT 9695
+#define HTTP_PORT 8080
+
+#define IPV6_DEFAULT_VERSION 6
+#define IPV6_DEFAULT_TRAFFIC_CLASS 0
+#define IPV6_DEFAULT_FLOW_LABEL 0
+
+#define expected_lbl wldr_notification_lbl.expected_lbl
+#define received_lbl wldr_notification_lbl.received_lbl
+
+static inline uint8_t messageHandler_GetIPPacketType(const uint8_t *message) {
+ return HICN_IP_VERSION(message);
+}
+
+static inline void messageHandler_UpdateTCPCheckSum(uint8_t *message,
+ uint16_t *old_val,
+ uint16_t *new_val,
+ uint8_t size) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv4_TYPE:
+ for (uint8_t i = 0; i < size; i++) {
+ uint16_t old_csum = ~(H4T(message).csum);
+ uint16_t not_old_val = ~(*old_val);
+ uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
+
+ while (sum >> 16) {
+ sum = (sum >> 16) + (sum & UINT16_T_MASK);
+ }
+
+ H4T(message).csum = ~sum;
+ ++old_val;
+ ++new_val;
+ }
+ break;
+ case IPv6_TYPE:
+ for (uint8_t i = 0; i < size; i++) {
+ uint16_t old_csum = ~(H6T(message).csum);
+ uint16_t not_old_val = ~(*old_val);
+ uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
+
+ while (sum >> 16) {
+ sum = (sum >> 16) + (sum & UINT16_T_MASK);
+ }
+
+ H6T(message).csum = ~sum;
+ ++old_val;
+ ++new_val;
+ }
+ break;
+ default:
+ return;
+ }
+}
+
+static inline void messageHandler_UpdateIPv4CheckSum(uint8_t *message,
+ uint16_t *old_val,
+ uint16_t *new_val,
+ uint8_t size) {
+ for (uint8_t i = 0; i < size; i++) {
+ uint16_t old_csum = ~(H4(message).csum);
+ uint16_t not_old_val = ~(*old_val);
+ uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
+
+ while (sum >> 16) {
+ sum = (sum >> 16) + (sum & UINT16_T_MASK);
+ }
+
+ H4(message).csum = ~sum;
+ ++old_val;
+ ++new_val;
+ }
+}
+
+static inline size_t messageHandler_GetEmptyTCPPacketSize(unsigned ipVersion) {
+ if (ipVersion == IPv4_TYPE)
+ return IPV4_HDRLEN + TCP_HDRLEN;
+ else if (ipVersion == IPv6_TYPE)
+ return IPV6_HDRLEN + TCP_HDRLEN;
+ else
+ return 0;
+}
+
+static inline size_t messageHandler_GetICMPPacketSize(unsigned ipVersion) {
+ if (ipVersion == IPv4_TYPE)
+ return IPV4_HDRLEN + ICMP_HDRLEN;
+ else if (ipVersion == IPv6_TYPE)
+ return IPV6_HDRLEN + ICMP_HDRLEN;
+ else
+ return 0;
+}
+
+static inline size_t messageHandler_GetIPHeaderLength(unsigned ipVersion) {
+ if (ipVersion == IPv4_TYPE)
+ return IPV4_HDRLEN;
+ else if (ipVersion == IPv6_TYPE)
+ return IPV6_HDRLEN;
+ else
+ return 0;
+}
+
+static inline bool messageHandler_IsValidHIcnPacket(const uint8_t *message) {
+ uint8_t version = messageHandler_GetIPPacketType(message);
+ if (version == IPv6_TYPE || version == IPv4_TYPE) {
+ return true;
+ }
+ return false;
+}
+
+static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return (uint8_t)H6(message).nxt;
+ case IPv4_TYPE:
+ return (uint8_t)H4(message).protocol;
+ default:
+ return 0;
+ }
+}
+
+static inline bool messageHandler_IsTCP(const uint8_t *message) {
+ if (messageHandler_NextHeaderType(message) != IPPROTO_TCP) return false;
+ return true;
+}
+
+static inline bool messageHandler_IsInterest(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return false;
+
+ bool flag;
+ hicn_packet_test_ece((hicn_header_t *)message,
+ &flag); // ECE flag is set to 0 in interest packets
+ if (flag == false) return true;
+ return false;
+}
+
+static inline bool messageHandler_IsData(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return false;
+
+ bool flag;
+ hicn_packet_test_ece((hicn_header_t *)message,
+ &flag); // ECE flag is set to 1 in data packets
+ if (flag == true) return true;
+ return false;
+}
+
+static inline bool messageHandler_IsWldrNotification(const uint8_t *message) {
+ // this function returns true only if the packet is an ICMP packet in Wldr
+ // form. type must be equal to ICMP_WLDR_TYPE and code equal to ICMP_WLDR_CODE
+ uint8_t next_header = messageHandler_NextHeaderType(message);
+
+ const uint8_t *icmp_ptr;
+ if (next_header == IPPROTO_ICMP) {
+ icmp_ptr = message + IPV4_HDRLEN;
+ } else if (next_header == IPPROTO_ICMPV6) {
+ icmp_ptr = message + IPV6_HDRLEN;
+ } else {
+ return false;
+ }
+
+ uint8_t type = ((_icmp_header_t *)icmp_ptr)->type;
+ uint8_t code = ((_icmp_header_t *)icmp_ptr)->code;
+ if (type == ICMP_WLDR_TYPE && code == ICMP_WLDR_CODE) {
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool messageHandler_IsLoadBalancerProbe(const uint8_t *message) {
+ uint8_t next_header = messageHandler_NextHeaderType(message);
+
+ const uint8_t *icmp_ptr;
+ if (next_header == IPPROTO_ICMP) {
+ icmp_ptr = message + IPV4_HDRLEN;
+ } else if (next_header == IPPROTO_ICMPV6) {
+ icmp_ptr = message + IPV6_HDRLEN;
+ } else {
+ return false;
+ }
+
+ uint8_t type = ((_icmp_header_t *)icmp_ptr)->type;
+ if (type == ICMP_LB_TYPE) {
+ return true;
+ }
+
+ return false;
+}
+
+static inline uint16_t messageHandler_GetTotalPacketLength(
+ const uint8_t *message) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return ntohs((uint16_t)HICN_V6_LEN(message)) + IPV6_HDRLEN;
+ case IPv4_TYPE:
+ return ntohs((uint16_t)HICN_V4_LEN(message));
+ default:
+ return 0;
+ }
+}
+
+static inline uint32_t messageHandler_GetSegment(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return 0;
+
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return ntohl((uint32_t)H6T(message).seq);
+ case IPv4_TYPE:
+ return ntohl((uint32_t)H4T(message).seq);
+ default:
+ return 0;
+ }
+}
+
+static inline uint16_t messageHandler_GetExpectedWldrLabel(
+ const uint8_t *message) {
+ const uint8_t *icmp_ptr;
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ icmp_ptr = message + IPV6_HDRLEN;
+ break;
+ case IPv4_TYPE:
+ icmp_ptr = message + IPV4_HDRLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->expected_lbl);
+}
+
+static inline uint16_t messageHandler_GetWldrLastReceived(
+ const uint8_t *message) {
+ const uint8_t *icmp_ptr;
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ icmp_ptr = message + IPV6_HDRLEN;
+ break;
+ case IPv4_TYPE:
+ icmp_ptr = message + IPV4_HDRLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->received_lbl);
+}
+
+static inline uint16_t messageHandler_GetWldrLabel(const uint8_t *message) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return ntohs((uint16_t)H6T(message).window);
+ case IPv4_TYPE:
+ return ntohs((uint16_t)H4T(message).window);
+ default:
+ return 0;
+ }
+}
+
+static inline void messageHandler_SetWldrLabel(uint8_t *message,
+ uint16_t label) {
+ uint16_t old_val = messageHandler_GetWldrLabel(message);
+
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ H6T(message).window = htons(label);
+ break;
+ case IPv4_TYPE:
+ H4T(message).window = htons(label);
+ break;
+ default:
+ break;
+ }
+
+ messageHandler_UpdateTCPCheckSum(message, &old_val, &label, 1);
+}
+
+static inline void messageHandler_ResetWldrLabel(uint8_t *message) {
+ messageHandler_SetWldrLabel(message, 0);
+}
+
+static inline bool messageHandler_HasWldr(const uint8_t *message) {
+ if (messageHandler_IsTCP(message)) {
+ uint16_t lbl = messageHandler_GetWldrLabel(message);
+ if (lbl != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static inline uint8_t messageHandler_GetProbePacketType(
+ const uint8_t *message) {
+ const uint8_t *icmp_ptr;
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ icmp_ptr = message + IPV6_HDRLEN;
+ break;
+ case IPv4_TYPE:
+ icmp_ptr = message + IPV4_HDRLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ return ((_icmp_header_t *)icmp_ptr)->code;
+}
+
+static inline uint32_t messageHandler_GetPathLabel(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return 0;
+
+ uint32_t path_label;
+ int res = hicn_data_get_path_label((hicn_header_t *)message, &path_label);
+ if (res < 0) return 0;
+ return path_label;
+}
+
+static inline void messageHandler_SetPathLabel(uint8_t *message,
+ uint32_t new_path_label) {
+ if (!messageHandler_IsTCP(message)) return;
+
+ uint32_t old_path_label;
+ int res = hicn_data_get_path_label((hicn_header_t *)message, &old_path_label);
+ if (res < 0) return;
+
+ hicn_data_set_path_label((hicn_header_t *)message, new_path_label);
+
+ messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&old_path_label,
+ (uint16_t *)&new_path_label, 2);
+}
+
+static inline void messageHandler_UpdatePathLabel(uint8_t *message,
+ uint8_t outFace) {
+ if (!messageHandler_IsTCP(message)) return;
+
+ uint32_t pl_old_32bit = messageHandler_GetPathLabel(message);
+ uint8_t pl_old_8bit = (uint8_t)(pl_old_32bit >> 24UL);
+ uint32_t pl_new_32bit =
+ (uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL);
+
+ hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit);
+
+ messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit,
+ (uint16_t *)&pl_new_32bit, 2);
+}
+
+static inline void messageHandler_ResetPathLabel(uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return;
+
+ uint32_t pl_old_32bit = messageHandler_GetPathLabel(message);
+ uint32_t pl_new_32bit = 0;
+ hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit);
+ messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit,
+ (uint16_t *)&pl_new_32bit, 2);
+}
+
+static inline uint16_t messageHandler_GetInterestLifetime(
+ const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return 0;
+
+ hicn_lifetime_t lifetime;
+ int res = hicn_interest_get_lifetime((hicn_header_t *)message, &lifetime);
+ if (res < 0) return 0;
+ return lifetime;
+}
+
+static inline bool messageHandler_HasInterestLifetime(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return false;
+
+ if (messageHandler_GetInterestLifetime(message) == 0) return false;
+ return true;
+}
+
+static inline uint32_t messageHandler_GetContentExpiryTime(
+ const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return 0;
+
+ uint32_t expirationTime;
+ int res =
+ hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime);
+ if (res < 0) return 0;
+ return expirationTime;
+}
+
+static inline bool messageHandler_HasContentExpiryTime(const uint8_t *message) {
+ if (!messageHandler_IsTCP(message)) return 0;
+
+ uint32_t expirationTime;
+ int res =
+ hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime);
+ if (res < 0) return false;
+
+ if (expirationTime == NEVER_EXPIRE) return false;
+
+ return true;
+}
+
+static inline void *messageHandler_GetSource(const uint8_t *message) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return &H6(message).saddr;
+ break;
+ case IPv4_TYPE:
+ return &H4(message).saddr;
+ break;
+ default:
+ return NULL;
+ }
+}
+
+static inline void *messageHandler_GetDestination(const uint8_t *message) {
+ switch (messageHandler_GetIPPacketType(message)) {
+ case IPv6_TYPE:
+ return &H6(message).daddr;
+ break;
+ case IPv4_TYPE:
+ return &H4(message).daddr;
+ break;
+ default:
+ return NULL;
+ }
+}
+
+static inline void messageHandler_SetSource_IPv6(uint8_t *message,
+ struct in6_addr *address) {
+ if (messageHandler_IsTCP(message)) {
+ uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message);
+ messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 8);
+ }
+ H6(message).saddr.as_in6addr = *address;
+}
+
+static inline void messageHandler_SetDestination_IPv6(
+ uint8_t *message, struct in6_addr *address) {
+ if (messageHandler_IsTCP(message)) {
+ uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message);
+ messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 8);
+ }
+ H6(message).daddr.as_in6addr = *address;
+}
+
+static inline void messageHandler_SetSource_IPv4(uint8_t *message,
+ uint32_t *address) {
+ // update tcp checksum
+ uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message);
+ if (messageHandler_IsTCP(message)) {
+ messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 2);
+ }
+ // update IPv4 cheksum
+ // the IPv4 checksum is not part of the psudo header for TCP checksum
+ // calculation we can update them separetelly
+ messageHandler_UpdateIPv4CheckSum(message, old_src, (uint16_t *)address, 2);
+
+ H4(message).saddr.as_u32 = *address;
+}
+
+static inline void messageHandler_SetDestination_IPv4(uint8_t *message,
+ uint32_t *address) {
+ uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message);
+ if (messageHandler_IsTCP(message)) {
+ messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 2);
+ }
+ messageHandler_UpdateIPv4CheckSum(message, old_dst, (uint16_t *)address, 2);
+ H4(message).daddr.as_u32 = *address;
+}
+
+static inline void messageHandler_SetWldrNotification(uint8_t *notification,
+ uint8_t *original,
+ uint16_t expected,
+ uint16_t received) {
+ hicn_header_t *h = (hicn_header_t *)notification;
+ switch (messageHandler_GetIPPacketType(original)) {
+ case IPv6_TYPE: {
+ *h = (hicn_header_t){.v6 = {
+ .ip =
+ {
+ .version_class_flow = htonl(
+ (IPV6_DEFAULT_VERSION << 28) |
+ (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
+ (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
+ .len = htons(ICMP_HDRLEN),
+ .nxt = IPPROTO_ICMPV6,
+ .hlim = 5,
+ },
+ .wldr =
+ {
+ .type = ICMP_WLDR_TYPE,
+ .code = ICMP_WLDR_CODE,
+ .expected_lbl = htons(expected),
+ .received_lbl = htons(received),
+ },
+ }};
+ messageHandler_SetSource_IPv6(
+ notification,
+ (struct in6_addr *)messageHandler_GetDestination(original));
+ messageHandler_SetDestination_IPv6(
+ notification, (struct in6_addr *)messageHandler_GetSource(original));
+ break;
+ }
+ case IPv4_TYPE: {
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static inline void messageHandler_SetProbePacket(uint8_t *message,
+ uint8_t probeType,
+ struct in6_addr *src,
+ struct in6_addr *dst) {
+ hicn_header_t *h = (hicn_header_t *)message;
+ *h = (hicn_header_t){
+ .v6 = {
+ .ip =
+ {
+ .version_class_flow =
+ htonl((IPV6_DEFAULT_VERSION << 28) |
+ (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
+ (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
+ .len = htons(ICMP_HDRLEN),
+ .nxt = IPPROTO_ICMPV6,
+ .hlim = 5, // this should be 1, but ... just to be safe
+ },
+ .icmp =
+ {
+ .type = ICMP_LB_TYPE,
+ .code = probeType,
+ },
+ }};
+ messageHandler_SetSource_IPv6(message, src);
+ messageHandler_SetDestination_IPv6(message, dst);
+}
+
+#endif // Metis_metis_MessageHandler