srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_arp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_arp.cpp')
-rw-r--r--tests/test_arp.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/tests/test_arp.cpp b/tests/test_arp.cpp
new file mode 100644
index 0000000..247782b
--- /dev/null
+++ b/tests/test_arp.cpp
@@ -0,0 +1,89 @@
+#include <doctest/doctest.h>
+
+#include <vector>
+
+#include "packeteer/net/arp.hpp"
+
+using namespace packeteer::net;
+
+namespace {
+
+std::vector<unsigned char> 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<unsigned char> 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<unsigned char, 4>{10, 0, 0, 1});
+ CHECK(arp->target_ip->bytes == std::array<unsigned char, 4>{10, 0, 0, 2});
+ CHECK(arp->sender_mac->bytes == std::array<unsigned char, 6>{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<unsigned char, 4>{10, 0, 0, 2});
+}
+
+TEST_CASE("parse_arp rejects a truncated header") {
+ std::vector<unsigned char> 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<unsigned char> 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<unsigned char> 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());
+}