diff options
Diffstat (limited to 'libtransport/src/core/prefix.cc')
-rw-r--r-- | libtransport/src/core/prefix.cc | 311 |
1 files changed, 161 insertions, 150 deletions
diff --git a/libtransport/src/core/prefix.cc b/libtransport/src/core/prefix.cc index eea4aeb8b..8c5b153bc 100644 --- a/libtransport/src/core/prefix.cc +++ b/libtransport/src/core/prefix.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,8 +13,10 @@ * limitations under the License. */ +#include <glog/logging.h> #include <hicn/transport/core/prefix.h> #include <hicn/transport/errors/errors.h> +#include <hicn/transport/portability/endianess.h> #include <hicn/transport/utils/string_tokenizer.h> #ifndef _WIN32 @@ -25,21 +27,17 @@ extern "C" { #include <hicn/transport/portability/win_portability.h> #endif +#include <openssl/rand.h> + #include <cstring> #include <memory> #include <random> -#include <openssl/rand.h> - namespace transport { namespace core { -Prefix::Prefix() { std::memset(&ip_prefix_, 0, sizeof(ip_prefix_t)); } - -Prefix::Prefix(const char *prefix) : Prefix(std::string(prefix)) {} - -Prefix::Prefix(std::string &&prefix) : Prefix(prefix) {} +Prefix::Prefix() { std::memset(&hicn_ip_prefix_, 0, sizeof(hicn_ip_prefix_t)); } Prefix::Prefix(const std::string &prefix) { utils::StringTokenizer st(prefix, "/"); @@ -56,7 +54,7 @@ Prefix::Prefix(const std::string &prefix) { buildPrefix(ip_address, uint16_t(atoi(prefix_length.c_str())), family); } -Prefix::Prefix(std::string &prefix, uint16_t prefix_length) { +Prefix::Prefix(const std::string &prefix, uint16_t prefix_length) { int family = get_addr_family(prefix.c_str()); buildPrefix(prefix, prefix_length, family); } @@ -68,24 +66,28 @@ Prefix::Prefix(const core::Name &content_name, uint16_t prefix_length) { throw errors::InvalidIpAddressException(); } - ip_prefix_ = content_name.toIpAddress(); - ip_prefix_.len = prefix_length; - ip_prefix_.family = family; + hicn_ip_prefix_ = content_name.toIpAddress(); + hicn_ip_prefix_.len = (u8)prefix_length; + hicn_ip_prefix_.family = family; } -void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length, +void Prefix::buildPrefix(const std::string &prefix, uint16_t prefix_length, int family) { if (!checkPrefixLengthAndAddressFamily(prefix_length, family)) { throw errors::InvalidIpAddressException(); } + std::memset(&hicn_ip_prefix_, 0, sizeof(hicn_ip_prefix_t)); + int ret; switch (family) { case AF_INET: - ret = inet_pton(AF_INET, prefix.c_str(), ip_prefix_.address.v4.buffer); + ret = + inet_pton(AF_INET, prefix.c_str(), hicn_ip_prefix_.address.v4.buffer); break; case AF_INET6: - ret = inet_pton(AF_INET6, prefix.c_str(), ip_prefix_.address.v6.buffer); + ret = inet_pton(AF_INET6, prefix.c_str(), + hicn_ip_prefix_.address.v6.buffer); break; default: throw errors::InvalidIpAddressException(); @@ -95,14 +97,22 @@ void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length, throw errors::InvalidIpAddressException(); } - ip_prefix_.len = prefix_length; - ip_prefix_.family = family; + hicn_ip_prefix_.len = (u8)prefix_length; + hicn_ip_prefix_.family = family; } -std::unique_ptr<Sockaddr> Prefix::toSockaddr() { +bool Prefix::operator<(const Prefix &other) const { + return hicn_ip_prefix_cmp(&hicn_ip_prefix_, &other.hicn_ip_prefix_) < 0; +} + +bool Prefix::operator==(const Prefix &other) const { + return hicn_ip_prefix_cmp(&hicn_ip_prefix_, &other.hicn_ip_prefix_) == 0; +} + +std::unique_ptr<Sockaddr> Prefix::toSockaddr() const { Sockaddr *ret = nullptr; - switch (ip_prefix_.family) { + switch (hicn_ip_prefix_.family) { case AF_INET6: ret = (Sockaddr *)new Sockaddr6; break; @@ -113,72 +123,79 @@ std::unique_ptr<Sockaddr> Prefix::toSockaddr() { throw errors::InvalidIpAddressException(); } - if (ip_prefix_to_sockaddr(&ip_prefix_, ret) < 0) { + if (hicn_ip_prefix_to_sockaddr(&hicn_ip_prefix_, ret) < 0) { throw errors::InvalidIpAddressException(); } return std::unique_ptr<Sockaddr>(ret); } -uint16_t Prefix::getPrefixLength() { return ip_prefix_.len; } +uint16_t Prefix::getPrefixLength() const { return hicn_ip_prefix_.len; } Prefix &Prefix::setPrefixLength(uint16_t prefix_length) { - ip_prefix_.len = prefix_length; - return *this; -} - -int Prefix::getAddressFamily() { return ip_prefix_.family; } + if (!checkPrefixLengthAndAddressFamily(prefix_length, + hicn_ip_prefix_.family)) { + throw errors::InvalidIpAddressException(); + } -Prefix &Prefix::setAddressFamily(int address_family) { - ip_prefix_.family = address_family; + hicn_ip_prefix_.len = (u8)prefix_length; return *this; } +int Prefix::getAddressFamily() const { return hicn_ip_prefix_.family; } + std::string Prefix::getNetwork() const { - if (!checkPrefixLengthAndAddressFamily(ip_prefix_.len, ip_prefix_.family)) { + if (!checkPrefixLengthAndAddressFamily(hicn_ip_prefix_.len, + hicn_ip_prefix_.family)) { throw errors::InvalidIpAddressException(); } - std::size_t size = - ip_prefix_.family == 4 + AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; - - std::string network(size, 0); + char buffer[INET6_ADDRSTRLEN]; - if (ip_prefix_ntop_short(&ip_prefix_, (char *)network.c_str(), size) < 0) { + if (hicn_ip_prefix_ntop_short(&hicn_ip_prefix_, buffer, INET6_ADDRSTRLEN) < + 0) { throw errors::RuntimeException( "Impossible to retrieve network from ip address."); } - return network; + return buffer; } -int Prefix::contains(const ip_address_t &content_name) const { - int res = - ip_address_cmp(&content_name, &(ip_prefix_.address), ip_prefix_.family); - - if (ip_prefix_.len != (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN_BITS - : IPV4_ADDR_LEN_BITS)) { - const u8 *ip_prefix_buffer = - ip_address_get_buffer(&(ip_prefix_.address), ip_prefix_.family); - const u8 *content_name_buffer = - ip_address_get_buffer(&content_name, ip_prefix_.family); - uint8_t mask = 0xFF >> (ip_prefix_.len % 8); - mask = ~mask; - - res += (ip_prefix_buffer[ip_prefix_.len] & mask) == - (content_name_buffer[ip_prefix_.len] & mask); +bool Prefix::contains(const hicn_ip_address_t &content_name) const { + uint64_t mask[2] = {0, 0}; + auto content_name_copy = content_name; + auto network_copy = hicn_ip_prefix_.address; + + auto prefix_length = getPrefixLength(); + if (hicn_ip_prefix_.family == AF_INET) { + prefix_length += 3 * IPV4_ADDR_LEN_BITS; } - return res; -} + if (prefix_length == 0) { + mask[0] = mask[1] = 0; + } else if (prefix_length <= 64) { + mask[0] = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length)); + mask[1] = 0; + } else if (prefix_length == 128) { + mask[0] = mask[1] = 0xffffffffffffffff; + } else { + prefix_length -= 64; + mask[0] = 0xffffffffffffffff; + mask[1] = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length)); + } -int Prefix::contains(const core::Name &content_name) const { - return contains(content_name.toIpAddress().address); + // Apply mask + content_name_copy.v6.as_u64[0] &= mask[0]; + content_name_copy.v6.as_u64[1] &= mask[1]; + + network_copy.v6.as_u64[0] &= mask[0]; + network_copy.v6.as_u64[1] &= mask[1]; + + return hicn_ip_address_cmp(&network_copy, &content_name_copy) == 0; } -Name Prefix::getName() const { - std::string s(getNetwork()); - return Name(s); +bool Prefix::contains(const core::Name &content_name) const { + return contains(content_name.toIpAddress().address); } /* @@ -187,23 +204,25 @@ Name Prefix::getName() const { */ Name Prefix::getName(const core::Name &mask, const core::Name &components, const core::Name &content_name) const { - if (ip_prefix_.family != mask.getAddressFamily() || - ip_prefix_.family != components.getAddressFamily() || - ip_prefix_.family != content_name.getAddressFamily()) + if (hicn_ip_prefix_.family != mask.getAddressFamily() || + hicn_ip_prefix_.family != components.getAddressFamily() || + hicn_ip_prefix_.family != content_name.getAddressFamily()) throw errors::RuntimeException( - "Prefix, mask, components and content name are not of the same address " - "family"); - - ip_address_t mask_ip = mask.toIpAddress().address; - ip_address_t component_ip = components.toIpAddress().address; - ip_address_t name_ip = content_name.toIpAddress().address; - const u8 *mask_ip_buffer = ip_address_get_buffer(&mask_ip, ip_prefix_.family); + "Prefix, mask, components and content name are not of the same" + "address family"); + + hicn_ip_address_t mask_ip = mask.toIpAddress().address; + hicn_ip_address_t component_ip = components.toIpAddress().address; + hicn_ip_address_t name_ip = content_name.toIpAddress().address; + const u8 *mask_ip_buffer = + hicn_ip_address_get_buffer(&mask_ip, hicn_ip_prefix_.family); const u8 *component_ip_buffer = - ip_address_get_buffer(&component_ip, ip_prefix_.family); - u8 *name_ip_buffer = - const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family)); + hicn_ip_address_get_buffer(&component_ip, hicn_ip_prefix_.family); + u8 *name_ip_buffer = const_cast<u8 *>( + hicn_ip_address_get_buffer(&name_ip, hicn_ip_prefix_.family)); - int addr_len = ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN; + int addr_len = + hicn_ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN; for (int i = 0; i < addr_len; i++) { if (mask_ip_buffer[i]) { @@ -211,108 +230,98 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components, } } - // if (this->contains(name_ip)) - // throw errors::RuntimeException("Mask overrides the prefix"); - return Name(ip_prefix_.family, (uint8_t *)&name_ip); -} - -Name Prefix::getRandomName() const { - ip_address_t name_ip = ip_prefix_.address; - u8 *name_ip_buffer = - const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family)); - - int addr_len = - (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN * 8 : IPV4_ADDR_LEN * 8) - - ip_prefix_.len; - - size_t size = (size_t)ceil((float)addr_len / 8.0); - uint8_t *buffer = (uint8_t *) malloc(sizeof(uint8_t) * size); - - RAND_bytes(buffer, size); - - int j = 0; - for (uint8_t i = (uint8_t)ceil((float)ip_prefix_.len / 8.0); - i < (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN); - i++) { - name_ip_buffer[i] = buffer[j]; - j++; - } - free(buffer); - - return Name(ip_prefix_.family, (uint8_t *)&name_ip); + return Name(hicn_ip_prefix_.family, (uint8_t *)&name_ip); } /* * Map a name in a different name prefix to this name prefix */ Name Prefix::mapName(const core::Name &content_name) const { - if (ip_prefix_.family != content_name.getAddressFamily()) + if (hicn_ip_prefix_.family != content_name.getAddressFamily()) throw errors::RuntimeException( "Prefix content name are not of the same address " "family"); - ip_address_t name_ip = content_name.toIpAddress().address; - const u8 *ip_prefix_buffer = - ip_address_get_buffer(&(ip_prefix_.address), ip_prefix_.family); - u8 *name_ip_buffer = - const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family)); - - memcpy(name_ip_buffer, ip_prefix_buffer, ip_prefix_.len / 8); - - if (ip_prefix_.len != (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN_BITS - : IPV4_ADDR_LEN_BITS)) { - uint8_t mask = 0xFF >> (ip_prefix_.len % 8); - name_ip_buffer[ip_prefix_.len / 8 + 1] = - (name_ip_buffer[ip_prefix_.len / 8 + 1] & mask) | - (ip_prefix_buffer[ip_prefix_.len / 8 + 1] & ~mask); + hicn_ip_address_t name_ip = content_name.toIpAddress().address; + const u8 *hicn_ip_prefix_buffer = hicn_ip_address_get_buffer( + &(hicn_ip_prefix_.address), hicn_ip_prefix_.family); + u8 *name_ip_buffer = const_cast<u8 *>( + hicn_ip_address_get_buffer(&name_ip, hicn_ip_prefix_.family)); + + memcpy(name_ip_buffer, hicn_ip_prefix_buffer, hicn_ip_prefix_.len / 8); + + if (hicn_ip_prefix_.len != (hicn_ip_prefix_.family == AF_INET6 + ? IPV6_ADDR_LEN_BITS + : IPV4_ADDR_LEN_BITS)) { + uint8_t mask = 0xFF >> (hicn_ip_prefix_.len % 8); + name_ip_buffer[hicn_ip_prefix_.len / 8 + 1] = + (name_ip_buffer[hicn_ip_prefix_.len / 8 + 1] & mask) | + (hicn_ip_prefix_buffer[hicn_ip_prefix_.len / 8 + 1] & ~mask); } - return Name(ip_prefix_.family, (uint8_t *)&name_ip); + return Name(hicn_ip_prefix_.family, (uint8_t *)&name_ip); } -Prefix &Prefix::setNetwork(std::string &network) { - if (!inet_pton(AF_INET6, network.c_str(), ip_prefix_.address.v6.buffer)) { +Prefix &Prefix::setNetwork(const std::string &network) { + if (hicn_ip_address_pton(network.c_str(), &hicn_ip_prefix_.address) < 0) { throw errors::RuntimeException("The network name is not valid."); } return *this; } +Name Prefix::makeName() const { return makeNameWithIndex(0); } + Name Prefix::makeRandomName() const { - srand((unsigned int)time(nullptr)); - - if (ip_prefix_.family == AF_INET6) { - std::default_random_engine eng((std::random_device())()); - std::uniform_int_distribution<uint32_t> idis( - 0, std::numeric_limits<uint32_t>::max()); - uint64_t random_number = idis(eng); - - uint32_t hash_size_bits = IPV6_ADDR_LEN_BITS - ip_prefix_.len; - uint64_t ip_address[2]; - memcpy(ip_address, ip_prefix_.address.v6.buffer, sizeof(uint64_t)); - memcpy(ip_address + 1, ip_prefix_.address.v6.buffer + 8, sizeof(uint64_t)); - std::string network(IPV6_ADDR_LEN * 3, 0); - - // Let's do the magic ;) - int shift_size = hash_size_bits > sizeof(random_number) * 8 - ? sizeof(random_number) * 8 - : hash_size_bits; - - ip_address[1] >>= shift_size; - ip_address[1] <<= shift_size; - - ip_address[1] |= random_number >> (sizeof(uint64_t) * 8 - shift_size); - - if (!inet_ntop(ip_prefix_.family, ip_address, (char *)network.c_str(), - IPV6_ADDR_LEN * 3)) { - throw errors::RuntimeException( - "Impossible to retrieve network from ip address."); - } + std::default_random_engine eng((std::random_device())()); + std::uniform_int_distribution<uint32_t> idis( + 0, std::numeric_limits<uint32_t>::max()); + uint64_t random_number = idis(eng); + + return makeNameWithIndex(random_number); +} + +Name Prefix::makeNameWithIndex(std::uint64_t index) const { + uint16_t prefix_length = getPrefixLength(); - return Name(network); + Name ret; + + // Adjust prefix length depending on the address family + if (getAddressFamily() == AF_INET) { + // Sanity check + DCHECK(prefix_length <= 32); + // Convert prefix length to ip46_address_t prefix length + prefix_length += IPV4_ADDR_LEN_BITS * 3; + } + + std::memcpy(ret.getStructReference().prefix.v6.as_u8, + hicn_ip_prefix_.address.v6.as_u8, sizeof(hicn_ip_address_t)); + + // Convert index in network byte order + index = portability::host_to_net(index); + + // Apply mask + uint64_t mask; + if (prefix_length == 0) { + mask = 0; + } else if (prefix_length <= 64) { + mask = 0; + } else if (prefix_length == 128) { + mask = 0xffffffffffffffff; + } else { + prefix_length -= 64; + mask = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length)); } - return Name(); + ret.getStructReference().prefix.v6.as_u64[1] &= mask; + // Eventually truncate index if too big + index &= ~mask; + + // Apply index + ret.getStructReference().prefix.v6.as_u64[1] |= index; + + // Done + return ret; } bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length, @@ -332,7 +341,9 @@ bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length, return true; } -ip_prefix_t &Prefix::toIpPrefixStruct() { return ip_prefix_; } +const hicn_ip_prefix_t &Prefix::toIpPrefixStruct() const { + return hicn_ip_prefix_; +} } // namespace core |