#include #include #include "wireframe/filter.hpp" namespace { // pcap_open_dead() creates a handle that isn't attached to any real // interface - exactly what pcap_compile() needs (linktype + snaplen) // without requiring root or a live device. struct DeadHandle { pcap_t* handle; explicit DeadHandle(int datalink) : handle(pcap_open_dead(datalink, 65535)) {} ~DeadHandle() { if (handle) pcap_close(handle); } }; } // namespace TEST_CASE("compile_filter accepts a valid tcpdump-style expression") { DeadHandle dead(DLT_EN10MB); REQUIRE(dead.handle != nullptr); bpf_program prog{}; auto err = wireframe::compile_filter(dead.handle, "tcp port 80", &prog); CHECK_FALSE(err.has_value()); pcap_freecode(&prog); } TEST_CASE("compile_filter accepts a compound expression") { DeadHandle dead(DLT_EN10MB); REQUIRE(dead.handle != nullptr); bpf_program prog{}; auto err = wireframe::compile_filter(dead.handle, "host 10.0.0.1 and not icmp", &prog); CHECK_FALSE(err.has_value()); pcap_freecode(&prog); } TEST_CASE("compile_filter rejects invalid syntax with an error message") { DeadHandle dead(DLT_EN10MB); REQUIRE(dead.handle != nullptr); bpf_program prog{}; auto err = wireframe::compile_filter(dead.handle, "this is not a valid filter !!", &prog); REQUIRE(err.has_value()); CHECK_FALSE(err->empty()); } TEST_CASE("compile_filter works against DLT_RAW, not just Ethernet") { DeadHandle dead(DLT_RAW); REQUIRE(dead.handle != nullptr); bpf_program prog{}; auto err = wireframe::compile_filter(dead.handle, "udp", &prog); CHECK_FALSE(err.has_value()); pcap_freecode(&prog); } TEST_CASE("compile_filter rejects an Ethernet-only expression against DLT_RAW") { DeadHandle dead(DLT_RAW); REQUIRE(dead.handle != nullptr); bpf_program prog{}; // "ether" primitives are meaningless without a link-layer header. auto err = wireframe::compile_filter(dead.handle, "ether host 00:11:22:33:44:55", &prog); CHECK(err.has_value()); }