/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2013-2023, Regents of the University of California. * * This file is part of ndn-tools (Named Data Networking Essential Tools). * See AUTHORS.md for complete list of ndn-tools authors and contributors. * * ndn-tools is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * ndn-tools, e.g., in COPYING.md file. If not, see . * * See AUTHORS.md for complete list of ndn-cxx authors and contributors. * * @author Alexander Afanasyev * @author Davide Pesavento */ #include "dissector.hpp" #include #include #include #include namespace ndn::dissect { Dissector::Dissector(std::istream& input, std::ostream& output, const Options& options) : m_options(options) , m_in(input) , m_out(output) { } void Dissector::dissect() { size_t offset = 0; try { while (m_in.peek() != std::istream::traits_type::eof()) { auto block = Block::fromStream(m_in); printBlock(block); offset += block.size(); } } catch (const std::exception& e) { std::cerr << "ERROR: " << e.what() << " at offset " << offset << "\n"; } } // http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr static const char GLYPH_VERTICAL[] = "\u2502 "; // "│ " static const char GLYPH_VERTICAL_AND_RIGHT[] = "\u251c\u2500"; // "├─" static const char GLYPH_UP_AND_RIGHT[] = "\u2514\u2500"; // "└─" static const char GLYPH_SPACE[] = " "; void Dissector::printBranches() { for (size_t i = 0; i < m_branches.size(); ++i) { if (i == m_branches.size() - 1) { m_out << (m_branches[i] ? GLYPH_VERTICAL_AND_RIGHT : GLYPH_UP_AND_RIGHT); } else { m_out << (m_branches[i] ? GLYPH_VERTICAL : GLYPH_SPACE); } } } // https://docs.named-data.net/NDN-packet-spec/current/types.html static const std::map TLV_DICT = { {tlv::Interest , "Interest"}, {tlv::Data , "Data"}, {tlv::Name , "Name"}, // Name components {tlv::GenericNameComponent , "GenericNameComponent"}, {tlv::ImplicitSha256DigestComponent , "ImplicitSha256DigestComponent"}, {tlv::ParametersSha256DigestComponent , "ParametersSha256DigestComponent"}, {tlv::KeywordNameComponent , "KeywordNameComponent"}, {tlv::SegmentNameComponent , "SegmentNameComponent"}, {tlv::ByteOffsetNameComponent , "ByteOffsetNameComponent"}, {tlv::VersionNameComponent , "VersionNameComponent"}, {tlv::TimestampNameComponent , "TimestampNameComponent"}, {tlv::SequenceNumNameComponent , "SequenceNumNameComponent"}, // Interest packet {tlv::CanBePrefix , "CanBePrefix"}, {tlv::MustBeFresh , "MustBeFresh"}, {tlv::ForwardingHint , "ForwardingHint"}, {tlv::Nonce , "Nonce"}, {tlv::InterestLifetime , "InterestLifetime"}, {tlv::HopLimit , "HopLimit"}, {tlv::ApplicationParameters , "ApplicationParameters"}, {tlv::InterestSignatureInfo , "InterestSignatureInfo"}, {tlv::InterestSignatureValue , "InterestSignatureValue"}, // Data packet {tlv::MetaInfo , "MetaInfo"}, {tlv::Content , "Content"}, {tlv::SignatureInfo , "SignatureInfo"}, {tlv::SignatureValue , "SignatureValue"}, {tlv::ContentType , "ContentType"}, {tlv::FreshnessPeriod , "FreshnessPeriod"}, {tlv::FinalBlockId , "FinalBlockId"}, // (Interest)SignatureInfo {tlv::SignatureType , "SignatureType"}, {tlv::KeyLocator , "KeyLocator"}, {tlv::KeyDigest , "KeyDigest"}, {tlv::SignatureNonce , "SignatureNonce"}, {tlv::SignatureTime , "SignatureTime"}, {tlv::SignatureSeqNum , "SignatureSeqNum"}, // Certificate {tlv::ValidityPeriod , "ValidityPeriod"}, {tlv::NotBefore , "NotBefore"}, {tlv::NotAfter , "NotAfter"}, {tlv::AdditionalDescription , "AdditionalDescription"}, {tlv::DescriptionEntry , "DescriptionEntry"}, {tlv::DescriptionKey , "DescriptionKey"}, {tlv::DescriptionValue , "DescriptionValue"}, // SafeBag {tlv::security::SafeBag , "SafeBag"}, {tlv::security::EncryptedKey , "EncryptedKey"}, }; void Dissector::printType(uint32_t type) { m_out << type << " ("; auto it = TLV_DICT.find(type); if (it != TLV_DICT.end()) { m_out << it->second; } else if ((type >= tlv::AppPrivateBlock1 && type <= 252) || type >= tlv::AppPrivateBlock2) { m_out << "UNKNOWN_APP"; } else { m_out << "RESERVED"; } m_out << ")"; } void Dissector::printBlock(const Block& block) { printBranches(); printType(block.type()); m_out << " (size: " << block.value_size() << ")"; try { if (block.type() != tlv::SignatureValue && block.type() != tlv::InterestSignatureValue && (block.type() != tlv::Content || m_options.dissectContent)) { block.parse(); } } catch (const tlv::Error&) { // pass (e.g., leaf block reached) } const auto& elements = block.elements(); if (elements.empty()) { m_out << " [["; escape(m_out, {reinterpret_cast(block.value()), block.value_size()}); m_out << "]]"; } m_out << "\n"; m_branches.push_back(true); for (size_t i = 0; i < elements.size(); ++i) { if (i == elements.size() - 1) { // no more branches to draw at this level of the tree m_branches.back() = false; } printBlock(elements[i]); } m_branches.pop_back(); } } // namespace ndn::dissect