noderequest_test.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 <gtest/gtest.h> 6 #include <limits> 7 #include <tins/tins.h> 8 #include "noderequest.hpp" 9 10 using namespace crazytrace; 11 12 TEST(NodeRequestTest, EchoRequest) 13 { 14 const Tins::HWAddress<6> source_mac("52:54:00:b2:fa:7f"); 15 const Tins::HWAddress<6> destination_mac("52:54:00:b2:fa:7e"); 16 const Tins::IPv6Address source_address("fd00::1"); 17 const Tins::IPv6Address destination_address("fd00::2"); 18 constexpr int hoplimit = 55; 19 constexpr int icmp_identifier = 56; 20 constexpr int icmp_sequence = 1; 21 const Tins::RawPDU::payload_type payload = {8, 4, 5, 9, 255, 0, 0, 0, 0, 0}; 22 23 Tins::EthernetII packet = Tins::EthernetII(destination_mac, source_mac) / 24 Tins::IPv6(destination_address, source_address) / 25 Tins::ICMPv6(Tins::ICMPv6::Types::ECHO_REQUEST); 26 Tins::IPv6& inner_ipv6 = packet.rfind_pdu<Tins::IPv6>(); 27 inner_ipv6.hop_limit(hoplimit); 28 Tins::ICMPv6& inner_icmpv6 = inner_ipv6.rfind_pdu<Tins::ICMPv6>(); 29 inner_icmpv6.identifier(icmp_identifier); 30 inner_icmpv6.sequence(icmp_sequence); 31 inner_icmpv6.inner_pdu(Tins::RawPDU(payload)); 32 33 /* Serializing the package is necessary to automatically calculate checksums 34 * and other fields. */ 35 const Tins::PDU::serialization_type serialized_packet = packet.serialize(); 36 ASSERT_LE(serialized_packet.size(), std::numeric_limits<uint32_t>::max()); 37 const Tins::EthernetII final_packet( 38 serialized_packet.data(), 39 static_cast<uint32_t>(serialized_packet.size())); 40 41 const NodeRequest request(final_packet); 42 43 EXPECT_EQ(request.get_type(), NodeRequestType::ICMP_ECHO_REQUEST); 44 EXPECT_EQ(request.get_source_mac(), source_mac); 45 EXPECT_EQ(request.get_destination_mac(), destination_mac); 46 EXPECT_EQ(request.get_source_address(), source_address); 47 EXPECT_EQ(request.get_destination_address(), destination_address); 48 EXPECT_EQ(request.get_hoplimit(), hoplimit); 49 EXPECT_EQ(request.get_udp_sport(), 0); 50 EXPECT_EQ(request.get_udp_dport(), 0); 51 EXPECT_EQ(request.get_icmp_identifier(), icmp_identifier); 52 EXPECT_EQ(request.get_icmp_sequence(), icmp_sequence); 53 EXPECT_EQ(request.get_payload(), payload); 54 55 std::ostringstream test_output; 56 test_output << request; 57 EXPECT_EQ(test_output.str(), 58 "REQUEST ICMP_ECHO_REQUEST: fd00::1 (52:54:00:b2:fa:7f) -> " 59 "fd00::2 (52:54:00:b2:fa:7e) Hoplimit=55: ID=56 SEQ=1 Payload: " 60 "08 04 05 09 ff 00 00 00 00 00"); 61 } 62 63 TEST(NodeRequestTest, NdpRequest) 64 { 65 const Tins::HWAddress<6> source_mac("52:54:00:b2:fa:7f"); 66 const Tins::HWAddress<6> destination_mac("33:33:ff:48:b2:ae"); 67 const Tins::IPv6Address source_address("fd00::1"); 68 const Tins::IPv6Address destination_address("ff02::1:ff48:b2ae"); 69 const Tins::IPv6Address target_address("fd00::2"); 70 constexpr int hoplimit = 2; 71 72 Tins::EthernetII packet = 73 Tins::EthernetII(destination_mac, source_mac) / 74 Tins::IPv6(destination_address, source_address) / 75 Tins::ICMPv6(Tins::ICMPv6::Types::NEIGHBOUR_SOLICIT); 76 Tins::IPv6& inner_ipv6 = packet.rfind_pdu<Tins::IPv6>(); 77 inner_ipv6.hop_limit(hoplimit); 78 Tins::ICMPv6& inner_icmpv6 = inner_ipv6.rfind_pdu<Tins::ICMPv6>(); 79 inner_icmpv6.target_addr(target_address); 80 81 /* Serializing the package is necessary to automatically calculate checksums 82 * and other fields. */ 83 const Tins::PDU::serialization_type serialized_packet = packet.serialize(); 84 ASSERT_LE(serialized_packet.size(), std::numeric_limits<uint32_t>::max()); 85 const Tins::EthernetII final_packet( 86 serialized_packet.data(), 87 static_cast<uint32_t>(serialized_packet.size())); 88 89 const NodeRequest request(final_packet); 90 91 EXPECT_EQ(request.get_type(), NodeRequestType::ICMP_NDP); 92 EXPECT_EQ(request.get_source_mac(), source_mac); 93 EXPECT_EQ(request.get_destination_mac(), destination_mac); 94 EXPECT_EQ(request.get_source_address(), source_address); 95 EXPECT_EQ(request.get_destination_address(), target_address); 96 EXPECT_EQ(request.get_hoplimit(), hoplimit); 97 EXPECT_EQ(request.get_udp_sport(), 0); 98 EXPECT_EQ(request.get_udp_dport(), 0); 99 EXPECT_EQ(request.get_icmp_identifier(), 0); 100 EXPECT_EQ(request.get_icmp_sequence(), 0); 101 EXPECT_TRUE(request.get_payload().empty()); 102 103 std::ostringstream test_output; 104 test_output << request; 105 EXPECT_EQ(test_output.str(), 106 "REQUEST ICMP_NDP: fd00::1 (52:54:00:b2:fa:7f) -> fd00::2 " 107 "(33:33:ff:48:b2:ae) Hoplimit=2: Looking for fd00::2"); 108 } 109 110 TEST(NodeRequestTest, UdpRequest) 111 { 112 const Tins::HWAddress<6> source_mac("52:54:00:b2:fa:7f"); 113 const Tins::HWAddress<6> destination_mac("52:54:00:b2:fa:7e"); 114 const Tins::IPv6Address source_address("fd00::1"); 115 const Tins::IPv6Address destination_address("fd00::2"); 116 constexpr int hoplimit = 55; 117 constexpr int udp_sport = 54739; 118 constexpr int udp_dport = 33434; 119 const Tins::RawPDU::payload_type payload = {8, 4, 5, 9, 255, 0, 0, 0, 0, 0}; 120 121 Tins::EthernetII packet = Tins::EthernetII(destination_mac, source_mac) / 122 Tins::IPv6(destination_address, source_address) / 123 Tins::UDP(udp_dport, udp_sport); 124 Tins::IPv6& inner_ipv6 = packet.rfind_pdu<Tins::IPv6>(); 125 inner_ipv6.hop_limit(hoplimit); 126 Tins::UDP& inner_udp = inner_ipv6.rfind_pdu<Tins::UDP>(); 127 inner_udp.inner_pdu(Tins::RawPDU(payload)); 128 129 /* Serializing the package is necessary to automatically calculate checksums 130 * and other fields. */ 131 const Tins::PDU::serialization_type serialized_packet = packet.serialize(); 132 ASSERT_LE(serialized_packet.size(), std::numeric_limits<uint32_t>::max()); 133 const Tins::EthernetII final_packet( 134 serialized_packet.data(), 135 static_cast<uint32_t>(serialized_packet.size())); 136 137 const NodeRequest request(final_packet); 138 139 EXPECT_EQ(request.get_type(), NodeRequestType::UDP); 140 EXPECT_EQ(request.get_source_mac(), source_mac); 141 EXPECT_EQ(request.get_destination_mac(), destination_mac); 142 EXPECT_EQ(request.get_source_address(), source_address); 143 EXPECT_EQ(request.get_destination_address(), destination_address); 144 EXPECT_EQ(request.get_hoplimit(), hoplimit); 145 EXPECT_EQ(request.get_udp_sport(), udp_sport); 146 EXPECT_EQ(request.get_udp_dport(), udp_dport); 147 EXPECT_EQ(request.get_icmp_identifier(), 0); 148 EXPECT_EQ(request.get_icmp_sequence(), 0); 149 EXPECT_EQ(request.get_payload(), payload); 150 151 std::ostringstream test_output; 152 test_output << request; 153 EXPECT_EQ( 154 test_output.str(), 155 "REQUEST UDP: fd00::1 (52:54:00:b2:fa:7f) -> fd00::2 " 156 "(52:54:00:b2:fa:7e) Hoplimit=55: DPORT=33434 SPORT=54739 LENGTH=10"); 157 } 158 159 TEST(NodeRequestTest, UnknownRequest) 160 { 161 const Tins::HWAddress<6> source_mac("52:54:00:b2:fa:7f"); 162 const Tins::HWAddress<6> destination_mac("52:54:00:b2:fa:7e"); 163 const Tins::IPv6Address source_address("fd00::1"); 164 const Tins::IPv6Address destination_address("fd00::2"); 165 constexpr int hoplimit = 2; 166 167 Tins::EthernetII packet = 168 Tins::EthernetII(destination_mac, source_mac) / 169 Tins::IPv6(destination_address, source_address) / 170 Tins::ICMPv6(Tins::ICMPv6::Types::NEIGHBOUR_ADVERT); 171 Tins::IPv6& inner_ipv6 = packet.rfind_pdu<Tins::IPv6>(); 172 inner_ipv6.hop_limit(hoplimit); 173 174 /* Serializing the package is necessary to automatically calculate checksums 175 * and other fields. */ 176 const Tins::PDU::serialization_type serialized_packet = packet.serialize(); 177 ASSERT_LE(serialized_packet.size(), std::numeric_limits<uint32_t>::max()); 178 const Tins::EthernetII final_packet( 179 serialized_packet.data(), 180 static_cast<uint32_t>(serialized_packet.size())); 181 182 const NodeRequest request(final_packet); 183 184 EXPECT_EQ(request.get_type(), NodeRequestType::UNKNOWN); 185 EXPECT_EQ(request.get_source_mac(), source_mac); 186 EXPECT_EQ(request.get_destination_mac(), destination_mac); 187 EXPECT_EQ(request.get_source_address(), source_address); 188 EXPECT_EQ(request.get_destination_address(), destination_address); 189 EXPECT_EQ(request.get_hoplimit(), hoplimit); 190 EXPECT_EQ(request.get_udp_sport(), 0); 191 EXPECT_EQ(request.get_udp_dport(), 0); 192 EXPECT_EQ(request.get_icmp_identifier(), 0); 193 EXPECT_EQ(request.get_icmp_sequence(), 0); 194 EXPECT_TRUE(request.get_payload().empty()); 195 196 std::ostringstream test_output; 197 test_output << request; 198 EXPECT_EQ(test_output.str(), 199 "REQUEST UNKNOWN: fd00::1 (52:54:00:b2:fa:7f) -> fd00::2 " 200 "(52:54:00:b2:fa:7e) Hoplimit=2"); 201 }