Skip to content

Commit 7f99131

Browse files
authored
Fix packets with Linktype_RAW (101) not being recognized by the BPF filters correctly. (#2222)
* Fix packets with Linktype_RAW (101) not being recognized by the BPF filters correctly. This fixes a regression during the transition to a non-libpcap parser described in #2221, where filters would stop working for packets of type RAW. The change also restores a test to keep track of the behaviour, with the change being that the packets are now reported as platform agnostic type (LINKTYPE_RAW) instead of the platform specific type (LINKTYPE_DLT_RAW), and only perform the conversion internally. * Add suppression for unused function warning. * Fix typos. * Fix attribute definition. * Update patch to be under use pcap macro. * Fix comment wording.
1 parent ff876fc commit 7f99131

2 files changed

Lines changed: 86 additions & 14 deletions

File tree

Pcap++/src/PcapFilter.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
namespace pcpp
1919
{
20-
2120
static const int DEFAULT_SNAPLEN = 9000;
2221

2322
namespace internal
@@ -131,13 +130,42 @@ namespace pcpp
131130
#endif
132131
}
133132

133+
namespace
134+
{
135+
#ifdef USE_PCAP
136+
/// @brief Applies linktype patches to ensure compatibility with BPF filters.
137+
/// @param linktype The original link layer type.
138+
/// @return The patched link layer type suitable for BPF filters.
139+
LinkLayerType patchLinktype2dlt(LinkLayerType linktype)
140+
{
141+
switch (linktype)
142+
{
143+
// NOTE: Issue #2221
144+
// Libpcap maps LINKTYPE_RAW to the old DLT_RAW. LINKTYPE_RAW is not that well supported for BPF filters.
145+
// https://github.com/the-tcpdump-group/libpcap/blob/720fb235648dd06eaa5b0fc0e7b6bac84bf2bf28/pcap-common.c#L1559-L1560
146+
case LinkLayerType::LINKTYPE_RAW:
147+
{
148+
# ifdef __OpenBSD__
149+
return LinkLayerType::LINKTYPE_DLT_RAW2; // OpenBSD uses a different DLT_RAW value.
150+
# else
151+
return LinkLayerType::LINKTYPE_DLT_RAW1;
152+
# endif // !__OpenBSD__
153+
}
154+
default:
155+
return linktype;
156+
}
157+
}
158+
#endif // USE_PCAP
159+
} // namespace
160+
134161
BpfFilterWrapper::BpfProgramUPtr BpfFilterWrapper::compileFilter(std::string const& filter, LinkLayerType linkType)
135162
{
136163
if (filter.empty())
137164
return nullptr;
138165

139166
#ifdef USE_PCAP
140-
auto pcap = std::unique_ptr<pcap_t, internal::PcapCloseDeleter>(pcap_open_dead(linkType, DEFAULT_SNAPLEN));
167+
auto pcap = std::unique_ptr<pcap_t, internal::PcapCloseDeleter>(
168+
pcap_open_dead(patchLinktype2dlt(linkType), DEFAULT_SNAPLEN));
141169
if (pcap == nullptr)
142170
{
143171
return nullptr;

Tests/Pcap++Test/Tests/FilterTests.cpp

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -836,25 +836,69 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer)
836836
// check if GeneralFilter::matches(...) work properly for packets with different LinkLayerType
837837

838838
// pcpp::LINKTYPE_NULL layer
839-
pcpp::PcapFileReaderDevice fileReaderDev1(NULL_LOOPBACK_PCAP_PATH);
840-
PTF_ASSERT_TRUE(fileReaderDev1.open());
841-
pcpp::RawPacketVector rawPacketVec;
842-
fileReaderDev1.getNextPackets(rawPacketVec);
843-
fileReaderDev1.close();
839+
{
840+
pcpp::PcapFileReaderDevice fileReaderDev1(NULL_LOOPBACK_PCAP_PATH);
841+
PTF_ASSERT_TRUE(fileReaderDev1.open());
842+
pcpp::RawPacketVector rawPacketVec;
843+
fileReaderDev1.getNextPackets(rawPacketVec);
844+
fileReaderDev1.close();
845+
846+
int validCounter = 0;
847+
for (auto* rawPacketPtr : rawPacketVec)
848+
{
849+
pcpp::BPFStringFilter bpfStringFilter(
850+
"len = " +
851+
std::to_string(rawPacketPtr->getRawDataLen())); // checking against real filter, not the "" filter
852+
if (bpfStringFilter.matches(*rawPacketPtr) && rawPacketPtr->getLinkLayerType() == pcpp::LINKTYPE_NULL)
853+
{
854+
++validCounter;
855+
}
856+
}
857+
PTF_ASSERT_EQUAL(validCounter, 3);
858+
rawPacketVec.clear();
859+
}
844860

861+
pcpp::RawPacketVector rawPacketVec;
845862
int validCounter = 0;
846-
for (auto* rawPacketPtr : rawPacketVec)
863+
// pcpp::LINKTYPE_RAW layer
847864
{
848-
pcpp::BPFStringFilter bpfStringFilter(
849-
"len = " +
850-
std::to_string(rawPacketPtr->getRawDataLen())); // checking against real filter, not the "" filter
851-
if (bpfStringFilter.matches(*rawPacketPtr) && rawPacketPtr->getLinkLayerType() == pcpp::LINKTYPE_NULL)
865+
pcpp::PcapFileReaderDevice fileReaderDev1(RAW_IP_PCAP_PATH);
866+
PTF_ASSERT_TRUE(fileReaderDev1.open());
867+
fileReaderDev1.getNextPackets(rawPacketVec);
868+
for (auto* rawPacketPtr : rawPacketVec)
852869
{
853-
++validCounter;
870+
pcpp::Packet packet(rawPacketPtr);
871+
if (pcpp::IPv4Layer* ip4layer = packet.getLayerOfType<pcpp::IPv4Layer>())
872+
{
873+
pcpp::BPFStringFilter bpfStringFilter(
874+
"host " +
875+
ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter
876+
if (bpfStringFilter.matches(*rawPacketPtr))
877+
{
878+
if (rawPacketPtr->getLinkLayerType() == pcpp::LINKTYPE_RAW)
879+
{
880+
++validCounter;
881+
}
882+
}
883+
}
854884
}
885+
PTF_ASSERT_EQUAL(validCounter, 50);
886+
rawPacketVec.clear();
887+
}
888+
889+
// pcpp::LINKTYPE_RAW layer with device integrated filter
890+
{
891+
pcpp::PcapFileReaderDevice dev(RAW_IP_PCAP_PATH);
892+
PTF_ASSERT_TRUE(dev.open());
893+
894+
PTF_ASSERT_TRUE(dev.setFilter("ip"));
895+
896+
dev.getNextPackets(rawPacketVec);
897+
PTF_ASSERT_EQUAL(validCounter, rawPacketVec.size());
855898
}
856-
PTF_ASSERT_EQUAL(validCounter, 3);
899+
857900
rawPacketVec.clear();
901+
validCounter = 0;
858902

859903
// pcpp::LINKTYPE_LINUX_SLL layer
860904
pcpp::PcapFileReaderDevice fileReaderDev2(SLL_PCAP_PATH);

0 commit comments

Comments
 (0)