noderequest.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2024-2025 Marek Küthe <m.k@mk16.de> 2 // 3 // SPDX-License-Identifier: GPL-3.0-or-later 4 5 #include "noderequest.hpp" 6 #include <iostream> 7 8 using namespace crazytrace; 9 10 crazytrace::NodeRequest::NodeRequest(const Tins::EthernetII& packet) : 11 _type(NodeRequestType::UNKNOWN), 12 _hoplimit(0), 13 _udp_dport(0), 14 _udp_sport(0), 15 _icmp_identifier(0), 16 _icmp_sequence(0) 17 { 18 this->_source_mac = packet.src_addr(); 19 this->_destination_mac = packet.dst_addr(); 20 21 if (packet.find_pdu<Tins::IPv6>() != nullptr) 22 { 23 const Tins::IPv6& ipv6 = packet.rfind_pdu<Tins::IPv6>(); 24 25 this->_source_address = ipv6.src_addr(); 26 this->_destination_address = ipv6.dst_addr(); 27 this->_hoplimit = ipv6.hop_limit(); 28 29 switch (ipv6.next_header()) 30 { 31 case Tins::Constants::IP::PROTO_ICMPV6: 32 { 33 const Tins::ICMPv6& icmpv6 = ipv6.rfind_pdu<Tins::ICMPv6>(); 34 switch (icmpv6.type()) 35 { 36 case Tins::ICMPv6::Types::NEIGHBOUR_SOLICIT: 37 this->_type = NodeRequestType::ICMP_NDP; 38 if (!icmpv6.has_target_addr()) 39 throw std::runtime_error( 40 "ICMP NDP packet has no target address " 41 "attribute."); 42 43 this->_destination_address = icmpv6.target_addr(); 44 break; 45 case Tins::ICMPv6::Types::ECHO_REQUEST: 46 { 47 this->_type = NodeRequestType::ICMP_ECHO_REQUEST; 48 this->_icmp_identifier = icmpv6.identifier(); 49 this->_icmp_sequence = icmpv6.sequence(); 50 const Tins::RawPDU& raw_icmpv6 = 51 icmpv6.rfind_pdu<Tins::RawPDU>(); 52 this->_payload = raw_icmpv6.payload(); 53 break; 54 } 55 default: 56 /* Not supported */ 57 break; 58 } 59 break; 60 } 61 case Tins::Constants::IP::PROTO_UDP: 62 { 63 const Tins::UDP& udp = packet.rfind_pdu<Tins::UDP>(); 64 const Tins::RawPDU& raw_udp = udp.rfind_pdu<Tins::RawPDU>(); 65 this->_type = NodeRequestType::UDP; 66 this->_udp_dport = udp.dport(); 67 this->_udp_sport = udp.sport(); 68 this->_payload = raw_udp.payload(); 69 break; 70 } 71 default: 72 /* Not supported */ 73 break; 74 } 75 } 76 } 77 78 NodeRequestType crazytrace::NodeRequest::get_type() const noexcept 79 { 80 return this->_type; 81 } 82 83 const Tins::HWAddress<6>& 84 crazytrace::NodeRequest::get_source_mac() const noexcept 85 { 86 return this->_source_mac; 87 } 88 89 const Tins::HWAddress<6>& 90 crazytrace::NodeRequest::get_destination_mac() const noexcept 91 { 92 return this->_destination_mac; 93 } 94 95 const Tins::IPv6Address& 96 crazytrace::NodeRequest::get_source_address() const noexcept 97 { 98 return this->_source_address; 99 } 100 101 const Tins::IPv6Address& 102 crazytrace::NodeRequest::get_destination_address() const noexcept 103 { 104 return this->_destination_address; 105 } 106 107 uint8_t crazytrace::NodeRequest::get_hoplimit() const noexcept 108 { 109 return this->_hoplimit; 110 } 111 112 uint16_t crazytrace::NodeRequest::get_udp_sport() const noexcept 113 { 114 return this->_udp_sport; 115 } 116 117 uint16_t crazytrace::NodeRequest::get_udp_dport() const noexcept 118 { 119 return this->_udp_dport; 120 } 121 122 uint16_t crazytrace::NodeRequest::get_icmp_identifier() const noexcept 123 { 124 return this->_icmp_identifier; 125 } 126 127 uint16_t crazytrace::NodeRequest::get_icmp_sequence() const noexcept 128 { 129 return this->_icmp_sequence; 130 } 131 132 const Tins::RawPDU::payload_type& 133 crazytrace::NodeRequest::get_payload() const noexcept 134 { 135 return this->_payload; 136 } 137 138 std::ostream& crazytrace::operator<<(std::ostream& os, 139 NodeRequest const & noderequest) 140 { 141 std::string type_string; 142 switch (noderequest._type) 143 { 144 case NodeRequestType::ICMP_ECHO_REQUEST: 145 type_string = "ICMP_ECHO_REQUEST"; 146 break; 147 case NodeRequestType::ICMP_NDP: 148 type_string = "ICMP_NDP"; 149 break; 150 case NodeRequestType::UDP: 151 type_string = "UDP"; 152 break; 153 default: 154 type_string = "UNKNOWN"; 155 break; 156 } 157 os << "REQUEST " << type_string << ": " << noderequest._source_address 158 << " (" << noderequest._source_mac << ") -> " 159 << noderequest._destination_address << " (" 160 << noderequest._destination_mac << ") " 161 << "Hoplimit=" << static_cast<unsigned>(noderequest._hoplimit); 162 163 switch (noderequest._type) 164 { 165 case NodeRequestType::ICMP_ECHO_REQUEST: 166 { 167 os << ": ID=" << noderequest._icmp_identifier 168 << " SEQ=" << noderequest._icmp_sequence << " Payload:"; 169 for (const auto& byte : noderequest._payload) 170 { 171 os << std::format(" {:02x}", static_cast<int>(byte)); 172 } 173 break; 174 } 175 case NodeRequestType::ICMP_NDP: 176 os << ": Looking for " << noderequest._destination_address; 177 break; 178 case NodeRequestType::UDP: 179 os << ": DPORT=" << noderequest._udp_dport 180 << " SPORT=" << noderequest._udp_sport 181 << " LENGTH=" << noderequest._payload.size(); 182 break; 183 default: 184 break; 185 } 186 187 return os; 188 }