#include #include #include "packeteer/net/arp.hpp" using namespace packeteer::net; namespace { std::vector arp_request() { return { 0x00, 0x01, // hardware type = Ethernet 0x08, 0x00, // protocol type = IPv4 0x06, // hardware len = 6 0x04, // protocol len = 4 0x00, 0x01, // opcode = request 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x01, // sender MAC 10, 0, 0, 1, // sender IP 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target MAC (unknown, all zero) 10, 0, 0, 2, // target IP }; } std::vector arp_reply() { return { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, // opcode = reply 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x02, // sender MAC (the one who was asked) 10, 0, 0, 2, // sender IP 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x01, // target MAC (the original requester) 10, 0, 0, 1, // target IP }; } } // namespace TEST_CASE("parse_arp decodes a request with Ethernet/IPv4 addressing") { auto arp = parse_arp(arp_request()); REQUIRE(arp.has_value()); CHECK(arp->header.opcode == kArpOpRequest); REQUIRE(arp->sender_ip.has_value()); REQUIRE(arp->sender_mac.has_value()); REQUIRE(arp->target_ip.has_value()); CHECK(arp->sender_ip->bytes == std::array{10, 0, 0, 1}); CHECK(arp->target_ip->bytes == std::array{10, 0, 0, 2}); CHECK(arp->sender_mac->bytes == std::array{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x01}); } TEST_CASE("parse_arp decodes a reply") { auto arp = parse_arp(arp_reply()); REQUIRE(arp.has_value()); CHECK(arp->header.opcode == kArpOpReply); REQUIRE(arp->sender_ip.has_value()); CHECK(arp->sender_ip->bytes == std::array{10, 0, 0, 2}); } TEST_CASE("parse_arp rejects a truncated header") { std::vector bytes(5, 0); CHECK_FALSE(parse_arp(bytes).has_value()); } TEST_CASE("parse_arp decodes the header but skips addresses for non-Ethernet/IPv4") { std::vector bytes = { 0x00, 0x06, // hardware type = IEEE 802 (arbitrary, just not the common case) 0x08, 0x00, 0x08, // hardware len = 8, not 6 0x04, 0x00, 0x01, }; auto arp = parse_arp(bytes); REQUIRE(arp.has_value()); CHECK(arp->header.hardware_len == 8); CHECK_FALSE(arp->sender_ip.has_value()); CHECK_FALSE(arp->sender_mac.has_value()); } TEST_CASE("parse_arp treats a header claiming Ethernet/IPv4 but too short to hold it as header-only") { std::vector bytes = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, // truncated sender MAC }; auto arp = parse_arp(bytes); REQUIRE(arp.has_value()); CHECK_FALSE(arp->sender_ip.has_value()); }