diff options
Diffstat (limited to 'libtransport/src/core/packet.cc')
-rw-r--r-- | libtransport/src/core/packet.cc | 713 |
1 files changed, 361 insertions, 352 deletions
diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc index 6815868f0..bcd0b8498 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-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,15 +13,18 @@ * limitations under the License. */ +#include <glog/logging.h> +#include <hicn/transport/auth/crypto_hash.h> +#include <hicn/transport/core/global_object_pool.h> #include <hicn/transport/core/packet.h> #include <hicn/transport/errors/malformed_packet_exception.h> #include <hicn/transport/utils/hash.h> -#include <hicn/transport/utils/log.h> extern "C" { #ifndef _WIN32 TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") #endif +#include <hicn/base.h> #include <hicn/error.h> } @@ -31,521 +34,527 @@ namespace core { const core::Name Packet::base_name("0::0|0"); -Packet::Packet(Format format) - : packet_(utils::MemBuf::create(getHeaderSizeFromFormat(format, 256)) - .release()), - packet_start_(reinterpret_cast<hicn_header_t *>(packet_->writableData())), - header_head_(packet_.get()), - payload_head_(nullptr), - format_(format) { - if (hicn_packet_init_header(format, packet_start_) < 0) { - throw errors::RuntimeException("Unexpected error initializing the packet."); - } - - packet_->append(getHeaderSizeFromFormat(format_)); +Packet::Packet(Type type, Format format, std::size_t additional_header_size) + : utils::MemBuf(utils::MemBuf(CREATE, 2048)), + payload_type_(PayloadType::UNSPECIFIED) { + /* + * We define the format and the storage area of the packet buffer we + * manipulate + */ + setFormat(format); + setBuffer(); + initializeType(type); // type requires packet format + initialize(additional_header_size); +} + +Packet::Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size) + : utils::MemBuf(COPY_BUFFER, buffer, size), + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); +} + +Packet::Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, + std::size_t size) + : utils::MemBuf(WRAP_BUFFER, buffer, length, size), + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); +} + +Packet::Packet(CreateOp, Type type, uint8_t *buffer, std::size_t length, + std::size_t size, Format format, + std::size_t additional_header_size) + : utils::MemBuf(WRAP_BUFFER, buffer, length, size), + payload_type_(PayloadType::UNSPECIFIED) { + clear(); + setType(type); + setFormat(format); + setBuffer(); + initialize(additional_header_size); +} + +Packet::Packet(MemBuf &&buffer) + : utils::MemBuf(std::move(buffer)), + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); } -Packet::Packet(MemBufPtr &&buffer) - : packet_(std::move(buffer)), - packet_start_(reinterpret_cast<hicn_header_t *>(packet_->writableData())), - header_head_(packet_.get()), - payload_head_(nullptr), - format_(getFormatFromBuffer(packet_->writableData())) {} - -Packet::Packet(const uint8_t *buffer, std::size_t size) - : Packet(MemBufPtr(utils::MemBuf::copyBuffer(buffer, size).release())) {} +/* + * In the two following constructors, we inherit the pkbuf and only need to + * recompute the pointer fields, aka the buffer. + */ Packet::Packet(Packet &&other) - : packet_(std::move(other.packet_)), - packet_start_(other.packet_start_), - header_head_(other.header_head_), - payload_head_(other.payload_head_), - format_(other.format_) { - other.packet_start_ = nullptr; - other.header_head_ = nullptr; - other.payload_head_ = nullptr; - other.format_ = HF_UNSPEC; + : utils::MemBuf(std::move(other)), + pkbuf_(other.pkbuf_), + payload_type_(PayloadType::UNSPECIFIED) { + hicn_packet_reset(&other.pkbuf_); +} + +Packet::Packet(const Packet &other) + : utils::MemBuf(other), + pkbuf_(other.pkbuf_), + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); } Packet::~Packet() {} -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(); +Packet &Packet::operator=(const Packet &other) { + if (this != &other) { + *this = other; + setBuffer(); } - return header_length; + + return *this; } -bool Packet::isInterest(const uint8_t *buffer) { - bool is_interest = false; +std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() { + return std::static_pointer_cast<utils::MemBuf>(shared_from_this()); +} - if (TRANSPORT_EXPECT_FALSE(hicn_packet_test_ece((const hicn_header_t *)buffer, - &is_interest) < 0)) { - throw errors::RuntimeException( - "Impossible to retrieve ece flag from packet"); - } +Packet::Format Packet::getFormat() const { + return hicn_packet_get_format(&pkbuf_); +} - return !is_interest; +void Packet::setFormat(Packet::Format format) { + hicn_packet_set_format(&pkbuf_, format); } -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(); +void Packet::initialize(std::size_t additional_header_size) { + if (hicn_packet_init_header(&pkbuf_, additional_header_size) < 0) { + throw errors::RuntimeException("Unexpected error initializing the packet."); } - return payload_length; + auto header_size = getHeaderSizeFromFormat(getFormat()); + DCHECK(header_size <= tailroom()); + append(header_size); + DCHECK(additional_header_size <= tailroom()); + append(additional_header_size); } -std::size_t Packet::payloadSize() const { - return getPayloadSizeFromBuffer(format_, - reinterpret_cast<uint8_t *>(packet_start_)); +void Packet::analyze() { + if (hicn_packet_analyze(&pkbuf_) < 0) + throw errors::MalformedPacketException(); } -std::size_t Packet::headerSize() const { - return getHeaderSizeFromBuffer(format_, - reinterpret_cast<uint8_t *>(packet_start_)); +Packet::Type Packet::getType() const { return hicn_packet_get_type(&pkbuf_); } + +void Packet::initializeType(Packet::Type type) { + hicn_packet_initialize_type(&pkbuf_, type); } -Packet &Packet::appendPayload(std::unique_ptr<utils::MemBuf> &&payload) { - separateHeaderPayload(); +void Packet::setType(Packet::Type type) { hicn_packet_set_type(&pkbuf_, type); } - if (!payload_head_) { - payload_head_ = payload.get(); +void Packet::setBuffer() { + hicn_packet_set_buffer(&pkbuf_, writableData(), + this->capacity() - this->headroom(), this->length()); +} + +PayloadType Packet::getPayloadType() const { + if (payload_type_ == PayloadType::UNSPECIFIED) { + hicn_payload_type_t ret; + + if (hicn_packet_get_payload_type(&pkbuf_, &ret) < 0) { + throw errors::RuntimeException("Impossible to retrieve payload type."); + } + + payload_type_ = (PayloadType)ret; } - header_head_->prependChain(std::move(payload)); - updateLength(); + return payload_type_; +} + +Packet &Packet::setPayloadType(PayloadType payload_type) { + if (hicn_packet_set_payload_type(&pkbuf_, hicn_payload_type_t(payload_type)) < + 0) { + throw errors::RuntimeException("Error setting payload type of the packet."); + } + + payload_type_ = payload_type; return *this; } -Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) { - return appendPayload(utils::MemBuf::copyBuffer(buffer, length)); +std::unique_ptr<utils::MemBuf> Packet::getPayload() const { + auto ret = clone(); + ret->trimStart(headerSize()); + return ret; } -Packet &Packet::appendHeader(std::unique_ptr<utils::MemBuf> &&header) { - separateHeaderPayload(); +Packet &Packet::appendPayload(std::unique_ptr<utils::MemBuf> &&payload) { + prependChain(std::move(payload)); + updateLength(); + return *this; +} + +Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) { + prependPayload(&buffer, &length); - if (!payload_head_) { - header_head_->prependChain(std::move(header)); - } else { - payload_head_->prependChain(std::move(header)); + if (length) { + appendPayload(utils::MemBuf::copyBuffer(buffer, length)); } updateLength(); return *this; } -Packet &Packet::appendHeader(const uint8_t *buffer, std::size_t length) { - return appendHeader(utils::MemBuf::copyBuffer(buffer, length)); +std::size_t Packet::headerSize() const { + std::size_t len; + hicn_packet_get_header_len(&pkbuf_, &len); + return len; } -std::unique_ptr<utils::MemBuf> Packet::getPayload() const { - const_cast<Packet *>(this)->separateHeaderPayload(); +std::size_t Packet::payloadSize() const { + std::size_t len; + hicn_packet_get_payload_len(&pkbuf_, &len); + return len; +} + +auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const { + auth::CryptoHash hash; + hash.setType(algorithm); + + // Copy IP+TCP/ICMP header before zeroing them + u8 header_copy[HICN_HDRLEN_MAX]; + size_t header_len; + hicn_packet_save_header(&pkbuf_, header_copy, &header_len, + /* copy_ah */ false); + const_cast<Packet *>(this)->resetForHash(); - // Hopefully the payload is contiguous - if (TRANSPORT_EXPECT_FALSE(payload_head_ && - payload_head_->next() != header_head_)) { - payload_head_->gather(payloadSize()); + hash.computeDigest(this); + hicn_packet_load_header(&pkbuf_, header_copy, header_len); + + return hash; +} + +void Packet::reset() { + clear(); + hicn_packet_reset(&pkbuf_); + setBuffer(); + payload_type_ = PayloadType::UNSPECIFIED; + name_.clear(); + + if (isChained()) { + separateChain(next(), prev()); } +} - return payload_head_->cloneOne(); +bool Packet::isInterest() { + return hicn_packet_get_type(&pkbuf_) == HICN_PACKET_TYPE_INTEREST; } Packet &Packet::updateLength(std::size_t length) { std::size_t total_length = length; - for (utils::MemBuf *current = payload_head_; - current && current != header_head_; current = current->next()) { + const utils::MemBuf *current = this; + do { total_length += current->length(); + current = current->next(); + } while (current != this); + + if (hicn_packet_set_len(&pkbuf_, total_length) < 0) { + throw errors::RuntimeException("Error setting the packet length."); } - if (hicn_packet_set_payload_length(format_, packet_start_, total_length) < - 0) { - throw errors::RuntimeException("Error setting the packet payload."); + total_length -= headerSize(); + + if (hicn_packet_set_payload_length(&pkbuf_, total_length) < 0) { + throw errors::RuntimeException("Error setting the packet payload length."); } return *this; } -PayloadType Packet::getPayloadType() const { - hicn_payload_type_t ret = HPT_UNSPEC; - - if (hicn_packet_get_payload_type(packet_start_, &ret) < 0) { - throw errors::RuntimeException("Impossible to retrieve payload type."); - } +void Packet::dump() const { + LOG(INFO) << "HEADER -- Length: " << headerSize(); + LOG(INFO) << "PAYLOAD -- Length: " << payloadSize(); - return PayloadType(ret); + const utils::MemBuf *current = this; + do { + LOG(INFO) << "MemBuf Length: " << current->length(); + dump((uint8_t *)current->data(), current->length()); + current = current->next(); + } while (current != this); } -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."); - } +void Packet::setChecksum() { + size_t header_len = 0; + if (hicn_packet_get_header_len(&pkbuf_, &header_len) < 0) + throw errors::RuntimeException( + "Error setting getting packet header length."); - return *this; -} + uint16_t partial_csum = csum(data() + header_len, length() - header_len, 0); -Packet::Format Packet::getFormat() const { - if (format_ == HF_UNSPEC) { - if (hicn_packet_get_format(packet_start_, &format_) < 0) { - throw errors::MalformedPacketException(); - } + for (utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); } - return format_; + if (hicn_packet_compute_header_checksum(&pkbuf_, partial_csum) < 0) { + throw errors::MalformedPacketException(); + } } -const std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() const { - return packet_; -} +bool Packet::checkIntegrity() const { + size_t header_len = 0; + if (hicn_packet_get_header_len(&pkbuf_, &header_len) < 0) + throw errors::RuntimeException( + "Error setting getting packet header length."); -void Packet::dump() const { - const_cast<Packet *>(this)->separateHeaderPayload(); + uint16_t partial_csum = csum(data() + header_len, length() - header_len, 0); - std::cout << "HEADER -- Length: " << headerSize() << std::endl; - hicn_packet_dump((uint8_t *)header_head_->data(), headerSize()); + for (const utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); + } - std::cout << std::endl << "PAYLOAD -- Length: " << payloadSize() << std::endl; - for (utils::MemBuf *current = payload_head_; - current && current != header_head_; current = current->next()) { - std::cout << "MemBuf Length: " << current->length() << std::endl; - hicn_packet_dump((uint8_t *)current->data(), current->length()); + if (hicn_packet_check_integrity_no_payload(&pkbuf_, partial_csum) < 0) { + return false; } + + return true; } -void Packet::setSignatureSize(std::size_t size_bytes) { - int ret = hicn_packet_set_signature_size(format_, packet_start_, size_bytes); +bool Packet::hasAH() const { return HICN_PACKET_FORMAT_IS_AH(getFormat()); } - if (ret < 0) { +utils::MemBuf::Ptr Packet::getSignature() const { + if (!hasAH()) { throw errors::RuntimeException("Packet without Authentication Header."); } - packet_->append(size_bytes); - updateLength(); -} - -uint8_t *Packet::getSignature() const { uint8_t *signature; - int ret = hicn_packet_get_signature(format_, packet_start_, &signature); + int ret = hicn_packet_get_signature(&pkbuf_, &signature); if (ret < 0) { - throw errors::RuntimeException("Packet without Authentication Header."); + throw errors::RuntimeException("Error getting signature."); } - return signature; + utils::MemBuf::Ptr membuf = PacketManager<>::getInstance().getMemBuf(); + membuf->append(getSignatureFieldSize()); + memcpy(membuf->writableData(), signature, getSignatureFieldSize()); + + return membuf; } -void Packet::setSignatureTimestamp(const uint64_t ×tamp) { - int ret = - hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp); +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(&pkbuf_, &field_size); if (ret < 0) { - throw errors::RuntimeException("Error setting the signature timestamp."); + throw errors::RuntimeException("Error reading signature field size"); } + return field_size; } -uint64_t Packet::getSignatureTimestamp() const { - uint64_t return_value; - int ret = hicn_packet_get_signature_timestamp(format_, packet_start_, - &return_value); +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(&pkbuf_, &padding); if (ret < 0) { - throw errors::RuntimeException("Error getting the signature timestamp."); + throw errors::RuntimeException("Error reading signature padding"); + } + + size_t size = getSignatureFieldSize() - padding; + if (size < 0) { + throw errors::RuntimeException("Error reading signature size"); } - return return_value; + return size; } -void Packet::setValidationAlgorithm( - const utils::CryptoSuite &validation_algorithm) { - int ret = hicn_packet_set_validation_algorithm(format_, packet_start_, - uint8_t(validation_algorithm)); +uint64_t Packet::getSignatureTimestamp() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); + } + uint64_t timestamp; + int ret = hicn_packet_get_signature_timestamp(&pkbuf_, ×tamp); if (ret < 0) { - throw errors::RuntimeException("Error setting the validation algorithm."); + throw errors::RuntimeException("Error getting the signature timestamp."); } + return timestamp; } -utils::CryptoSuite Packet::getValidationAlgorithm() const { - uint8_t return_value; - int ret = hicn_packet_get_validation_algorithm(format_, packet_start_, - &return_value); +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(&pkbuf_, &key_id.first, &key_id.second); if (ret < 0) { throw errors::RuntimeException("Error getting the validation algorithm."); } - - return utils::CryptoSuite(return_value); + return key_id; } -void Packet::setKeyId(const utils::KeyId &key_id) { - 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::CryptoSuite Packet::getValidationAlgorithm() const { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } -} - -utils::KeyId Packet::getKeyId() const { - utils::KeyId return_value; - int ret = hicn_packet_get_key_id(format_, packet_start_, &return_value.first, - &return_value.second); + uint8_t return_value; + int ret = hicn_packet_get_validation_algorithm(&pkbuf_, &return_value); if (ret < 0) { throw errors::RuntimeException("Error getting the validation algorithm."); } - - return return_value; -} - -utils::CryptoHash Packet::computeDigest(utils::CryptoHashType algorithm) const { - utils::CryptoHasher hasher(static_cast<utils::CryptoHashType>(algorithm)); - hasher.init(); - - // 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(); - - auto current = header_head_; - do { - hasher.updateBytes(current->data(), current->length()); - current = current->next(); - } while (current != header_head_); - - hicn_packet_copy_header(format_, &header_copy, packet_start_, false); - - return hasher.finalize(); + return auth::CryptoSuite(return_value); } -bool Packet::checkIntegrity() const { - if (hicn_packet_check_integrity(format_, packet_start_) < 0) { - return false; +void Packet::setSignature(const utils::MemBuf::Ptr &signature) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return true; -} - -Packet &Packet::setSyn() { - if (hicn_packet_set_syn(packet_start_) < 0) { - throw errors::RuntimeException("Error setting syn bit in the packet."); + uint8_t *signature_field; + int ret = hicn_packet_get_signature(&pkbuf_, &signature_field); + if (ret < 0) { + throw errors::RuntimeException("Error getting signature."); } - - return *this; + memcpy(signature_field, signature->data(), signature->length()); } -Packet &Packet::resetSyn() { - if (hicn_packet_reset_syn(packet_start_) < 0) { - throw errors::RuntimeException("Error resetting syn bit in the packet."); +void Packet::setSignatureFieldSize(std::size_t size) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return *this; -} - -bool Packet::testSyn() const { - bool res = false; - if (hicn_packet_test_syn(packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing syn bit in the packet."); + int ret = hicn_packet_set_signature_size(&pkbuf_, size); + if (ret < 0) { + throw errors::RuntimeException("Error setting signature size."); } - - return res; } -Packet &Packet::setAck() { - if (hicn_packet_set_ack(packet_start_) < 0) { - throw errors::RuntimeException("Error setting ack bit in the packet."); +void Packet::setSignatureSize(std::size_t size) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return *this; -} - -Packet &Packet::resetAck() { - if (hicn_packet_reset_ack(packet_start_) < 0) { - throw errors::RuntimeException("Error resetting ack bit in the packet."); + size_t padding = getSignatureFieldSize() - size; + if (padding < 0) { + throw errors::RuntimeException("Error setting signature padding."); } - return *this; -} - -bool Packet::testAck() const { - bool res = false; - if (hicn_packet_test_ack(packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing ack bit in the packet."); + int ret = hicn_packet_set_signature_padding(&pkbuf_, padding); + if (ret < 0) { + throw errors::RuntimeException("Error setting signature padding."); } - - return res; } -Packet &Packet::setRst() { - if (hicn_packet_set_rst(packet_start_) < 0) { - throw errors::RuntimeException("Error setting rst bit in the packet."); +void Packet::setSignatureTimestamp(const uint64_t ×tamp) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return *this; -} - -Packet &Packet::resetRst() { - if (hicn_packet_reset_rst(packet_start_) < 0) { - throw errors::RuntimeException("Error resetting rst bit in the packet."); + int ret = hicn_packet_set_signature_timestamp(&pkbuf_, timestamp); + if (ret < 0) { + throw errors::RuntimeException("Error setting the signature timestamp."); } - - return *this; } -bool Packet::testRst() const { - bool res = false; - if (hicn_packet_test_rst(packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing rst bit in the packet."); +void Packet::setKeyId(const auth::KeyId &key_id) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return res; -} - -Packet &Packet::setFin() { - if (hicn_packet_set_fin(packet_start_) < 0) { - throw errors::RuntimeException("Error setting fin bit in the packet."); + int ret = hicn_packet_set_key_id(&pkbuf_, key_id.first, key_id.second); + if (ret < 0) { + throw errors::RuntimeException("Error setting the key id."); } - - return *this; } -Packet &Packet::resetFin() { - if (hicn_packet_reset_fin(packet_start_) < 0) { - throw errors::RuntimeException("Error resetting fin bit in the packet."); +void Packet::setValidationAlgorithm( + const auth::CryptoSuite &validation_algorithm) { + if (!hasAH()) { + throw errors::RuntimeException("Packet without Authentication Header."); } - return *this; -} - -bool Packet::testFin() const { - bool res = false; - if (hicn_packet_test_fin(packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing fin bit in the packet."); + int ret = hicn_packet_set_validation_algorithm(&pkbuf_, + uint8_t(validation_algorithm)); + if (ret < 0) { + throw errors::RuntimeException("Error setting the validation algorithm."); } +} - return res; +Packet::Format Packet::toAHFormat(const Format &format) { + return hicn_get_ah_format(format); } -Packet &Packet::resetFlags() { - resetSyn(); - resetAck(); - resetRst(); - resetFin(); +Packet::Format Packet::getFormatFromBuffer(const uint8_t *buffer, + std::size_t length) { + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); - return *this; + return hicn_packet_get_format(&pkbuf); } -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; +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 = HICN_PACKET_FORMAT_IS_AH(format); + return is_ah * (header_length + signature_size) + (!is_ah) * header_length; } -Packet &Packet::setSrcPort(uint16_t srcPort) { - if (hicn_packet_set_src_port(packet_start_, srcPort) < 0) { - throw errors::RuntimeException("Error setting source port in the packet."); - } +std::size_t Packet::getHeaderSizeFromBuffer(const uint8_t *buffer, + std::size_t length) { + size_t header_length; - return *this; -} + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); -Packet &Packet::setDstPort(uint16_t dstPort) { - if (hicn_packet_set_dst_port(packet_start_, dstPort) < 0) { - throw errors::RuntimeException( - "Error setting destination port in the packet."); - } + int rc = hicn_packet_get_header_len(&pkbuf, &header_length); + if (TRANSPORT_EXPECT_FALSE(rc < 0)) throw errors::MalformedPacketException(); - return *this; + return header_length; } -uint16_t Packet::getSrcPort() const { - uint16_t port = 0; - - if (hicn_packet_get_src_port(packet_start_, &port) < 0) { - throw errors::RuntimeException("Error reading source port in the packet."); - } - - return port; -} +std::size_t Packet::getPayloadSizeFromBuffer(const uint8_t *buffer, + std::size_t length) { + std::size_t payload_length; -uint16_t Packet::getDstPort() const { - uint16_t port = 0; + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); - if (hicn_packet_get_dst_port(packet_start_, &port) < 0) { - throw errors::RuntimeException( - "Error reading destination port in the packet."); - } + int rc = hicn_packet_get_payload_len(&pkbuf, &payload_length); + if (TRANSPORT_EXPECT_FALSE(rc < 0)) throw errors::MalformedPacketException(); - return port; + return payload_length; } -Packet &Packet::setTTL(uint8_t hops) { - if (hicn_packet_set_hoplimit(packet_start_, hops) < 0) { - throw errors::RuntimeException("Error setting TTL."); - } - - return *this; +void Packet::dump(uint8_t *buffer, std::size_t length) { + hicn_packet_dump(buffer, length); } -uint8_t Packet::getTTL() const { - uint8_t hops = 0; - if (hicn_packet_get_hoplimit(packet_start_, &hops) < 0) { - throw errors::RuntimeException("Error reading TTL."); - } - - return hops; +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; } -void Packet::separateHeaderPayload() { - if (payload_head_) { - return; - } - - int signature_size = 0; - if (_is_ah(format_)) { - signature_size = (uint32_t)getSignatureSize(); - } - - auto header_size = getHeaderSizeFromFormat(format_, signature_size); - auto payload_length = packet_->length() - header_size; - - packet_->trimEnd(packet_->length()); - - auto payload = packet_->cloneOne(); - payload_head_ = payload.get(); - payload_head_->advance(header_size); - payload_head_->append(payload_length); - packet_->prependChain(std::move(payload)); - packet_->append(header_size); +void Packet::saveHeader(u8 *header, size_t *header_len) { + hicn_packet_save_header(&pkbuf_, header, header_len, /* copy_ah */ false); } -void Packet::resetPayload() { - if (packet_->isChained()) { - packet_->separateChain(packet_->next(), packet_->prev()); - payload_head_ = nullptr; - updateLength(); - } +void Packet::loadHeader(u8 *header, size_t header_len) { + hicn_packet_load_header(&pkbuf_, header, header_len); } } // end namespace core |