diff options
Diffstat (limited to 'libtransport/src/core/packet.cc')
-rw-r--r-- | libtransport/src/core/packet.cc | 618 |
1 files changed, 351 insertions, 267 deletions
diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc index 51337201f..df27444af 100644 --- a/libtransport/src/core/packet.cc +++ b/libtransport/src/core/packet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -41,13 +41,6 @@ Packet::Packet(Format format, std::size_t additional_header_size) setFormat(format_, additional_header_size); } -Packet::Packet(MemBuf &&buffer) - : utils::MemBuf(std::move(buffer)), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(getFormatFromBuffer(data(), length())), - payload_type_(PayloadType::UNSPECIFIED) {} - Packet::Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size) : utils::MemBuf(COPY_BUFFER, buffer, size), packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), @@ -74,11 +67,11 @@ Packet::Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size, setFormat(format_, additional_header_size); } -Packet::Packet(const Packet &other) - : utils::MemBuf(other), +Packet::Packet(MemBuf &&buffer) + : utils::MemBuf(std::move(buffer)), packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(other.header_offset_), - format_(other.format_), + header_offset_(0), + format_(getFormatFromBuffer(data(), length())), payload_type_(PayloadType::UNSPECIFIED) {} Packet::Packet(Packet &&other) @@ -92,6 +85,13 @@ Packet::Packet(Packet &&other) other.header_offset_ = 0; } +Packet::Packet(const Packet &other) + : utils::MemBuf(other), + packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), + header_offset_(other.header_offset_), + format_(other.format_), + payload_type_(PayloadType::UNSPECIFIED) {} + Packet::~Packet() {} Packet &Packet::operator=(const Packet &other) { @@ -103,29 +103,19 @@ Packet &Packet::operator=(const Packet &other) { return *this; } -std::size_t Packet::getHeaderSizeFromBuffer(Format format, - const uint8_t *buffer) { - size_t header_length; - - if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer, - &header_length) < 0) { - throw errors::MalformedPacketException(); - } - - return header_length; +std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() { + return std::static_pointer_cast<utils::MemBuf>(shared_from_this()); } -bool Packet::isInterest(const uint8_t *buffer) { - bool is_interest = false; - - if (TRANSPORT_EXPECT_FALSE(hicn_packet_test_ece(HF_INET6_TCP, - (const hicn_header_t *)buffer, - &is_interest) < 0)) { - throw errors::RuntimeException( - "Impossible to retrieve ece flag from packet"); +Packet::Format Packet::getFormat() const { + // We check packet start because after a movement it will result in a nullptr + if (format_ == HF_UNSPEC && length()) { + if (hicn_packet_get_format(packet_start_, &format_) < 0) { + LOG(ERROR) << "Unexpected packet format HF_UNSPEC."; + } } - return !is_interest; + return format_; } void Packet::setFormat(Packet::Format format, @@ -136,47 +126,43 @@ void Packet::setFormat(Packet::Format format, } auto header_size = getHeaderSizeFromFormat(format_); - assert(header_size <= tailroom()); + DCHECK(header_size <= tailroom()); append(header_size); - assert(additional_header_size <= tailroom()); + DCHECK(additional_header_size <= tailroom()); append(additional_header_size); header_offset_ = length(); } -bool Packet::isInterest() { return Packet::isInterest(data()); } +PayloadType Packet::getPayloadType() const { + if (payload_type_ == PayloadType::UNSPECIFIED) { + hicn_payload_type_t ret; -std::size_t Packet::getPayloadSizeFromBuffer(Format format, - const uint8_t *buffer) { - std::size_t payload_length; - if (TRANSPORT_EXPECT_FALSE( - hicn_packet_get_payload_length(format, (hicn_header_t *)buffer, - &payload_length) < 0)) { - throw errors::MalformedPacketException(); + if (hicn_packet_get_payload_type(format_, packet_start_, &ret) < 0) { + throw errors::RuntimeException("Impossible to retrieve payload type."); + } + + payload_type_ = (PayloadType)ret; } - return payload_length; + return payload_type_; } -std::size_t Packet::payloadSize() const { - std::size_t ret = 0; - - if (length()) { - ret = getPayloadSizeFromBuffer(format_, - reinterpret_cast<uint8_t *>(packet_start_)); +Packet &Packet::setPayloadType(PayloadType payload_type) { + if (hicn_packet_set_payload_type(format_, packet_start_, + hicn_payload_type_t(payload_type)) < 0) { + throw errors::RuntimeException("Error setting payload type of the packet."); } - return ret; + payload_type_ = payload_type; + return *this; } -std::size_t Packet::headerSize() const { - if (header_offset_ == 0 && length()) { - const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer( - format_, reinterpret_cast<uint8_t *>(packet_start_)); - } - - return header_offset_; +std::unique_ptr<utils::MemBuf> Packet::getPayload() const { + auto ret = clone(); + ret->trimStart(headerSize()); + return ret; } Packet &Packet::appendPayload(std::unique_ptr<utils::MemBuf> &&payload) { @@ -196,12 +182,56 @@ Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) { return *this; } -std::unique_ptr<utils::MemBuf> Packet::getPayload() const { - auto ret = clone(); - ret->trimStart(headerSize()); +std::size_t Packet::headerSize() const { + if (header_offset_ == 0 && length()) { + const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer( + format_, reinterpret_cast<uint8_t *>(packet_start_)); + } + + return header_offset_; +} + +std::size_t Packet::payloadSize() const { + std::size_t ret = 0; + + if (length()) { + ret = getPayloadSizeFromBuffer(format_, + reinterpret_cast<uint8_t *>(packet_start_)); + } + return ret; } +auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const { + auth::CryptoHash hash; + hash.setType(algorithm); + + // Copy IP+TCP/ICMP header before zeroing them + hicn_header_t header_copy; + hicn_packet_copy_header(format_, packet_start_, &header_copy, false); + const_cast<Packet *>(this)->resetForHash(); + + hash.computeDigest(this); + hicn_packet_copy_header(format_, &header_copy, packet_start_, false); + + return hash; +} + +void Packet::reset() { + clear(); + packet_start_ = reinterpret_cast<hicn_header_t *>(writableData()); + header_offset_ = 0; + format_ = HF_UNSPEC; + payload_type_ = PayloadType::UNSPECIFIED; + name_.clear(); + + if (isChained()) { + separateChain(next(), prev()); + } +} + +bool Packet::isInterest() { return Packet::isInterest(data(), format_); } + Packet &Packet::updateLength(std::size_t length) { std::size_t total_length = length; @@ -221,47 +251,6 @@ Packet &Packet::updateLength(std::size_t length) { return *this; } -PayloadType Packet::getPayloadType() const { - if (payload_type_ == PayloadType::UNSPECIFIED) { - hicn_payload_type_t ret; - if (hicn_packet_get_payload_type(packet_start_, &ret) < 0) { - throw errors::RuntimeException("Impossible to retrieve payload type."); - } - - payload_type_ = (PayloadType)ret; - } - - return payload_type_; -} - -Packet &Packet::setPayloadType(PayloadType payload_type) { - if (hicn_packet_set_payload_type(packet_start_, - hicn_payload_type_t(payload_type)) < 0) { - throw errors::RuntimeException("Error setting payload type of the packet."); - } - - payload_type_ = payload_type; - - return *this; -} - -Packet::Format Packet::getFormat() const { - /** - * We check packet start because after a movement it will result in a nullptr - */ - if (format_ == HF_UNSPEC && length()) { - if (hicn_packet_get_format(packet_start_, &format_) < 0) { - LOG(ERROR) << "Unexpected packet format HF_UNSPEC."; - } - } - - return format_; -} - -std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() { - return std::static_pointer_cast<utils::MemBuf>(shared_from_this()); -} - void Packet::dump() const { LOG(INFO) << "HEADER -- Length: " << headerSize(); LOG(INFO) << "PAYLOAD -- Length: " << payloadSize(); @@ -274,180 +263,42 @@ void Packet::dump() const { } while (current != this); } -void Packet::dump(uint8_t *buffer, std::size_t length) { - hicn_packet_dump(buffer, length); -} - -void Packet::setSignatureSize(std::size_t size_bytes) { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - int ret = hicn_packet_set_signature_size(format_, packet_start_, size_bytes); - - if (ret < 0) { - throw errors::RuntimeException("Error setting signature size."); - } -} - -void Packet::setSignatureSizeGap(std::size_t size_bytes) { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - int ret = hicn_packet_set_signature_gap(format_, packet_start_, - (uint8_t)size_bytes); - - if (ret < 0) { - throw errors::RuntimeException("Error setting signature size."); - } -} - -uint8_t *Packet::getSignature() const { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - uint8_t *signature; - int ret = hicn_packet_get_signature(format_, packet_start_, &signature); - - if (ret < 0) { - throw errors::RuntimeException("Error getting signature."); - } - - return signature; -} - -void Packet::setSignatureTimestamp(const uint64_t ×tamp) { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - int ret = - hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp); - - if (ret < 0) { - throw errors::RuntimeException("Error setting the signature timestamp."); - } -} - -uint64_t Packet::getSignatureTimestamp() const { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - uint64_t return_value; - int ret = hicn_packet_get_signature_timestamp(format_, packet_start_, - &return_value); - - if (ret < 0) { - throw errors::RuntimeException("Error getting the signature timestamp."); - } - - return return_value; -} - -void Packet::setValidationAlgorithm( - const auth::CryptoSuite &validation_algorithm) { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - int ret = hicn_packet_set_validation_algorithm(format_, packet_start_, - uint8_t(validation_algorithm)); - - if (ret < 0) { - throw errors::RuntimeException("Error setting the validation algorithm."); - } -} - -auth::CryptoSuite Packet::getValidationAlgorithm() const { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - uint8_t return_value; - int ret = hicn_packet_get_validation_algorithm(format_, packet_start_, - &return_value); - - if (ret < 0) { - throw errors::RuntimeException("Error getting the validation algorithm."); - } - - return auth::CryptoSuite(return_value); -} - -void Packet::setKeyId(const auth::KeyId &key_id) { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } - - int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first); - - if (ret < 0) { - throw errors::RuntimeException("Error setting the key id."); - } -} - -auth::KeyId Packet::getKeyId() const { - if (!authenticationHeader()) { - throw errors::RuntimeException("Packet without Authentication Header."); - } +void Packet::setChecksum() { + if (_is_tcp(format_)) { + uint16_t partial_csum = + csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); - auth::KeyId return_value; - int ret = hicn_packet_get_key_id(format_, packet_start_, &return_value.first, - &return_value.second); + for (utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); + } - if (ret < 0) { - throw errors::RuntimeException("Error getting the validation algorithm."); + if (hicn_packet_compute_header_checksum(format_, packet_start_, + partial_csum) < 0) { + throw errors::MalformedPacketException(); + } } - - return return_value; -} - -auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const { - auth::CryptoHash hash; - hash.setType(algorithm); - - // Copy IP+TCP/ICMP header before zeroing them - hicn_header_t header_copy; - - hicn_packet_copy_header(format_, packet_start_, &header_copy, false); - - const_cast<Packet *>(this)->resetForHash(); - - hash.computeDigest(this); - hicn_packet_copy_header(format_, &header_copy, packet_start_, false); - - return hash; } bool Packet::checkIntegrity() const { - uint16_t partial_csum = - csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); + if (_is_tcp(format_)) { + uint16_t partial_csum = + csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); - for (const utils::MemBuf *current = next(); current != this; - current = current->next()) { - partial_csum = csum(current->data(), current->length(), ~partial_csum); - } + for (const utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); + } - if (hicn_packet_check_integrity_no_payload(format_, packet_start_, - partial_csum) < 0) { - return false; + if (hicn_packet_check_integrity_no_payload(format_, packet_start_, + partial_csum) < 0) { + return false; + } } return true; } -void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) { - auto last = prev(); - auto to_copy = std::min(*size, last->tailroom()); - std::memcpy(last->writableTail(), *buffer, to_copy); - last->append(to_copy); - *size -= to_copy; - *buffer += to_copy; -} - Packet &Packet::setSyn() { if (hicn_packet_set_syn(format_, packet_start_) < 0) { throw errors::RuntimeException("Error setting syn bit in the packet."); @@ -553,29 +404,23 @@ Packet &Packet::resetFlags() { resetAck(); resetRst(); resetFin(); - return *this; } std::string Packet::printFlags() const { std::string flags; - if (testSyn()) { flags += "S"; } - if (testAck()) { flags += "A"; } - if (testRst()) { flags += "R"; } - if (testFin()) { flags += "F"; } - return flags; } @@ -634,6 +479,245 @@ uint8_t Packet::getTTL() const { return hops; } +bool Packet::hasAH() const { return _is_ah(format_); } + +std::vector<uint8_t> Packet::getSignature() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + uint8_t *signature; + int ret = hicn_packet_get_signature(format_, packet_start_, &signature); + + if (ret < 0) { + throw errors::RuntimeException("Error getting signature."); + } + + return std::vector<uint8_t>(signature, signature + getSignatureFieldSize()); +} + +std::size_t Packet::getSignatureFieldSize() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + size_t field_size; + int ret = hicn_packet_get_signature_size(format_, packet_start_, &field_size); + if (ret < 0) { + throw errors::RuntimeException("Error reading signature field size"); + } + return field_size; +} + +std::size_t Packet::getSignatureSize() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + size_t padding; + int ret = hicn_packet_get_signature_padding(format_, packet_start_, &padding); + if (ret < 0) { + throw errors::RuntimeException("Error reading signature padding"); + } + + size_t size = getSignatureFieldSize() - padding; + if (size < 0) { + throw errors::RuntimeException("Error reading signature size"); + } + + return size; +} + +uint64_t Packet::getSignatureTimestamp() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + uint64_t timestamp; + int ret = + hicn_packet_get_signature_timestamp(format_, packet_start_, ×tamp); + if (ret < 0) { + throw errors::RuntimeException("Error getting the signature timestamp."); + } + return timestamp; +} + +auth::KeyId Packet::getKeyId() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + auth::KeyId key_id; + int ret = hicn_packet_get_key_id(format_, packet_start_, &key_id.first, + &key_id.second); + if (ret < 0) { + throw errors::RuntimeException("Error getting the validation algorithm."); + } + return key_id; +} + +auth::CryptoSuite Packet::getValidationAlgorithm() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + uint8_t return_value; + int ret = hicn_packet_get_validation_algorithm(format_, packet_start_, + &return_value); + if (ret < 0) { + throw errors::RuntimeException("Error getting the validation algorithm."); + } + return auth::CryptoSuite(return_value); +} + +void Packet::setSignature(const std::vector<uint8_t> &signature) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + uint8_t *signature_field; + int ret = hicn_packet_get_signature(format_, packet_start_, &signature_field); + if (ret < 0) { + throw errors::RuntimeException("Error getting signature."); + } + memcpy(signature_field, signature.data(), signature.size()); +} + +void Packet::setSignatureFieldSize(std::size_t size) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + int ret = hicn_packet_set_signature_size(format_, packet_start_, size); + if (ret < 0) { + throw errors::RuntimeException("Error setting signature size."); + } +} + +void Packet::setSignatureSize(std::size_t size) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + size_t padding = getSignatureFieldSize() - size; + if (padding < 0) { + throw errors::RuntimeException("Error setting signature padding."); + } + + int ret = hicn_packet_set_signature_padding(format_, packet_start_, padding); + if (ret < 0) { + throw errors::RuntimeException("Error setting signature padding."); + } +} + +void Packet::setSignatureTimestamp(const uint64_t ×tamp) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + int ret = + hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp); + if (ret < 0) { + throw errors::RuntimeException("Error setting the signature timestamp."); + } +} + +void Packet::setKeyId(const auth::KeyId &key_id) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first); + if (ret < 0) { + throw errors::RuntimeException("Error setting the key id."); + } +} + +void Packet::setValidationAlgorithm( + const auth::CryptoSuite &validation_algorithm) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + + int ret = hicn_packet_set_validation_algorithm(format_, packet_start_, + uint8_t(validation_algorithm)); + if (ret < 0) { + throw errors::RuntimeException("Error setting the validation algorithm."); + } +} + +Packet::Format Packet::toAHFormat(const Format &format) { + return hicn_get_ah_format(format); +} + +Packet::Format Packet::getFormatFromBuffer(const uint8_t *buffer, + std::size_t /* length */) { + Packet::Format format = HF_UNSPEC; + hicn_packet_get_format((const hicn_header_t *)buffer, &format); + return format; +} + +std::size_t Packet::getHeaderSizeFromFormat(Format format, + std::size_t signature_size) { + std::size_t header_length; + hicn_packet_get_header_length_from_format(format, &header_length); + int is_ah = _is_ah(format); + return is_ah * (header_length + signature_size) + (!is_ah) * header_length; +} + +std::size_t Packet::getHeaderSizeFromBuffer(Format format, + const uint8_t *buffer) { + size_t header_length; + + if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer, + &header_length) < 0) { + throw errors::MalformedPacketException(); + } + + return header_length; +} + +std::size_t Packet::getPayloadSizeFromBuffer(Format format, + const uint8_t *buffer) { + std::size_t payload_length; + if (TRANSPORT_EXPECT_FALSE( + hicn_packet_get_payload_length(format, (hicn_header_t *)buffer, + &payload_length) < 0)) { + throw errors::MalformedPacketException(); + } + + return payload_length; +} + +bool Packet::isInterest(const uint8_t *buffer, Format format) { + int is_interest = 0; + + if (TRANSPORT_EXPECT_FALSE(format == Format::HF_UNSPEC)) { + format = getFormatFromBuffer(buffer, /* Unused length */ 128); + } + + if (TRANSPORT_EXPECT_FALSE( + hicn_packet_is_interest(format, (const hicn_header_t *)buffer, + &is_interest) < 0)) { + throw errors::RuntimeException("Error reading ece flag from packet"); + } + + return is_interest; +} + +void Packet::dump(uint8_t *buffer, std::size_t length) { + hicn_packet_dump(buffer, length); +} + +void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) { + auto last = prev(); + auto to_copy = std::min(*size, last->tailroom()); + std::memcpy(last->writableTail(), *buffer, to_copy); + last->append(to_copy); + *size -= to_copy; + *buffer += to_copy; +} + } // end namespace core } // end namespace transport |