/* * 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_rd = { .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, .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_rd = { .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, .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_rd.type = HICN_MAPME_ICMP_TYPE_ACK_IPV4; mh->icmp_rd.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_rd.type = HICN_MAPME_ICMP_TYPE_ACK_IPV6; mh->icmp_rd.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_rd.type) ? mh->ip.daddr : mh->ip.saddr, }, .len = mh->len, }; *params = (mapme_params_t) { .protocol = IPPROTO_IP, .type = (mh->icmp_rd.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_rd.type) ? mh->ip.daddr : mh->ip.saddr, }, .len = mh->len, }; *params = (mapme_params_t) { .protocol = IPPROTO_IPV6, .type = (mh->icmp_rd.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: */