diff --git a/Examples/.clang-tidy b/Examples/.clang-tidy new file mode 100644 index 0000000000..72ea744fa2 --- /dev/null +++ b/Examples/.clang-tidy @@ -0,0 +1,6 @@ +Checks: '-concurrency-mt-unsafe, +-cppcoreguidelines-avoid-const-or-ref-data-members, +-cppcoreguidelines-non-private-member-variables-in-classes, +-cppcoreguidelines-pro-type-union-access' + +InheritParentConfig: true diff --git a/Examples/ArpSpoofing/main.cpp b/Examples/ArpSpoofing/main.cpp index 64865cf184..ecec25d9c4 100644 --- a/Examples/ArpSpoofing/main.cpp +++ b/Examples/ArpSpoofing/main.cpp @@ -15,7 +15,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -33,19 +33,19 @@ static struct option L3FwdOptions[] = { */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hv] -i interface_ip -c victim_ip -g gateway_ip" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -i interface_ip : The IPv4 address of interface to use" << std::endl - << " -c victim_ip : The IPv4 address of the victim" << std::endl - << " -g gateway_ip : The IPv4 address of the gateway" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << std::endl; + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' + << pcpp::AppName::get() << " [-hv] -i interface_ip -c victim_ip -g gateway_ip" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -i interface_ip : The IPv4 address of interface to use" << '\n' + << " -c victim_ip : The IPv4 address of the victim" << '\n' + << " -g gateway_ip : The IPv4 address of the gateway" << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -v : Displays the current version and exists" << '\n' + << '\n'; } /** @@ -53,9 +53,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -64,8 +64,8 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe // Create an ARP packet and change its fields pcpp::Packet arpRequest(500); - pcpp::MacAddress macSrc = pDevice->getMacAddress(); - pcpp::MacAddress macDst(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + const pcpp::MacAddress macSrc = pDevice->getMacAddress(); + const pcpp::MacAddress macDst(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); pcpp::EthLayer ethLayer(macSrc, macDst, static_cast(PCPP_ETHERTYPE_ARP)); pcpp::ArpLayer arpLayer(pcpp::ArpRequest(pDevice->getMacAddress(), pDevice->getIPv4Address(), ipAddr)); @@ -77,7 +77,7 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe pcpp::ArpFilter arpFilter(pcpp::ARP_REPLY); if (!pDevice->setFilter(arpFilter)) { - std::cerr << "Could not set ARP filter on device" << std::endl; + std::cerr << "Could not set ARP filter on device" << '\n'; return pcpp::MacAddress::Zero; } @@ -90,17 +90,17 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe if (capturedPackets.size() < 1) { - std::cerr << "No arp reply was captured. Couldn't retrieve MAC address for IP " << ipAddr << std::endl; + std::cerr << "No arp reply was captured. Couldn't retrieve MAC address for IP " << ipAddr << '\n'; return pcpp::MacAddress::Zero; } // parse arp reply and extract the MAC address - pcpp::Packet arpReply(capturedPackets.front()); + const pcpp::Packet arpReply(capturedPackets.front()); if (arpReply.isPacketOfType(pcpp::ARP)) { return arpReply.getLayerOfType()->getSenderMacAddress(); } - std::cerr << "No arp reply was captured. Couldn't retrieve MAC address for IP " << ipAddr << std::endl; + std::cerr << "No arp reply was captured. Couldn't retrieve MAC address for IP " << ipAddr << '\n'; return pcpp::MacAddress::Zero; } @@ -118,7 +118,7 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew { EXIT_WITH_ERROR("Failed to find gateway MAC address: " << e.what()); } - std::cout << "Got gateway MAC address: " << gatewayMacAddr << std::endl; + std::cout << "Got gateway MAC address: " << gatewayMacAddr << '\n'; // Get the victim MAC address pcpp::MacAddress victimMacAddr; @@ -130,9 +130,9 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew { EXIT_WITH_ERROR("Failed to find victim MAC address: " << e.what()); } - std::cout << "Got victim MAC address: " << victimMacAddr << std::endl; + std::cout << "Got victim MAC address: " << victimMacAddr << '\n'; - pcpp::MacAddress deviceMacAddress = pDevice->getMacAddress(); + const pcpp::MacAddress deviceMacAddress = pDevice->getMacAddress(); // Create ARP reply for the gateway pcpp::Packet gwArpReply(500); @@ -151,15 +151,15 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew victimArpReply.computeCalculateFields(); // Send ARP replies to gateway and to victim every 5 seconds - std::cout << "Sending ARP replies to victim and to gateway every 5 seconds..." << std::endl << std::endl; - while (1) + std::cout << "Sending ARP replies to victim and to gateway every 5 seconds..." << '\n' << '\n'; + while (true) { pDevice->sendPacket(gwArpReply); std::cout << "Sent ARP reply: " << gatewayAddr << " [gateway] is at MAC address " << deviceMacAddress << " [me]" - << std::endl; + << '\n'; pDevice->sendPacket(victimArpReply); std::cout << "Sent ARP reply: " << victimAddr << " [victim] is at MAC address " << deviceMacAddress << " [me]" - << std::endl; + << '\n'; std::this_thread::sleep_for(std::chrono::seconds(5)); } } @@ -170,7 +170,9 @@ int main(int argc, char* argv[]) // Get arguments from user for incoming interface and outgoing interface - std::string iface = "", victim = "", gateway = ""; + std::string iface; + std::string victim; + std::string gateway; int optionIndex = 0; int opt = 0; while ((opt = getopt_long(argc, argv, "i:c:g:hv", L3FwdOptions, &optionIndex)) != -1) @@ -202,7 +204,7 @@ int main(int argc, char* argv[]) } // Both incoming and outgoing interfaces must be provided by user - if (iface == "" || victim == "" || gateway == "") + if (iface.empty() || victim.empty() || gateway.empty()) { EXIT_WITH_ERROR("Please specify both interface IP, victim IP and gateway IP"); } diff --git a/Examples/Arping/main.cpp b/Examples/Arping/main.cpp index e6e03177f6..61d2f8aed2 100644 --- a/Examples/Arping/main.cpp +++ b/Examples/Arping/main.cpp @@ -20,11 +20,11 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) -#define DEFAULT_MAX_TRIES 1000000 +constexpr auto DEFAULT_MAX_TRIES = 1000000; // clang-format off static struct option ArpingOptions[] = { @@ -47,25 +47,25 @@ static struct option ArpingOptions[] = { void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvl] [-c count] [-w timeout] [-s mac_addr] [-S ip_addr] -i interface -T ip_addr" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << " -c count : Send 'count' requests" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -l : Print the list of interfaces and exists" << '\n' + << " -c count : Send 'count' requests" << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" - << std::endl - << " -s mac_addr : Set source MAC address" << std::endl - << " -S ip_addr : Set source IP address" << std::endl - << " -T ip_addr : Set target IP address" << std::endl - << " -w timeout : How long to wait for a reply (in seconds)" << std::endl - << std::endl; + << '\n' + << " -s mac_addr : Set source MAC address" << '\n' + << " -S ip_addr : Set source IP address" << '\n' + << " -T ip_addr : Set target IP address" << '\n' + << " -w timeout : How long to wait for a reply (in seconds)" << '\n' + << '\n'; } /** @@ -73,9 +73,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -87,11 +87,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -101,7 +101,7 @@ void listInterfaces() */ void onApplicationInterrupted(void* cookie) { - auto shouldStop = static_cast(cookie); + auto* shouldStop = static_cast(cookie); *shouldStop = true; } @@ -165,7 +165,7 @@ int main(int argc, char* argv[]) targetIpProvided = true; break; case 'c': - maxTries = atoi(optarg); + maxTries = std::stoi(optarg); break; case 'h': printUsage(); @@ -177,7 +177,7 @@ int main(int argc, char* argv[]) listInterfaces(); break; case 'w': - timeoutSec = atoi(optarg); + timeoutSec = std::stoi(optarg); break; default: printUsage(); @@ -187,11 +187,15 @@ int main(int argc, char* argv[]) // verify that interface name or IP were provided if (!ifaceNameOrIpProvided) + { EXIT_WITH_ERROR("You must provide at least interface name or interface IP (-i switch)"); + } // verify target IP was provided if (!targetIpProvided) + { EXIT_WITH_ERROR("You must provide target IP (-T switch)"); + } pcpp::PcapLiveDevice* dev = nullptr; @@ -200,32 +204,46 @@ int main(int argc, char* argv[]) { dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(ifaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } } else + { EXIT_WITH_ERROR("Interface name or IP empty"); + } // open device in promiscuous mode if (!dev->open()) + { EXIT_WITH_ERROR("Couldn't open interface device '" << dev->getName() << "'"); + } // if source MAC not provided - use the interface MAC address if (sourceMac == pcpp::MacAddress::Zero) + { sourceMac = dev->getMacAddress(); + } // if source MAC is still invalid, it means it couldn't be extracted from interface if (sourceMac == pcpp::MacAddress::Zero) + { EXIT_WITH_ERROR("MAC address couldn't be extracted from interface"); + } if (sourceIP == pcpp::IPv4Address::Zero) + { sourceIP = dev->getIPv4Address(); + } if (sourceIP == pcpp::IPv4Address::Zero) + { EXIT_WITH_ERROR("Source IPv4 address wasn't supplied and couldn't be retrieved from interface"); + } // let's go double arpResponseTimeMS = 0; - int i = 1; + int idx = 1; // suppressing errors to avoid cluttering stdout pcpp::Logger::getInstance().suppressLogs(); @@ -234,17 +252,17 @@ int main(int argc, char* argv[]) bool shouldStop = false; pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); - while (i <= maxTries && !shouldStop) + while (idx <= maxTries && !shouldStop) { // use the getMacAddress utility to send an ARP request and resolve the MAC address - pcpp::MacAddress result = pcpp::NetworkUtils::getInstance().getMacAddress(targetIP, dev, arpResponseTimeMS, - sourceMac, sourceIP, timeoutSec); + const pcpp::MacAddress result = pcpp::NetworkUtils::getInstance().getMacAddress( + targetIP, dev, arpResponseTimeMS, sourceMac, sourceIP, timeoutSec); // failed fetching MAC address if (result == pcpp::MacAddress::Zero) { // PcapPlusPlus logger saves the last internal error message - std::cout << "Arping index=" << i << " : " << pcpp::Logger::getInstance().getLastError() << std::endl; + std::cout << "Arping index=" << idx << " : " << pcpp::Logger::getInstance().getLastError() << '\n'; } else // Succeeded fetching MAC address { @@ -252,10 +270,10 @@ int main(int argc, char* argv[]) std::cout.precision(3); std::cout << "Reply from " << targetIP << " " << "[" << result << "] " << std::fixed << arpResponseTimeMS << "ms " - << "index=" << i << std::endl; + << "index=" << idx << '\n'; } - i++; + ++idx; } dev->close(); diff --git a/Examples/DNSResolver/main.cpp b/Examples/DNSResolver/main.cpp index 3a0a121fce..96a5cb2ed2 100644 --- a/Examples/DNSResolver/main.cpp +++ b/Examples/DNSResolver/main.cpp @@ -11,7 +11,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -32,31 +32,30 @@ static struct option DNSResolverOptions[] = { */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvl] [-t timeout] [-d dns_server] [-g gateway] [-i interface] -s hostname" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << " -s hostname : Hostname to resolve" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -l : Print the list of interfaces and exists" << '\n' + << " -s hostname : Hostname to resolve" << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " "address. If not set" - << std::endl - << " one of the interfaces that has a default gateway will be used" << std::endl + << '\n' + << " one of the interfaces that has a default gateway will be used" << '\n' << " -d dns_server: IPv4 address of DNS server to send the DNS request to. If not set the DNS request " "will be sent to the gateway" - << std::endl + << '\n' << " -g gateway : IPv4 address of the gateway to send the DNS request to. If not set the default " "gateway will be chosen" - << std::endl - << " -t timeout : How long to wait for a reply (in seconds). Default timeout is 5 seconds" - << std::endl - << std::endl; + << '\n' + << " -t timeout : How long to wait for a reply (in seconds). Default timeout is 5 seconds" << '\n' + << '\n'; } /** @@ -64,9 +63,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -78,11 +77,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -92,7 +91,7 @@ void listInterfaces() */ void onApplicationInterrupted(void* cookie) { - auto device = (pcpp::PcapLiveDevice*)cookie; + auto* device = reinterpret_cast(cookie); device->close(); } @@ -161,7 +160,7 @@ int main(int argc, char* argv[]) } case 't': { - timeoutSec = atoi(optarg); + timeoutSec = std::stoi(optarg); break; } default: @@ -174,7 +173,9 @@ int main(int argc, char* argv[]) // make sure that hostname is provided if (!hostnameProvided) + { EXIT_WITH_ERROR("Hostname not provided"); + } // find the interface to send the DNS request from pcpp::PcapLiveDevice* dev = nullptr; @@ -184,7 +185,9 @@ int main(int argc, char* argv[]) { dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } } // if interface name or IP was not provided - find a device that has a default gateway else @@ -201,10 +204,12 @@ int main(int argc, char* argv[]) } if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find an interface with a default gateway"); + } } - std::cout << "Using interface '" << dev->getIPv4Address() << "'" << std::endl; + std::cout << "Using interface '" << dev->getIPv4Address() << "'" << '\n'; // suppressing errors to avoid cluttering stdout pcpp::Logger::getInstance().suppressLogs(); @@ -217,21 +222,21 @@ int main(int argc, char* argv[]) // find the IPv4 address for provided hostname double responseTime = 0; uint32_t dnsTTL = 0; - pcpp::IPv4Address resultIP = pcpp::NetworkUtils::getInstance().getIPv4Address( + const pcpp::IPv4Address resultIP = pcpp::NetworkUtils::getInstance().getIPv4Address( hostname, dev, responseTime, dnsTTL, timeoutSec, dnsServerIP, gatewayIP); if (resultIP == pcpp::IPv4Address::Zero) { - std::cout << std::endl << "Could not resolve hostname [" << hostname << "]" << std::endl; + std::cout << '\n' << "Could not resolve hostname [" << hostname << "]" << '\n'; } else { - std::cout << std::endl + std::cout << '\n' << "IP address of [" << hostname << "] is: " << resultIP << " DNS-TTL=" << dnsTTL - << " time=" << (int)responseTime << "ms" << std::endl; + << " time=" << (int)responseTime << "ms" << '\n'; } } catch (const std::exception&) { - std::cout << std::endl << "Could not resolve hostname [" << hostname << "]" << std::endl; + std::cout << '\n' << "Could not resolve hostname [" << hostname << "]" << '\n'; } } diff --git a/Examples/DnsSpoofing/main.cpp b/Examples/DnsSpoofing/main.cpp index c6f2644f31..72b5074236 100644 --- a/Examples/DnsSpoofing/main.cpp +++ b/Examples/DnsSpoofing/main.cpp @@ -14,7 +14,7 @@ #include #include #if !defined(_WIN32) -# include +# include #endif #include "IpAddress.h" #include "RawPacket.h" @@ -37,7 +37,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -57,11 +57,10 @@ static struct option DnsSpoofingOptions[] = { */ struct DnsSpoofStats { - int numOfSpoofedDnsRequests; + int numOfSpoofedDnsRequests{ 0 }; std::unordered_map spoofedHosts; - DnsSpoofStats() : numOfSpoofedDnsRequests(0) - {} + DnsSpoofStats() = default; }; /** @@ -72,10 +71,9 @@ struct DnsSpoofingArgs pcpp::IPAddress dnsServer; std::vector dnsHostsToSpoof; DnsSpoofStats stats; - bool shouldStop; + bool shouldStop{ false }; - DnsSpoofingArgs() : shouldStop(false) - {} + DnsSpoofingArgs() = default; }; /** @@ -84,31 +82,29 @@ struct DnsSpoofingArgs void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvl] [-o host1,host2,...,host_n] [-c ip_address] -i interface -d ip_address" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of available interfaces" << std::endl - << " -i interface : The interface name or interface IP address to use." << std::endl - << " Use the -l switch to see all interfaces" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -l : Print the list of available interfaces" << '\n' + << " -i interface : The interface name or interface IP address to use." << '\n' + << " Use the -l switch to see all interfaces" << '\n' << " -d ip_address : The IP address of the spoofed DNS server. Supports both IPv4 and IPv6" - << std::endl - << " (all responses will be sent with this IP address)" << std::endl - << " -c ip_address : Spoof only DNS requests coming from a specific IP address" << std::endl - << " -o host1,host2,...,host_n : A comma-separated list of hosts to spoof. If list is not given," - << std::endl + << '\n' + << " (all responses will be sent with this IP address)" << '\n' + << " -c ip_address : Spoof only DNS requests coming from a specific IP address" << '\n' + << " -o host1,host2,...,host_n : A comma-separated list of hosts to spoof. If list is not given," << '\n' << " all hosts will be spoofed. If an host contains '*' all sub-domains" - << std::endl - << " will be spoofed, for example: if '*.google.com' is given" << std::endl - << " then 'mail.google.com', 'tools.google.com', etc. will be spoofed" - << std::endl - << std::endl; + << '\n' + << " will be spoofed, for example: if '*.google.com' is given" << '\n' + << " then 'mail.google.com', 'tools.google.com', etc. will be spoofed" << '\n' + << '\n'; } /** @@ -116,9 +112,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -130,11 +126,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -145,30 +141,36 @@ void listInterfaces() */ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) { - DnsSpoofingArgs* args = (DnsSpoofingArgs*)cookie; + auto* args = reinterpret_cast(cookie); // create a parsed packet from the raw packet pcpp::Packet dnsRequest(packet); if (!dnsRequest.isPacketOfType(pcpp::DNS) || !dnsRequest.isPacketOfType(pcpp::IP) || !dnsRequest.isPacketOfType(pcpp::UDP) || !dnsRequest.isPacketOfType(pcpp::Ethernet)) + { return; + } // extract all packet layers - pcpp::EthLayer* ethLayer = dnsRequest.getLayerOfType(); - pcpp::IPLayer* ipLayer = dnsRequest.getLayerOfType(); - pcpp::UdpLayer* udpLayer = dnsRequest.getLayerOfType(); - pcpp::DnsLayer* dnsLayer = dnsRequest.getLayerOfType(); + auto* ethLayer = dnsRequest.getLayerOfType(); + auto* ipLayer = dnsRequest.getLayerOfType(); + auto* udpLayer = dnsRequest.getLayerOfType(); + auto* dnsLayer = dnsRequest.getLayerOfType(); // skip DNS requests with more than 1 request or with 0 requests if (dnsLayer->getDnsHeader()->numberOfQuestions != pcpp::hostToNet16(1) || dnsLayer->getFirstQuery() == nullptr) + { return; + } // skip DNS requests which are not of class IN and type A (IPv4) or AAAA (IPv6) - pcpp::DnsType dnsType = (args->dnsServer.isIPv4() ? pcpp::DNS_TYPE_A : pcpp::DNS_TYPE_AAAA); + const pcpp::DnsType dnsType = (args->dnsServer.isIPv4() ? pcpp::DNS_TYPE_A : pcpp::DNS_TYPE_AAAA); pcpp::DnsQuery* dnsQuery = dnsLayer->getFirstQuery(); if (dnsQuery->getDnsType() != dnsType || dnsQuery->getDnsClass() != pcpp::DNS_CLASS_IN) + { return; + } // empty dnsHostsToSpoof means spoofing all hosts if (!args->dnsHostsToSpoof.empty()) @@ -186,20 +188,22 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* } if (!hostMatch) + { return; + } } // create a response out of the request packet // reverse src and dst MAC addresses - pcpp::MacAddress srcMac = ethLayer->getSourceMac(); + const pcpp::MacAddress srcMac = ethLayer->getSourceMac(); ethLayer->setSourceMac(ethLayer->getDestMac()); ethLayer->setDestMac(srcMac); // reverse src and dst IP addresses - pcpp::IPAddress srcIP = ipLayer->getSrcIPAddress(); - pcpp::IPv4Layer* ip4Layer = dynamic_cast(ipLayer); - pcpp::IPv6Layer* ip6Layer = dynamic_cast(ipLayer); + const pcpp::IPAddress srcIP = ipLayer->getSrcIPAddress(); + auto* ip4Layer = dynamic_cast(ipLayer); + auto* ip6Layer = dynamic_cast(ipLayer); if (ip4Layer != nullptr) { ip4Layer->setSrcIPv4Address(ip4Layer->getDstIPv4Address()); @@ -217,7 +221,7 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* } // reverse src and dst UDP ports - uint16_t srcPort = udpLayer->getUdpHeader()->portSrc; + const uint16_t srcPort = udpLayer->getUdpHeader()->portSrc; udpLayer->getUdpHeader()->portSrc = udpLayer->getUdpHeader()->portDst; udpLayer->getUdpHeader()->portDst = srcPort; @@ -226,21 +230,27 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* if (args->dnsServer.isIPv4()) { pcpp::IPv4DnsResourceData dnsServer(args->dnsServer.getIPv4()); - if (!dnsLayer->addAnswer(dnsQuery->getName(), pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 1, &dnsServer)) + if (dnsLayer->addAnswer(dnsQuery->getName(), pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 1, &dnsServer) == nullptr) + { return; + } } else { pcpp::IPv6DnsResourceData dnsServer(args->dnsServer.getIPv6()); - if (!dnsLayer->addAnswer(dnsQuery->getName(), pcpp::DNS_TYPE_AAAA, pcpp::DNS_CLASS_IN, 1, &dnsServer)) + if (dnsLayer->addAnswer(dnsQuery->getName(), pcpp::DNS_TYPE_AAAA, pcpp::DNS_CLASS_IN, 1, &dnsServer) == nullptr) + { return; + } } dnsRequest.computeCalculateFields(); // send DNS response back to the network if (!dev->sendPacket(dnsRequest)) + { return; + } args->stats.numOfSpoofedDnsRequests++; args->stats.spoofedHosts[dnsQuery->getName()]++; @@ -263,25 +273,25 @@ bool stringCountComparer(const std::pair& first, const std::pa */ void onApplicationInterrupted(void* cookie) { - DnsSpoofingArgs* args = (DnsSpoofingArgs*)cookie; - if (args->stats.spoofedHosts.size() == 0) + auto* args = reinterpret_cast(cookie); + if (args->stats.spoofedHosts.empty()) { - std::cout << std::endl << "Application closing. No hosts were spoofed." << std::endl; + std::cout << '\n' << "Application closing. No hosts were spoofed." << '\n'; } else { - std::cout << std::endl - << "Summary of spoofed hosts:" << std::endl - << "-------------------------" << std::endl - << std::endl - << "Total spoofed: " << args->stats.numOfSpoofedDnsRequests << std::endl - << "Number of host spoofed: " << args->stats.spoofedHosts.size() << std::endl - << std::endl; + std::cout << '\n' + << "Summary of spoofed hosts:" << '\n' + << "-------------------------" << '\n' + << '\n' + << "Total spoofed: " << args->stats.numOfSpoofedDnsRequests << '\n' + << "Number of host spoofed: " << args->stats.spoofedHosts.size() << '\n' + << '\n'; // create a table std::vector columnNames; - columnNames.push_back("Host"); - columnNames.push_back("# of times spoofed"); + columnNames.emplace_back("Host"); + columnNames.emplace_back("# of times spoofed"); std::vector columnsWidths; columnsWidths.push_back(40); columnsWidths.push_back(18); @@ -313,7 +323,9 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, { // open device if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open capture device"); + } // set a filter to capture only DNS requests and client IP if provided pcpp::PortFilter dnsPortFilter(53, pcpp::DST); @@ -330,7 +342,9 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, pcpp::AndFilter andFilter(filterForAnd); if (!dev->setFilter(andFilter)) + { EXIT_WITH_ERROR("Cannot set DNS and client IP filter for device"); + } // make args for callback DnsSpoofingArgs args; @@ -339,7 +353,9 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, // start capturing DNS requests if (!dev->startCapture(handleDnsRequest, &args)) + { EXIT_WITH_ERROR("Cannot start packet capture"); + } // register the on app close event to print summary stats on app termination pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args); @@ -347,7 +363,7 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, // run an endless loop until ctrl+c is pressed while (!args.shouldStop) { - std::cout << "Spoofed " << args.stats.numOfSpoofedDnsRequests << " DNS requests so far" << std::endl; + std::cout << "Spoofed " << args.stats.numOfSpoofedDnsRequests << " DNS requests so far" << '\n'; std::this_thread::sleep_for(std::chrono::seconds(5)); } } @@ -426,12 +442,14 @@ int main(int argc, char* argv[]) } case 'o': { - std::string input = optarg; + const std::string input = optarg; std::istringstream stream(input); std::string token; while (std::getline(stream, token, ',')) + { hostList.push_back(token); + } break; } default: @@ -452,15 +470,21 @@ int main(int argc, char* argv[]) dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } // verify DNS server IP is a valid IPv4 address if (dnsServer.isZero()) + { EXIT_WITH_ERROR("Spoof DNS server IP provided is empty or not a valid IPv4 address"); + } // verify client IP is valid if set if (clientIpSet && clientIP.isZero()) + { EXIT_WITH_ERROR("Client IP to spoof is invalid"); + } doDnsSpoofing(dev, dnsServer, clientIP, hostList); } diff --git a/Examples/DpdkBridge/AppWorkerThread.h b/Examples/DpdkBridge/AppWorkerThread.h index fd25f25326..77dadfe8a9 100644 --- a/Examples/DpdkBridge/AppWorkerThread.h +++ b/Examples/DpdkBridge/AppWorkerThread.h @@ -16,22 +16,19 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { private: AppWorkerConfig& m_WorkerConfig; - bool m_Stop; + bool m_Stop{ true }; uint32_t m_CoreId; public: explicit AppWorkerThread(AppWorkerConfig& workerConfig) - : m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES + 1) + : m_WorkerConfig(workerConfig), m_CoreId(MAX_NUM_OF_CORES + 1) {} - virtual ~AppWorkerThread() - { - // do nothing - } + ~AppWorkerThread() override = default; // implement abstract methods - bool run(uint32_t coreId) + bool run(uint32_t coreId) override { m_CoreId = coreId; m_Stop = false; @@ -39,21 +36,22 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread pcpp::DpdkDevice* txDevice = m_WorkerConfig.TxDevice; // if no DPDK devices were assigned to this worker/core don't enter the main loop and exit - if (!rxDevice || !txDevice) + if ((rxDevice == nullptr) || (txDevice == nullptr)) { return true; } -#define MAX_RECEIVE_BURST 64 + constexpr auto MAX_RECEIVE_BURST = 64; pcpp::MBufRawPacket* packetArr[MAX_RECEIVE_BURST] = {}; // main loop, runs until be told to stop + // cppcheck-suppress knownConditionTrueFalse while (!m_Stop) { for (uint16_t i = 0; i < m_WorkerConfig.RxQueues; i++) { // receive packets from network on the specified DPDK device - uint16_t packetsReceived = rxDevice->receivePackets(packetArr, MAX_RECEIVE_BURST, i); + const uint16_t packetsReceived = rxDevice->receivePackets(packetArr, MAX_RECEIVE_BURST, i); if (packetsReceived > 0) { @@ -64,22 +62,21 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread } // free packet array (frees all mbufs as well) - for (int i = 0; i < MAX_RECEIVE_BURST; i++) + for (auto& packet : packetArr) { - if (packetArr[i] != nullptr) - delete packetArr[i]; + delete packet; } return true; } - void stop() + void stop() override { // assign the stop flag which will cause the main loop to end m_Stop = true; } - uint32_t getCoreId() const + uint32_t getCoreId() const override { return m_CoreId; } diff --git a/Examples/DpdkBridge/Common.h b/Examples/DpdkBridge/Common.h index 1cfdff2d04..deef6969a2 100644 --- a/Examples/DpdkBridge/Common.h +++ b/Examples/DpdkBridge/Common.h @@ -19,7 +19,7 @@ #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -27,7 +27,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -39,10 +39,10 @@ struct AppWorkerConfig { uint32_t CoreId; - pcpp::DpdkDevice* RxDevice; - uint16_t RxQueues; - pcpp::DpdkDevice* TxDevice; + pcpp::DpdkDevice* RxDevice{ nullptr }; + uint16_t RxQueues{ 1 }; + pcpp::DpdkDevice* TxDevice{ nullptr }; - AppWorkerConfig() : CoreId(MAX_NUM_OF_CORES + 1), RxDevice(nullptr), RxQueues(1), TxDevice(nullptr) + AppWorkerConfig() : CoreId(MAX_NUM_OF_CORES + 1) {} }; diff --git a/Examples/DpdkBridge/main.cpp b/Examples/DpdkBridge/main.cpp index 791db7ba24..dedc72a86a 100644 --- a/Examples/DpdkBridge/main.cpp +++ b/Examples/DpdkBridge/main.cpp @@ -35,9 +35,9 @@ #include #include -#define COLLECT_STATS_EVERY_SEC 1 -#define DEFAULT_MBUF_POOL_SIZE 4095 -#define DEFAULT_QUEUE_QUANTITY 1 +constexpr auto COLLECT_STATS_EVERY_SEC = 1; +constexpr auto DEFAULT_MBUF_POOL_SIZE = 4095; +constexpr auto DEFAULT_QUEUE_QUANTITY = 1; // clang-format off static struct option DpdkBridgeOptions[] = { @@ -57,34 +57,33 @@ static struct option DpdkBridgeOptions[] = { */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hlv] [-c CORE_MASK] [-m POOL_SIZE] [-q QUEUE_QTY] -d PORT_1,PORT_2" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -l|--list : Print the list of DPDK ports and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' + << pcpp::AppName::get() << " [-hlv] [-c CORE_MASK] [-m POOL_SIZE] [-q QUEUE_QTY] -d PORT_1,PORT_2" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h|--help : Displays this help message and exits" << '\n' + << " -l|--list : Print the list of DPDK ports and exits" << '\n' + << " -v|--version : Displays the current version and exits" << '\n' << " -c|--core-mask CORE_MASK : Core mask of cores to use. For example: use 7 " "(binary 0111) to use cores 0,1,2." - << std::endl + << '\n' << " Default is using all cores except management core" - << std::endl + << '\n' << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with. " "Default value is 4095\n" - << std::endl + << '\n' << " -d|--dpdk-ports PORT_1,PORT_2 : A comma-separated list of two DPDK port numbers to " "be bridged." - << std::endl + << '\n' << " To see all available DPDK ports use the -l switch" - << std::endl + << '\n' << " -q|--queue-quantity QUEUE_QTY : Quantity of RX queues to be opened for each DPDK " "device. Default value is 1" - << std::endl - << std::endl; + << '\n' + << '\n'; } /** @@ -92,9 +91,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -103,7 +102,7 @@ void printAppVersion() */ void listDpdkPorts() { - pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); + pcpp::CoreMask const coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); // initialize DPDK if (!pcpp::DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE)) @@ -111,10 +110,10 @@ void listDpdkPorts() EXIT_WITH_ERROR("couldn't initialize DPDK"); } - std::cout << "DPDK port list:" << std::endl; + std::cout << "DPDK port list:" << '\n'; // go over all available DPDK devices and print info for each one - std::vector deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); + std::vector const deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); for (const auto& iter : deviceList) { pcpp::DpdkDevice* dev = iter; @@ -122,17 +121,16 @@ void listDpdkPorts() << " Port #" << dev->getDeviceId() << ":" << " MAC address='" << dev->getMacAddress() << "';" << " PCI address='" << dev->getPciAddress() << "';" - << " PMD='" << dev->getPMDName() << "'" << std::endl; + << " PMD='" << dev->getPMDName() << "'" << '\n'; } } struct DpdkBridgeArgs { - bool shouldStop; - std::vector* workerThreadsVector; + bool shouldStop{ false }; + std::vector* workerThreadsVector{ nullptr }; - DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(nullptr) - {} + DpdkBridgeArgs() = default; }; /** @@ -140,9 +138,9 @@ struct DpdkBridgeArgs */ void onApplicationInterrupted(void* cookie) { - DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie; + auto* args = reinterpret_cast(cookie); - std::cout << std::endl << std::endl << "Application stopped" << std::endl; + std::cout << '\n' << '\n' << "Application stopped" << '\n'; // stop worker threads pcpp::DpdkDeviceList::getInstance().stopDpdkWorkerThreads(); @@ -155,17 +153,17 @@ void onApplicationInterrupted(void* cookie) */ void printStats(pcpp::DpdkDevice* device) { - pcpp::DpdkDevice::DpdkDeviceStats stats; + pcpp::DpdkDevice::DpdkDeviceStats stats{}; device->getStatistics(stats); - std::cout << std::endl << "Statistics for port " << device->getDeviceId() << ":" << std::endl; + std::cout << '\n' << "Statistics for port " << device->getDeviceId() << ":" << '\n'; std::vector columnNames; - columnNames.push_back(" "); - columnNames.push_back("Total Packets"); - columnNames.push_back("Packets/sec"); - columnNames.push_back("Total Bytes"); - columnNames.push_back("Bytes/sec"); + columnNames.emplace_back(" "); + columnNames.emplace_back("Total Packets"); + columnNames.emplace_back("Packets/sec"); + columnNames.emplace_back("Total Bytes"); + columnNames.emplace_back("Bytes/sec"); std::vector columnLengths; columnLengths.push_back(10); @@ -219,22 +217,22 @@ int main(int argc, char* argv[]) } case 'c': { - coreMaskToUse = atoi(optarg); + coreMaskToUse = std::stoi(optarg); break; } case 'd': { - std::string portListAsString = std::string(optarg); + const std::string portListAsString = std::string(optarg); std::stringstream stream(portListAsString); std::string portAsString; - int port; + int port = 0; // break comma-separated string into string list while (getline(stream, portAsString, ',')) { - char c; + char chr = 0; std::stringstream stream2(portAsString); stream2 >> port; - if (stream2.fail() || stream2.get(c)) + if (stream2.fail() || stream2.get(chr)) { // not an integer EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); @@ -250,12 +248,12 @@ int main(int argc, char* argv[]) } case 'm': { - mBufPoolSize = atoi(optarg); + mBufPoolSize = std::stoi(optarg); break; } case 'q': { - queueQuantity = atoi(optarg); + queueQuantity = std::stoi(optarg); break; } case 'h': @@ -370,14 +368,14 @@ int main(int argc, char* argv[]) sleep(1); // Print stats every COLLECT_STATS_EVERY_SEC seconds - // cppcheck-suppress moduloofone + // cppcheck-suppress [moduloofone, knownConditionTrueFalse] if (counter % COLLECT_STATS_EVERY_SEC == 0) { // Clear screen and move to top left std::cout << "\033[2J\033[1;1H"; // Print devices traffic stats - std::cout << "Stats #" << statsCounter++ << std::endl << "==========" << std::endl; + std::cout << "Stats #" << statsCounter++ << '\n' << "==========" << '\n'; printStats(dpdkDevicesToUse.at(0)); printStats(dpdkDevicesToUse.at(1)); } diff --git a/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h b/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h index ca2221f332..41768d684b 100644 --- a/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h +++ b/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h @@ -18,7 +18,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { private: AppWorkerConfig& m_WorkerConfig; - bool m_Stop; + bool m_Stop{ true }; uint32_t m_CoreId; PacketStats m_Stats; PacketMatchingEngine& m_PacketMatchingEngine; @@ -26,14 +26,10 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread public: AppWorkerThread(AppWorkerConfig& workerConfig, PacketMatchingEngine& matchingEngine) - : m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES + 1), - m_PacketMatchingEngine(matchingEngine) + : m_WorkerConfig(workerConfig), m_CoreId(MAX_NUM_OF_CORES + 1), m_PacketMatchingEngine(matchingEngine) {} - virtual ~AppWorkerThread() - { - // do nothing - } + ~AppWorkerThread() override = default; PacketStats& getStats() { @@ -42,7 +38,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread // implement abstract methods - bool run(uint32_t coreId) + bool run(uint32_t coreId) override { m_CoreId = coreId; m_Stop = false; @@ -53,7 +49,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread // if needed, create the pcap file writer which all matched packets will be written into if (m_WorkerConfig.writeMatchedPacketsToFile) { - pcapWriter = new pcpp::PcapFileWriterDevice(m_WorkerConfig.pathToWritePackets.c_str()); + pcapWriter = new pcpp::PcapFileWriterDevice(m_WorkerConfig.pathToWritePackets); if (!pcapWriter->open()) { EXIT_WITH_ERROR("Couldn't open pcap writer device"); @@ -61,12 +57,12 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread } // if no DPDK devices were assigned to this worker/core don't enter the main loop and exit - if (m_WorkerConfig.inDataCfg.size() == 0) + if (m_WorkerConfig.inDataCfg.empty()) { return true; } -#define MAX_RECEIVE_BURST 64 + constexpr auto MAX_RECEIVE_BURST = 64; pcpp::MBufRawPacket* packetArr[MAX_RECEIVE_BURST] = {}; // main loop, runs until be told to stop @@ -82,7 +78,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread pcpp::DpdkDevice* dev = iter.first; // receive packets from network on the specified DPDK device and RX queue - uint16_t packetsReceived = dev->receivePackets(packetArr, MAX_RECEIVE_BURST, iter2); + const uint16_t packetsReceived = dev->receivePackets(packetArr, MAX_RECEIVE_BURST, iter2); for (int i = 0; i < packetsReceived; i++) { @@ -92,11 +88,11 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread // collect packet statistics m_Stats.collectStats(parsedPacket); - bool packetMatched; + bool packetMatched = false; // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to // an existing or new flow - uint32_t hash = pcpp::hash5Tuple(&parsedPacket); + const uint32_t hash = pcpp::hash5Tuple(&parsedPacket); auto iter3 = m_FlowTable.find(hash); // if packet belongs to an already existing flow @@ -146,28 +142,25 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread } // free packet array (frees all mbufs as well) - for (int i = 0; i < MAX_RECEIVE_BURST; i++) + for (auto& idx : packetArr) { - if (packetArr[i] != nullptr) - delete packetArr[i]; + + delete idx; } // close and delete pcap file writer - if (pcapWriter != nullptr) - { - delete pcapWriter; - } + delete pcapWriter; return true; } - void stop() + void stop() override { // assign the stop flag which will cause the main loop to end m_Stop = true; } - uint32_t getCoreId() const + uint32_t getCoreId() const override { return m_CoreId; } diff --git a/Examples/DpdkExample-FilterTraffic/Common.h b/Examples/DpdkExample-FilterTraffic/Common.h index 0ff1444131..094fe1069c 100644 --- a/Examples/DpdkExample-FilterTraffic/Common.h +++ b/Examples/DpdkExample-FilterTraffic/Common.h @@ -12,6 +12,9 @@ #include #include +// Forward declaration to fix use of undeclared identifier +void printUsage(); + /** * Macros for exiting the application with error */ @@ -19,7 +22,8 @@ #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + printUsage(); \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -27,11 +31,11 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) -typedef std::unordered_map> InputDataConfig; +using InputDataConfig = std::unordered_map>; /** * Contains all the configuration needed for the worker thread including: @@ -42,12 +46,11 @@ struct AppWorkerConfig { uint32_t coreId; InputDataConfig inDataCfg; - pcpp::DpdkDevice* sendPacketsTo; - bool writeMatchedPacketsToFile; + pcpp::DpdkDevice* sendPacketsTo{ nullptr }; + bool writeMatchedPacketsToFile{ false }; std::string pathToWritePackets; - AppWorkerConfig() - : coreId(MAX_NUM_OF_CORES + 1), sendPacketsTo(nullptr), writeMatchedPacketsToFile(false), pathToWritePackets("") + AppWorkerConfig() : coreId(MAX_NUM_OF_CORES + 1) {} }; @@ -59,48 +62,64 @@ struct PacketStats public: uint8_t workerId; - int packetCount; - int ethCount; - int arpCount; - int ipv4Count; - int ipv6Count; - int tcpCount; - int udpCount; - int httpCount; - int dnsCount; - int tlsCount; - - int matchedTcpFlows; - int matchedUdpFlows; - int matchedPackets; - - PacketStats() - : workerId(MAX_NUM_OF_CORES + 1), packetCount(0), ethCount(0), arpCount(0), ipv4Count(0), ipv6Count(0), - tcpCount(0), udpCount(0), httpCount(0), dnsCount(0), tlsCount(0), matchedTcpFlows(0), matchedUdpFlows(0), - matchedPackets(0) + int packetCount{ 0 }; + int ethCount{ 0 }; + int arpCount{ 0 }; + int ipv4Count{ 0 }; + int ipv6Count{ 0 }; + int tcpCount{ 0 }; + int udpCount{ 0 }; + int httpCount{ 0 }; + int dnsCount{ 0 }; + int tlsCount{ 0 }; + + int matchedTcpFlows{ 0 }; + int matchedUdpFlows{ 0 }; + int matchedPackets{ 0 }; + + PacketStats() : workerId(MAX_NUM_OF_CORES + 1) + {} void collectStats(pcpp::Packet& packet) { packetCount++; if (packet.isPacketOfType(pcpp::Ethernet)) + { ethCount++; + } if (packet.isPacketOfType(pcpp::ARP)) + { arpCount++; + } if (packet.isPacketOfType(pcpp::IPv4)) + { ipv4Count++; + } if (packet.isPacketOfType(pcpp::IPv6)) + { ipv6Count++; + } if (packet.isPacketOfType(pcpp::TCP)) + { tcpCount++; + } if (packet.isPacketOfType(pcpp::UDP)) + { udpCount++; + } if (packet.isPacketOfType(pcpp::HTTP)) + { httpCount++; + } if (packet.isPacketOfType(pcpp::DNS)) + { dnsCount++; + } if (packet.isPacketOfType(pcpp::SSL)) + { tlsCount++; + } } void collectStats(const PacketStats& stats) diff --git a/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h b/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h index e5354898ed..d4ec77d413 100644 --- a/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h @@ -17,27 +17,36 @@ class PacketMatchingEngine pcpp::IPv4Address m_SrcIpToMatch, m_DstIpToMatch; uint16_t m_SrcPortToMatch, m_DstPortToMatch; pcpp::ProtocolType m_ProtocolToMatch; - bool m_MatchSrcIp, m_MatchDstIp; - bool m_MatchSrcPort, m_MatchDstPort; - bool m_MatchProtocol; + bool m_MatchSrcIp{ false }, m_MatchDstIp{ false }; + bool m_MatchSrcPort{ false }, m_MatchDstPort{ false }; + bool m_MatchProtocol{ false }; public: PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), - m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), - m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchSrcIp = true; + } if (m_DstIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchDstIp = true; + } if (m_SrcPortToMatch != 0) + { m_MatchSrcPort = true; + } if (m_DstPortToMatch != 0) + { m_MatchDstPort = true; + } if (m_ProtocolToMatch == pcpp::TCP || m_ProtocolToMatch == pcpp::UDP) + { m_MatchProtocol = true; + } } bool isMatched(pcpp::Packet& packet) @@ -49,7 +58,7 @@ class PacketMatchingEngine return false; } - pcpp::IPv4Layer* ip4Layer = packet.getLayerOfType(); + auto* ip4Layer = packet.getLayerOfType(); if (m_MatchSrcIp && (ip4Layer->getSrcIPv4Address() != m_SrcIpToMatch)) { return false; @@ -63,7 +72,8 @@ class PacketMatchingEngine if (m_MatchSrcPort || m_MatchDstPort) { - uint16_t srcPort, dstPort; + uint16_t srcPort = 0; + uint16_t dstPort = 0; if (packet.isPacketOfType(pcpp::TCP)) { srcPort = packet.getLayerOfType()->getSrcPort(); diff --git a/Examples/DpdkExample-FilterTraffic/main.cpp b/Examples/DpdkExample-FilterTraffic/main.cpp index be72a1ed81..5a236cbb78 100644 --- a/Examples/DpdkExample-FilterTraffic/main.cpp +++ b/Examples/DpdkExample-FilterTraffic/main.cpp @@ -38,8 +38,8 @@ #include #include -#define DEFAULT_MBUF_POOL_SIZE 4095 -#define MAX_QUEUES 64 +constexpr auto DEFAULT_MBUF_POOL_SIZE = 4095; +constexpr auto MAX_QUEUES = 64; // clang-format off static struct option FilterTrafficOptions[] = { @@ -68,53 +68,50 @@ static struct option FilterTrafficOptions[] = { void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() - << " [-hvl] [-s PORT] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" - << std::endl + << " [-hvl] [-s PORT] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" << '\n' << " [-c CORE_MASK] [-m POOL_SIZE] [-r NUM_QUEUES] [-t NUM_QUEUES] -d PORT_1,PORT_3,...,PORT_N" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -l|--list : Print the list of DPDK ports and exists" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h|--help : Displays this help message and exits" << '\n' + << " -v|--version : Displays the current version and exits" << '\n' + << " -l|--list : Print the list of DPDK ports and exists" << '\n' << " -d|--dpdk-ports PORT_1,PORT_3,...,PORT_N : A comma-separated list of DPDK port numbers to receive" - << std::endl + << '\n' << " packets from. To see all available DPDK ports use the -l " "switch" - << std::endl - << " -s|--send-matched-packets PORT : DPDK port to send matched packets to" << std::endl + << '\n' + << " -s|--send-matched-packets PORT : DPDK port to send matched packets to" << '\n' << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH. Packets" - << std::endl + << '\n' << " matched by core X will be saved under " "'FILEPATH/CoreX.pcap'" - << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl - << " -o|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" - << std::endl - << " -c|--core-mask CORE_MASK : Core mask of cores to use." << std::endl + << '\n' + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << '\n' + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << '\n' + << " -p|--match-source-port PORT : Match source TCP/UDP port" << '\n' + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << '\n' + << " -o|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" << '\n' + << " -c|--core-mask CORE_MASK : Core mask of cores to use." << '\n' << " For example: use 7 (binary 0111) to use cores 0,1,2." - << std::endl - << " Default is using all cores except management core" - << std::endl - << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with." << std::endl - << " Default value is 4095" << std::endl + << '\n' + << " Default is using all cores except management core" << '\n' + << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with." << '\n' + << " Default value is 4095" << '\n' << " -r|--rx-queues NUM_QUEUES : Number of RX queues to open. Cannot exceed the max " "allowed by the NIC or " - << MAX_QUEUES << std::endl - << " The default is 1" << std::endl + << MAX_QUEUES << '\n' + << " The default is 1" << '\n' << " -t|--tx-queues NUM_QUEUES : Number of TX queues to open. Cannot exceed the max " "allowed by the NIC or " - << MAX_QUEUES << std::endl - << " The default is 1" << std::endl - << std::endl; + << MAX_QUEUES << '\n' + << " The default is 1" << '\n' + << '\n'; } /** @@ -122,9 +119,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -133,7 +130,7 @@ void printAppVersion() */ void listDpdkPorts() { - pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); + const pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); // initialize DPDK if (!pcpp::DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE)) @@ -141,17 +138,17 @@ void listDpdkPorts() EXIT_WITH_ERROR("couldn't initialize DPDK"); } - std::cout << "DPDK port list:" << std::endl; + std::cout << "DPDK port list:" << '\n'; // go over all available DPDK devices and print info for each one - std::vector deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); + const std::vector deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); for (const auto& dev : deviceList) { std::cout << " " << " Port #" << dev->getDeviceId() << ":" << " MAC address='" << dev->getMacAddress() << "';" << " PCI address='" << dev->getPciAddress() << "';" - << " PMD='" << dev->getPMDName() << "'" << std::endl; + << " PMD='" << dev->getPMDName() << "'" << '\n'; } } @@ -162,7 +159,8 @@ void listDpdkPorts() void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, std::vector& coresToUse, bool writePacketsToDisk, const std::string& packetFilePath, pcpp::DpdkDevice* sendPacketsTo, - std::vector& workerConfigArr, int workerConfigArrLen, uint16_t rxQueues) + std::vector& workerConfigArr, int /*workerConfigArrLen*/, + uint16_t rxQueues) { // create a list of pairs of DpdkDevice and RX queues for all RX queues in all requested devices int totalNumOfRxQueues = 0; @@ -171,7 +169,7 @@ void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, { for (int rxQueueIndex = 0; rxQueueIndex < rxQueues; rxQueueIndex++) { - std::pair curPair(iter, rxQueueIndex); + const std::pair curPair(iter, rxQueueIndex); deviceAndRxQVec.push_back(curPair); } totalNumOfRxQueues += rxQueues; @@ -179,63 +177,64 @@ void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, // calculate how many RX queues each core will read packets from. We divide the total number of RX queues with total // number of core - int numOfRxQueuesPerCore = totalNumOfRxQueues / coresToUse.size(); - int rxQueuesRemainder = totalNumOfRxQueues % coresToUse.size(); + const int numOfRxQueuesPerCore = static_cast(totalNumOfRxQueues / coresToUse.size()); + int rxQueuesRemainder = static_cast(totalNumOfRxQueues % coresToUse.size()); // prepare the configuration for every core: divide the devices and RX queue for each device with the various cores - int i = 0; - std::vector>::iterator pairVecIter = deviceAndRxQVec.begin(); + int idx = 0; + auto pairVecIter = deviceAndRxQVec.begin(); for (const auto& core : coresToUse) { - std::cout << "Using core " << (int)core.Id << std::endl; - workerConfigArr[i].coreId = core.Id; - workerConfigArr[i].writeMatchedPacketsToFile = writePacketsToDisk; + std::cout << "Using core " << (int)core.Id << '\n'; + workerConfigArr[idx].coreId = core.Id; + workerConfigArr[idx].writeMatchedPacketsToFile = writePacketsToDisk; std::stringstream packetFileName; - packetFileName << packetFilePath << "Core" << workerConfigArr[i].coreId << ".pcap"; - workerConfigArr[i].pathToWritePackets = packetFileName.str(); + packetFileName << packetFilePath << "Core" << workerConfigArr[idx].coreId << ".pcap"; + workerConfigArr[idx].pathToWritePackets = packetFileName.str(); - workerConfigArr[i].sendPacketsTo = sendPacketsTo; + workerConfigArr[idx].sendPacketsTo = sendPacketsTo; for (int rxQIndex = 0; rxQIndex < numOfRxQueuesPerCore; rxQIndex++) { if (pairVecIter == deviceAndRxQVec.end()) + { break; - workerConfigArr[i].inDataCfg[pairVecIter->first].push_back(pairVecIter->second); + } + workerConfigArr[idx].inDataCfg[pairVecIter->first].push_back(pairVecIter->second); ++pairVecIter; } if (rxQueuesRemainder > 0 && (pairVecIter != deviceAndRxQVec.end())) { - workerConfigArr[i].inDataCfg[pairVecIter->first].push_back(pairVecIter->second); + workerConfigArr[idx].inDataCfg[pairVecIter->first].push_back(pairVecIter->second); ++pairVecIter; rxQueuesRemainder--; } // print configuration for core - std::cout << " Core configuration:" << std::endl; - for (const auto& iter2 : workerConfigArr[i].inDataCfg) + std::cout << " Core configuration:" << '\n'; + for (const auto& iter2 : workerConfigArr[idx].inDataCfg) { std::cout << " DPDK device#" << iter2.first->getDeviceId() << ": "; for (const auto& iter3 : iter2.second) { std::cout << "RX-Queue#" << iter3 << "; "; } - std::cout << std::endl; + std::cout << '\n'; } - if (workerConfigArr[i].inDataCfg.size() == 0) + if (workerConfigArr[idx].inDataCfg.empty()) { - std::cout << " None" << std::endl; + std::cout << " None" << '\n'; } - i++; + ++idx; } } struct FilterTrafficArgs { - bool shouldStop; - std::vector* workerThreadsVector; + bool shouldStop{ false }; + std::vector* workerThreadsVector{ nullptr }; - FilterTrafficArgs() : shouldStop(false), workerThreadsVector(nullptr) - {} + FilterTrafficArgs() = default; }; /** @@ -243,8 +242,8 @@ struct FilterTrafficArgs */ void printStats(const PacketStats& threadStats, const std::string& columnName) { - std::vector columnNames = { columnName, "Count" }; - std::vector columnsWidths = { 21, 10 }; + const std::vector columnNames = { columnName, "Count" }; + const std::vector columnsWidths = { 21, 10 }; pcpp::TablePrinter printer(columnNames, columnsWidths); printer.printRow("Eth count|" + std::to_string(threadStats.ethCount), '|'); @@ -269,9 +268,9 @@ void printStats(const PacketStats& threadStats, const std::string& columnName) */ void onApplicationInterrupted(void* cookie) { - FilterTrafficArgs* args = (FilterTrafficArgs*)cookie; + auto* args = reinterpret_cast(cookie); - std::cout << std::endl << std::endl << "Application stopped" << std::endl; + std::cout << '\n' << '\n' << "Application stopped" << '\n'; // stop worker threads pcpp::DpdkDeviceList::getInstance().stopDpdkWorkerThreads(); @@ -281,8 +280,8 @@ void onApplicationInterrupted(void* cookie) std::vector threadStatsVec; for (const auto& iter : *(args->workerThreadsVector)) { - AppWorkerThread* thread = (AppWorkerThread*)(iter); - PacketStats threadStats = thread->getStats(); + auto* thread = dynamic_cast(iter); + const PacketStats threadStats = thread->getStats(); aggregatedStats.collectStats(threadStats); threadStatsVec.push_back(threadStats); delete thread; @@ -294,12 +293,12 @@ void onApplicationInterrupted(void* cookie) // no need to print table if no packets were received if (threadStats.packetCount == 0) { - std::cout << "Core #" << std::to_string(threadStats.workerId) << " - no packets received" << std::endl; + std::cout << "Core #" << std::to_string(threadStats.workerId) << " - no packets received" << '\n'; continue; } printStats(threadStats, "Core #" + std::to_string(threadStats.workerId) + " Stat"); - std::cout << std::endl; + std::cout << '\n'; } // print aggregated stats if packets were received @@ -324,14 +323,14 @@ int main(int argc, char* argv[]) bool writePacketsToDisk = false; - std::string packetFilePath = ""; + std::string packetFilePath; pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); int sendPacketsToPort = -1; int optionIndex = 0; - int opt; + int opt = 0; uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE; @@ -354,17 +353,17 @@ int main(int argc, char* argv[]) } case 'd': { - std::string portListAsString = std::string(optarg); + const std::string portListAsString = std::string(optarg); std::stringstream stream(portListAsString); std::string portAsString; - int port; + int port = 0; // break comma-separated string into string list while (getline(stream, portAsString, ',')) { - char c; + char chr = 0; std::stringstream stream2(portAsString); stream2 >> port; - if (stream2.fail() || stream2.get(c)) + if (stream2.fail() || stream2.get(chr)) { // not an integer EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); @@ -381,12 +380,12 @@ int main(int argc, char* argv[]) } case 's': { - sendPacketsToPort = atoi(optarg); + sendPacketsToPort = std::stoi(optarg); break; } case 'c': { - coreMaskToUse = atoi(optarg); + coreMaskToUse = std::stoi(optarg); break; } case 'f': @@ -401,7 +400,7 @@ int main(int argc, char* argv[]) } case 'm': { - mBufPoolSize = atoi(optarg); + mBufPoolSize = std::stoul(optarg); break; } case 'i': @@ -430,7 +429,7 @@ int main(int argc, char* argv[]) } case 'p': { - int ret = atoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); @@ -440,7 +439,7 @@ int main(int argc, char* argv[]) } case 'P': { - int ret = atoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); @@ -450,11 +449,15 @@ int main(int argc, char* argv[]) } case 'o': { - std::string protocol = std::string(optarg); + const std::string protocol = std::string(optarg); if (protocol == "TCP") + { protocolToMatch = pcpp::TCP; + } else if (protocol == "UDP") + { protocolToMatch = pcpp::UDP; + } else { EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); @@ -463,7 +466,7 @@ int main(int argc, char* argv[]) } case 'r': { - rxQueues = atoi(optarg); + rxQueues = std::stoul(optarg); if (rxQueues == 0) { EXIT_WITH_ERROR("Cannot open the device with 0 RX queues"); @@ -476,7 +479,7 @@ int main(int argc, char* argv[]) } case 't': { - txQueues = atoi(optarg); + txQueues = std::stoul(optarg); if (txQueues == 0) { EXIT_WITH_ERROR("Cannot open the device with 0 TX queues"); @@ -571,12 +574,12 @@ int main(int argc, char* argv[]) } std::cout << "Opened device #" << dev->getDeviceId() << " with " << rxQueues << " RX queues and " << txQueues << " TX queues." - << " RSS hash functions:" << std::endl; - std::vector rssHashFunctions = + << " RSS hash functions:" << '\n'; + const std::vector rssHashFunctions = dev->rssHashFunctionMaskToString(dev->getConfiguredRssHashFunction()); for (const auto& hashFunc : rssHashFunctions) { - std::cout << " " << hashFunc << std::endl; + std::cout << " " << hashFunc << '\n'; } } @@ -590,18 +593,18 @@ int main(int argc, char* argv[]) // prepare configuration for every core std::vector workerConfigArr(coresToUse.size()); prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, - workerConfigArr, coresToUse.size(), rxQueues); + workerConfigArr, static_cast(coresToUse.size()), rxQueues); PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); // create worker thread for every core std::vector workerThreadVec; - int i = 0; + int idx = 0; for (auto iter = coresToUse.begin(); iter != coresToUse.end(); ++iter) { - AppWorkerThread* newWorker = new AppWorkerThread(workerConfigArr[i], matchingEngine); + auto* newWorker = new AppWorkerThread(workerConfigArr[idx], matchingEngine); workerThreadVec.push_back(newWorker); - i++; + ++idx; } // start all worker threads diff --git a/Examples/ExampleApp/main.cpp b/Examples/ExampleApp/main.cpp index 89f3bdf6d2..af362a9168 100644 --- a/Examples/ExampleApp/main.cpp +++ b/Examples/ExampleApp/main.cpp @@ -3,13 +3,13 @@ #include #include -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // open a pcap file for reading pcpp::PcapFileReaderDevice reader("1_packet.pcap"); if (!reader.open()) { - std::cerr << "Error opening the pcap file" << std::endl; + std::cerr << "Error opening the pcap file" << '\n'; return 1; } @@ -17,23 +17,23 @@ int main(int argc, char* argv[]) pcpp::RawPacket rawPacket; if (!reader.getNextPacket(rawPacket)) { - std::cerr << "Couldn't read the first packet in the file" << std::endl; + std::cerr << "Couldn't read the first packet in the file" << '\n'; return 1; } // parse the raw packet into a parsed packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // verify the packet is IPv4 if (parsedPacket.isPacketOfType(pcpp::IPv4)) { // extract source and dest IPs - pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); - pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); + const pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); + const pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // print source and dest IPs std::cout << "Source IP is '" << srcIP << "'; " - << "Dest IP is '" << destIP << "'" << std::endl; + << "Dest IP is '" << destIP << "'" << '\n'; } // close the file diff --git a/Examples/HttpAnalyzer/HttpStatsCollector.h b/Examples/HttpAnalyzer/HttpStatsCollector.h index 9554509641..e46a092856 100644 --- a/Examples/HttpAnalyzer/HttpStatsCollector.h +++ b/Examples/HttpAnalyzer/HttpStatsCollector.h @@ -82,16 +82,15 @@ struct HttpGeneralStats struct HttpMessageStats { // total number of HTTP messages of that type (request/response) - int numOfMessages; + int numOfMessages{}; // rate of HTTP messages of that type - Rate messageRate; + Rate messageRate{}; // total size (in bytes) of data in headers - int totalMessageHeaderSize; + int totalMessageHeaderSize{}; // average header size - double averageMessageHeaderSize; + double averageMessageHeaderSize{}; - virtual ~HttpMessageStats() - {} + virtual ~HttpMessageStats() = default; virtual void clear() { @@ -130,11 +129,11 @@ struct HttpResponseStats : HttpMessageStats // a map for counting the content-types seen in traffic std::unordered_map contentTypeCount; // total number of responses containing the "content-length" field - int numOfMessagesWithContentLength; + int numOfMessagesWithContentLength{}; // total body size extracted by responses containing "content-length" field - int totalContentLengthSize; + int totalContentLengthSize{}; // average body size - double averageContentLengthSize; + double averageContentLengthSize{}; void clear() override { @@ -156,10 +155,9 @@ class HttpStatsCollector /** * C'tor - clear all structures */ - explicit HttpStatsCollector(uint16_t dstPort) + explicit HttpStatsCollector(uint16_t dstPort) : m_DstPort(dstPort) { clear(); - m_DstPort = dstPort; } /** @@ -169,29 +167,33 @@ class HttpStatsCollector { // verify packet is TCP if (!httpPacket->isPacketOfType(pcpp::TCP)) + { return; + } // verify packet is port 80 - pcpp::TcpLayer* tcpLayer = httpPacket->getLayerOfType(); - if (!(tcpLayer->getDstPort() == m_DstPort || tcpLayer->getSrcPort() == m_DstPort)) + auto* tcpLayer = httpPacket->getLayerOfType(); + if (tcpLayer->getDstPort() != m_DstPort && tcpLayer->getSrcPort() != m_DstPort) + { return; + } // collect general HTTP traffic stats on this packet - uint32_t hashVal = collectHttpTrafficStats(httpPacket); + const uint32_t hashVal = collectHttpTrafficStats(httpPacket); // if packet is an HTTP request - collect HTTP request stats on this packet if (httpPacket->isPacketOfType(pcpp::HTTPRequest)) { - pcpp::HttpRequestLayer* req = httpPacket->getLayerOfType(); - pcpp::TcpLayer* tcpLayer1 = httpPacket->getLayerOfType(); + auto* req = httpPacket->getLayerOfType(); + auto* tcpLayer1 = httpPacket->getLayerOfType(); collectHttpGeneralStats(tcpLayer1, req, hashVal); collectRequestStats(req); } // if packet is an HTTP response - collect HTTP response stats on this packet else if (httpPacket->isPacketOfType(pcpp::HTTPResponse)) { - pcpp::HttpResponseLayer* res = httpPacket->getLayerOfType(); - pcpp::TcpLayer* tcpLayer1 = httpPacket->getLayerOfType(); + auto* res = httpPacket->getLayerOfType(); + auto* tcpLayer1 = httpPacket->getLayerOfType(); collectHttpGeneralStats(tcpLayer1, res, hashVal); collectResponseStats(res); } @@ -206,10 +208,10 @@ class HttpStatsCollector void calcRates() { // getting current machine time - double curTime = getCurTime(); + const double curTime = getCurTime(); // getting time from last rate calculation until now - double diffSec = curTime - m_LastCalcRateTime; + const double diffSec = curTime - m_LastCalcRateTime; // calculating current rates which are the changes from last rate calculation until now divided by the time // passed from last rate calculation until now @@ -230,7 +232,7 @@ class HttpStatsCollector } // getting the time from the beginning of stats collection until now - double diffSecTotal = curTime - m_StartTime; + const double diffSecTotal = curTime - m_StartTime; // calculating total rate which is the change from beginning of stats collection until now divided by time // passed from beginning of stats collection until now @@ -324,16 +326,16 @@ class HttpStatsCollector */ uint32_t collectHttpTrafficStats(pcpp::Packet* httpPacket) { - pcpp::TcpLayer* tcpLayer = httpPacket->getLayerOfType(); + auto* tcpLayer = httpPacket->getLayerOfType(); // count traffic - m_GeneralStats.amountOfHttpTraffic += tcpLayer->getLayerPayloadSize(); + m_GeneralStats.amountOfHttpTraffic += static_cast(tcpLayer->getLayerPayloadSize()); // count packet num m_GeneralStats.numOfHttpPackets++; // calculate a hash key for this flow to be used in the flow table - uint32_t hashVal = pcpp::hash5Tuple(httpPacket); + const uint32_t hashVal = pcpp::hash5Tuple(httpPacket); // if flow is a new flow (meaning it's not already in the flow table) if (m_FlowTable.find(hashVal) == m_FlowTable.end()) @@ -344,7 +346,7 @@ class HttpStatsCollector } // calculate averages - if (m_FlowTable.size() != 0) + if (!m_FlowTable.empty()) { m_GeneralStats.averageAmountOfDataPerFlow = static_cast(m_GeneralStats.amountOfHttpTraffic) / static_cast(m_FlowTable.size()); @@ -362,7 +364,9 @@ class HttpStatsCollector { // if num of current opened transaction is negative it means something went completely wrong if (m_FlowTable[flowKey].numOfOpenTransactions < 0) + { return; + } if (message->getProtocol() == pcpp::HTTPRequest) { @@ -370,7 +374,9 @@ class HttpStatsCollector // a re-transmitted packet and should be ignored if (m_FlowTable[flowKey].curSeqNumberRequests >= pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) + { return; + } // a new request - increase num of open transactions m_FlowTable[flowKey].numOfOpenTransactions++; @@ -395,7 +401,9 @@ class HttpStatsCollector // a re-transmitted packet and should be ignored if (m_FlowTable[flowKey].curSeqNumberResponses >= pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) + { return; + } // a response - decrease num of open transactions m_FlowTable[flowKey].numOfOpenTransactions--; @@ -417,10 +425,12 @@ class HttpStatsCollector m_GeneralStats.numOfHttpTransactions++; // calc average transactions per flow - if (m_FlowTable.size() != 0) + if (!m_FlowTable.empty()) + { m_GeneralStats.averageNumOfHttpTransactionsPerFlow = static_cast(m_GeneralStats.numOfHttpTransactions) / static_cast(m_FlowTable.size()); + } } // set last seen sequence number @@ -434,15 +444,19 @@ class HttpStatsCollector void collectRequestStats(pcpp::HttpRequestLayer* req) { m_RequestStats.numOfMessages++; - m_RequestStats.totalMessageHeaderSize += req->getHeaderLen(); + m_RequestStats.totalMessageHeaderSize += static_cast(req->getHeaderLen()); if (m_RequestStats.numOfMessages != 0) + { m_RequestStats.averageMessageHeaderSize = static_cast(m_RequestStats.totalMessageHeaderSize) / static_cast(m_RequestStats.numOfMessages); + } // extract hostname and add to hostname count map pcpp::HeaderField* hostField = req->getFieldByName(PCPP_HTTP_HOST_FIELD); if (hostField != nullptr) + { m_RequestStats.hostnameCount[hostField->getFieldValue()]++; + } m_RequestStats.methodCount[req->getFirstLine()->getMethod()]++; } @@ -453,21 +467,25 @@ class HttpStatsCollector void collectResponseStats(pcpp::HttpResponseLayer* res) { m_ResponseStats.numOfMessages++; - m_ResponseStats.totalMessageHeaderSize += res->getHeaderLen(); + m_ResponseStats.totalMessageHeaderSize += static_cast(res->getHeaderLen()); if (m_ResponseStats.numOfMessages != 0) + { m_ResponseStats.averageMessageHeaderSize = static_cast(m_ResponseStats.totalMessageHeaderSize) / static_cast(m_ResponseStats.numOfMessages); + } // extract content-length (if exists) pcpp::HeaderField* contentLengthField = res->getFieldByName(PCPP_HTTP_CONTENT_LENGTH_FIELD); if (contentLengthField != nullptr) { m_ResponseStats.numOfMessagesWithContentLength++; - m_ResponseStats.totalContentLengthSize += atoi(contentLengthField->getFieldValue().c_str()); + m_ResponseStats.totalContentLengthSize += std::stoi(contentLengthField->getFieldValue()); if (m_ResponseStats.numOfMessagesWithContentLength != 0) + { m_ResponseStats.averageContentLengthSize = static_cast(m_ResponseStats.totalContentLengthSize) / static_cast(m_ResponseStats.numOfMessagesWithContentLength); + } } // extract content-type and add to content-type map @@ -479,9 +497,11 @@ class HttpStatsCollector // sometimes content-type contains also the charset it uses. // for example: "application/javascript; charset=UTF-8" // remove charset as it's not relevant for these stats - size_t charsetPos = contentType.find(";"); + size_t const charsetPos = contentType.find(';'); if (charsetPos != std::string::npos) + { contentType.resize(charsetPos); + } m_ResponseStats.contentTypeCount[contentType]++; } @@ -489,21 +509,21 @@ class HttpStatsCollector // collect status code - create one string from status code and status description (for example: 200 OK) std::ostringstream stream; stream << res->getFirstLine()->getStatusCodeAsInt(); - std::string statusCode = stream.str() + " " + res->getFirstLine()->getStatusCodeString(); + const std::string statusCode = stream.str() + " " + res->getFirstLine()->getStatusCodeString(); m_ResponseStats.statusCodeCount[statusCode]++; } - double getCurTime(void) + static double getCurTime() { - struct timeval tv; + struct timeval tmVal{}; - gettimeofday(&tv, nullptr); + gettimeofday(&tmVal, nullptr); - return ((static_cast(tv.tv_sec)) + static_cast(tv.tv_usec / 1000000.0)); + return ((static_cast(tmVal.tv_sec)) + (static_cast(tmVal.tv_usec) / 1000000.0)); } - HttpGeneralStats m_GeneralStats; - HttpGeneralStats m_PrevGeneralStats; + HttpGeneralStats m_GeneralStats{}; + HttpGeneralStats m_PrevGeneralStats{}; HttpRequestStats m_RequestStats; HttpRequestStats m_PrevRequestStats; HttpResponseStats m_ResponseStats; @@ -511,7 +531,7 @@ class HttpStatsCollector std::unordered_map m_FlowTable; - double m_LastCalcRateTime; - double m_StartTime; + double m_LastCalcRateTime{}; + double m_StartTime{}; uint16_t m_DstPort; }; diff --git a/Examples/HttpAnalyzer/main.cpp b/Examples/HttpAnalyzer/main.cpp index 3667a3612a..101b2745a0 100644 --- a/Examples/HttpAnalyzer/main.cpp +++ b/Examples/HttpAnalyzer/main.cpp @@ -35,16 +35,16 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) #define PRINT_STAT_LINE(description, counter, measurement) \ std::cout << std::left << std::setw(40) << (std::string(description) + ":") << std::right << std::setw(15) \ << std::fixed << std::showpoint << std::setprecision(3) << counter << " [" << measurement << "]" \ - << std::endl; + << '\n'; -#define DEFAULT_CALC_RATES_PERIOD_SEC 2 +constexpr auto DEFAULT_CALC_RATES_PERIOD_SEC = 2; // clang-format off static struct option HttpAnalyzerOptions[] = { @@ -72,39 +72,37 @@ struct HttpPacketArrivedData */ void printUsage() { - std::cout << std::endl - << "Usage: PCAP file mode:" << std::endl - << "----------------------" << std::endl - << pcpp::AppName::get() << " [-vh] -f input_file" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" - << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl - << "Usage: Live traffic mode:" << std::endl - << "-------------------------" << std::endl - << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] [-p dst_port] -i interface" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl + std::cout << '\n' + << "Usage: PCAP file mode:" << '\n' + << "----------------------" << '\n' + << pcpp::AppName::get() << " [-vh] -f input_file" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n' + << "Usage: Live traffic mode:" << '\n' + << "-------------------------" << '\n' + << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] [-p dst_port] -i interface" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " "address" - << std::endl - << " -p dst_port : Use the specified port (optional parameter, the default is 80)" << std::endl + << '\n' + << " -p dst_port : Use the specified port (optional parameter, the default is 80)" << '\n' << " -o output_file : Save all captured HTTP packets to a pcap file. Notice this may cause " "performance degradation" - << std::endl + << '\n' << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" - << std::endl - << " -d : Disable periodic rates calculation" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << std::endl; + << '\n' + << " -d : Disable periodic rates calculation" << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -l : Print the list of interfaces and exists" << '\n' + << '\n'; } /** @@ -112,9 +110,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -126,32 +124,29 @@ void listInterfaces() const std::vector& liveDevices = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& device : liveDevices) { std::cout << " -> Name: '" << device->getName() << "' IP address: " << device->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } void printStatsHeadline(const std::string& description) { - std::cout << std::endl - << description << std::endl - << std::string(description.length(), '-') << std::endl - << std::endl; + std::cout << '\n' << description << '\n' << std::string(description.length(), '-') << '\n' << '\n'; } /** * packet capture callback - called whenever a packet arrives */ -void httpPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) +void httpPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* /*dev*/, void* cookie) { // parse the packet pcpp::Packet parsedPacket(packet); - HttpPacketArrivedData* data = static_cast(cookie); + auto* data = static_cast(cookie); // give the packet to the collector data->statsCollector->collectStats(&parsedPacket); @@ -169,8 +164,8 @@ void httpPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* void printMethods(const HttpRequestStats& reqStatscollector) { // create the table - std::vector columnNames = { "Method", "Count" }; - std::vector columnsWidths = { 9, 5 }; + const std::vector columnNames = { "Method", "Count" }; + const std::vector columnsWidths = { 9, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // Copy elements to a vector @@ -250,8 +245,8 @@ bool hostnameComparer(const std::pair& leftHost, const std::pa void printHostnames(HttpRequestStats& reqStatscollector) { // create the table - std::vector columnNames = { "Hostname", "Count" }; - std::vector columnsWidths = { 40, 5 }; + const std::vector columnNames = { "Hostname", "Count" }; + const std::vector columnsWidths = { 40, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); @@ -276,8 +271,8 @@ void printHostnames(HttpRequestStats& reqStatscollector) void printStatusCodes(const HttpResponseStats& resStatscollector) { // create the table - std::vector columnNames = { "Status Code", "Count" }; - std::vector columnsWidths = { 28, 5 }; + const std::vector columnNames = { "Status Code", "Count" }; + const std::vector columnsWidths = { 28, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // prints the status codes in lexical order @@ -301,8 +296,8 @@ void printStatusCodes(const HttpResponseStats& resStatscollector) void printContentTypes(const HttpResponseStats& resStatscollector) { // create the table - std::vector columnNames = { "Content-type", "Count" }; - std::vector columnsWidths = { 30, 5 }; + const std::vector columnNames = { "Content-type", "Count" }; + const std::vector columnsWidths = { 30, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // prints the content-types in lexical order @@ -406,12 +401,16 @@ void analyzeHttpFromPcapFile(const std::string& pcapFileName, uint16_t dstPort) std::unique_ptr reader(pcpp::IFileReaderDevice::getReader(pcapFileName)); if (!reader->open()) + { EXIT_WITH_ERROR("Could not open input pcap file"); + } // set a port filter on the reader device to process only HTTP packets pcpp::PortFilter httpPortFilter(dstPort, pcpp::SRC_OR_DST); if (!reader->setFilter(httpPortFilter)) + { EXIT_WITH_ERROR("Could not set up filter on file"); + } // read the input file packet by packet and give it to the HttpStatsCollector for collecting stats HttpStatsCollector collector(dstPort); @@ -423,7 +422,7 @@ void analyzeHttpFromPcapFile(const std::string& pcapFileName, uint16_t dstPort) } // print stats summary - std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; + std::cout << '\n' << '\n' << "STATS SUMMARY" << '\n' << "=============" << '\n'; printStatsSummary(collector); // close input file @@ -438,17 +437,21 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod { // open the device if (!dev->open()) + { EXIT_WITH_ERROR("Could not open the device"); + } pcpp::PortFilter httpPortFilter(dstPort, pcpp::SRC_OR_DST); if (!dev->setFilter(httpPortFilter)) + { EXIT_WITH_ERROR("Could not set up filter on device"); + } // if needed to save the captured packets to file - open a writer device std::unique_ptr pcapWriter; - if (savePacketsToFileName != "") + if (!savePacketsToFileName.empty()) { - pcapWriter.reset(new pcpp::PcapFileWriterDevice(savePacketsToFileName)); + pcapWriter = std::make_unique(savePacketsToFileName); if (!pcapWriter->open()) { EXIT_WITH_ERROR("Could not open pcap file for writing"); @@ -456,7 +459,7 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod } // start capturing packets and collecting stats - HttpPacketArrivedData data; + HttpPacketArrivedData data{}; HttpStatsCollector collector(dstPort); data.statsCollector = &collector; data.pcapWriter = pcapWriter.get(); @@ -486,7 +489,7 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod collector.calcRates(); // print stats summary - std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; + std::cout << '\n' << '\n' << "STATS SUMMARY" << '\n' << "=============" << '\n'; printStatsSummary(collector); // close and free the writer device @@ -503,13 +506,13 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - std::string interfaceNameOrIP = ""; + std::string interfaceNameOrIP; std::string port = "80"; bool printRatesPeriodically = true; int printRatePeriod = DEFAULT_CALC_RATES_PERIOD_SEC; - std::string savePacketsToFileName = ""; + std::string savePacketsToFileName; - std::string readPacketsFromPcapFileName = ""; + std::string readPacketsFromPcapFileName; int optionIndex = 0; int opt = 0; @@ -533,7 +536,7 @@ int main(int argc, char* argv[]) savePacketsToFileName = optarg; break; case 'r': - printRatePeriod = atoi(optarg); + printRatePeriod = std::stoi(optarg); break; case 'd': printRatesPeriodically = false; @@ -554,16 +557,20 @@ int main(int argc, char* argv[]) } // if no interface nor input pcap file were provided - exit with error - if (readPacketsFromPcapFileName == "" && interfaceNameOrIP == "") + if (readPacketsFromPcapFileName.empty() && interfaceNameOrIP.empty()) + { EXIT_WITH_ERROR("Neither interface nor input pcap file were provided"); + } // get the port - int nPort = atoi(port.c_str()); + const int nPort = std::stoi(port); if (nPort <= 0 || nPort > 65535) + { EXIT_WITH_ERROR("Please input a number between 0 to 65535"); + } // analyze in pcap file mode - if (readPacketsFromPcapFileName != "") + if (!readPacketsFromPcapFileName.empty()) { analyzeHttpFromPcapFile(readPacketsFromPcapFileName, nPort); } @@ -571,7 +578,9 @@ int main(int argc, char* argv[]) { pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } // start capturing and analyzing traffic analyzeHttpFromLiveTraffic(dev, printRatesPeriodically, printRatePeriod, savePacketsToFileName, nPort); diff --git a/Examples/IPDefragUtil/main.cpp b/Examples/IPDefragUtil/main.cpp index 24930fe7ad..85ee91667e 100644 --- a/Examples/IPDefragUtil/main.cpp +++ b/Examples/IPDefragUtil/main.cpp @@ -14,7 +14,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -33,17 +33,17 @@ static struct option DefragUtilOptions[] = { */ struct DefragStats { - int totalPacketsRead; - int ipv4Packets; - int ipv6Packets; - int ipv4PacketsMatchIpIDs; - int ipv6PacketsMatchFragIDs; - int ipPacketsMatchBpfFilter; - int ipv4FragmentsMatched; - int ipv6FragmentsMatched; - int ipv4PacketsDefragmented; - int ipv6PacketsDefragmented; - int totalPacketsWritten; + int totalPacketsRead{}; + int ipv4Packets{}; + int ipv6Packets{}; + int ipv4PacketsMatchIpIDs{}; + int ipv6PacketsMatchFragIDs{}; + int ipPacketsMatchBpfFilter{}; + int ipv4FragmentsMatched{}; + int ipv6FragmentsMatched{}; + int ipv4PacketsDefragmented{}; + int ipv6PacketsDefragmented{}; + int totalPacketsWritten{}; void clear() { @@ -61,30 +61,28 @@ struct DefragStats void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " input_file -o output_file [-d frag_ids] [-f bpf_filter] [-a] [-h] [-v]" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " input_file : Input pcap/pcapng file" << std::endl - << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" - << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' + << pcpp::AppName::get() << " input_file -o output_file [-d frag_ids] [-f bpf_filter] [-a] [-h] [-v]" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " input_file : Input pcap/pcapng file" << '\n' + << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" << '\n' << " -d frag_ids : De-fragment only fragments that match this comma-separated list of IP IDs (for IPv4) " "or" - << std::endl - << " fragment IDs (for IPv6) in decimal format" << std::endl + << '\n' + << " fragment IDs (for IPv6) in decimal format" << '\n' << " -f bpf_filter : De-fragment only fragments that match bpf_filter. Filter should be provided in " "Berkeley Packet Filter (BPF)" - << std::endl - << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl + << '\n' + << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << '\n' << " -a : Copy all packets (those who were de-fragmented and those who weren't) to output file" - << std::endl - << " -v : Displays the current version and exits" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + << '\n' + << " -v : Displays the current version and exits" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n'; } /** @@ -92,9 +90,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -112,7 +110,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr // create an instance of IPReassembly pcpp::IPReassembly ipReassembly; - pcpp::IPReassembly::ReassemblyStatus status; + pcpp::IPReassembly::ReassemblyStatus status = pcpp::IPReassembly::NON_IP_PACKET; // read all packet from input file while (reader->getNextPacket(rawPacket)) @@ -159,7 +157,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr if (filterByIpID) { // get the IPv4 layer - pcpp::IPv4Layer* ipv4Layer = parsedPacket.getLayerOfType(); + auto* ipv4Layer = parsedPacket.getLayerOfType(); if (ipv4Layer != nullptr) { // check if packet ID matches one of the IP IDs requested by the user @@ -174,11 +172,11 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr } // get the IPv6 layer - pcpp::IPv6Layer* ipv6Layer = parsedPacket.getLayerOfType(); + auto* ipv6Layer = parsedPacket.getLayerOfType(); if (ipv6Layer != nullptr && ipv6Layer->isFragment()) { // if this packet is a fragment, get the fragmentation header - pcpp::IPv6FragmentationHeader* fragHdr = ipv6Layer->getExtensionOfType(); + auto* fragHdr = ipv6Layer->getExtensionOfType(); // check if fragment ID matches one of the fragment IDs requested by the user if (fragIDs.find(pcpp::netToHost32(fragHdr->getFragHeader()->id)) != fragIDs.end()) @@ -213,9 +211,13 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr if (status == pcpp::IPReassembly::REASSEMBLED) { if (isIPv4Packet) + { stats.ipv4PacketsDefragmented++; + } else if (isIPv6Packet) + { stats.ipv6PacketsDefragmented++; + } // free packet delete result; @@ -227,9 +229,13 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr status == pcpp::IPReassembly::MALFORMED_FRAGMENT || status == pcpp::IPReassembly::REASSEMBLED) { if (isIPv4Packet) + { stats.ipv4FragmentsMatched++; + } else if (isIPv6Packet) + { stats.ipv6FragmentsMatched++; + } } } // if packet isn't marked for de-fragmentation but the user asked to write all packets to output file @@ -249,25 +255,27 @@ void printStats(const DefragStats& stats, bool filterByIpID, bool filterByBpf) std::ostringstream stream; stream << "Summary:\n"; stream << "========\n"; - stream << "Total packets read: " << stats.totalPacketsRead << std::endl; - stream << "IPv4 packets read: " << stats.ipv4Packets << std::endl; - stream << "IPv6 packets read: " << stats.ipv6Packets << std::endl; + stream << "Total packets read: " << stats.totalPacketsRead << '\n'; + stream << "IPv4 packets read: " << stats.ipv4Packets << '\n'; + stream << "IPv6 packets read: " << stats.ipv6Packets << '\n'; if (filterByIpID) { - stream << "IPv4 packets match fragment ID list: " << stats.ipv4PacketsMatchIpIDs << std::endl; - stream << "IPv6 packets match fragment ID list: " << stats.ipv6PacketsMatchFragIDs << std::endl; + stream << "IPv4 packets match fragment ID list: " << stats.ipv4PacketsMatchIpIDs << '\n'; + stream << "IPv6 packets match fragment ID list: " << stats.ipv6PacketsMatchFragIDs << '\n'; } if (filterByBpf) - stream << "IP packets match BPF filter: " << stats.ipPacketsMatchBpfFilter << std::endl; + { + stream << "IP packets match BPF filter: " << stats.ipPacketsMatchBpfFilter << '\n'; + } stream << "Total fragments matched: " << (stats.ipv4FragmentsMatched + stats.ipv6FragmentsMatched) - << std::endl; - stream << "IPv4 fragments matched: " << stats.ipv4FragmentsMatched << std::endl; - stream << "IPv6 fragments matched: " << stats.ipv6FragmentsMatched << std::endl; + << '\n'; + stream << "IPv4 fragments matched: " << stats.ipv4FragmentsMatched << '\n'; + stream << "IPv6 fragments matched: " << stats.ipv6FragmentsMatched << '\n'; stream << "Total packets reassembled: " - << (stats.ipv4PacketsDefragmented + stats.ipv6PacketsDefragmented) << std::endl; - stream << "IPv4 packets reassembled: " << stats.ipv4PacketsDefragmented << std::endl; - stream << "IPv6 packets reassembled: " << stats.ipv6PacketsDefragmented << std::endl; - stream << "Total packets written to output file: " << stats.totalPacketsWritten << std::endl; + << (stats.ipv4PacketsDefragmented + stats.ipv6PacketsDefragmented) << '\n'; + stream << "IPv4 packets reassembled: " << stats.ipv4PacketsDefragmented << '\n'; + stream << "IPv6 packets reassembled: " << stats.ipv6PacketsDefragmented << '\n'; + stream << "Total packets written to output file: " << stats.totalPacketsWritten << '\n'; std::cout << stream.str(); } @@ -282,9 +290,9 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - std::string outputFile = ""; + std::string outputFile; bool filterByBpfFilter = false; - std::string bpfFilter = ""; + std::string bpfFilter; bool filterByFragID = false; std::unordered_map fragIDMap; bool copyAllPacketsToOutputFile = false; @@ -307,14 +315,14 @@ int main(int argc, char* argv[]) filterByFragID = true; // read the IP ID / Frag ID list into the map fragIDMap.clear(); - std::string ipIDsAsString = std::string(optarg); + const std::string ipIDsAsString = std::string(optarg); std::stringstream stream(ipIDsAsString); std::string ipIDStr; // break comma-separated string into string list while (std::getline(stream, ipIDStr, ',')) { // convert the IP ID to uint16_t - uint32_t fragID = (uint32_t)atoi(ipIDStr.c_str()); + const auto fragID = std::stoul(ipIDStr); // add the frag ID into the map if it doesn't already exist fragIDMap.emplace(fragID, true); } @@ -332,7 +340,9 @@ int main(int argc, char* argv[]) bpfFilter = optarg; pcpp::BPFStringFilter filter(bpfFilter); if (!filter.verifyFilter()) + { EXIT_WITH_ERROR("Illegal BPF filter"); + } break; } case 'a': @@ -353,16 +363,18 @@ int main(int argc, char* argv[]) } } - std::string inputFile = ""; + std::string inputFile; - int expectedParams = 1; + const int expectedParams = 1; int paramIndex = -1; for (int i = optind; i < argc; i++) { paramIndex++; if (paramIndex > expectedParams) + { EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); + } switch (paramIndex) { @@ -377,12 +389,12 @@ int main(int argc, char* argv[]) } } - if (inputFile == "") + if (inputFile.empty()) { EXIT_WITH_ERROR("Input file name was not given"); } - if (outputFile == "") + if (outputFile.empty()) { EXIT_WITH_ERROR("Output file name was not given"); } @@ -400,7 +412,8 @@ int main(int argc, char* argv[]) if (dynamic_cast(reader) != nullptr) { - writer = new pcpp::PcapFileWriterDevice(outputFile, ((pcpp::PcapFileReaderDevice*)reader)->getLinkLayerType()); + writer = new pcpp::PcapFileWriterDevice( + outputFile, (dynamic_cast(reader))->getLinkLayerType()); } else if (dynamic_cast(reader) != nullptr) { diff --git a/Examples/IPFragUtil/main.cpp b/Examples/IPFragUtil/main.cpp index 93b09bd0ad..7330fe524b 100644 --- a/Examples/IPFragUtil/main.cpp +++ b/Examples/IPFragUtil/main.cpp @@ -16,7 +16,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -36,15 +36,15 @@ static struct option FragUtilOptions[] = { */ struct FragStats { - int totalPacketsRead; - int ipv4Packets; - int ipv6Packets; - int ipv4PacketsMatchIpIDs; - int ipPacketsMatchBpfFilter; - int ipPacketsUnderSize; - int ipv4PacketsFragmented; - int ipv6PacketsFragmented; - int totalPacketsWritten; + int totalPacketsRead{}; + int ipv4Packets{}; + int ipv6Packets{}; + int ipv4PacketsMatchIpIDs{}; + int ipPacketsMatchBpfFilter{}; + int ipPacketsUnderSize{}; + int ipv4PacketsFragmented{}; + int ipv6PacketsFragmented{}; + int totalPacketsWritten{}; void clear() { @@ -62,30 +62,29 @@ struct FragStats void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " input_file -s frag_size -o output_file [-d ip_ids] [-f bpf_filter] [-a] [-h] [-v]" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " input_file : Input pcap/pcapng file" << std::endl - << " -s frag_size : Size of each fragment" << std::endl - << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" - << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " input_file : Input pcap/pcapng file" << '\n' + << " -s frag_size : Size of each fragment" << '\n' + << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" << '\n' << " -d ip_ids : Fragment only packets that match this comma-separated list of IP IDs in decimal " "format" - << std::endl + << '\n' << " -f bpf_filter : Fragment only packets that match bpf_filter. Filter should be provided in Berkeley " "Packet Filter (BPF)" - << std::endl - << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl + << '\n' + << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << '\n' << " -a : Copy all packets (those who were fragmented and those who weren't) to output file" - << std::endl - << " -v : Displays the current version and exits" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + << '\n' + << " -v : Displays the current version and exits" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n'; } /** @@ -93,9 +92,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -112,7 +111,9 @@ void setIPv4FragmentParams(pcpp::IPv4Layer* fragIpLayer, size_t fragOffset, bool // if this is not the last fragment, set a "more fragments" flag if (!lastFrag) + { fragOffsetValue |= (uint16_t)0x20; + } // write fragment flags + fragment offset to packet fragIpLayer->getIPv4Header()->fragmentOffset = fragOffsetValue; @@ -123,7 +124,7 @@ void setIPv4FragmentParams(pcpp::IPv4Layer* fragIpLayer, size_t fragOffset, bool */ void setIPv6FragmentParams(pcpp::IPv6Layer* fragIpLayer, size_t fragOffset, bool lastFrag, uint32_t fragId) { - pcpp::IPv6FragmentationHeader fragHeader(fragId, fragOffset, lastFrag); + const pcpp::IPv6FragmentationHeader fragHeader(fragId, fragOffset, lastFrag); fragIpLayer->addExtension(fragHeader); } @@ -135,7 +136,8 @@ uint32_t generateRandomNumber() uint32_t result = 0; for (int i = 4; i > 0; i--) { - uint8_t randomNum = (uint8_t)rand() % 256; + // NOLINTNEXTLINE(cert-msc30-c,cert-msc50-cpp) + const uint8_t randomNum = (uint8_t)rand() % 256; // sufficient randomness for example result += (uint32_t)pow(randomNum, i); } @@ -154,33 +156,43 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS pcpp::RawPacketVector& resultFragments) { // parse raw packet - pcpp::Packet packet(rawPacket); + const pcpp::Packet packet(rawPacket); // check if IPv4/6 pcpp::ProtocolType ipProto = pcpp::UnknownProtocol; if (packet.isPacketOfType(pcpp::IPv4)) + { ipProto = pcpp::IPv4; + } else if (packet.isPacketOfType(pcpp::IPv6)) + { ipProto = pcpp::IPv6; + } else + { return; + } pcpp::Layer* ipLayer = nullptr; if (ipProto == pcpp::IPv4) + { ipLayer = packet.getLayerOfType(); - else // ipProto == IPv6 + } + else + { // ipProto == IPv6 ipLayer = packet.getLayerOfType(); + } // if packet payload size is less than the requested fragment size, don't fragment and return if (ipLayer->getLayerPayloadSize() <= fragmentSize) { - pcpp::RawPacket* copyOfRawPacket = new pcpp::RawPacket(*rawPacket); + auto* copyOfRawPacket = new pcpp::RawPacket(*rawPacket); resultFragments.pushBack(copyOfRawPacket); return; } // generate a random number for IPv6 fragment ID (not used in IPv4 packets) - uint32_t randomNum = generateRandomNumber(); + const uint32_t randomNum = generateRandomNumber(); // go over the payload and create fragments until reaching the end of the payload size_t curOffset = 0; @@ -199,15 +211,19 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS // create the fragment packet // first, duplicate the input packet and create a new parsed packet out of it - pcpp::RawPacket* newFragRawPacket = new pcpp::RawPacket(*packet.getRawPacket()); + auto* newFragRawPacket = new pcpp::RawPacket(*packet.getRawPacket()); pcpp::Packet newFrag(newFragRawPacket); // find the IPv4/6 layer of the new fragment pcpp::Layer* fragIpLayer = nullptr; if (ipProto == pcpp::IPv4) + { fragIpLayer = newFrag.getLayerOfType(); - else // ipProto == IPv6 + } + else + { // ipProto == IPv6 fragIpLayer = newFrag.getLayerOfType(); + } // delete all layers above IP layer newFrag.removeAllLayersAfter(fragIpLayer); @@ -218,9 +234,13 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS // set fragment parameters in IPv4/6 layer if (ipProto == pcpp::IPv4) - setIPv4FragmentParams((pcpp::IPv4Layer*)fragIpLayer, curOffset, lastFrag); - else // ipProto == IPv6 - setIPv6FragmentParams((pcpp::IPv6Layer*)fragIpLayer, curOffset, lastFrag, randomNum); + { + setIPv4FragmentParams(dynamic_cast(fragIpLayer), curOffset, lastFrag); + } + else + { // ipProto == IPv6 + setIPv6FragmentParams(dynamic_cast(fragIpLayer), curOffset, lastFrag, randomNum); + } // compute all calculated fields of the new fragment newFrag.computeCalculateFields(); @@ -271,7 +291,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr pcpp::ProtocolType ipProto = pcpp::UnknownProtocol; // check if packet is of type IPv4 - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); if (parsedPacket.isPacketOfType(pcpp::IPv4)) { ipProto = pcpp::IPv4; @@ -291,7 +311,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr if (filterByIpID) { // get the IPv4 layer - pcpp::IPv4Layer* ipLayer = parsedPacket.getLayerOfType(); + auto* ipLayer = parsedPacket.getLayerOfType(); if (ipLayer != nullptr) { // check if packet ID matches one of the IP IDs requested by the user @@ -321,9 +341,13 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr else if (resultFrags.size() > 1) // packet was fragmented { if (ipProto == pcpp::IPv4) + { stats.ipv4PacketsFragmented++; - else // ipProto == IPv6 + } + else + { // ipProto == IPv6 stats.ipv6PacketsFragmented++; + } } // write the result fragments if either: (1) packet was indeed fragmented, @@ -331,7 +355,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr if (resultFrags.size() > 1 || copyAllPacketsToOutputFile) { writer->writePackets(resultFrags); - stats.totalPacketsWritten += resultFrags.size(); + stats.totalPacketsWritten += static_cast(resultFrags.size()); } } // even if packet didn't pass the filters but user requested to write all packet to output file, write it @@ -351,17 +375,21 @@ void printStats(const FragStats& stats, bool filterByIpID, bool filterByBpf) std::ostringstream stream; stream << "Summary:\n"; stream << "========\n"; - stream << "Total packets read: " << stats.totalPacketsRead << std::endl; - stream << "IPv4 packets read: " << stats.ipv4Packets << std::endl; - stream << "IPv6 packets read: " << stats.ipv6Packets << std::endl; + stream << "Total packets read: " << stats.totalPacketsRead << '\n'; + stream << "IPv4 packets read: " << stats.ipv4Packets << '\n'; + stream << "IPv6 packets read: " << stats.ipv6Packets << '\n'; if (filterByIpID) - stream << "IPv4 packets match IP ID list: " << stats.ipv4PacketsMatchIpIDs << std::endl; + { + stream << "IPv4 packets match IP ID list: " << stats.ipv4PacketsMatchIpIDs << '\n'; + } if (filterByBpf) - stream << "IP packets match BPF filter: " << stats.ipPacketsMatchBpfFilter << std::endl; - stream << "IP packets smaller than fragment size: " << stats.ipPacketsUnderSize << std::endl; - stream << "IPv4 packets fragmented: " << stats.ipv4PacketsFragmented << std::endl; - stream << "IPv6 packets fragmented: " << stats.ipv6PacketsFragmented << std::endl; - stream << "Total packets written to output file: " << stats.totalPacketsWritten << std::endl; + { + stream << "IP packets match BPF filter: " << stats.ipPacketsMatchBpfFilter << '\n'; + } + stream << "IP packets smaller than fragment size: " << stats.ipPacketsUnderSize << '\n'; + stream << "IPv4 packets fragmented: " << stats.ipv4PacketsFragmented << '\n'; + stream << "IPv6 packets fragmented: " << stats.ipv6PacketsFragmented << '\n'; + stream << "Total packets written to output file: " << stats.totalPacketsWritten << '\n'; std::cout << stream.str(); } @@ -376,10 +404,10 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - std::string outputFile = ""; + std::string outputFile; int fragSize = -1; bool filterByBpfFilter = false; - std::string bpfFilter = ""; + std::string bpfFilter; bool filterByIpID = false; std::unordered_map ipIDMap; bool copyAllPacketsToOutputFile = false; @@ -399,11 +427,15 @@ int main(int argc, char* argv[]) } case 's': { - fragSize = atoi(optarg); + fragSize = std::stoi(optarg); if (fragSize < 1) + { EXIT_WITH_ERROR("Fragment size must be a positive integer"); + } if (fragSize % 8 != 0) + { EXIT_WITH_ERROR("Fragment size must divide by 8"); + } break; } case 'd': @@ -411,14 +443,14 @@ int main(int argc, char* argv[]) filterByIpID = true; // read the IP ID list into the map ipIDMap.clear(); - std::string ipIDsAsString = std::string(optarg); + const std::string ipIDsAsString = std::string(optarg); std::stringstream stream(ipIDsAsString); std::string ipIDStr; // break comma-separated string into string list while (std::getline(stream, ipIDStr, ',')) { // convert the IP ID to uint16_t - uint16_t ipID = (uint16_t)atoi(ipIDStr.c_str()); + const auto ipID = static_cast(std::stoul(ipIDStr)); // add the IP ID into the map if it doesn't already exist ipIDMap.emplace(ipID, true); } @@ -436,7 +468,9 @@ int main(int argc, char* argv[]) bpfFilter = optarg; pcpp::BPFStringFilter filter(bpfFilter); if (!filter.verifyFilter()) + { EXIT_WITH_ERROR("Illegal BPF filter"); + } break; } case 'a': @@ -457,9 +491,9 @@ int main(int argc, char* argv[]) } } - std::string inputFile = ""; + std::string inputFile; - int expectedParams = 1; + const int expectedParams = 1; int paramIndex = -1; // go over user params and look the input file @@ -467,7 +501,9 @@ int main(int argc, char* argv[]) { paramIndex++; if (paramIndex > expectedParams) + { EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); + } switch (paramIndex) { @@ -482,12 +518,12 @@ int main(int argc, char* argv[]) } } - if (inputFile == "") + if (inputFile.empty()) { EXIT_WITH_ERROR("Input file name was not given"); } - if (outputFile == "") + if (outputFile.empty()) { EXIT_WITH_ERROR("Output file name was not given"); } @@ -510,7 +546,8 @@ int main(int argc, char* argv[]) if (dynamic_cast(reader) != nullptr) { - writer = new pcpp::PcapFileWriterDevice(outputFile, ((pcpp::PcapFileReaderDevice*)reader)->getLinkLayerType()); + writer = new pcpp::PcapFileWriterDevice( + outputFile, (dynamic_cast(reader))->getLinkLayerType()); } else if (dynamic_cast(reader) != nullptr) { diff --git a/Examples/IcmpFileTransfer/Common.cpp b/Examples/IcmpFileTransfer/Common.cpp index 4b1e8df751..ff690091fb 100644 --- a/Examples/IcmpFileTransfer/Common.cpp +++ b/Examples/IcmpFileTransfer/Common.cpp @@ -16,7 +16,7 @@ # define SEPARATOR '/' #endif -#define DEFAULT_BLOCK_SIZE 1400 +constexpr auto DEFAULT_BLOCK_SIZE = 1400; static struct option IcmpFTOptions[] = { { "interface", required_argument, nullptr, 'i' }, @@ -35,42 +35,43 @@ static struct option IcmpFTOptions[] = { do \ { \ printUsage(thisSide, otherSide); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) void printUsage(const std::string& thisSide, const std::string& otherSide) { - std::string messagesPerSecShort = (thisSide == "pitcher") ? "[-p messages_per_sec] " : ""; - std::string messagesPerSecLong = (thisSide == "pitcher") ? " -p messages_per_sec : Set number of messages to " - "be sent per seconds. Default is max possible speed\n" - : ""; + const std::string messagesPerSecShort = (thisSide == "pitcher") ? "[-p messages_per_sec] " : ""; + const std::string messagesPerSecLong = (thisSide == "pitcher") + ? " -p messages_per_sec : Set number of messages to " + "be sent per seconds. Default is max possible speed\n" + : ""; - std::string thisSideInterface = thisSide + "_interface"; - std::string otherSideIP = otherSide + "_ip"; + const std::string thisSideInterface = thisSide + "_interface"; + const std::string otherSideIP = otherSide + "_ip"; std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-h] [-v] [-l] -i " << thisSideInterface << " -d " << otherSideIP - << " -s file_path -r " << messagesPerSecShort << "[-b block_size]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl + << " -s file_path -r " << messagesPerSecShort << "[-b block_size]" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' << " -i " << thisSideInterface - << " : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl - << " -d " << otherSideIP << " : " << otherSide << " IPv4 address" << std::endl - << " -s file_path : Send file mode: send file_path to " << otherSide << std::endl - << " -r : Receive file mode: receive file from " << otherSide << std::endl + << " : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << '\n' + << " -d " << otherSideIP << " : " << otherSide << " IPv4 address" << '\n' + << " -s file_path : Send file mode: send file_path to " << otherSide << '\n' + << " -r : Receive file mode: receive file from " << otherSide << '\n' << messagesPerSecLong << " -b block_size : Set the size of data chunk sent in each ICMP message (in bytes). Default is " - << DEFAULT_BLOCK_SIZE << " bytes. Relevant only" << std::endl - << " in send file mode (when -s is set)" << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << DEFAULT_BLOCK_SIZE << " bytes. Relevant only" << '\n' + << " in send file mode (when -s is set)" << '\n' + << " -l : Print the list of interfaces and exit" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Display this help message and exit" << '\n' + << '\n'; } /** @@ -78,9 +79,9 @@ void printUsage(const std::string& thisSide, const std::string& otherSide) */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -92,11 +93,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -139,12 +140,14 @@ void readCommandLineArguments(int argc, char* argv[], const std::string& thisSid break; case 'p': if (thisSide == "catcher") + { EXIT_WITH_ERROR_PRINT_USAGE("Unknown option -p"); - packetsPerSec = atoi(optarg); + } + packetsPerSec = std::stoi(optarg); packetsPerSecSet = true; break; case 'b': - blockSize = atoi(optarg); + blockSize = std::stoi(optarg); blockSizeSet = true; break; case 'h': @@ -165,7 +168,9 @@ void readCommandLineArguments(int argc, char* argv[], const std::string& thisSid // extract my IP address by interface name or IP address string if (interfaceNameOrIP.empty()) + { EXIT_WITH_ERROR_PRINT_USAGE("Please provide " << thisSide << " interface name or IP"); + } pcpp::IPv4Address interfaceIP; try @@ -177,14 +182,18 @@ void readCommandLineArguments(int argc, char* argv[], const std::string& thisSid { pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR_PRINT_USAGE("Cannot find interface by provided name"); + } myIP = dev->getIPv4Address(); } // validate pitcher/catcher IP address if (otherSideIPAsString.empty()) + { EXIT_WITH_ERROR_PRINT_USAGE("Please provide " << otherSide << " IP address"); + } pcpp::IPv4Address tempIP; try @@ -199,23 +208,33 @@ void readCommandLineArguments(int argc, char* argv[], const std::string& thisSid // verify only one of sender and receiver switches are set if (sender && receiver) + { EXIT_WITH_ERROR_PRINT_USAGE("Cannot set both send file mode (-s) and receive file mode (-r) switches"); + } if (!sender && !receiver) + { EXIT_WITH_ERROR_PRINT_USAGE("Must set either send file mode (-s) or receive file mode (-r) switches"); + } // cannot set block size if in receiving file mode if (!sender && blockSizeSet) + { EXIT_WITH_ERROR_PRINT_USAGE("Setting block size (-b switch) is relevant for sending files only"); + } // validate block size if (blockSize < 1 || blockSize > 1464) + { EXIT_WITH_ERROR_PRINT_USAGE("Block size must be a positive integer lower or equal to 1464 bytes (which is the " "maximum size for a standard packet)"); + } // validate packets per sec if (packetsPerSecSet && packetsPerSec < 1) + { EXIT_WITH_ERROR_PRINT_USAGE("message_per_sec must be a positive value greater or equal to 1"); + } } bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, @@ -227,7 +246,9 @@ bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcp // keep IP ID in the range of 0x1234-0xfff0 if (ipID == 0xfff0) + { ipID = 0x1234; + } // create the different layers @@ -243,9 +264,13 @@ bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcp // then ICMP pcpp::IcmpLayer icmpLayer; if (sendRequest && icmpLayer.setEchoRequestData(icmpMsgId, 0, msgType, data, dataLen) == nullptr) + { EXIT_WITH_ERROR("Cannot set ICMP echo request data"); + } else if (!sendRequest && icmpLayer.setEchoReplyData(icmpMsgId, 0, msgType, data, dataLen) == nullptr) + { EXIT_WITH_ERROR("Cannot set ICMP echo response data"); + } // create an new packet and add all layers to it pcpp::Packet packet; @@ -275,11 +300,11 @@ bool sendIcmpResponse(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pc std::string getFileNameFromPath(const std::string& filePath) { // find the last "\\" or "/" (depends on the os) - where path ends and filename starts - size_t i = filePath.rfind(SEPARATOR, filePath.length()); - if (i != std::string::npos) + const size_t idx = filePath.rfind(SEPARATOR, filePath.length()); + if (idx != std::string::npos) { // extract filename from path - return filePath.substr(i + 1, filePath.length() - i); + return filePath.substr(idx + 1, filePath.length() - idx); } return filePath; diff --git a/Examples/IcmpFileTransfer/Common.h b/Examples/IcmpFileTransfer/Common.h index baf7c0d3e8..5afa931a2b 100644 --- a/Examples/IcmpFileTransfer/Common.h +++ b/Examples/IcmpFileTransfer/Common.h @@ -4,28 +4,31 @@ #include "IpAddress.h" #include "PcapLiveDevice.h" -#define ICMP_FT_WAITING_FT_START 0x345a56c8e7f3cd67ULL -#define ICMP_FT_START 0xd45ae6c2e7a3cd67ULL -#define ICMP_FT_WAITING_DATA 0x6d5f86c817fb5d7eULL -#define ICMP_FT_DATA 0x3d5a76c827f35d77ULL -#define ICMP_FT_ACK 0x395156c857fbcc6aULL -#define ICMP_FT_END 0x144156cbeffa2687ULL -#define ICMP_FT_ABORT 0x146158cbafff2b8aULL +enum : uint64_t +{ + ICMP_FT_WAITING_FT_START = 0x345a56c8e7f3cd67ULL, + ICMP_FT_START = 0xd45ae6c2e7a3cd67ULL, + ICMP_FT_WAITING_DATA = 0x6d5f86c817fb5d7eULL, + ICMP_FT_DATA = 0x3d5a76c827f35d77ULL, + ICMP_FT_ACK = 0x395156c857fbcc6aULL, + ICMP_FT_END = 0x144156cbeffa2687ULL, + ICMP_FT_ABORT = 0x146158cbafff2b8aULL +}; -#define ONE_MBYTE 1048576 +constexpr auto ONE_MBYTE = 1048576; #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) #define EXIT_WITH_ERROR_AND_RUN_COMMAND(reason, command) \ do \ { \ - command; \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + static_cast(command); \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -40,7 +43,7 @@ void listInterfaces(); */ void readCommandLineArguments(int argc, char* argv[], const std::string& thisSide, const std::string& otherSide, bool& sender, bool& receiver, pcpp::IPv4Address& myIP, pcpp::IPv4Address& otherSideIP, - std::string& fileNameToSend, int& packetPerSec, size_t& blockSize); + std::string& fileNameToSend, int& packetsPerSec, size_t& blockSize); /** * Send an ICMP request from source to dest with certain ICMP ID, msgType will be written in the timestamp field of the diff --git a/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp b/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp index 5d5f8f576b..28d66b03e5 100644 --- a/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp +++ b/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp @@ -49,11 +49,11 @@ struct IcmpFileContentDataSend { pcpp::IPv4Address pitcherIPAddr; pcpp::IPv4Address catcherIPAddr; - std::ifstream* file; - bool readingFromFile; - uint32_t MBSent; - size_t blockSize; - char* memblock; + std::ifstream* file{}; + bool readingFromFile{}; + uint32_t MBSent{}; + size_t blockSize{}; + char* memblock{}; }; /** @@ -63,47 +63,59 @@ struct IcmpFileContentDataSend static bool waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return false; + } if (icmpVoidData == nullptr) + { return false; + } - IcmpFileTransferStart* icmpFTStart = (IcmpFileTransferStart*)icmpVoidData; + auto* icmpFTStart = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP request - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoRequestData() == nullptr) + { return false; + } // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) + { return false; + } // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher // in this case the catcher is waiting for a file-transfer start message from the pitcher containing the file name // which is of type ICMP_FT_START - uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; if (resMsg != ICMP_FT_START) + { return false; + } // extract the file name from the ICMP request data - icmpFTStart->fileName = std::string((char*)icmpLayer->getEchoRequestData()->data); + icmpFTStart->fileName = std::string(reinterpret_cast(icmpLayer->getEchoRequestData()->data)); // extract ethernet layer and ICMP ID to be able to respond to the pitcher - pcpp::EthLayer* ethLayer = parsedPacket.getLayerOfType(); - uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); + auto* ethLayer = parsedPacket.getLayerOfType(); + const uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); // send the pitcher an ICMP response containing an ack message (of type ICMP_FT_ACK) so it knows the catcher has // received the file name and it's ready to start getting the file data if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFTStart->catcherIPAddr, icmpFTStart->pitcherIPAddr, icmpId, ICMP_FT_ACK, nullptr, 0)) + { EXIT_WITH_ERROR("Cannot send ACK message to pitcher"); + } // set the current ICMP ID. It's important for the catcher to keep track of the ICMP ID to make sure it doesn't miss // any message @@ -117,33 +129,41 @@ static bool waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the pitcher and * write them to the local file */ -static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) +static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* /*dev*/, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return false; + } if (icmpVoidData == nullptr) + { return false; + } - IcmpFileContentDataRecv* icmpData = (IcmpFileContentDataRecv*)icmpVoidData; + auto* icmpData = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP request - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoRequestData() == nullptr) + { return false; + } // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpData->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpData->catcherIPAddr) + { return false; + } // extract message type from the ICMP request. Message type is written in ICMP request timestamp field - uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; // if message type is ICMP_FT_END it means pitcher finished sending all file chunks if (resMsg == ICMP_FT_END) @@ -155,13 +175,17 @@ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev } // if message type is not ICMP_FT_END not ICMP_FT_DATA - do nothing, it's probably an ICMP request not relevant for // this file transfer - else if (resMsg != ICMP_FT_DATA) + if (resMsg != ICMP_FT_DATA) + { return false; + } // compare the ICMP ID of the request to the ICMP ID we expect to see. If it's smaller than expected it means // catcher already saw this message so it can be ignored if (pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id) < icmpData->expectedIcmpId) + { return false; + } // if ICMP ID is bigger than expected it probably means catcher missed one or more packets. Since a reliability // mechanism isn't currently implemented in this program, the only thing left to do is to exit the program with an @@ -180,7 +204,8 @@ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev icmpData->expectedIcmpId++; // write the data received from the pitcher to the local file - icmpData->file->write((char*)icmpLayer->getEchoRequestData()->data, icmpLayer->getEchoRequestData()->dataLength); + icmpData->file->write(reinterpret_cast(icmpLayer->getEchoRequestData()->data), + static_cast(icmpLayer->getEchoRequestData()->dataLength)); // add chunk size to the aggregated file size icmpData->fileSize += icmpLayer->getEchoRequestData()->dataLength; @@ -205,25 +230,33 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(catcherIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Cannot find network interface with IP '" << catcherIP << "'"); + } // try to open the interface (device) if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open network interface"); + } // set an ICMP protocol filter so it'll capture only ICMP packets pcpp::ProtoFilter protocolFilter(pcpp::ICMP); if (!dev->setFilter(protocolFilter)) + { EXIT_WITH_ERROR("Can't set ICMP filter on device"); + } - std::cout << "Waiting for pitcher to send a file..." << std::endl; + std::cout << "Waiting for pitcher to send a file..." << '\n'; IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, "", 0 }; // wait until the pitcher sends an ICMP request with the file name in its data int res = dev->startCaptureBlockingMode(waitForFileTransferStart, &icmpFTStart, -1); - if (!res) + if (res == 0) + { EXIT_WITH_ERROR("Cannot start capturing packets"); + } // create a new file with the name provided by the pitcher std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out | std::ios::binary); @@ -238,20 +271,22 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) // get all file data from the pitcher. This method blocks until all file is received res = dev->startCaptureBlockingMode(getFileContent, &icmpFileContentData, -1); - if (!res) + if (res == 0) { file.close(); EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str())); } - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Finished getting file '" << icmpFTStart.fileName << "' " - << "[received " << icmpFileContentData.fileSize << " bytes]" << std::endl; + << "[received " << icmpFileContentData.fileSize << " bytes]" << '\n'; } else + { EXIT_WITH_ERROR("Cannot create file"); + } // remove the filter and close the device (interface) dev->clearFilter(); @@ -266,44 +301,57 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) static bool startFileTransfer(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return false; + } if (icmpVoidData == nullptr) + { return false; + } - IcmpFileTransferStart* icmpFTStart = (IcmpFileTransferStart*)icmpVoidData; + auto* icmpFTStart = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP request - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoRequestData() == nullptr) + { return false; + } // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) + { return false; + } // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher // in this case the catcher is waiting for a keep-alive message from the pitcher which is of type // ICMP_FT_WAITING_FT_START - uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; if (resMsg != ICMP_FT_WAITING_FT_START) + { return false; + } // extract ethernet layer and ICMP ID to be able to respond to the pitcher - pcpp::EthLayer* ethLayer = parsedPacket.getLayerOfType(); - uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); + auto* ethLayer = parsedPacket.getLayerOfType(); + const uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); // send the ICMP response containing the file name back to the pitcher if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFTStart->catcherIPAddr, - icmpFTStart->pitcherIPAddr, icmpId, ICMP_FT_START, (uint8_t*)icmpFTStart->fileName.c_str(), + icmpFTStart->pitcherIPAddr, icmpId, ICMP_FT_START, + const_cast(reinterpret_cast(icmpFTStart->fileName.c_str())), icmpFTStart->fileName.length() + 1)) + { EXIT_WITH_ERROR("Cannot send file transfer start message to pitcher"); + } return true; } @@ -315,42 +363,54 @@ static bool startFileTransfer(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return false; + } if (icmpVoidData == nullptr) + { return false; + } - IcmpFileContentDataSend* icmpFileContentData = (IcmpFileContentDataSend*)icmpVoidData; + auto* icmpFileContentData = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP request - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoRequestData() == nullptr) + { return false; + } // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFileContentData->catcherIPAddr) + { return false; + } // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher - uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; // if the pitcher sent an abort message, exit the program if (resMsg == ICMP_FT_ABORT) + { EXIT_WITH_ERROR("Got an abort message from pitcher. Exiting..."); + } // if it's not an abort message, catcher is only waiting for data messages which are of type ICMP_FT_WAITING_DATA if (resMsg != ICMP_FT_WAITING_DATA) + { return false; + } // extract ethernet layer and ICMP ID to be able to respond to the pitcher - pcpp::EthLayer* ethLayer = parsedPacket.getLayerOfType(); - uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); + auto* ethLayer = parsedPacket.getLayerOfType(); + const uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); // if all file was already sent to the pitcher if (!icmpFileContentData->readingFromFile) @@ -359,21 +419,27 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // to it if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_END, nullptr, 0)) + { EXIT_WITH_ERROR("Cannot send file transfer end message to pitcher"); + } // then return true so the sendFile() will stop blocking return true; } // try to read another block of data from the file - if (icmpFileContentData->file->read(icmpFileContentData->memblock, icmpFileContentData->blockSize)) + if (icmpFileContentData->file->read(icmpFileContentData->memblock, + static_cast(icmpFileContentData->blockSize))) { // if managed to read a full block, send it via the ICMP response to the pitcher. The data chunk will be sent in // the response data if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_DATA, - (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->blockSize)) + reinterpret_cast(icmpFileContentData->memblock), + icmpFileContentData->blockSize)) + { EXIT_WITH_ERROR("Cannot send file transfer data message to pitcher"); + } // print a dot ('.') on every 1MB sent icmpFileContentData->MBSent += icmpFileContentData->blockSize; @@ -390,8 +456,11 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // response data if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_DATA, - (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->file->gcount())) + reinterpret_cast(icmpFileContentData->memblock), + icmpFileContentData->file->gcount())) + { EXIT_WITH_ERROR("Cannot send file transfer last data message to pitcher"); + } // set an indication that all file was delivered to the pitcher icmpFileContentData->readingFromFile = false; @@ -418,16 +487,22 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(catcherIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Cannot find network interface with IP '" << catcherIP << "'"); + } // try to open the interface (device) if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open network interface"); + } // set an ICMP protocol filter so it'll capture only ICMP packets pcpp::ProtoFilter protocolFilter(pcpp::ICMP); if (!dev->setFilter(protocolFilter)) + { EXIT_WITH_ERROR("Can't set ICMP filter on device"); + } // try the open the file for reading std::ifstream file(filePath.c_str(), std::ios::in | std::ios::binary); @@ -436,15 +511,15 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP { // extract file size file.seekg(0, std::ios_base::end); - uint32_t fileSize = file.tellg(); + const uint32_t fileSize = file.tellg(); // go back to the beginning of the file file.seekg(0, std::ios::beg); // remove the path and keep just the file name. This is the name that will be delivered to the pitcher - std::string fileName = getFileNameFromPath(filePath); + const std::string fileName = getFileNameFromPath(filePath); - std::cout << "Waiting for pitcher to send a keep-alive signal..." << std::endl; + std::cout << "Waiting for pitcher to send a keep-alive signal..." << '\n'; IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, fileName, 0 }; @@ -453,8 +528,10 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // the ICMP response data int res = dev->startCaptureBlockingMode(startFileTransfer, &icmpFTStart, -1); // if an error occurred - if (!res) + if (res == 0) + { EXIT_WITH_ERROR("Cannot start capturing packets"); + } std::cout << "Sending file '" << fileName << "' "; @@ -472,16 +549,20 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP file.close(); // if capture failed, exit the program - if (!res) + if (res == 0) + { EXIT_WITH_ERROR("Cannot start capturing packets"); + } - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Finished sending '" << fileName << "' " - << "[sent " << fileSize << " bytes]" << std::endl; + << "[sent " << fileSize << " bytes]" << '\n'; } - else // if file couldn't be opened + else + { // if file couldn't be opened EXIT_WITH_ERROR("Cannot open file '" << filePath << "'"); + } // close the device dev->close(); @@ -494,7 +575,8 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - bool sender, receiver; + bool sender = false; + bool receiver = false; pcpp::IPv4Address pitcherIP; pcpp::IPv4Address catcherIP; std::string fileNameToSend; @@ -502,7 +584,10 @@ int main(int argc, char* argv[]) size_t blockSize = 0; // disable stdout buffering so all std::cout command will be printed immediately - setbuf(stdout, nullptr); + if (setvbuf(stdout, nullptr, _IONBF, 0) != 0) + { + std::cerr << "Failed to disable stdout buffering" << '\n'; + } // read and parse command line arguments. This method also takes care of arguments correctness. If they're not // correct, it'll exit the program @@ -511,8 +596,12 @@ int main(int argc, char* argv[]) // send a file to the pitcher if (sender) + { sendFile(fileNameToSend, pitcherIP, catcherIP, blockSize); - // receive a file from the pitcher + // receive a file from the pitcher + } else if (receiver) + { receiveFile(pitcherIP, catcherIP); + } } diff --git a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp index 1aec9c6856..06e80c93fc 100644 --- a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp +++ b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp @@ -6,6 +6,7 @@ * For more information please refer to README.md */ +#include #include #include #include @@ -21,10 +22,9 @@ #include "Common.h" #include "SystemUtils.h" -#define SEND_TIMEOUT_BEFORE_FT_START 3 - -#define SLEEP_BETWEEN_ABORT_MESSAGES 100000 // 100 msec -#define NUM_OF_ABORT_MESSAGES_TO_SEND 5 +constexpr auto SEND_TIMEOUT_BEFORE_FT_START = 3; +constexpr auto SLEEP_BETWEEN_ABORT_MESSAGES = 100000; // 100 msec +constexpr auto NUM_OF_ABORT_MESSAGES_TO_SEND = 5; #ifdef _MSC_VER # include @@ -55,7 +55,7 @@ void usleep(__int64 usec) */ struct IcmpFileTransferStartSend { - uint16_t icmpMsgId; + uint16_t icmpMsgId{}; pcpp::IPv4Address pitcherIPAddr; pcpp::IPv4Address catcherIPAddr; }; @@ -78,54 +78,66 @@ struct IcmpFileContentData { pcpp::IPv4Address pitcherIPAddr; pcpp::IPv4Address catcherIPAddr; - std::ofstream* file; - uint16_t expectedIcmpId; - uint32_t fileSize; - uint32_t MBReceived; - bool fileTransferCompleted; - bool fileTransferError; + std::ofstream* file{}; + uint16_t expectedIcmpId{}; + uint32_t fileSize{}; + uint32_t MBReceived{}; + bool fileTransferCompleted{}; + bool fileTransferError{}; }; /** * A callback used in the receiveFile() method and responsible to wait for the catcher to send an ICMP response * containing the file name to be received */ -static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) +static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* /*dev*/, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return; + } if (icmpVoidData == nullptr) + { return; + } - IcmpFileTransferStartRecv* icmpFTStart = (IcmpFileTransferStartRecv*)icmpVoidData; + auto* icmpFTStart = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP reply - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoReplyData() == nullptr) + { return; + } // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpFTStart->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->pitcherIPAddr) + { return; + } // extract the message type in the ICMP reply timestamp field and check if it's ICMP_FT_START - uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; if (resMsg != ICMP_FT_START) + { return; + } // verify there is data in the ICMP reply if (icmpLayer->getEchoReplyData()->data == nullptr) + { return; + } // extract the file name from the ICMP reply data - icmpFTStart->fileName = std::string((char*)icmpLayer->getEchoReplyData()->data); + icmpFTStart->fileName = std::string(reinterpret_cast(icmpLayer->getEchoReplyData()->data)); // signal the receiveFile() file name was extracted and it can stop capturing packets icmpFTStart->gotFileTransferStartMsg = true; @@ -135,33 +147,41 @@ static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the catcher and * write them to the local file */ -static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) +static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* /*dev*/, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return; + } if (icmpVoidData == nullptr) + { return; + } - IcmpFileContentData* icmpFileContentData = (IcmpFileContentData*)icmpVoidData; + auto* icmpFileContentData = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP reply - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoReplyData() == nullptr) + { return; + } // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFileContentData->pitcherIPAddr) + { return; + } // extract the message type from the ICMP reply timestamp field - uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; + const uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; // if message type is ICMP_FT_END it means all file was sent by the catcher. In that case set the // icmpFileContentData->fileTransferCompleted to true the receiveFile() method checks that flag periodically and @@ -175,7 +195,9 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev // if message type isn't ICMP_FT_END and ICMP_FT_DATA, ignore it if (resMsg != ICMP_FT_DATA) + { return; + } // if got to here it means it's an ICMP_FT_DATA message @@ -185,23 +207,25 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev if (pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) != icmpFileContentData->expectedIcmpId) { icmpFileContentData->fileTransferError = true; - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Didn't get expected ICMP message #" << icmpFileContentData->expectedIcmpId << ", got #" - << pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) << std::endl; + << pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) << '\n'; return; } // verify the ICMP reply has data if (icmpLayer->getEchoReplyData()->data == nullptr) + { return; + } // increment the expected ICMP ID icmpFileContentData->expectedIcmpId++; // write the file data chunk in the ICMP reply data to the output file - icmpFileContentData->file->write((char*)icmpLayer->getEchoReplyData()->data, - icmpLayer->getEchoReplyData()->dataLength); + icmpFileContentData->file->write(reinterpret_cast(icmpLayer->getEchoReplyData()->data), + static_cast(icmpLayer->getEchoReplyData()->dataLength)); // count the bytes received icmpFileContentData->fileSize += icmpLayer->getEchoReplyData()->dataLength; @@ -223,34 +247,44 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(pitcherIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Cannot find network interface with IP '" << pitcherIP << "'"); + } // try to open the interface (device) if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open network interface "); + } // get the MAC address of the interface - pcpp::MacAddress pitcherMacAddr = dev->getMacAddress(); + const pcpp::MacAddress pitcherMacAddr = dev->getMacAddress(); if (pitcherMacAddr == pcpp::MacAddress::Zero) + { EXIT_WITH_ERROR("Cannot find pitcher MAC address"); + } // discover the MAC address of the catcher by sending an ARP ping to it double arpResTO = 0; - pcpp::MacAddress catcherMacAddr = + const pcpp::MacAddress catcherMacAddr = pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); if (catcherMacAddr == pcpp::MacAddress::Zero) + { EXIT_WITH_ERROR("Cannot find catcher MAC address"); + } uint16_t icmpId = 1; IcmpFileTransferStartRecv icmpFTStart = { pitcherIP, catcherIP, false, "" }; - std::cout << "Waiting for catcher to start sending a file..." << std::endl; + std::cout << "Waiting for catcher to start sending a file..." << '\n'; // set an ICMP protocol filter so it'll capture only ICMP packets pcpp::ProtoFilter protocolFilter(pcpp::ICMP); if (!dev->setFilter(protocolFilter)) + { EXIT_WITH_ERROR("Can't set ICMP filter on device"); + } // since it's the pitcher's job to send ICMP requests and the catcher's job to get them and send ICMP replies, // sending a file from the catcher to the pitcher is a bit more complicated @@ -260,7 +294,9 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // start capturing ICMP packets. The waitForFileTransferStart callback should look for the catcher reply and set // icmpFTStart.gotFileTransferStartMsg to true if (!dev->startCapture(waitForFileTransferStart, &icmpFTStart)) + { EXIT_WITH_ERROR("Cannot start capturing packets"); + } // while didn't receive response from the catcher, keep sending the ICMP_FT_WAITING_FT_START message while (!icmpFTStart.gotFileTransferStartMsg) @@ -295,7 +331,9 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // we use sleep instead uint32_t sleepBetweenPackets = 0; if (packetPerSec > 1) + { sleepBetweenPackets = (uint32_t)(1000000UL / packetPerSec); + } // start capturing ICMP packets. The getFileContent callback should look for the catcher replies containing data // chunks of the file and write them to the opened file. When catcher signals the end of the file transfer, the @@ -316,9 +354,13 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // if rate limit was set by the user, sleep between sending packets if (packetPerSec > 1) + { std::this_thread::sleep_for(std::chrono::microseconds(sleepBetweenPackets)); + } else if (packetPerSec == 1) + { std::this_thread::sleep_for(std::chrono::seconds(1)); + } icmpId++; } @@ -343,13 +385,15 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p } // file transfer was completed successfully - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Finished getting file '" << icmpFTStart.fileName << "' " - << "[received " << icmpFileContentData.fileSize << " bytes]" << std::endl; + << "[received " << icmpFileContentData.fileSize << " bytes]" << '\n'; } else + { EXIT_WITH_ERROR("Cannot create file"); + } // close the device dev->close(); @@ -359,42 +403,50 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p * A callback used in the sendFile() method and responsible to wait for ICMP responses coming from the catcher * indicating it's alive and ready for file transfer to start */ -static bool waitForFileTransferStartAck(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) +static bool waitForFileTransferStartAck(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* /*dev*/, void* icmpVoidData) { // first, parse the packet - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); // verify it's ICMP and IPv4 (IPv6 and ICMPv6 are not supported) if (!parsedPacket.isPacketOfType(pcpp::ICMP) || !parsedPacket.isPacketOfType(pcpp::IPv4)) + { return false; + } if (icmpVoidData == nullptr) + { return false; + } - IcmpFileTransferStartSend* icmpData = (IcmpFileTransferStartSend*)icmpVoidData; + auto* icmpData = reinterpret_cast(icmpVoidData); // extract the ICMP layer, verify it's an ICMP reply - pcpp::IcmpLayer* icmpLayer = parsedPacket.getLayerOfType(); + auto* icmpLayer = parsedPacket.getLayerOfType(); if (icmpLayer->getEchoReplyData() == nullptr) + { return false; + } // verify the ICMP ID of the reply matched the ICMP ID the pitcher sent in the request if (icmpLayer->getEchoReplyData()->header->id != pcpp::hostToNet16(icmpData->icmpMsgId)) + { return false; + } // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP - pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); + auto* ip4Layer = parsedPacket.getLayerOfType(); if (ip4Layer->getSrcIPv4Address() != icmpData->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpData->pitcherIPAddr) + { return false; + } // verify the message type is ICMP_FT_ACK - uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; - if (resMsg != ICMP_FT_ACK) - return false; + const uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; - // if arrived to here it means we got a response from the catcher and it's ready for file transfer to start - return true; + // if it is true then it means the catcher is ready for file transfer to start + return resMsg == ICMP_FT_ACK; } /** @@ -406,26 +458,34 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(pitcherIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Cannot find network interface with IP '" << pitcherIP << "'"); + } // try to open the interface (device) if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open network interface "); + } // get the MAC address of the interface - pcpp::MacAddress pitcherMacAddr = dev->getMacAddress(); + const pcpp::MacAddress pitcherMacAddr = dev->getMacAddress(); if (pitcherMacAddr == pcpp::MacAddress::Zero) + { EXIT_WITH_ERROR("Cannot find pitcher MAC address"); + } // discover the MAC address of the catcher by sending an ARP ping to it double arpResTO = 0; - pcpp::MacAddress catcherMacAddr = + const pcpp::MacAddress catcherMacAddr = pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); if (catcherMacAddr == pcpp::MacAddress::Zero) + { EXIT_WITH_ERROR("Cannot find catcher MAC address"); + } // create a buffer that will be used to send data chunks of the file - uint8_t* memblock = new uint8_t[blockSize]; + auto* memblock = new uint8_t[blockSize]; memset(memblock, 0, blockSize); // try the open the file for reading @@ -434,7 +494,7 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP if (file.is_open()) { // remove the path and keep just the file name. This is the name that will be delivered to the catcher - std::string fileName = getFileNameFromPath(filePath); + const std::string fileName = getFileNameFromPath(filePath); // go back to the beginning of the file file.seekg(0, std::ios::beg); @@ -442,33 +502,39 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP uint16_t icmpId = 1; // copy the file name to the buffer - strcpy((char*)memblock, fileName.c_str()); + fileName.copy(reinterpret_cast(memblock), std::min(blockSize - 1, fileName.length())); IcmpFileTransferStartSend ftStartData = { icmpId, pitcherIP, catcherIP }; - std::cout << "Waiting for catcher..." << std::endl; + std::cout << "Waiting for catcher..." << '\n'; // establish connection with the catcher by sending it ICMP requests that contains the file name and wait for a // response keep sending these requests until the catcher answers or until the program is stopped - while (1) + while (true) { // send the catcher an ICMP request that includes an special ICMP_FT_START message in the timestamp field // and the filename in the request data. The catcher should intercept this message and send an ICMP response // with an ICMP_FT_ACK message in the timestamp field if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_START, memblock, fileName.length() + 1)) + { EXIT_WITH_ERROR("Cannot send file transfer start message"); + } // now wait for the catcher to answer. The timeout is SEND_TIMEOUT_BEFORE_FT_START. After that another ICMP // request will be sent - int res = + const int res = dev->startCaptureBlockingMode(waitForFileTransferStartAck, &ftStartData, SEND_TIMEOUT_BEFORE_FT_START); - if (!res) + if (res == 0) + { EXIT_WITH_ERROR("Cannot start capturing packets"); + } // res == 1 means we got the catcher response so we can break the endless loop if (res == 1) + { break; + } // increase ICMP ID so we won't send the same ICMP ID again icmpId++; @@ -488,23 +554,31 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and we use // sleep instead if (packetPerSec > 1) + { sleepBetweenPackets = (uint32_t)(1000000UL / packetPerSec); + } // read one chunk of the file and send it to catcher. This loop breaks when it is reaching the end of the file // and can't read a block of size blockSize from the file - while (file.read((char*)memblock, blockSize)) + while (file.read(reinterpret_cast(memblock), static_cast(blockSize))) { // send an ICMP request to the catcher containing the data chunk.The message type (set in the timestamp // field) is ICMP_FT_DATA so the catcher knows it's a data chunk if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, memblock, blockSize)) + { EXIT_WITH_ERROR("Cannot send file data message"); + } // use usleep or sleep (see comment a few lines below) if (packetPerSec > 1) + { std::this_thread::sleep_for(std::chrono::microseconds(sleepBetweenPackets)); + } else if (packetPerSec == 1) + { std::this_thread::sleep_for(std::chrono::seconds(1)); + } bytesSentSoFar += blockSize; @@ -525,7 +599,9 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP { if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, memblock, file.gcount())) + { EXIT_WITH_ERROR("Cannot send file data message"); + } bytesSentSoFar += file.gcount(); std::cout << "."; @@ -535,15 +611,19 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // field) to the catcher to indicate all file was sent if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_END, nullptr, 0)) + { EXIT_WITH_ERROR("Cannot send file transfer end message"); + } - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Finished sending '" << fileName << "' " - << "[sent " << bytesSentSoFar << " bytes]" << std::endl; + << "[sent " << bytesSentSoFar << " bytes]" << '\n'; } else + { EXIT_WITH_ERROR("Cannot open file '" << filePath << "'"); + } // close the file and the device. Free the memory for memblock file.close(); @@ -558,7 +638,8 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - bool sender, receiver; + bool sender = false; + bool receiver = false; pcpp::IPv4Address pitcherIP; pcpp::IPv4Address catcherIP; std::string fileNameToSend; @@ -566,7 +647,10 @@ int main(int argc, char* argv[]) size_t blockSize = 0; // disable stdout buffering so all std::cout command will be printed immediately - setbuf(stdout, nullptr); + if (setvbuf(stdout, nullptr, _IONBF, 0) != 0) + { + std::cerr << "Failed to disable stdout buffering" << '\n'; + } // read and parse command line arguments. This method also takes care of arguments correctness. If they're not // correct, it'll exit the program @@ -575,8 +659,12 @@ int main(int argc, char* argv[]) // send a file to the catcher if (sender) + { sendFile(fileNameToSend, pitcherIP, catcherIP, blockSize, packetsPerSec); - // receive a file from the catcher + // receive a file from the catcher + } else if (receiver) + { receiveFile(pitcherIP, catcherIP, packetsPerSec); + } } diff --git a/Examples/KniPong/main.cpp b/Examples/KniPong/main.cpp index beb5f89e97..f6ab00f99e 100644 --- a/Examples/KniPong/main.cpp +++ b/Examples/KniPong/main.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -34,15 +34,16 @@ #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) -#define IO_BUFF_SIZE (1 << 14) -#define WANT_POLLIN (-2) -#define WANT_POLLOUT (-3) #define DEFAULT_KNI_NAME "pcppkni0" -#define DEFAULT_PORT 62604 + +constexpr auto IO_BUFF_SIZE = (1 << 14); +constexpr auto WANT_POLLIN = (-2); +constexpr auto WANT_POLLOUT = (-3); +constexpr auto DEFAULT_PORT = 62604; namespace { @@ -52,14 +53,14 @@ namespace std::string kniIp; std::string outIp; std::string kniName; - uint16_t kniPort; + uint16_t kniPort{}; }; - typedef int linuxFd; + using linuxFd = int; struct LinuxSocket { - inline operator int() const + operator int() const { return m_Socket; } @@ -75,16 +76,16 @@ namespace unsigned long arpPacketsOutFail; }; - static bool doContinue = true; + volatile sig_atomic_t doContinue = 1; /** * Print application version */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -93,23 +94,22 @@ namespace */ inline void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hv] [-n KNI_DEVICE_NAME] [-p PORT] -s SRC_IPV4 -d DST_IPV4" - << std::endl - << std::endl - << "Options:" << std::endl - << " -s --src SRC_IPV4 : IPv4 address to assign to the created KNI device" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' + << pcpp::AppName::get() << " [-hv] [-n KNI_DEVICE_NAME] [-p PORT] -s SRC_IPV4 -d DST_IPV4" << '\n' + << '\n' + << "Options:" << '\n' + << " -s --src SRC_IPV4 : IPv4 address to assign to the created KNI device" << '\n' << " -d --dst DST_IPV4 : Virtual IPv4 address to communicate with. Must be in /24 " "subnet with SRC_IPV4" - << std::endl + << '\n' << " -n --name KNI_DEVICE_NAME : Name for KNI device. Default: \"" << DEFAULT_KNI_NAME << "\"" - << std::endl - << " -p --port PORT : Port for communication. Default: " << DEFAULT_PORT << std::endl - << " -v --version : Displays the current version and exits" << std::endl - << " -h --help : Displays this help message and exits" << std::endl - << std::endl; + << '\n' + << " -p --port PORT : Port for communication. Default: " << DEFAULT_PORT << '\n' + << " -v --version : Displays the current version and exits" << '\n' + << " -h --help : Displays this help message and exits" << '\n' + << '\n'; } inline void parseArgs(int argc, char* argv[], KniPongArgs& args) @@ -164,7 +164,9 @@ namespace } // Default name for KNI device: if (args.kniName.empty()) + { args.kniName = DEFAULT_KNI_NAME; + } if (args.kniIp.empty()) { printUsage(); @@ -207,27 +209,27 @@ namespace */ struct KniDummyCallbacks { - static int changeMtuNew(uint16_t, unsigned int) + static int changeMtuNew(uint16_t /*unused*/, unsigned int /*unused*/) { return 0; } - static int changeMtuOld(uint8_t, unsigned int) + static int changeMtuOld(uint8_t /*unused*/, unsigned int /*unused*/) { return 0; } - static int configNetworkIfNew(uint16_t, uint8_t) + static int configNetworkIfNew(uint16_t /*unused*/, uint8_t /*unused*/) { return 0; } - static int configNetworkIfOld(uint8_t, uint8_t) + static int configNetworkIfOld(uint8_t /*unused*/, uint8_t /*unused*/) { return 0; } - static int configMacAddress(uint16_t, uint8_t[]) + static int configMacAddress(uint16_t /*unused*/, uint8_t /*unused*/[]) { return 0; } - static int configPromiscusity(uint16_t, uint8_t) + static int configPromiscusity(uint16_t /*unused*/, uint8_t /*unused*/) { return 0; } @@ -251,17 +253,17 @@ namespace /** * Setup IP of net device by calling the ip unix utility */ - inline bool setKniIp(const pcpp::IPv4Address& ip, const std::string& kniName) + inline bool setKniIp(const pcpp::IPv4Address& ipAddr, const std::string& kniName) { std::ostringstream command; - command << "ip a add " << ip << "/24 dev " << kniName; + command << "ip a add " << ipAddr << "/24 dev " << kniName; pcpp::executeShellCommand(command.str()); command.str(""); - command << "ip a | grep " << ip; + command << "ip a | grep " << ipAddr; try { - std::string result = pcpp::executeShellCommand(command.str()); - return result != ""; + const std::string result = pcpp::executeShellCommand(command.str()); + return !result.empty(); } catch (const std::runtime_error&) { @@ -276,12 +278,14 @@ namespace { { // Setup DPDK - pcpp::CoreMask cm = 0x3; - bool dpdkInitSuccess = pcpp::DpdkDeviceList::initDpdk(cm, 1023); + const pcpp::CoreMask cMask = 0x3; + const bool dpdkInitSuccess = pcpp::DpdkDeviceList::initDpdk(cMask, 1023); if (!dpdkInitSuccess) + { EXIT_WITH_ERROR("Failed to init DPDK"); + } } - pcpp::IPv4Address kniIp = args.kniIp; + const pcpp::IPv4Address kniIp = args.kniIp; // Setup device config pcpp::KniDevice* device = nullptr; pcpp::KniDevice::KniDeviceConfiguration devConfig; @@ -298,23 +302,37 @@ namespace devConfig.bindKthread = false; pcpp::KniDeviceList& kniDeviceList = pcpp::KniDeviceList::getInstance(); if (!kniDeviceList.isInitialized()) + { EXIT_WITH_ERROR("Can't initialize KNI device list"); + } device = kniDeviceList.createDevice(devConfig, 1024); if (device == nullptr) + { EXIT_WITH_ERROR("Can't create KNI device"); + } // Check KNI device and start request thread if (!device->isInitialized()) + { EXIT_WITH_ERROR("KNI device was not initialized correctly"); + } if (!device->open()) + { EXIT_WITH_ERROR("Could not open KNI device"); + } if (!device->startRequestHandlerThread(0, 500000000)) + { EXIT_WITH_ERROR("Could not start KNI device request handler thread"); + } // Assign IP if (!setKniIp(kniIp, args.kniName)) + { EXIT_WITH_ERROR("Can't set KNI device IP"); + } // Turn device on for Linux Kernel if (!device->setLinkState(pcpp::KniDevice::LINK_UP)) + { EXIT_WITH_ERROR("Can't set KNI device link state to UP"); + } return device; } @@ -323,27 +341,24 @@ namespace */ inline LinuxSocket setupLinuxSocket(const KniPongArgs& args) { // Open socket - enum - { - INVALID_FD = -1 - }; - LinuxSocket sock; + constexpr auto INVALID_FD = -1; + LinuxSocket sock{}; if ((sock.m_Socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_FD) { - int old_errno = errno; - EXIT_WITH_ERROR("Could not open socket" << std::endl << "Errno: " << std::strerror(old_errno)); + const int old_errno = errno; + EXIT_WITH_ERROR("Could not open socket" << '\n' << "Errno: " << std::strerror(old_errno)); } // Bind socket to KNI device IP - struct sockaddr_in egress; + struct sockaddr_in egress{}; std::memset(&egress, 0, sizeof(egress)); egress.sin_family = AF_INET; egress.sin_addr.s_addr = inet_addr(args.kniIp.c_str()); egress.sin_port = pcpp::hostToNet16(args.kniPort); - if (bind(sock, (struct sockaddr*)&egress, sizeof(egress)) == -1) + if (bind(sock, reinterpret_cast(&egress), sizeof(egress)) == -1) { - int old_errno = errno; + const int old_errno = errno; close(sock); - EXIT_WITH_ERROR("Could not bind socket" << std::endl << "Errno: " << std::strerror(old_errno)); + EXIT_WITH_ERROR("Could not bind socket" << '\n' << "Errno: " << std::strerror(old_errno)); } return sock; @@ -354,9 +369,9 @@ namespace */ inline void processArp(pcpp::Packet& packet, pcpp::ArpLayer* arpLayer) { - pcpp::MacAddress rndMac("00:42:43:74:11:54"); + const pcpp::MacAddress rndMac("00:42:43:74:11:54"); pcpp::EthLayer* ethernetLayer = nullptr; - pcpp::arphdr arpHdr; + pcpp::arphdr arpHdr{}; pcpp::arphdr* origArpHdr = arpLayer->getArpHeader(); // Copy ARP request std::memcpy(&arpHdr, origArpHdr, sizeof(arpHdr)); @@ -375,7 +390,7 @@ namespace // Setup Ethernet addresses in Ethernet layer ethernetLayer = packet.getLayerOfType(); - pcpp::ether_header ethHdr; + pcpp::ether_header ethHdr{}; pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); std::memcpy(ethHdr.dstMac, origEthHdr->srcMac, sizeof(ethHdr.dstMac)); @@ -394,7 +409,7 @@ namespace pcpp::IPv4Layer* ipLayer = nullptr; ethernetLayer = packet.getLayerOfType(); - pcpp::ether_header ethHdr; + pcpp::ether_header ethHdr{}; pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); // Swap MACs for Ethernet layer @@ -403,23 +418,27 @@ namespace std::memcpy(origEthHdr, ðHdr, sizeof(ethHdr)); ipLayer = packet.getLayerOfType(); - if (ipLayer == nullptr) // Some invalid packet + if (ipLayer == nullptr) + { // Some invalid packet return false; - pcpp::iphdr ipHdr; + } + pcpp::iphdr ipHdr{}; pcpp::iphdr* origIpHdr = ipLayer->getIPv4Header(); std::memcpy(&ipHdr, origIpHdr, sizeof(ipHdr)); - if (pcpp::netToHost16(ipHdr.fragmentOffset) & 0x1FFF) // Fragmented packet + if ((pcpp::netToHost16(ipHdr.fragmentOffset) & 0x1FFF) != 0) + { // Fragmented packet return false; + } // Swap src and dst IPs std::memcpy(&ipHdr.ipSrc, &origIpHdr->ipDst, sizeof(ipHdr.ipSrc)); std::memcpy(&ipHdr.ipDst, &origIpHdr->ipSrc, sizeof(ipHdr.ipDst)); // Randomize IP id - ipHdr.ipId = std::rand() & 0xFFFF; + ipHdr.ipId = std::rand() & 0xFFFF; // NOLINT(cert-msc30-c,cert-msc50-cpp) // Set by RFC791 ipHdr.timeToLive = 64; std::memcpy(origIpHdr, &ipHdr, sizeof(ipHdr)); - pcpp::udphdr udpHdr; + pcpp::udphdr udpHdr{}; pcpp::udphdr* origUdpHdr = udpLayer->getUdpHeader(); std::memcpy(&udpHdr, origUdpHdr, sizeof(udpHdr)); // Swap src and dst ports @@ -438,7 +457,7 @@ namespace */ bool processBurst(pcpp::MBufRawPacket packets[], uint32_t numOfPackets, pcpp::KniDevice* kni, void* cookie) { - PacketStats* packetStats = (PacketStats*)cookie; + auto* packetStats = reinterpret_cast(cookie); pcpp::Packet packet; pcpp::ArpLayer* arpLayer = nullptr; pcpp::UdpLayer* udpLayer = nullptr; @@ -453,7 +472,9 @@ namespace processArp(packet, arpLayer); // Packet is ready to be sent -> have no fields to recalculate if (!kni->sendPacket(packet)) + { ++packetStats->arpPacketsOutFail; + } arpLayer = nullptr; continue; } @@ -463,7 +484,9 @@ namespace ++packetStats->udpPacketsIn; //! Warning (echo-Mike): DO NOT normalize next logic statement it relays on short circuiting if (!processUdp(packet, udpLayer) || !kni->sendPacket(packet)) + { ++packetStats->udpPacketsOutFail; + } udpLayer = nullptr; continue; } @@ -479,55 +502,65 @@ namespace */ void connectUDPSocket(const LinuxSocket& sock, const KniPongArgs& args) { - struct sockaddr_in ingress; + struct sockaddr_in ingress{}; std::memset(&ingress, 0, sizeof(ingress)); ingress.sin_family = AF_INET; ingress.sin_addr.s_addr = inet_addr(args.outIp.c_str()); ingress.sin_port = pcpp::hostToNet16(args.kniPort); - if (connect(sock, (struct sockaddr*)&ingress, sizeof(ingress)) == -1) + if (connect(sock, reinterpret_cast(&ingress), sizeof(ingress)) == -1) { - int old_errno = errno; + const int old_errno = errno; close(sock); - EXIT_WITH_ERROR("Could not connect socket" << std::endl << "Errno: " << std::strerror(old_errno)); + EXIT_WITH_ERROR("Could not connect socket" << '\n' << "Errno: " << std::strerror(old_errno)); } } /** * Reworked fillbuf from netcat. See description in pingPongProcess */ - ssize_t fillbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) + ssize_t fillbuf(linuxFd fDesc, unsigned char buff[], size_t& buffPos) { - size_t num = IO_BUFF_SIZE - buffPos; - ssize_t n; - - n = read(fd, buff + buffPos, num); - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = WANT_POLLIN; - if (n <= 0) - return n; - buffPos += n; - return n; + const size_t num = IO_BUFF_SIZE - buffPos; + ssize_t nSize = 0; + + nSize = read(fDesc, buff + buffPos, num); + if (nSize == -1 && (errno == EAGAIN || errno == EINTR)) + { + nSize = WANT_POLLIN; + } + if (nSize <= 0) + { + return nSize; + } + buffPos += nSize; + return nSize; } /** * Reworked drainbuf from netcat. See description in pingPongProcess */ - ssize_t drainbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) + ssize_t drainbuf(linuxFd fDesc, unsigned char buff[], size_t& buffPos) { - ssize_t n; - ssize_t adjust; - - n = write(fd, buff, buffPos); - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = WANT_POLLOUT; - if (n <= 0) - return n; + ssize_t nSize = 0; + ssize_t adjust = 0; + + nSize = write(fDesc, buff, buffPos); + if (nSize == -1 && (errno == EAGAIN || errno == EINTR)) + { + nSize = WANT_POLLOUT; + } + if (nSize <= 0) + { + return nSize; + } /* adjust buffer */ - adjust = buffPos - n; + adjust = static_cast(buffPos) - nSize; if (adjust > 0) - std::memmove(buff, buff + n, adjust); - buffPos -= n; - return n; + { + std::memmove(buff, buff + nSize, adjust); + } + buffPos -= nSize; + return nSize; } /** @@ -545,14 +578,16 @@ namespace { struct pollfd pfd[4]; - const int POLL_STDIN = 0, POLL_NETOUT = 1, POLL_NETIN = 2, POLL_STDOUT = 3; + const int POLL_STDIN = 0; + const int POLL_NETOUT = 1; + const int POLL_NETIN = 2; + const int POLL_STDOUT = 3; const int DEFAULT_POLL_TIMEOUT = 3000; // milisec unsigned char netbuff[IO_BUFF_SIZE]; size_t netbuffPos = 0; unsigned char ttybuff[IO_BUFF_SIZE]; size_t ttybuffPos = 0; - int n; - ssize_t ret; + ssize_t ret = 0; /* stdin */ pfd[POLL_STDIN].fd = STDIN_FILENO; @@ -567,7 +602,7 @@ namespace pfd[POLL_STDOUT].fd = STDOUT_FILENO; pfd[POLL_STDOUT].events = 0; - while (doContinue) + while (doContinue != 0) { /* both inputs are gone, buffers are empty, we are done */ if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 && ttybuffPos == 0 && netbuffPos == 0) @@ -576,19 +611,21 @@ namespace } /* both outputs are gone, we can't continue */ if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) + { return; + } /* poll */ - int num_fds = poll(pfd, 4, DEFAULT_POLL_TIMEOUT); + const int num_fds = poll(pfd, 4, DEFAULT_POLL_TIMEOUT); /* treat poll errors */ if (num_fds == -1) { - int old_errno = errno; + const int old_errno = errno; if (old_errno != EINTR) { close(sock); - EXIT_WITH_ERROR("poll returned an error" << std::endl << "Errno: " << std::strerror(old_errno)); + EXIT_WITH_ERROR("poll returned an error" << '\n' << "Errno: " << std::strerror(old_errno)); } continue; } @@ -599,82 +636,108 @@ namespace } /* treat socket error conditions */ - for (n = 0; n < 4; ++n) + for (auto& req : pfd) { - if (pfd[n].revents & (POLLERR | POLLNVAL)) + if ((req.revents & (POLLERR | POLLNVAL)) != 0) { - pfd[n].fd = -1; + req.fd = -1; } } /* reading is possible after HUP */ - if (pfd[POLL_STDIN].events & POLLIN && pfd[POLL_STDIN].revents & POLLHUP && - !(pfd[POLL_STDIN].revents & POLLIN)) + if (((pfd[POLL_STDIN].events & POLLIN) != 0) && ((pfd[POLL_STDIN].revents & POLLHUP) != 0) && + ((pfd[POLL_STDIN].revents & POLLIN) == 0)) { pfd[POLL_STDIN].fd = -1; } - if (pfd[POLL_NETIN].events & POLLIN && pfd[POLL_NETIN].revents & POLLHUP && - !(pfd[POLL_NETIN].revents & POLLIN)) + if (((pfd[POLL_NETIN].events & POLLIN) != 0) && ((pfd[POLL_NETIN].revents & POLLHUP) != 0) && + ((pfd[POLL_NETIN].revents & POLLIN) == 0)) { pfd[POLL_NETIN].fd = -1; } - if (pfd[POLL_NETOUT].revents & POLLHUP) + if ((pfd[POLL_NETOUT].revents & POLLHUP) != 0) { pfd[POLL_NETOUT].fd = -1; } /* if HUP, stop watching stdout */ - if (pfd[POLL_STDOUT].revents & POLLHUP) + if ((pfd[POLL_STDOUT].revents & POLLHUP) != 0) + { pfd[POLL_STDOUT].fd = -1; + } /* if no net out, stop watching stdin */ if (pfd[POLL_NETOUT].fd == -1) + { pfd[POLL_STDIN].fd = -1; + } /* if no stdout, stop watching net in */ if (pfd[POLL_STDOUT].fd == -1) { if (pfd[POLL_NETIN].fd != -1) + { shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + } pfd[POLL_NETIN].fd = -1; } /* try to read from stdin */ - if (pfd[POLL_STDIN].revents & POLLIN && ttybuffPos < IO_BUFF_SIZE) + if (((pfd[POLL_STDIN].revents & POLLIN) != 0) && ttybuffPos < IO_BUFF_SIZE) { ret = fillbuf(pfd[POLL_STDIN].fd, ttybuff, ttybuffPos); if (ret == WANT_POLLIN) + { pfd[POLL_STDIN].events = POLLIN; + } else if (ret == 0 || ret == -1) + { pfd[POLL_STDIN].fd = -1; + } /* read something - poll net out */ if (ttybuffPos > 0) + { pfd[POLL_NETOUT].events = POLLOUT; + } /* filled buffer - remove self from polling */ if (ttybuffPos == IO_BUFF_SIZE) + { pfd[POLL_STDIN].events = 0; + } } /* try to write to network */ - if (pfd[POLL_NETOUT].revents & POLLOUT && ttybuffPos > 0) + if (((pfd[POLL_NETOUT].revents & POLLOUT) != 0) && ttybuffPos > 0) { ret = drainbuf(pfd[POLL_NETOUT].fd, ttybuff, ttybuffPos); if (ret == WANT_POLLOUT) + { pfd[POLL_NETOUT].events = POLLOUT; + } else if (ret == -1) + { pfd[POLL_NETOUT].fd = -1; + } /* buffer empty - remove self from polling */ if (ttybuffPos == 0) + { pfd[POLL_NETOUT].events = 0; + } /* buffer no longer full - poll stdin again */ if (ttybuffPos < IO_BUFF_SIZE) + { pfd[POLL_STDIN].events = POLLIN; + } } /* try to read from network */ - if (pfd[POLL_NETIN].revents & POLLIN && netbuffPos < IO_BUFF_SIZE) + if (((pfd[POLL_NETIN].revents & POLLIN) != 0) && netbuffPos < IO_BUFF_SIZE) { ret = fillbuf(pfd[POLL_NETIN].fd, netbuff, netbuffPos); if (ret == WANT_POLLIN) + { pfd[POLL_NETIN].events = POLLIN; + } else if (ret == -1) + { pfd[POLL_NETIN].fd = -1; + } /* eof on net in - remove from pfd */ if (ret == 0) { @@ -683,25 +746,37 @@ namespace } /* read something - poll stdout */ if (netbuffPos > 0) + { pfd[POLL_STDOUT].events = POLLOUT; + } /* filled buffer - remove self from polling */ if (netbuffPos == IO_BUFF_SIZE) + { pfd[POLL_NETIN].events = 0; + } } /* try to write to stdout */ - if (pfd[POLL_STDOUT].revents & POLLOUT && netbuffPos > 0) + if (((pfd[POLL_STDOUT].revents & POLLOUT) != 0) && netbuffPos > 0) { ret = drainbuf(pfd[POLL_STDOUT].fd, netbuff, netbuffPos); if (ret == WANT_POLLOUT) + { pfd[POLL_STDOUT].events = POLLOUT; + } else if (ret == -1) + { pfd[POLL_STDOUT].fd = -1; + } /* buffer empty - remove self from polling */ if (netbuffPos == 0) + { pfd[POLL_STDOUT].events = 0; + } /* buffer no longer full - poll net in again */ if (netbuffPos < IO_BUFF_SIZE) + { pfd[POLL_NETIN].events = POLLIN; + } } /* stdin gone and queue empty? */ @@ -719,9 +794,9 @@ namespace } // namespace -extern "C" void signal_handler(int) +extern "C" void signal_handler(int /*unused*/) { - doContinue = false; + doContinue = 0; } /** @@ -729,36 +804,36 @@ extern "C" void signal_handler(int) */ int main(int argc, char* argv[]) { - PacketStats packetStats; + PacketStats packetStats{}; std::memset(&packetStats, 0, sizeof(packetStats)); KniPongArgs args; - std::srand(std::time(nullptr)); + std::srand(std::time(nullptr)); // NOLINT(cert-msc32-c,cert-msc51-cpp) pcpp::AppName::init(argc, argv); parseArgs(argc, argv, args); pcpp::KniDevice* device = setupKniDevice(args); - LinuxSocket sock = setupLinuxSocket(args); + const LinuxSocket sock = setupLinuxSocket(args); if (!device->startCapture(processBurst, &packetStats)) { close(sock); EXIT_WITH_ERROR("Could not start capture thread on KNI device"); } connectUDPSocket(sock, args); - std::signal(SIGINT, signal_handler); - std::cout << "Ready for input:" << std::endl; + static_cast(std::signal(SIGINT, signal_handler)); + std::cout << "Ready for input:" << '\n'; pingPongProcess(sock); //! Close socket before device close(sock); device->stopCapture(); device->close(); device->stopRequestHandlerThread(); - std::cout << std::endl - << std::endl - << "Packet statistics from KNI thread:" << std::endl - << " Total packets met: " << packetStats.totalPackets << std::endl - << " UDP packets met: " << packetStats.udpPacketsIn << std::endl - << " Failed PONG packets: " << packetStats.udpPacketsOutFail << std::endl - << " ARP packets met: " << packetStats.arpPacketsIn << std::endl - << " Failed ARP replay packets: " << packetStats.arpPacketsOutFail << std::endl - << std::endl; + std::cout << '\n' + << '\n' + << "Packet statistics from KNI thread:" << '\n' + << " Total packets met: " << packetStats.totalPackets << '\n' + << " UDP packets met: " << packetStats.udpPacketsIn << '\n' + << " Failed PONG packets: " << packetStats.udpPacketsOutFail << '\n' + << " ARP packets met: " << packetStats.arpPacketsIn << '\n' + << " Failed ARP replay packets: " << packetStats.arpPacketsOutFail << '\n' + << '\n'; return 0; } diff --git a/Examples/PcapPlusPlus-benchmark/benchmark-google.cpp b/Examples/PcapPlusPlus-benchmark/benchmark-google.cpp index e12ccc30e6..e1a5c79203 100644 --- a/Examples/PcapPlusPlus-benchmark/benchmark-google.cpp +++ b/Examples/PcapPlusPlus-benchmark/benchmark-google.cpp @@ -12,7 +12,7 @@ #include -static std::string pcapFileName = ""; +static std::string pcapFileName; static void BM_PcapFileRead(benchmark::State& state) { @@ -24,10 +24,10 @@ static void BM_PcapFileRead(benchmark::State& state) return; } - size_t totalBytes = 0; - size_t totalPackets = 0; + int64_t totalBytes = 0; + int64_t totalPackets = 0; pcpp::RawPacket rawPacket; - for (auto _ : state) + for (auto unused : state) { if (!reader.getNextPacket(rawPacket)) { @@ -75,9 +75,9 @@ static void BM_PcapFileWrite(benchmark::State& state) packet.addLayer(&tcpLayer); packet.computeCalculateFields(); - size_t totalBytes = 0; - size_t totalPackets = 0; - for (auto _ : state) + int64_t totalBytes = 0; + int64_t totalPackets = 0; + for (auto unused : state) { // Write packet to file writer.writePacket(*(packet.getRawPacket())); @@ -96,8 +96,8 @@ BENCHMARK(BM_PcapFileWrite); static void BM_PacketParsing(benchmark::State& state) { // Open the pcap file for reading - size_t totalBytes = 0; - size_t totalPackets = 0; + int64_t totalBytes = 0; + int64_t totalPackets = 0; pcpp::PcapFileReaderDevice reader(pcapFileName); if (!reader.open()) { @@ -106,7 +106,7 @@ static void BM_PacketParsing(benchmark::State& state) } pcpp::RawPacket rawPacket; - for (auto _ : state) + for (auto unused : state) { if (!reader.getNextPacket(rawPacket)) { @@ -126,7 +126,7 @@ static void BM_PacketParsing(benchmark::State& state) } // Parse packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // Use parsedPacket to prevent compiler optimizations assert(parsedPacket.getFirstLayer()); @@ -144,37 +144,40 @@ BENCHMARK(BM_PacketParsing); static void BM_PacketCrafting(benchmark::State& state) { - size_t totalBytes = 0; - size_t totalPackets = 0; + int64_t totalBytes = 0; + int64_t totalPackets = 0; - for (auto _ : state) + for (auto unused : state) { - uint8_t randNum = static_cast(rand() % 256); + // NOLINTNEXTLINE(cert-msc30-c,cert-msc50-cpp) + const auto randNum = static_cast(rand() % 256); // sufficient randomness for example pcpp::Packet packet; // Generate random MAC addresses - pcpp::MacAddress srcMac(randNum, randNum, randNum, randNum, randNum, randNum); - pcpp::MacAddress dstMac(randNum, randNum, randNum, randNum, randNum, randNum); + const pcpp::MacAddress srcMac(randNum, randNum, randNum, randNum, randNum, randNum); + const pcpp::MacAddress dstMac(randNum, randNum, randNum, randNum, randNum, randNum); packet.addLayer(new pcpp::EthLayer(srcMac, dstMac), true); // Randomly choose between IPv4 and IPv6 - if (randNum % 2) + if ((randNum % 2) != 0) { packet.addLayer(new pcpp::IPv4Layer(randNum, randNum), true); } else { - std::array srcIP = { randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum, - randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum }; - std::array dstIP = { randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum, - randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum }; + const std::array srcIP = { randNum, randNum, randNum, randNum, randNum, randNum, + randNum, randNum, randNum, randNum, randNum, randNum, + randNum, randNum, randNum, randNum }; + const std::array dstIP = { randNum, randNum, randNum, randNum, randNum, randNum, + randNum, randNum, randNum, randNum, randNum, randNum, + randNum, randNum, randNum, randNum }; packet.addLayer(new pcpp::IPv6Layer(srcIP, dstIP), true); } // Randomly choose between TCP and UDP - if (randNum % 2) + if ((randNum % 2) != 0) { packet.addLayer(new pcpp::TcpLayer(randNum % 65536, randNum % 65536), true); } @@ -209,7 +212,7 @@ int main(int argc, char** argv) { if (idx == argc - 1) { - std::cerr << "Please provide a pcap file name after --pcap-file" << std::endl; + std::cerr << "Please provide a pcap file name after --pcap-file" << '\n'; return 1; } @@ -220,7 +223,7 @@ int main(int argc, char** argv) if (pcapFileName.empty()) { - std::cerr << "Please provide a pcap file name using --pcap-file" << std::endl; + std::cerr << "Please provide a pcap file name using --pcap-file" << '\n'; return 1; } diff --git a/Examples/PcapPlusPlus-benchmark/benchmark.cpp b/Examples/PcapPlusPlus-benchmark/benchmark.cpp index 96c77ca63f..4889633935 100644 --- a/Examples/PcapPlusPlus-benchmark/benchmark.cpp +++ b/Examples/PcapPlusPlus-benchmark/benchmark.cpp @@ -30,9 +30,11 @@ size_t count = 0; bool handle_dns(Packet& packet) { if (!packet.isPacketOfType(DNS)) + { return true; + } - DnsLayer* dnsLayer = packet.getLayerOfType(); + auto* dnsLayer = packet.getLayerOfType(); DnsQuery* query = dnsLayer->getFirstQuery(); while (query != nullptr) @@ -51,7 +53,7 @@ bool handle_dns(Packet& packet) return true; } -bool handle_packet(Packet& packet) +bool handle_packet(Packet& /*packet*/) { count++; return true; @@ -64,8 +66,8 @@ int main(int argc, char* argv[]) std::cout << "Usage: " << *argv << " \n"; return 1; } - std::string input_type(argv[2]); - int total_runs = std::stoi(argv[3]); + const std::string input_type(argv[2]); + const int total_runs = std::stoi(argv[3]); size_t total_packets = 0; std::vector durations; for (int i = 0; i < total_runs; ++i) @@ -105,5 +107,5 @@ int main(int argc, char* argv[]) using std::chrono::duration_cast; using std::chrono::milliseconds; auto total_time_in_ms = duration_cast(total_time).count(); - std::cout << (total_packets / total_runs) << " " << (total_time_in_ms / durations.size()) << std::endl; + std::cout << (total_packets / total_runs) << " " << (total_time_in_ms / durations.size()) << '\n'; } diff --git a/Examples/PcapPrinter/main.cpp b/Examples/PcapPrinter/main.cpp index e1d9d7a8f5..f4690bc29e 100644 --- a/Examples/PcapPrinter/main.cpp +++ b/Examples/PcapPrinter/main.cpp @@ -34,7 +34,7 @@ static struct option PcapPrinterOptions[] = { do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -43,22 +43,22 @@ static struct option PcapPrinterOptions[] = { */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " pcap_file [-h] [-v] [-o output_file] [-c packet_count] [-i filter] [-s]" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " pcap_file : Input pcap/pcapng file name" << std::endl - << " -o output_file : Save output to text file (default output is stdout)" << std::endl - << " -c packet_count: Print only first packet_count number of packet" << std::endl - << " -i filter : Apply a BPF filter, meaning only filtered packets will be printed" << std::endl - << " -s : Print only file summary and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " pcap_file : Input pcap/pcapng file name" << '\n' + << " -o output_file : Save output to text file (default output is stdout)" << '\n' + << " -c packet_count: Print only first packet_count number of packet" << '\n' + << " -i filter : Apply a BPF filter, meaning only filtered packets will be printed" << '\n' + << " -s : Print only file summary and exit" << '\n' + << " -v : Display the current version and exit" << '\n' + << " -h : Display this help message and exit" << '\n' + << '\n'; } /** @@ -66,9 +66,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -76,17 +76,26 @@ std::string linkLayerToString(pcpp::LinkLayerType linkLayer) { if (linkLayer == pcpp::LINKTYPE_ETHERNET) + { return "Ethernet"; + } if (linkLayer == pcpp::LINKTYPE_IEEE802_5) + { return "IEEE 802.5 Token Ring"; - else if (linkLayer == pcpp::LINKTYPE_LINUX_SLL) + } + if (linkLayer == pcpp::LINKTYPE_LINUX_SLL) + { return "Linux cooked capture"; - else if (linkLayer == pcpp::LINKTYPE_LINUX_SLL2) + } + if (linkLayer == pcpp::LINKTYPE_LINUX_SLL2) + { return "Linux cooked capture v2"; - else if (linkLayer == pcpp::LINKTYPE_NULL) + } + if (linkLayer == pcpp::LINKTYPE_NULL) + { return "Null/Loopback"; - else if (linkLayer == pcpp::LINKTYPE_RAW || linkLayer == pcpp::LINKTYPE_DLT_RAW1 || - linkLayer == pcpp::LINKTYPE_DLT_RAW2) + } + if (linkLayer == pcpp::LINKTYPE_RAW || linkLayer == pcpp::LINKTYPE_DLT_RAW1 || linkLayer == pcpp::LINKTYPE_DLT_RAW2) { std::ostringstream stream; stream << "Raw IP (" << linkLayer << ")"; @@ -104,40 +113,48 @@ std::string linkLayerToString(pcpp::LinkLayerType linkLayer) std::string printFileSummary(pcpp::IFileReaderDevice* reader) { std::ostringstream stream; - stream << "File summary:" << std::endl; - stream << "~~~~~~~~~~~~~" << std::endl; - stream << " File name: " << reader->getFileName() << std::endl; - stream << " File size: " << reader->getFileSize() << " bytes" << std::endl; + stream << "File summary:" << '\n'; + stream << "~~~~~~~~~~~~~" << '\n'; + stream << " File name: " << reader->getFileName() << '\n'; + stream << " File size: " << reader->getFileSize() << " bytes" << '\n'; if (dynamic_cast(reader) != nullptr) { - pcpp::PcapFileReaderDevice* pcapReader = dynamic_cast(reader); - pcpp::LinkLayerType linkLayer = pcapReader->getLinkLayerType(); - stream << " Link layer type: " << linkLayerToString(linkLayer) << std::endl; + auto* pcapReader = dynamic_cast(reader); + const pcpp::LinkLayerType linkLayer = pcapReader->getLinkLayerType(); + stream << " Link layer type: " << linkLayerToString(linkLayer) << '\n'; } else if (dynamic_cast(reader) != nullptr) { - pcpp::SnoopFileReaderDevice* snoopReader = dynamic_cast(reader); - pcpp::LinkLayerType linkLayer = snoopReader->getLinkLayerType(); - stream << " Link layer type: " << linkLayerToString(linkLayer) << std::endl; + auto* snoopReader = dynamic_cast(reader); + const pcpp::LinkLayerType linkLayer = snoopReader->getLinkLayerType(); + stream << " Link layer type: " << linkLayerToString(linkLayer) << '\n'; } else if (dynamic_cast(reader) != nullptr) { - pcpp::PcapNgFileReaderDevice* pcapNgReader = dynamic_cast(reader); - if (pcapNgReader->getOS() != "") - stream << " OS: " << pcapNgReader->getOS() << std::endl; + auto* pcapNgReader = dynamic_cast(reader); + if (!pcapNgReader->getOS().empty()) + { + stream << " OS: " << pcapNgReader->getOS() << '\n'; + } - if (pcapNgReader->getCaptureApplication() != "") - stream << " Capture application: " << pcapNgReader->getCaptureApplication() << std::endl; + if (!pcapNgReader->getCaptureApplication().empty()) + { + stream << " Capture application: " << pcapNgReader->getCaptureApplication() << '\n'; + } - if (pcapNgReader->getCaptureFileComment() != "") - stream << " File comment: " << pcapNgReader->getCaptureFileComment() << std::endl; + if (!pcapNgReader->getCaptureFileComment().empty()) + { + stream << " File comment: " << pcapNgReader->getCaptureFileComment() << '\n'; + } - if (pcapNgReader->getHardware() != "") - stream << " Capture hardware: " << pcapNgReader->getHardware() << std::endl; + if (!pcapNgReader->getHardware().empty()) + { + stream << " Capture hardware: " << pcapNgReader->getHardware() << '\n'; + } } - stream << std::endl; + stream << '\n'; return stream.str(); } @@ -153,10 +170,10 @@ int printPcapPackets(pcpp::IFileReaderDevice* reader, std::ostream* out, int pac while (reader->getNextPacket(rawPacket) && packetCountSoFar != packetCount) { // parse the raw packet into a parsed packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // print packet to string - (*out) << parsedPacket.toString() << std::endl; + (*out) << parsedPacket.toString() << '\n'; packetCountSoFar++; } @@ -173,19 +190,21 @@ int printPcapNgPackets(pcpp::PcapNgFileReaderDevice* reader, std::ostream* out, // read packets from the file until end-of-file or until reached user requested packet count int packetCountSoFar = 0; pcpp::RawPacket rawPacket; - std::string packetComment = ""; + std::string packetComment; while (reader->getNextPacket(rawPacket, packetComment) && packetCountSoFar != packetCount) { // print packet comment if exists - if (packetComment != "") - (*out) << "Packet Comment: " << packetComment << std::endl; + if (!packetComment.empty()) + { + (*out) << "Packet Comment: " << packetComment << '\n'; + } // parse the raw packet into a parsed packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // print packet to string - (*out) << "Link layer type: " << linkLayerToString(rawPacket.getLinkLayerType()) << std::endl; - (*out) << parsedPacket.toString() << std::endl; + (*out) << "Link layer type: " << linkLayerToString(rawPacket.getLinkLayerType()) << '\n'; + (*out) << parsedPacket.toString() << '\n'; packetCountSoFar++; } @@ -201,10 +220,10 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - std::string inputPcapFileName = ""; - std::string outputPcapFileName = ""; + std::string inputPcapFileName; + std::string outputPcapFileName; - std::string filter = ""; + std::string filter; bool printOnlySummary = false; @@ -223,7 +242,7 @@ int main(int argc, char* argv[]) outputPcapFileName = optarg; break; case 'c': - packetCount = atoi(optarg); + packetCount = std::stoi(optarg); break; case 'i': filter = optarg; @@ -249,20 +268,20 @@ int main(int argc, char* argv[]) inputPcapFileName = argv[optind]; } - if (inputPcapFileName == "") + if (inputPcapFileName.empty()) { EXIT_WITH_ERROR("Input file name was not given"); } // write to output file if provided, otherwise output to cout - std::ofstream of; + std::ofstream ofs; std::ostream* out = &std::cout; - if (outputPcapFileName != "") + if (!outputPcapFileName.empty()) { - of.open(outputPcapFileName.c_str()); - out = &of; + ofs.open(outputPcapFileName.c_str()); + out = &ofs; } // open a pcap/pcapng file for reading @@ -275,7 +294,7 @@ int main(int argc, char* argv[]) } // set a filter if provided - if (filter != "") + if (!filter.empty()) { if (!reader->setFilter(filter)) { @@ -300,24 +319,24 @@ int main(int argc, char* argv[]) if (dynamic_cast(reader) != nullptr) { // print all requested packets in the pcap file - pcpp::PcapFileReaderDevice* pcapReader = dynamic_cast(reader); + auto* pcapReader = dynamic_cast(reader); printedPacketCount = printPcapPackets(pcapReader, out, packetCount); } else if (dynamic_cast(reader) != nullptr) { // print all requested packets in the pcap file - pcpp::SnoopFileReaderDevice* snoopReader = dynamic_cast(reader); + auto* snoopReader = dynamic_cast(reader); printedPacketCount = printPcapPackets(snoopReader, out, packetCount); } // if the file is a pcap-ng file else if (dynamic_cast(reader) != nullptr) { // print all requested packets in the pcap-ng file - pcpp::PcapNgFileReaderDevice* pcapNgReader = dynamic_cast(reader); + auto* pcapNgReader = dynamic_cast(reader); printedPacketCount = printPcapNgPackets(pcapNgReader, out, packetCount); } - (*out) << "Finished. Printed " << printedPacketCount << " packets" << std::endl; + (*out) << "Finished. Printed " << printedPacketCount << " packets" << '\n'; // close the file reader->close(); diff --git a/Examples/PcapSearch/main.cpp b/Examples/PcapSearch/main.cpp index f1af7e64d5..ffc30e3a7b 100644 --- a/Examples/PcapSearch/main.cpp +++ b/Examples/PcapSearch/main.cpp @@ -62,7 +62,7 @@ static struct option PcapSearchOptions[] = { do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -77,30 +77,30 @@ static struct option PcapSearchOptions[] = { */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() - << " [-h] [-v] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -d directory : Input directory" << std::endl - << " -n : Don't include sub-directories (default is include them)" << std::endl + << " [-h] [-v] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -d directory : Input directory" << '\n' + << " -n : Don't include sub-directories (default is include them)" << '\n' << " -s search_criteria : Criteria to search in Berkeley Packet Filter (BPF) syntax " "(http://biot.com/capstats/bpf.html)" - << std::endl - << " i.e: 'ip net 1.1.1.1'" << std::endl - << " -r file_name : Write a detailed search report to a file" << std::endl + << '\n' + << " i.e: 'ip net 1.1.1.1'" << '\n' + << " -r file_name : Write a detailed search report to a file" << '\n' << " -e extension_list : Set file extensions to search. The default is searching '.pcap' and " "'.pcapng' files." - << std::endl + << '\n' << " extension_list should be a comma-separated list of extensions, for " "example: pcap,net,dmp" - << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n'; } /** @@ -108,9 +108,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -119,7 +119,7 @@ void printAppVersion() */ std::string getExtension(const std::string& fileName) { - return fileName.substr(fileName.find_last_of(".") + 1); + return fileName.substr(fileName.find_last_of('.') + 1); } /** @@ -137,9 +137,9 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: if (detailedReportFile != nullptr) { // PcapPlusPlus logger saves the last internal error. Write this error to the report file - (*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl; + (*detailedReportFile) << "File '" << pcapFilePath << "':" << '\n'; (*detailedReportFile) << " "; - (*detailedReportFile) << pcpp::Logger::getInstance().getLastError() << std::endl; + (*detailedReportFile) << pcpp::Logger::getInstance().getLastError() << '\n'; } // free the reader memory and return @@ -157,7 +157,7 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: if (detailedReportFile != nullptr) { - (*detailedReportFile) << "File '" << pcapFilePath << "':" << std::endl; + (*detailedReportFile) << "File '" << pcapFilePath << "':" << '\n'; } int packetCount = 0; @@ -170,14 +170,16 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: if (detailedReportFile != nullptr) { // parse the packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // print layer by layer by layer as we want to add a few spaces before each layer std::vector packetLayers; parsedPacket.toStringList(packetLayers); for (const auto& layer : packetLayers) + { (*detailedReportFile) << "\n " << layer; - (*detailedReportFile) << std::endl; + } + (*detailedReportFile) << '\n'; } // count the packet read @@ -191,9 +193,11 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: if (detailedReportFile != nullptr) { if (packetCount > 0) + { (*detailedReportFile) << "\n"; + } - (*detailedReportFile) << " ----> Found " << packetCount << " packets" << std::endl << std::endl; + (*detailedReportFile) << " ----> Found " << packetCount << " packets" << '\n' << '\n'; } // free the reader memory @@ -217,7 +221,9 @@ void searchDirectories(const std::string& directory, bool includeSubDirectories, // dir is null usually when user has no access permissions if (dir == nullptr) + { return; + } struct dirent* entry = readdir(dir); @@ -226,17 +232,18 @@ void searchDirectories(const std::string& directory, bool includeSubDirectories, // go over all files in this directory while (entry != nullptr) { - std::string name(entry->d_name); + const std::string name(entry->d_name); // construct directory full path std::string dirPath = directory; - std::string dirSep = DIR_SEPARATOR; - if (0 != directory.compare(directory.length() - dirSep.length(), dirSep.length(), - dirSep)) // directory doesn't contain separator in the end + const std::string dirSep = DIR_SEPARATOR; + if (0 != directory.compare(directory.length() - dirSep.length(), dirSep.length(), dirSep)) + { // directory doesn't contain separator in the end dirPath += DIR_SEPARATOR; + } dirPath += name; - struct stat info; + struct stat info{}; // get file attributes if (stat(dirPath.c_str(), &info) != 0) @@ -246,12 +253,14 @@ void searchDirectories(const std::string& directory, bool includeSubDirectories, } // if the file is not a directory - if (!(info.st_mode & S_IFDIR)) + if ((info.st_mode & S_IFDIR) == 0U) { // check if the file extension matches the requested extensions to search. If it does, put the file name in // a list of files that should be searched (don't do the search just yet) if (extensionsToSearch.find(getExtension(name)) != extensionsToSearch.end()) + { pcapList.push_back(dirPath); + } entry = readdir(dir); continue; } @@ -266,8 +275,10 @@ void searchDirectories(const std::string& directory, bool includeSubDirectories, // if we got to here it means the file is actually a directory. If required to search sub-directories, call this // method recursively to search inside this sub-directory if (includeSubDirectories) + { searchDirectories(dirPath, true, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound); + } // move to the next file entry = readdir(dir); @@ -283,13 +294,13 @@ void searchDirectories(const std::string& directory, bool includeSubDirectories, for (const auto& iter : pcapList) { // do the actual search - int packetsFound = searchPcap(iter, searchCriteria, detailedReportFile); + const int packetsFound = searchPcap(iter, searchCriteria, detailedReportFile); // add to total matched packets totalFilesSearched++; if (packetsFound > 0) { - std::cout << packetsFound << " packets found in '" << iter << "'" << std::endl; + std::cout << packetsFound << " packets found in '" << iter << "'" << '\n'; totalPacketsFound += packetsFound; } } @@ -302,13 +313,13 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - std::string inputDirectory = ""; + std::string inputDirectory; - std::string searchCriteria = ""; + std::string searchCriteria; bool includeSubDirectories = true; - std::string detailedReportFileName = ""; + std::string detailedReportFileName; std::unordered_map extensionsToSearch; @@ -341,7 +352,7 @@ int main(int argc, char* argv[]) { // read the extension list into the map extensionsToSearch.clear(); - std::string extensionsListAsString = std::string(optarg); + const std::string extensionsListAsString = std::string(optarg); std::stringstream stream(extensionsListAsString); std::string extension; // break comma-separated string into string list @@ -349,7 +360,9 @@ int main(int argc, char* argv[]) { // add the extension into the map if it doesn't already exist if (extensionsToSearch.find(extension) == extensionsToSearch.end()) + { extensionsToSearch[extension] = true; + } } // verify list is not empty @@ -371,12 +384,12 @@ int main(int argc, char* argv[]) } } - if (inputDirectory == "") + if (inputDirectory.empty()) { EXIT_WITH_ERROR("Input directory was not given"); } - if (searchCriteria == "") + if (searchCriteria.empty()) { EXIT_WITH_ERROR("Search criteria was not given"); } @@ -397,7 +410,7 @@ int main(int argc, char* argv[]) // open the detailed report file if requested by the user std::ofstream* detailedReportFile = nullptr; - if (detailedReportFileName != "") + if (!detailedReportFileName.empty()) { detailedReportFile = new std::ofstream(); detailedReportFile->open(detailedReportFileName.c_str()); @@ -407,7 +420,7 @@ int main(int argc, char* argv[]) } } - std::cout << "Searching..." << std::endl; + std::cout << "Searching..." << '\n'; int totalDirSearched = 0; int totalFilesSearched = 0; int totalPacketsFound = 0; @@ -417,18 +430,20 @@ int main(int argc, char* argv[]) totalDirSearched, totalFilesSearched, totalPacketsFound); // after search is done, close the report file and delete its instance - std::cout << std::endl - << std::endl + std::cout << '\n' + << '\n' << "Done! Searched " << totalFilesSearched << " files in " << totalDirSearched << " directories, " - << totalPacketsFound << " packets were matched to search criteria" << std::endl; + << totalPacketsFound << " packets were matched to search criteria" << '\n'; if (detailedReportFile != nullptr) { if (detailedReportFile->is_open()) + { detailedReportFile->close(); + } delete detailedReportFile; - std::cout << "Detailed report written to '" << detailedReportFileName << "'" << std::endl; + std::cout << "Detailed report written to '" << detailedReportFileName << "'" << '\n'; } return 0; diff --git a/Examples/PcapSplitter/ConnectionSplitters.h b/Examples/PcapSplitter/ConnectionSplitters.h index f8b6f5e5e0..ae79184027 100644 --- a/Examples/PcapSplitter/ConnectionSplitters.h +++ b/Examples/PcapSplitter/ConnectionSplitters.h @@ -22,10 +22,10 @@ class TwoTupleSplitter : public ValueBasedSplitter * Find the 2-tuple flow for this packet and get the file number it belongs to. If flow is new, return a new file * number */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) override { // hash the 2-tuple and look for it in the flow table - uint32_t hash = pcpp::hash2Tuple(&packet); + const uint32_t hash = pcpp::hash2Tuple(&packet); // if flow isn't found in the flow table if (m_FlowTable.find(hash) == m_FlowTable.end()) @@ -61,16 +61,16 @@ class FiveTupleSplitter : public ValueBasedSplitter /** * A utility method that takes a packet and returns true if it's a TCP SYN packet */ - bool isTcpSyn(pcpp::Packet& packet) + static bool isTcpSyn(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::TCP)) { // extract the TCP layer - pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); + auto* tcpLayer = packet.getLayerOfType(); // extract SYN and ACK flags - bool isSyn = (tcpLayer->getTcpHeader()->synFlag == 1); - bool isNotAck = (tcpLayer->getTcpHeader()->ackFlag == 0); + const bool isSyn = (tcpLayer->getTcpHeader()->synFlag == 1); + const bool isNotAck = (tcpLayer->getTcpHeader()->ackFlag == 0); // return true only if it's a pure SYN packet (and not SYN/ACK) return (isSyn && isNotAck); @@ -90,10 +90,10 @@ class FiveTupleSplitter : public ValueBasedSplitter /** * Find the flow for this packet and get the file number it belongs to. If flow is new, return a new file number */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) override { // hash the 5-tuple and look for it in the flow table - uint32_t hash = pcpp::hash5Tuple(&packet); + const uint32_t hash = pcpp::hash5Tuple(&packet); // if flow isn't found in the flow table if (m_FlowTable.find(hash) == m_FlowTable.end()) @@ -113,13 +113,13 @@ class FiveTupleSplitter : public ValueBasedSplitter if (packet.isPacketOfType(pcpp::TCP)) { // if this is a TCP flow, check if this is a SYN packet - bool isSyn = isTcpSyn(packet); + const bool isSyn = isTcpSyn(packet); // if this is a SYN packet it means this is a beginning of a new flow //(with the same 5-tuple as the previous one), so assign a new file number to it. // unless the last packet was also SYN, which is an indication of SYN retransmission. // In this case don't assign a new file number - if (isSyn && m_TcpFlowTable.find(hash) != m_TcpFlowTable.end() && m_TcpFlowTable[hash] == false) + if (isSyn && m_TcpFlowTable.find(hash) != m_TcpFlowTable.end() && !m_TcpFlowTable[hash]) { m_FlowTable[hash] = getNextFileNumber(filesToClose); } @@ -144,8 +144,8 @@ class FiveTupleSplitter : public ValueBasedSplitter return m_FlowTable[hash]; } - void updateStringStream(std::ostringstream& sstream, const std::string& srcIp, uint16_t srcPort, - const std::string& dstIp, uint16_t dstPort) + static void updateStringStream(std::ostringstream& sstream, const std::string& srcIp, uint16_t srcPort, + const std::string& dstIp, uint16_t dstPort) { sstream << hyphenIP(srcIp) << "_" << srcPort << "-" << hyphenIP(dstIp) << "_" << dstPort; } @@ -153,7 +153,7 @@ class FiveTupleSplitter : public ValueBasedSplitter /** * Re-implement Splitter's getFileName() method, this time with the IPs/Ports/protocol value */ - std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) override { std::ostringstream sstream; @@ -168,11 +168,11 @@ class FiveTupleSplitter : public ValueBasedSplitter if (packet.isPacketOfType(pcpp::TCP)) { // extract TCP layer - pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); + auto* tcpLayer = packet.getLayerOfType(); if (tcpLayer != nullptr) { - uint16_t srcPort = tcpLayer->getSrcPort(); - uint16_t dstPort = tcpLayer->getDstPort(); + const uint16_t srcPort = tcpLayer->getSrcPort(); + const uint16_t dstPort = tcpLayer->getDstPort(); sstream << "tcp_"; @@ -183,6 +183,7 @@ class FiveTupleSplitter : public ValueBasedSplitter else if (((tcpLayer->getTcpHeader()->synFlag == 1) && (tcpLayer->getTcpHeader()->ackFlag == 1)) || (srcPort < dstPort)) { + // NOLINTNEXTLINE(readability-suspicious-call-argument) updateStringStream(sstream, getDstIPString(packet), dstPort, getSrcIPString(packet), srcPort); } else @@ -195,7 +196,7 @@ class FiveTupleSplitter : public ValueBasedSplitter else if (packet.isPacketOfType(pcpp::UDP)) { // for UDP packets, decide the server port by the lower port - pcpp::UdpLayer* udpLayer = packet.getLayerOfType(); + auto* udpLayer = packet.getLayerOfType(); if (udpLayer != nullptr) { sstream << "udp_"; @@ -203,12 +204,13 @@ class FiveTupleSplitter : public ValueBasedSplitter auto srcPort = udpLayer->getSrcPort(); auto dstPort = udpLayer->getDstPort(); - uint16_t firstPort = srcPort < dstPort ? dstPort : srcPort; - uint16_t secondPort = srcPort < dstPort ? srcPort : dstPort; + const uint16_t firstPort = srcPort < dstPort ? dstPort : srcPort; + const uint16_t secondPort = srcPort < dstPort ? srcPort : dstPort; - std::string firstIP = (srcPort < dstPort) ? getDstIPString(packet) : getSrcIPString(packet); - std::string secondIP = (srcPort < dstPort) ? getSrcIPString(packet) : getDstIPString(packet); + const std::string firstIP = (srcPort < dstPort) ? getDstIPString(packet) : getSrcIPString(packet); + const std::string secondIP = (srcPort < dstPort) ? getSrcIPString(packet) : getDstIPString(packet); + // NOLINTNEXTLINE(readability-suspicious-call-argument) updateStringStream(sstream, firstIP, firstPort, secondIP, secondPort); return outputPcapBasePath + sstream.str(); } diff --git a/Examples/PcapSplitter/IPPortSplitters.h b/Examples/PcapSplitter/IPPortSplitters.h index 1493d7571b..e636506354 100644 --- a/Examples/PcapSplitter/IPPortSplitters.h +++ b/Examples/PcapSplitter/IPPortSplitters.h @@ -24,7 +24,7 @@ class IPPortSplitter : public ValueBasedSplitter * be an existing flow or a new flow). When opening new flows it uses a virtual abstract method that should be * Implemented by inherited classes to determine to which file number the flow will be written to */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) override { // if it's not a TCP or UDP packet, put it in file #0 if (!packet.isPacketOfType(pcpp::TCP) && !packet.isPacketOfType(pcpp::UDP)) @@ -33,7 +33,7 @@ class IPPortSplitter : public ValueBasedSplitter } // hash the 5-tuple and look for it in the flow table - uint32_t hash = pcpp::hash5Tuple(&packet); + const uint32_t hash = pcpp::hash5Tuple(&packet); if (m_FlowTable.find(hash) != m_FlowTable.end()) { @@ -48,11 +48,11 @@ class IPPortSplitter : public ValueBasedSplitter if (packet.isPacketOfType(pcpp::TCP)) { // extract TCP layer - pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); + auto* tcpLayer = packet.getLayerOfType(); if (tcpLayer != nullptr) { - uint16_t srcPort = tcpLayer->getSrcPort(); - uint16_t dstPort = tcpLayer->getDstPort(); + const uint16_t srcPort = tcpLayer->getSrcPort(); + const uint16_t dstPort = tcpLayer->getDstPort(); if (tcpLayer->getTcpHeader()->synFlag) { @@ -64,31 +64,25 @@ class IPPortSplitter : public ValueBasedSplitter return m_FlowTable[hash]; } // SYN/ACK packet - else - { - m_FlowTable[hash] = - getFileNumberForValue(getValue(packet, SYN_ACK, srcPort, dstPort), filesToClose); - return m_FlowTable[hash]; - } - } - // Other TCP packet - else - { + m_FlowTable[hash] = - getFileNumberForValue(getValue(packet, TCP_OTHER, srcPort, dstPort), filesToClose); + getFileNumberForValue(getValue(packet, SYN_ACK, srcPort, dstPort), filesToClose); return m_FlowTable[hash]; } + // Other TCP packet + m_FlowTable[hash] = getFileNumberForValue(getValue(packet, TCP_OTHER, srcPort, dstPort), filesToClose); + return m_FlowTable[hash]; } } else if (packet.isPacketOfType(pcpp::UDP)) { // for UDP packets, decide the server port by the lower port - pcpp::UdpLayer* udpLayer = packet.getLayerOfType(); + auto* udpLayer = packet.getLayerOfType(); if (udpLayer != nullptr) { - uint16_t srcPort = udpLayer->getSrcPort(); - uint16_t dstPort = udpLayer->getDstPort(); + const uint16_t srcPort = udpLayer->getSrcPort(); + const uint16_t dstPort = udpLayer->getDstPort(); m_FlowTable[hash] = getFileNumberForValue(getValue(packet, UDP, srcPort, dstPort), filesToClose); return m_FlowTable[hash]; } @@ -102,10 +96,10 @@ class IPPortSplitter : public ValueBasedSplitter /** * Re-implement Splitter's getFileName() method, this time with the IP/port value */ - std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int /*fileNumber*/) override { // first set the base string as the outputPcapBasePath - std::string result = outputPcapBasePath; + const std::string& result = outputPcapBasePath; // if it's not a TCP or UDP packet, put it in file #0 if (!packet.isPacketOfType(pcpp::TCP) && !packet.isPacketOfType(pcpp::UDP)) @@ -116,11 +110,11 @@ class IPPortSplitter : public ValueBasedSplitter if (packet.isPacketOfType(pcpp::TCP)) { // extract TCP layer - pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); + auto* tcpLayer = packet.getLayerOfType(); if (tcpLayer != nullptr) { - uint16_t srcPort = tcpLayer->getSrcPort(); - uint16_t dstPort = tcpLayer->getDstPort(); + const uint16_t srcPort = tcpLayer->getSrcPort(); + const uint16_t dstPort = tcpLayer->getDstPort(); if (tcpLayer->getTcpHeader()->synFlag) { @@ -130,27 +124,22 @@ class IPPortSplitter : public ValueBasedSplitter return result + getValueString(packet, SYN, srcPort, dstPort); } // SYN/ACK packet - else - { - return result + getValueString(packet, SYN_ACK, srcPort, dstPort); - } + + return result + getValueString(packet, SYN_ACK, srcPort, dstPort); } // Other TCP packet - else - { - return result + getValueString(packet, TCP_OTHER, srcPort, dstPort); - } + return result + getValueString(packet, TCP_OTHER, srcPort, dstPort); } } else if (packet.isPacketOfType(pcpp::UDP)) { // for UDP packets, decide the server port by the lower port - pcpp::UdpLayer* udpLayer = packet.getLayerOfType(); + auto* udpLayer = packet.getLayerOfType(); if (udpLayer != nullptr) { - uint16_t srcPort = udpLayer->getSrcPort(); - uint16_t dstPort = udpLayer->getDstPort(); + const uint16_t srcPort = udpLayer->getSrcPort(); + const uint16_t dstPort = udpLayer->getDstPort(); return result + getValueString(packet, UDP, srcPort, dstPort); } } @@ -163,7 +152,7 @@ class IPPortSplitter : public ValueBasedSplitter /** * An enum for TCP/UDP packet type: can be either TCP-SYN, TCP-SYN/ACK, Other TCP packet of UDP packet */ - enum PacketType + enum PacketType : uint8_t { SYN, SYN_ACK, @@ -191,46 +180,58 @@ class IPPortSplitter : public ValueBasedSplitter /** * An auxiliary method for extracting packet's IPv4/IPv6 source address hashed as 4 bytes uint32_t value */ - uint32_t getSrcIPValue(pcpp::Packet& packet) + static uint32_t getSrcIPValue(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IPv4)) + { return packet.getLayerOfType()->getSrcIPv4Address().toInt(); - else if (packet.isPacketOfType(pcpp::IPv6)) - return pcpp::fnvHash((uint8_t*)packet.getLayerOfType()->getSrcIPv6Address().toBytes(), 16); - else - return 0; + } + if (packet.isPacketOfType(pcpp::IPv6)) + { + return pcpp::fnvHash( + const_cast(packet.getLayerOfType()->getSrcIPv6Address().toBytes()), 16); + } + return 0; } /** * An auxiliary method for extracting packet's IPv4/IPv6 dest address hashed as 4 bytes uint32_t value */ - uint32_t getDstIPValue(pcpp::Packet& packet) + static uint32_t getDstIPValue(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IPv4)) + { return packet.getLayerOfType()->getDstIPv4Address().toInt(); - else if (packet.isPacketOfType(pcpp::IPv6)) - return pcpp::fnvHash((uint8_t*)packet.getLayerOfType()->getDstIPv6Address().toBytes(), 16); - else - return 0; + } + if (packet.isPacketOfType(pcpp::IPv6)) + { + return pcpp::fnvHash( + const_cast(packet.getLayerOfType()->getDstIPv6Address().toBytes()), 16); + } + return 0; } /** * An auxiliary method to indicate whether an IPv4/IPv6 source address is multicast or not */ - bool isSrcIPMulticast(pcpp::Packet& packet) + static bool isSrcIPMulticast(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IP)) + { return packet.getLayerOfType()->getSrcIPAddress().isMulticast(); + } return false; } /** * An auxiliary method to indicate whether an IPv4/IPv6 dest address is multicast or not */ - bool isDstIPMulticast(pcpp::Packet& packet) + static bool isDstIPMulticast(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IP)) + { return packet.getLayerOfType()->getDstIPAddress().isMulticast(); + } return false; } }; @@ -259,7 +260,7 @@ class ClientIPSplitter : public IPPortSplitter * Implementation of the abstract method of IPPortSplitter. This method returns the client IP for a certain flow * by the logic written at the description of this class */ - uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { switch (packetType) { @@ -269,23 +270,33 @@ class ClientIPSplitter : public IPPortSplitter return getDstIPValue(packet); case UDP: if (isSrcIPMulticast(packet)) + { return getSrcIPValue(packet); + } else if (isDstIPMulticast(packet)) + { return getDstIPValue(packet); + } else + { return srcPort >= dstPort ? getSrcIPValue(packet) : getDstIPValue(packet); + } // other TCP packet default: if (srcPort >= dstPort) + { return getSrcIPValue(packet); + } else + { return getDstIPValue(packet); + } } } - std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { - std::string prefix = "client-ip-"; + const std::string prefix = "client-ip-"; switch (packetType) { @@ -295,18 +306,28 @@ class ClientIPSplitter : public IPPortSplitter return prefix + hyphenIP(getDstIPString(packet)); case UDP: if (isSrcIPMulticast(packet)) + { return prefix + hyphenIP(getSrcIPString(packet)); + } else if (isDstIPMulticast(packet)) + { return prefix + hyphenIP(getDstIPString(packet)); + } else + { return srcPort >= dstPort ? prefix + hyphenIP(getSrcIPString(packet)) : prefix + hyphenIP(getDstIPString(packet)); + } // other TCP packet default: if (srcPort >= dstPort) + { return prefix + hyphenIP(getSrcIPString(packet)); + } else + { return prefix + hyphenIP(getDstIPString(packet)); + } } } }; @@ -335,7 +356,7 @@ class ServerIPSplitter : public IPPortSplitter * Implementation of the abstract method of IPPortSplitter. This method returns the server IP for a certain flow * by the logic written at the description of this class */ - uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { switch (packetType) { @@ -345,23 +366,33 @@ class ServerIPSplitter : public IPPortSplitter return getSrcIPValue(packet); case UDP: if (isSrcIPMulticast(packet)) + { return getDstIPValue(packet); + } else if (isDstIPMulticast(packet)) + { return getSrcIPValue(packet); + } else + { return srcPort >= dstPort ? getDstIPValue(packet) : getSrcIPValue(packet); + } // other TCP packet default: if (srcPort >= dstPort) + { return getDstIPValue(packet); + } else + { return getSrcIPValue(packet); + } } } - std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { - std::string prefix = "server-ip-"; + const std::string prefix = "server-ip-"; switch (packetType) { @@ -371,18 +402,28 @@ class ServerIPSplitter : public IPPortSplitter return prefix + hyphenIP(getSrcIPString(packet)); case UDP: if (isSrcIPMulticast(packet)) + { return prefix + hyphenIP(getDstIPString(packet)); + } else if (isDstIPMulticast(packet)) + { return prefix + hyphenIP(getSrcIPString(packet)); + } else + { return srcPort >= dstPort ? prefix + hyphenIP(getDstIPString(packet)) : prefix + hyphenIP(getSrcIPString(packet)); + } // other TCP packet default: if (srcPort >= dstPort) + { return prefix + hyphenIP(getDstIPString(packet)); + } else + { return prefix + hyphenIP(getSrcIPString(packet)); + } } } }; @@ -412,7 +453,7 @@ class ServerPortSplitter : public IPPortSplitter * Implementation of the abstract method of IPPortSplitter. This method returns the server port for a certain flow * by the logic written at the description of this class */ - uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { switch (packetType) { @@ -422,20 +463,26 @@ class ServerPortSplitter : public IPPortSplitter return srcPort; case UDP: if (isSrcIPMulticast(packet)) + { return dstPort; + } else if (isDstIPMulticast(packet)) + { return srcPort; + } else + { return std::min(srcPort, dstPort); + } // other TCP packet default: return std::min(srcPort, dstPort); } } - std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { - std::string prefix = "server-port-"; + std::string const prefix = "server-port-"; uint16_t res = 0; switch (packetType) @@ -448,11 +495,17 @@ class ServerPortSplitter : public IPPortSplitter break; case UDP: if (isSrcIPMulticast(packet)) + { res = dstPort; + } else if (isDstIPMulticast(packet)) + { res = srcPort; + } else + { res = std::min(srcPort, dstPort); + } break; // other TCP packet default: @@ -491,7 +544,7 @@ class ClientPortSplitter : public IPPortSplitter * Implementation of the abstract method of IPPortSplitter. This method returns the client port for a certain flow * by the logic written at the description of this class */ - uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + uint32_t getValue(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { switch (packetType) { @@ -501,20 +554,26 @@ class ClientPortSplitter : public IPPortSplitter return dstPort; case UDP: if (isSrcIPMulticast(packet)) + { return srcPort; + } else if (isDstIPMulticast(packet)) + { return dstPort; + } else + { return std::max(srcPort, dstPort); + } // other TCP packet default: return std::max(srcPort, dstPort); } } - std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) + std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) override { - std::string prefix = "client-port-"; + const std::string prefix = "client-port-"; uint16_t res = 0; switch (packetType) @@ -527,11 +586,17 @@ class ClientPortSplitter : public IPPortSplitter break; case UDP: if (isSrcIPMulticast(packet)) + { res = srcPort; + } else if (isDstIPMulticast(packet)) + { res = dstPort; + } else + { res = std::max(srcPort, dstPort); + } break; // other TCP packet default: diff --git a/Examples/PcapSplitter/SimpleSplitters.h b/Examples/PcapSplitter/SimpleSplitters.h index e05abcb575..0e80e8a5c3 100644 --- a/Examples/PcapSplitter/SimpleSplitters.h +++ b/Examples/PcapSplitter/SimpleSplitters.h @@ -10,41 +10,40 @@ class PacketCountSplitter : public Splitter { private: - int m_PacketCount; + int m_PacketCount{ 0 }; int m_MaxPacketsPerFile; public: /** * A c'tor for this class which gets the packet count for each split file */ - explicit PacketCountSplitter(int maxPacketsPerFile) - { - m_PacketCount = 0; - m_MaxPacketsPerFile = maxPacketsPerFile; - } + explicit PacketCountSplitter(int maxPacketsPerFile) : m_MaxPacketsPerFile(maxPacketsPerFile) + {} /** * Return the current file number if its packet count didn't reach the limit, or else return the next * file number and close the current file */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& /*packet*/, std::vector& filesToClose) override { // check the current file number - int curFile = m_PacketCount / m_MaxPacketsPerFile; + const int curFile = m_PacketCount / m_MaxPacketsPerFile; // increment packet count m_PacketCount++; // check the new file number - int nextFile = m_PacketCount / m_MaxPacketsPerFile; + const int nextFile = m_PacketCount / m_MaxPacketsPerFile; // if reached packet count limit, close the previous file and return the next file number if (curFile != nextFile) + { filesToClose.push_back(curFile); + } return curFile; } /** * Make sure packet count is a positive number */ - bool isSplitterParamLegal(std::string& errorString) + bool isSplitterParamLegal(std::string& errorString) override { if (m_MaxPacketsPerFile < 1) { @@ -62,7 +61,7 @@ class PacketCountSplitter : public Splitter class FileSizeSplitter : public Splitter { private: - uint64_t m_TotalSize; + uint64_t m_TotalSize{ 0 }; uint64_t m_MaxBytesPerFile; static const int PCAP_FILE_HEADER_SIZE = 24; // == sizeof(pcap_file_header) @@ -72,35 +71,36 @@ class FileSizeSplitter : public Splitter /** * A c'tor for this class which gets the file size in bytes for each split file */ - explicit FileSizeSplitter(uint64_t maxBytesPerFile) + explicit FileSizeSplitter(uint64_t maxBytesPerFile) : m_MaxBytesPerFile(maxBytesPerFile - PCAP_FILE_HEADER_SIZE) { - m_TotalSize = 0; + // each file size contains a pcap header with size of PCAP_FILE_HEADER_SIZE - m_MaxBytesPerFile = maxBytesPerFile - PCAP_FILE_HEADER_SIZE; } /** * Return the current file number if its size didn't reach the file size limit, or else return the next * file number and close the current file */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) override { // check the current file - int prevFile = m_TotalSize / m_MaxBytesPerFile; + const int prevFile = static_cast(m_TotalSize / m_MaxBytesPerFile); // add the current packet size and packet header m_TotalSize += (uint64_t)packet.getRawPacket()->getRawDataLen() + PCAP_PACKET_HEADER_SIZE; // calculate the new file number - int nextFile = m_TotalSize / m_MaxBytesPerFile; + const int nextFile = static_cast(m_TotalSize / m_MaxBytesPerFile); // if reached the maximum size per file, close the previous file if (prevFile != nextFile) + { filesToClose.push_back(prevFile); + } return nextFile; } /** * Each file size must be at least in size of PCAP_FILE_HEADER_SIZE + PCAP_PACKET_HEADER_SIZE */ - bool isSplitterParamLegal(std::string& errorString) + bool isSplitterParamLegal(std::string& errorString) override { if (m_MaxBytesPerFile < PCAP_PACKET_HEADER_SIZE + 1) { @@ -129,10 +129,12 @@ class BpfCriteriaSplitter : public Splitter /** * Return file #0 if packet matches the BPF filer, and file #1 if it's not */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& packet, std::vector& /*filesToClose*/) override { if (pcpp::IPcapDevice::matchPacketWithFilter(filter, packet.getRawPacket())) + { return 0; + } return 1; } @@ -140,29 +142,32 @@ class BpfCriteriaSplitter : public Splitter * Re-implement Splitter's getFileName() method, clarifying which file was matched by the BPF * filter and which didn't */ - std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& /*packet*/, const std::string& outputPcapBasePath, int fileNumber) override { if (fileNumber == 0) + { return outputPcapBasePath + "match-bpf"; - else - return outputPcapBasePath + "not-match-bpf"; + } + return outputPcapBasePath + "not-match-bpf"; } /** * Verifies the BPF filter set in the c'tor is a valid BPF filter */ - bool isSplitterParamLegal(std::string& errorString) + bool isSplitterParamLegal(std::string& errorString) override { - if (m_BpfFilter == "") + if (m_BpfFilter.empty()) { errorString = "No BPF filter was set or set an empty one"; return false; } pcpp::BPFStringFilter localFilter(m_BpfFilter); - bool filterValid = localFilter.verifyFilter(); + const bool filterValid = localFilter.verifyFilter(); if (!filterValid) + { errorString = "BPF filter is not valid"; + } return filterValid; } @@ -180,7 +185,7 @@ class RoundRobinSplitter : public SplitterWithMaxFiles /** * Get the next file number, SplitterWithMaxFiles#getNextFileNumber() takes care of the round-robin method */ - int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) + int getFileNumber(pcpp::Packet& /*packet*/, std::vector& filesToClose) override { return getNextFileNumber(filesToClose); } @@ -188,7 +193,7 @@ class RoundRobinSplitter : public SplitterWithMaxFiles /** * Number of files must be a positive integer */ - bool isSplitterParamLegal(std::string& errorString) + bool isSplitterParamLegal(std::string& errorString) override { if (m_MaxFiles < 1) { diff --git a/Examples/PcapSplitter/Splitters.h b/Examples/PcapSplitter/Splitters.h index c6c43c30a0..055f664a8d 100644 --- a/Examples/PcapSplitter/Splitters.h +++ b/Examples/PcapSplitter/Splitters.h @@ -41,18 +41,17 @@ class Splitter * first packet that will be written to this file. The default implementation is the following: * ' /requested-path/original-file-name-[4-digit-number-starting-at-0000].pcap' */ - virtual std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) + virtual std::string getFileName(pcpp::Packet& /*packet*/, const std::string& outputPcapBasePath, int fileNumber) { std::ostringstream sstream; sstream << std::setw(4) << std::setfill('0') << fileNumber; - return outputPcapBasePath.c_str() + sstream.str(); + return outputPcapBasePath + sstream.str(); } /** * A virtual d'tor */ - virtual ~Splitter() - {} + virtual ~Splitter() = default; }; /** @@ -83,9 +82,11 @@ class SplitterWithMaxFiles : public Splitter */ void writingToFile(int fileNum, std::vector& filesToClose) { - int fileToClose; + int fileToClose = 0; if (m_LRUFileList.put(fileNum, &fileToClose) == 1) + { filesToClose.push_back(fileToClose); + } } /** @@ -101,7 +102,9 @@ class SplitterWithMaxFiles : public Splitter // zero or negative m_MaxFiles means no limit if (m_MaxFiles <= 0) + { nextFile = m_NextFile++; + } else // m_MaxFiles is positive, meaning there is a output file limit { nextFile = (m_NextFile) % m_MaxFiles; @@ -109,7 +112,7 @@ class SplitterWithMaxFiles : public Splitter } // put the next file in the LRU list - int fileToClose; + int fileToClose = 0; if (m_LRUFileList.put(nextFile, &fileToClose) == 1) { // if a file is pulled out of the LRU list - return it @@ -123,11 +126,8 @@ class SplitterWithMaxFiles : public Splitter * UNLIMITED_FILES_MAGIC_NUMBER, it's considered there's no output files limit */ explicit SplitterWithMaxFiles(int maxFiles, int firstFileNumber = 0) - : m_LRUFileList(MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) - { - m_MaxFiles = maxFiles; - m_NextFile = firstFileNumber; - } + : m_MaxFiles(maxFiles), m_NextFile(firstFileNumber), m_LRUFileList(MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) + {} public: static const int UNLIMITED_FILES_MAGIC_NUMBER = -12345; @@ -136,11 +136,13 @@ class SplitterWithMaxFiles : public Splitter * This method checks the maximum number of file parameter. If it equals UNLIMITED_FILES_MAGIC_NUMBER it means there * is no limit. Else it verifies the limit is a positive number */ - bool isSplitterParamLegal(std::string& errorString) + bool isSplitterParamLegal(std::string& errorString) override { // unlimited number of output files if (m_MaxFiles == UNLIMITED_FILES_MAGIC_NUMBER) + { return true; + } if (m_MaxFiles <= 0) { @@ -196,42 +198,46 @@ class ValueBasedSplitter : public SplitterWithMaxFiles /** * An auxiliary method for extracting packet's IPv4/IPv6 source address as string */ -std::string getSrcIPString(pcpp::Packet& packet) +inline std::string getSrcIPString(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IP)) + { return packet.getLayerOfType()->getSrcIPAddress().toString(); + } return "miscellaneous"; } /** * An auxiliary method for extracting packet's IPv4/IPv6 dest address string */ -std::string getDstIPString(pcpp::Packet& packet) +inline std::string getDstIPString(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::IP)) + { return packet.getLayerOfType()->getDstIPAddress().toString(); + } return "miscellaneous"; } /** * An auxiliary method for replacing '.' and ':' in IPv4/IPv6 addresses with '-' */ -std::string hyphenIP(std::string ipVal) +inline std::string hyphenIP(std::string ipVal) { // for IPv4 - replace '.' with '-' - int loc = ipVal.find("."); - while (loc >= 0) + auto loc = ipVal.find('.'); + while (loc != std::string::npos) { ipVal.replace(loc, 1, "-"); - loc = ipVal.find("."); + loc = ipVal.find('.'); } // for IPv6 - replace ':' with '-' - loc = ipVal.find(":"); - while (loc >= 0) + loc = ipVal.find(':'); + while (loc != std::string::npos) { ipVal.replace(loc, 1, "-"); - loc = ipVal.find(":"); + loc = ipVal.find(':'); } return ipVal; diff --git a/Examples/PcapSplitter/main.cpp b/Examples/PcapSplitter/main.cpp index 241b10ac7d..4e6fddc93b 100644 --- a/Examples/PcapSplitter/main.cpp +++ b/Examples/PcapSplitter/main.cpp @@ -73,7 +73,7 @@ static struct option PcapSplitterOptions[] = { do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -100,73 +100,67 @@ static struct option PcapSplitterOptions[] = { void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-h] [-v] [-i filter] -f pcap_file -o output_dir -m split_method [-p split_param]" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f pcap_file : Input pcap file name" << std::endl - << " -o output_dir : The directory where the output files shall be written" << std::endl - << " -m split_method : The method to split with. Can take one of the following params:" << std::endl - << " 'file-size' - split files by size in bytes" << std::endl - << " 'packet-count' - split files by packet count" << std::endl - << " 'client-ip' - split files by client IP, meaning all connections with" << std::endl - << " the same client IP will be in the same file" << std::endl - << " 'server-ip' - split files by server IP, meaning all connections with" << std::endl - << " the same server IP will be in the same file" << std::endl - << " 'server-port' - split files by server port, meaning all connections with" - << std::endl - << " the same server port will be in the same file" << std::endl - << " 'client-port' - split files by client port, meaning all connections with" - << std::endl - << " the same client port will be in the same file" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -f pcap_file : Input pcap file name" << '\n' + << " -o output_dir : The directory where the output files shall be written" << '\n' + << " -m split_method : The method to split with. Can take one of the following params:" << '\n' + << " 'file-size' - split files by size in bytes" << '\n' + << " 'packet-count' - split files by packet count" << '\n' + << " 'client-ip' - split files by client IP, meaning all connections with" << '\n' + << " the same client IP will be in the same file" << '\n' + << " 'server-ip' - split files by server IP, meaning all connections with" << '\n' + << " the same server IP will be in the same file" << '\n' + << " 'server-port' - split files by server port, meaning all connections with" << '\n' + << " the same server port will be in the same file" << '\n' + << " 'client-port' - split files by client port, meaning all connections with" << '\n' + << " the same client port will be in the same file" << '\n' << " 'ip-src-dst' - split files by IP src and dst (2-tuple), meaning all connections" - << std::endl - << " with the same IPs will be in the same file" << std::endl - << " 'connection' - split files by connection (5-tuple), meaning all packets" - << std::endl - << " of a connection will be in the same file" << std::endl - << " 'bpf-filter' - split file into two files: one that contains all packets" - << std::endl + << '\n' + << " with the same IPs will be in the same file" << '\n' + << " 'connection' - split files by connection (5-tuple), meaning all packets" << '\n' + << " of a connection will be in the same file" << '\n' + << " 'bpf-filter' - split file into two files: one that contains all packets" << '\n' << " matching the given BPF filter (file #0) and one that contains" - << std::endl - << " the rest of the packets (file #1)" << std::endl - << " 'round-robin' - split the file in a round-robin manner - each packet to a" - << std::endl - << " different file" << std::endl - << " -p split_param : The relevant parameter for the split method:" << std::endl - << " 'method = file-size' => split_param is the max size per file (in bytes)." - << std::endl - << " split_param is required for this method" << std::endl - << " 'method = packet-count' => split_param is the number of packet per file." << std::endl - << " split_param is required for this method" << std::endl - << " 'method = client-ip' => split_param is max number of files to open." << std::endl + << '\n' + << " the rest of the packets (file #1)" << '\n' + << " 'round-robin' - split the file in a round-robin manner - each packet to a" << '\n' + << " different file" << '\n' + << " -p split_param : The relevant parameter for the split method:" << '\n' + << " 'method = file-size' => split_param is the max size per file (in bytes)." << '\n' + << " split_param is required for this method" << '\n' + << " 'method = packet-count' => split_param is the number of packet per file." << '\n' + << " split_param is required for this method" << '\n' + << " 'method = client-ip' => split_param is max number of files to open." << '\n' << " If not provided the default is unlimited number of files" - << std::endl - << " 'method = server-ip' => split_param is max number of files to open." << std::endl + << '\n' + << " 'method = server-ip' => split_param is max number of files to open." << '\n' << " If not provided the default is unlimited number of files" - << std::endl - << " 'method = server-port' => split_param is max number of files to open." << std::endl + << '\n' + << " 'method = server-port' => split_param is max number of files to open." << '\n' << " If not provided the default is unlimited number of files" - << std::endl - << " 'method = ip-src-dst' => split_param is max number of files to open." << std::endl + << '\n' + << " 'method = ip-src-dst' => split_param is max number of files to open." << '\n' << " If not provided the default is unlimited number of files" - << std::endl - << " 'method = connection' => split_param is max number of files to open." << std::endl + << '\n' + << " 'method = connection' => split_param is max number of files to open." << '\n' << " If not provided the default is unlimited number of files" - << std::endl - << " 'method = bpf-filter' => split_param is the BPF filter to match upon" << std::endl + << '\n' + << " 'method = bpf-filter' => split_param is the BPF filter to match upon" << '\n' << " 'method = round-robin' => split_param is number of files to round-robin packets " "between" - << std::endl + << '\n' << " -i filter : Apply a BPF filter, meaning only filtered packets will be counted in the split" - << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n'; } /** @@ -174,9 +168,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -187,36 +181,38 @@ void printAppVersion() std::string getFileNameWithoutExtension(const std::string& path) { // if path is empty, return an empty string - if (path == "") + if (path.empty()) + { return ""; + } // find the last "\\" or "/" (depends on the os) - where path ends and filename starts - size_t i = path.rfind(SEPARATOR, path.length()); - if (i != std::string::npos) + size_t idx = path.rfind(SEPARATOR, path.length()); + if (idx != std::string::npos) { // extract filename from path - std::string fileNameWithExtension = path.substr(i + 1, path.length() - i); + std::string fileNameWithExtension = path.substr(idx + 1, path.length() - idx); // from the file name - remove the extension (the part after the ".") - i = fileNameWithExtension.rfind('.', fileNameWithExtension.length()); - if (i != std::string::npos) - return fileNameWithExtension.substr(0, i); + auto jdx = fileNameWithExtension.rfind('.', fileNameWithExtension.length()); + if (jdx != std::string::npos) + { + return fileNameWithExtension.substr(0, jdx); + } return fileNameWithExtension; } // filename without a path - else - { - // from the file name - remove the extension (the part after the ".") - i = path.rfind('.', path.length()); - if (i != std::string::npos) - return path.substr(0, i); - // filename doesn't have an extension - return path; + // from the file name - remove the extension (the part after the ".") + idx = path.rfind('.', path.length()); + if (idx != std::string::npos) + { + return path.substr(0, idx); } - return (""); + // filename doesn't have an extension + return path; } /** @@ -226,12 +222,12 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - std::string inputPcapFileName = ""; - std::string outputPcapDir = ""; + std::string inputPcapFileName; + std::string outputPcapDir; - std::string filter = ""; + std::string filter; - std::string method = ""; + std::string method; char param[1000]; memset(param, 0, 1000); @@ -275,12 +271,12 @@ int main(int argc, char* argv[]) } } - if (inputPcapFileName == "") + if (inputPcapFileName.empty()) { EXIT_WITH_ERROR("Input file name was not given"); } - if (outputPcapDir == "") + if (outputPcapDir.empty()) { EXIT_WITH_ERROR("Output directory name was not given"); } @@ -290,7 +286,7 @@ int main(int argc, char* argv[]) EXIT_WITH_ERROR("Output directory doesn't exist"); } - if (method == "") + if (method.empty()) { EXIT_WITH_ERROR("Split method was not given"); } @@ -300,52 +296,52 @@ int main(int argc, char* argv[]) // decide of the splitter to use, according to the user's choice if (method == SPLIT_BY_FILE_SIZE) { - uint64_t paramAsUint64 = (paramWasSet ? strtoull(param, nullptr, 10) : 0); - splitter.reset(new FileSizeSplitter(paramAsUint64)); + const uint64_t paramAsUint64 = (paramWasSet ? strtoull(param, nullptr, 10) : 0); + splitter = std::make_unique(paramAsUint64); } else if (method == SPLIT_BY_PACKET_COUNT) { - int paramAsInt = (paramWasSet ? atoi(param) : 0); - splitter.reset(new PacketCountSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : 0); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_IP_CLIENT) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new ClientIPSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_IP_SERVER) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new ServerIPSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_SERVER_PORT) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new ServerPortSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_CLIENT_PORT) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new ClientPortSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_2_TUPLE) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new TwoTupleSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_5_TUPLE) { - int paramAsInt = (paramWasSet ? atoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); - splitter.reset(new FiveTupleSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : SplitterWithMaxFiles::UNLIMITED_FILES_MAGIC_NUMBER); + splitter = std::make_unique(paramAsInt); } else if (method == SPLIT_BY_BPF_FILTER) { - splitter.reset(new BpfCriteriaSplitter(std::string(param))); + splitter = std::make_unique(std::string(param)); } else if (method == SPLIT_BY_ROUND_ROBIN) { - int paramAsInt = (paramWasSet ? atoi(param) : 0); - splitter.reset(new RoundRobinSplitter(paramAsInt)); + const int paramAsInt = (paramWasSet ? std::stoi(param) : 0); + splitter = std::make_unique(paramAsInt); } else { @@ -360,12 +356,12 @@ int main(int argc, char* argv[]) } // prepare the output file format: /requested-path/original-file-name-[4-digit-number-starting-at-0000].pcap - std::string outputPcapFileName = + const std::string outputPcapFileName = outputPcapDir + std::string(1, SEPARATOR) + getFileNameWithoutExtension(inputPcapFileName) + "-"; // open a pcap file for reading std::unique_ptr reader(pcpp::IFileReaderDevice::getReader(inputPcapFileName)); - bool isReaderPcapng = (dynamic_cast(reader.get()) != nullptr); + const bool isReaderPcapng = (dynamic_cast(reader.get()) != nullptr); if (reader == nullptr || !reader->open()) { @@ -373,16 +369,18 @@ int main(int argc, char* argv[]) } // set a filter if provided - if (filter != "") + if (!filter.empty()) { if (!reader->setFilter(filter)) + { EXIT_WITH_ERROR("Couldn't set filter '" << filter << "'"); + } } - std::cout << "Started..." << std::endl; + std::cout << "Started..." << '\n'; // determine output file extension - std::string outputFileExtenison = (isReaderPcapng ? ".pcapng" : ".pcap"); + const std::string outputFileExtenison = (isReaderPcapng ? ".pcapng" : ".pcap"); int packetCountSoFar = 0; int numOfFiles = 0; @@ -400,30 +398,33 @@ int main(int argc, char* argv[]) std::vector filesToClose; // call the splitter to get the file number to write the current packet to - int fileNum = splitter->getFileNumber(parsedPacket, filesToClose); + const int fileNum = splitter->getFileNumber(parsedPacket, filesToClose); // if file number is seen for the first time (meaning it's the first packet written to it) if (outputFiles.find(fileNum) == outputFiles.end()) { // get file name from the splitter and add the .pcap extension - std::string fileName = + const std::string fileName = splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; // create a new IFileWriterDevice for this file if (isReaderPcapng) { // if reader is pcapng, create a pcapng writer - outputFiles[fileNum].reset(new pcpp::PcapNgFileWriterDevice(fileName)); + outputFiles[fileNum] = std::make_unique(fileName); } else { // if reader is pcap, create a pcap writer - outputFiles[fileNum].reset(new pcpp::PcapFileWriterDevice(fileName, rawPacket.getLinkLayerType())); + outputFiles[fileNum] = + std::make_unique(fileName, rawPacket.getLinkLayerType()); } // open the writer if (!outputFiles[fileNum]->open()) + { break; + } numOfFiles++; } @@ -433,24 +434,27 @@ int main(int argc, char* argv[]) else if (outputFiles[fileNum] == nullptr) { // get file name from the splitter and add the .pcap extension - std::string fileName = + const std::string fileName = splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; // re-create the IFileWriterDevice object if (isReaderPcapng) { // if reader is pcapng, create a pcapng writer - outputFiles[fileNum].reset(new pcpp::PcapNgFileWriterDevice(fileName)); + outputFiles[fileNum] = std::make_unique(fileName); } else { // if reader is pcap, create a pcap writer - outputFiles[fileNum].reset(new pcpp::PcapFileWriterDevice(fileName, rawPacket.getLinkLayerType())); + outputFiles[fileNum] = + std::make_unique(fileName, rawPacket.getLinkLayerType()); } // open the writer in __append__ mode if (!outputFiles[fileNum]->open(true)) + { break; + } } // write the packet to the writer @@ -473,18 +477,17 @@ int main(int argc, char* argv[]) ++packetCountSoFar; } - std::cout << "Finished. Read and written " << packetCountSoFar << " packets to " << numOfFiles << " files" - << std::endl; + std::cout << "Finished. Read and written " << packetCountSoFar << " packets to " << numOfFiles << " files" << '\n'; // close the reader file reader->close(); // close the writer files which are still open - for (const auto& it : outputFiles) + for (const auto& itr : outputFiles) { - if (it.second != nullptr) + if (itr.second != nullptr) { - it.second->close(); + itr.second->close(); } } diff --git a/Examples/PfRingExample-FilterTraffic/Common.h b/Examples/PfRingExample-FilterTraffic/Common.h index 0d00e14820..a5a3396f12 100644 --- a/Examples/PfRingExample-FilterTraffic/Common.h +++ b/Examples/PfRingExample-FilterTraffic/Common.h @@ -11,7 +11,7 @@ #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -19,7 +19,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -31,41 +31,53 @@ struct PacketStats public: uint8_t ThreadId; - int PacketCount; - int EthCount; - int ArpCount; - int Ip4Count; - int Ip6Count; - int TcpCount; - int UdpCount; - int HttpCount; - - int MatchedTcpFlows; - int MatchedUdpFlows; - int MatchedPackets; - - PacketStats() - : ThreadId(MAX_NUM_OF_CORES + 1), PacketCount(0), EthCount(0), ArpCount(0), Ip4Count(0), Ip6Count(0), - TcpCount(0), UdpCount(0), HttpCount(0), MatchedTcpFlows(0), MatchedUdpFlows(0), MatchedPackets(0) + int PacketCount{ 0 }; + int EthCount{ 0 }; + int ArpCount{ 0 }; + int Ip4Count{ 0 }; + int Ip6Count{ 0 }; + int TcpCount{ 0 }; + int UdpCount{ 0 }; + int HttpCount{ 0 }; + + int MatchedTcpFlows{ 0 }; + int MatchedUdpFlows{ 0 }; + int MatchedPackets{ 0 }; + + PacketStats() : ThreadId(MAX_NUM_OF_CORES + 1) {} void collectStats(pcpp::Packet& packet) { PacketCount++; if (packet.isPacketOfType(pcpp::Ethernet)) + { EthCount++; + } if (packet.isPacketOfType(pcpp::ARP)) + { ArpCount++; + } if (packet.isPacketOfType(pcpp::IPv4)) + { Ip4Count++; + } if (packet.isPacketOfType(pcpp::IPv6)) + { Ip6Count++; + } if (packet.isPacketOfType(pcpp::TCP)) + { TcpCount++; + } if (packet.isPacketOfType(pcpp::UDP)) + { UdpCount++; + } if (packet.isPacketOfType(pcpp::HTTP)) + { HttpCount++; + } } void collectStats(const PacketStats& stats) @@ -100,13 +112,17 @@ struct PacketStats MatchedPackets = 0; } - std::string getStatValuesAsString(const std::string& delimiter) + std::string getStatValuesAsString(const std::string& delimiter) const { std::stringstream values; if (ThreadId == MAX_NUM_OF_CORES + 1) + { values << "Total" << delimiter; + } else + { values << (int)ThreadId << delimiter; + } values << PacketCount << delimiter; values << EthCount << delimiter; values << ArpCount << delimiter; @@ -130,18 +146,18 @@ struct PacketStats static const int narrowColumnWidth = 11; static const int wideColumnWidth = 18; - columnNames.push_back("Core ID"); - columnNames.push_back("Packet Cnt"); - columnNames.push_back("Eth Cnt"); - columnNames.push_back("ARP Cnt"); - columnNames.push_back("IPv4 Cnt"); - columnNames.push_back("IPv6 Cnt"); - columnNames.push_back("TCP Cnt"); - columnNames.push_back("UDP Cnt"); - columnNames.push_back("HTTP Cnt"); - columnNames.push_back("Matched TCP Flows"); - columnNames.push_back("Matched UDP Flows"); - columnNames.push_back("Matched Packets"); + columnNames.emplace_back("Core ID"); + columnNames.emplace_back("Packet Cnt"); + columnNames.emplace_back("Eth Cnt"); + columnNames.emplace_back("ARP Cnt"); + columnNames.emplace_back("IPv4 Cnt"); + columnNames.emplace_back("IPv6 Cnt"); + columnNames.emplace_back("TCP Cnt"); + columnNames.emplace_back("UDP Cnt"); + columnNames.emplace_back("HTTP Cnt"); + columnNames.emplace_back("Matched TCP Flows"); + columnNames.emplace_back("Matched UDP Flows"); + columnNames.emplace_back("Matched Packets"); columnWidths.push_back(7); columnWidths.push_back(narrowColumnWidth); diff --git a/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h b/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h index 64d4b4661c..b169217179 100644 --- a/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h @@ -16,27 +16,36 @@ class PacketMatchingEngine pcpp::IPv4Address m_SrcIpToMatch, m_DstIpToMatch; uint16_t m_SrcPortToMatch, m_DstPortToMatch; pcpp::ProtocolType m_ProtocolToMatch; - bool m_MatchSrcIp, m_MatchDstIp; - bool m_MatchSrcPort, m_MatchDstPort; - bool m_MatchProtocol; + bool m_MatchSrcIp{ false }, m_MatchDstIp{ false }; + bool m_MatchSrcPort{ false }, m_MatchDstPort{ false }; + bool m_MatchProtocol{ false }; public: PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), - m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), - m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchSrcIp = true; + } if (m_DstIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchDstIp = true; + } if (m_SrcPortToMatch != 0) + { m_MatchSrcPort = true; + } if (m_DstPortToMatch != 0) + { m_MatchDstPort = true; + } if (m_ProtocolToMatch == pcpp::TCP || m_ProtocolToMatch == pcpp::UDP) + { m_MatchProtocol = true; + } } bool isMatched(pcpp::Packet& packet) @@ -48,7 +57,7 @@ class PacketMatchingEngine return false; } - pcpp::IPv4Layer* ip4Layer = packet.getLayerOfType(); + auto* ip4Layer = packet.getLayerOfType(); if (m_MatchSrcIp && (ip4Layer->getSrcIPv4Address() != m_SrcIpToMatch)) { return false; @@ -62,7 +71,8 @@ class PacketMatchingEngine if (m_MatchSrcPort || m_MatchDstPort) { - uint16_t srcPort, dstPort; + uint16_t srcPort = 0; + uint16_t dstPort = 0; if (packet.isPacketOfType(pcpp::TCP)) { srcPort = packet.getLayerOfType()->getSrcPort(); diff --git a/Examples/PfRingExample-FilterTraffic/main.cpp b/Examples/PfRingExample-FilterTraffic/main.cpp index 7f7583ac9c..a5820f03d5 100644 --- a/Examples/PfRingExample-FilterTraffic/main.cpp +++ b/Examples/PfRingExample-FilterTraffic/main.cpp @@ -67,16 +67,13 @@ static struct option PfFilterTrafficOptions[] = { */ struct CaptureThreadArgs { - PacketStats* packetStatArr; - PacketMatchingEngine* matchingEngine; - std::unordered_map* flowTables; - pcpp::PfRingDevice* sendPacketsTo; - pcpp::PcapFileWriterDevice** pcapWriters; - - CaptureThreadArgs() - : packetStatArr(nullptr), matchingEngine(nullptr), flowTables(nullptr), sendPacketsTo(nullptr), - pcapWriters(nullptr) - {} + PacketStats* packetStatArr{ nullptr }; + PacketMatchingEngine* matchingEngine{ nullptr }; + std::unordered_map* flowTables{ nullptr }; + pcpp::PfRingDevice* sendPacketsTo{ nullptr }; + pcpp::PcapFileWriterDevice** pcapWriters{ nullptr }; + + CaptureThreadArgs() = default; }; /** @@ -85,43 +82,35 @@ struct CaptureThreadArgs void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" - << std::endl - << " [-c NUM_OF_THREADS] -n INTERFACE_NAME" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -l|--list : Print the list of PF_RING devices and exit" << std::endl - << " -n|--interface-name INTERFACE_NAME : A PF_RING interface name to receive packets from." - << std::endl - << " To see all available interfaces use the -l switch" - << std::endl - << " -s|--send-matched-packets INTERFACE_NAME : PF_RING interface name to send matched packets to" - << std::endl - << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." - << std::endl - << " Packets matched by thread X will be saved under" - << std::endl - << " 'FILEPATH/ThreadX.pcap'" << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl - << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" - << std::endl - << " -t|--num-of-threads NUM_OF_THREADS : Number of capture threads to open. Should be in" - << std::endl - << " the range of 1 to NUM_OF_CORES_ON_MACHINE-1." << std::endl - << " Default is using all machine cores except the core" - << std::endl - << " the application is running on" << std::endl - << std::endl; + << '\n' + << " [-c NUM_OF_THREADS] -n INTERFACE_NAME" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h|--help : Displays this help message and exits" << '\n' + << " -v|--version : Displays the current version and exits" << '\n' + << " -l|--list : Print the list of PF_RING devices and exit" << '\n' + << " -n|--interface-name INTERFACE_NAME : A PF_RING interface name to receive packets from." << '\n' + << " To see all available interfaces use the -l switch" << '\n' + << " -s|--send-matched-packets INTERFACE_NAME : PF_RING interface name to send matched packets to" << '\n' + << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." << '\n' + << " Packets matched by thread X will be saved under" << '\n' + << " 'FILEPATH/ThreadX.pcap'" << '\n' + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << '\n' + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << '\n' + << " -p|--match-source-port PORT : Match source TCP/UDP port" << '\n' + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << '\n' + << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" << '\n' + << " -t|--num-of-threads NUM_OF_THREADS : Number of capture threads to open. Should be in" << '\n' + << " the range of 1 to NUM_OF_CORES_ON_MACHINE-1." << '\n' + << " Default is using all machine cores except the core" << '\n' + << " the application is running on" << '\n' + << '\n'; } /** @@ -129,9 +118,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -160,7 +149,7 @@ void listPfRingDevices() << interfaceIndex.str() << " MAC address: " << std::setw(19) << (dev->getMacAddress() == pcpp::MacAddress::Zero ? "N/A" : dev->getMacAddress().toString()) << " Available RX channels: " << std::setw(3) << (int)dev->getTotalNumOfRxChannels() - << " MTU: " << dev->getMtu() << std::endl; + << " MTU: " << dev->getMtu() << '\n'; } // re-enable errors @@ -172,10 +161,10 @@ void listPfRingDevices() * the packet and matches it with the matching engine. If packet is matched it sends it to the TX interface (if needed) * or writes it to the thread's pcap file (if needed) */ -void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, +void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* /*device*/, void* userCookie) { - CaptureThreadArgs* args = (CaptureThreadArgs*)userCookie; + auto* args = reinterpret_cast(userCookie); for (uint32_t i = 0; i < numOfPackets; i++) { // parse packet @@ -188,8 +177,8 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or // new flow - uint32_t hash = pcpp::hash5Tuple(&packet); - std::unordered_map::const_iterator iter = args->flowTables[threadId].find(hash); + const uint32_t hash = pcpp::hash5Tuple(&packet); + const std::unordered_map::const_iterator iter = args->flowTables[threadId].find(hash); // if packet belongs to an already existing flow if (iter != args->flowTables[threadId].end() && iter->second) @@ -240,7 +229,7 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre */ void onApplicationInterrupted(void* cookie) { - bool* shouldStop = (bool*)cookie; + bool* shouldStop = reinterpret_cast(cookie); *shouldStop = true; } @@ -251,12 +240,12 @@ int main(int argc, char* argv[]) pcpp::PfRingDevice* dev = nullptr; - int totalNumOfCores = pcpp::getNumOfCores(); + const int totalNumOfCores = pcpp::getNumOfCores(); int numOfCaptureThreads = totalNumOfCores - 1; pcpp::PfRingDevice* sendPacketsToIface = nullptr; - std::string packetFilePath = ""; + std::string packetFilePath; bool writePacketsToDisk = true; pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; @@ -278,26 +267,32 @@ int main(int argc, char* argv[]) } case 'n': { - std::string ifaceName = std::string(optarg); - dev = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(ifaceName); + const std::string ifaceName = std::string(optarg); + dev = pcpp::PfRingDeviceList::getInstance().getDeviceByName(ifaceName); if (dev == nullptr) + { EXIT_WITH_ERROR("Could not find PF_RING device '" << ifaceName << "'"); + } break; } case 's': { - std::string sendPacketsToIfaceName = std::string(optarg); - sendPacketsToIface = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(sendPacketsToIfaceName); + const std::string sendPacketsToIfaceName = std::string(optarg); + sendPacketsToIface = pcpp::PfRingDeviceList::getInstance().getDeviceByName(sendPacketsToIfaceName); if (sendPacketsToIface == nullptr) + { EXIT_WITH_ERROR("Could not find PF_RING device '" << sendPacketsToIfaceName << "'"); + } break; } case 't': { - numOfCaptureThreads = atoi(optarg); + numOfCaptureThreads = std::stoi(optarg); if (numOfCaptureThreads < 1 || numOfCaptureThreads > totalNumOfCores - 1) + { EXIT_WITH_ERROR("Number of capture threads must be in the range of 1 to " << totalNumOfCores - 1); + } break; } case 'f': @@ -305,7 +300,9 @@ int main(int argc, char* argv[]) packetFilePath = std::string(optarg); // make sure the path ends with '/' if (packetFilePath.length() > 1 && (0 != packetFilePath.compare(packetFilePath.length() - 1, 1, "/"))) + { packetFilePath += "/"; + } writePacketsToDisk = true; break; @@ -336,7 +333,7 @@ int main(int argc, char* argv[]) } case 'p': { - int ret = atoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); @@ -346,7 +343,7 @@ int main(int argc, char* argv[]) } case 'P': { - int ret = atoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); @@ -356,11 +353,15 @@ int main(int argc, char* argv[]) } case 'r': { - std::string protocol = std::string(optarg); + std::string const protocol = std::string(optarg); if (protocol == "TCP") + { protocolToMatch = pcpp::TCP; + } else if (protocol == "UDP") + { protocolToMatch = pcpp::UDP; + } else { EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); @@ -391,17 +392,23 @@ int main(int argc, char* argv[]) } if (dev == nullptr) + { EXIT_WITH_ERROR_AND_PRINT_USAGE("Interface name was not provided"); + } // open the PF_RING device in multi-thread mode. Distribution of packets between threads will be done per-flow (as // opposed to round-robin) if (!dev->openMultiRxChannels(numOfCaptureThreads, pcpp::PfRingDevice::PerFlow)) + { EXIT_WITH_ERROR("Couldn't open " << numOfCaptureThreads << " RX channels on interface '" << dev->getDeviceName() << "'"); + } if (sendPacketsToIface != nullptr && !sendPacketsToIface->open()) + { EXIT_WITH_ERROR("Couldn't open PF_RING device '" << sendPacketsToIface->getDeviceName() << "' for sending matched packets"); + } pcpp::CoreMask coreMask = 0; int threadId = 0; @@ -412,7 +419,9 @@ int main(int argc, char* argv[]) // init each packet stats instance with an illegal core ID for (int coreId = 0; coreId < totalNumOfCores; coreId++) + { packetStatsArr[coreId].ThreadId = MAX_NUM_OF_CORES + 1; + } // mark only relevant cores by adding them to core mask // mark only relevant packet stats instances by setting their core ID @@ -461,7 +470,7 @@ int main(int argc, char* argv[]) } std::cout << "Start capturing on " << numOfCaptureThreads << " threads core mask = 0x" << std::hex << coreMask - << std::dec << std::endl; + << std::dec << '\n'; // prepare packet capture configuration CaptureThreadArgs args; @@ -499,14 +508,16 @@ int main(int argc, char* argv[]) for (int coreId = 0; coreId < totalNumOfCores; coreId++) { if ((coreMask & pcpp::SystemCores::IdToSystemCore[coreId].Mask) == 0) + { continue; + } pcapWriters[coreId]->close(); delete pcapWriters[coreId]; } } - std::cout << std::endl << std::endl << "Application stopped" << std::endl; + std::cout << '\n' << '\n' << "Application stopped" << '\n'; // print final stats for every capture thread plus sum of all threads and free worker threads memory PacketStats aggregatedStats; @@ -520,7 +531,9 @@ int main(int argc, char* argv[]) for (int i = 0; i < totalNumOfCores; i++) { if (packetStatsArr[i].ThreadId == MAX_NUM_OF_CORES + 1) + { continue; + } aggregatedStats.collectStats(packetStatsArr[i]); printer.printRow(packetStatsArr[i].getStatValuesAsString("|"), '|'); diff --git a/Examples/SSLAnalyzer/SSLStatsCollector.h b/Examples/SSLAnalyzer/SSLStatsCollector.h index c7015baa20..00d9268baf 100644 --- a/Examples/SSLAnalyzer/SSLStatsCollector.h +++ b/Examples/SSLAnalyzer/SSLStatsCollector.h @@ -26,27 +26,27 @@ struct Rate struct SSLGeneralStats { // total number of SSL flows - int numOfSSLFlows; + int numOfSSLFlows{}; // rate of SSL flows - Rate sslFlowRate; + Rate sslFlowRate{}; // total number of SSL packets - int numOfSSLPackets; + int numOfSSLPackets{}; // rate of SSL packets - Rate sslPacketRate; + Rate sslPacketRate{}; // average number of SSL packets per flow - double averageNumOfPacketsPerFlow; + double averageNumOfPacketsPerFlow{}; // total SSL traffic in bytes - int amountOfSSLTraffic; + int amountOfSSLTraffic{}; // average number of SSL traffic per flow - double averageAmountOfDataPerFlow; + double averageAmountOfDataPerFlow{}; // rate of SSL traffic - Rate sslTrafficRate; + Rate sslTrafficRate{}; // total stats collection time - double sampleTime; + double sampleTime{}; // number of flows which handshake was complete - int numOfHandshakeCompleteFlows; + int numOfHandshakeCompleteFlows{}; // number of flows that were terminated because of SSL/TLS alert - int numOfFlowsWithAlerts; + int numOfFlowsWithAlerts{}; // number of flows per SSL/TLS version std::unordered_map sslVersionCount; // number of flows per TCP port @@ -79,14 +79,13 @@ struct SSLGeneralStats struct ClientHelloStats { // total number of client-hello messages - int numOfMessages; + int numOfMessages{}; // rate of client-hello messages - Rate messageRate; + Rate messageRate{}; // a map for counting the server names seen in traffic std::unordered_map serverNameCount; - virtual ~ClientHelloStats() - {} + virtual ~ClientHelloStats() = default; virtual void clear() { @@ -103,14 +102,13 @@ struct ClientHelloStats struct ServerHelloStats { // total number of server-hello messages - int numOfMessages; + int numOfMessages{}; // rate of server-hello messages - Rate messageRate; + Rate messageRate{}; // count of the different chosen cipher-suites std::unordered_map cipherSuiteCount; - virtual ~ServerHelloStats() - {} + virtual ~ServerHelloStats() = default; virtual void clear() { @@ -142,10 +140,12 @@ class SSLStatsCollector { // verify packet is TCP and SSL/TLS if (!sslPacket->isPacketOfType(pcpp::TCP) || !sslPacket->isPacketOfType(pcpp::SSL)) + { return; + } // collect general SSL traffic stats on this packet - uint32_t hashVal = collectSSLTrafficStats(sslPacket); + const uint32_t hashVal = collectSSLTrafficStats(sslPacket); // if packet contains one or more SSL messages, collect stats on them if (sslPacket->isPacketOfType(pcpp::SSL)) @@ -163,10 +163,10 @@ class SSLStatsCollector void calcRates() { // getting current machine time - double curTime = getCurTime(); + const double curTime = getCurTime(); // getting time from last rate calculation until now - double diffSec = curTime - m_LastCalcRateTime; + const double diffSec = curTime - m_LastCalcRateTime; // calculating current rates which are the changes from last rate calculation until now divided by the time // passed from last rate calculation until now @@ -185,7 +185,7 @@ class SSLStatsCollector } // getting the time from the beginning of stats collection until now - double diffSecTotal = curTime - m_StartTime; + const double diffSecTotal = curTime - m_StartTime; // calculating total rate which is the change from beginning of stats collection until now divided by time // passed from beginning of stats collection until now @@ -270,16 +270,16 @@ class SSLStatsCollector */ uint32_t collectSSLTrafficStats(pcpp::Packet* sslpPacket) { - pcpp::TcpLayer* tcpLayer = sslpPacket->getLayerOfType(); + auto* tcpLayer = sslpPacket->getLayerOfType(); // count traffic - m_GeneralStats.amountOfSSLTraffic += tcpLayer->getLayerPayloadSize(); + m_GeneralStats.amountOfSSLTraffic += static_cast(tcpLayer->getLayerPayloadSize()); // count packet num m_GeneralStats.numOfSSLPackets++; // calculate a hash key for this flow to be used in the flow table - uint32_t hashVal = hash5Tuple(sslpPacket); + const uint32_t hashVal = hash5Tuple(sslpPacket); // if flow is a new flow (meaning it's not already in the flow table) if (m_FlowTable.find(hashVal) == m_FlowTable.end()) @@ -288,18 +288,22 @@ class SSLStatsCollector m_GeneralStats.numOfSSLFlows++; // find the SSL/TLS port and add it to the port count - uint16_t srcPort = tcpLayer->getSrcPort(); - uint16_t dstPort = tcpLayer->getDstPort(); + const uint16_t srcPort = tcpLayer->getSrcPort(); + const uint16_t dstPort = tcpLayer->getDstPort(); if (pcpp::SSLLayer::isSSLPort(srcPort)) + { m_GeneralStats.sslPortCount[srcPort]++; + } else + { m_GeneralStats.sslPortCount[dstPort]++; + } m_FlowTable[hashVal].clear(); } // calculate averages - if (m_FlowTable.size() != 0) + if (!m_FlowTable.empty()) { m_GeneralStats.averageAmountOfDataPerFlow = static_cast(m_GeneralStats.amountOfSSLTraffic) / static_cast(m_FlowTable.size()); @@ -316,15 +320,15 @@ class SSLStatsCollector void collectSSLStats(pcpp::Packet* sslPacket, uint32_t flowKey) { // go over all SSL messages in this packet - pcpp::SSLLayer* sslLayer = sslPacket->getLayerOfType(); + auto* sslLayer = sslPacket->getLayerOfType(); while (sslLayer != nullptr) { // check if the layer is an alert message - pcpp::SSLRecordType recType = sslLayer->getRecordType(); + const pcpp::SSLRecordType recType = sslLayer->getRecordType(); if (recType == pcpp::SSL_ALERT) { // if it's the first alert seen in this flow - if (m_FlowTable[flowKey].seenAlertPacket == false) + if (!m_FlowTable[flowKey].seenAlertPacket) { m_GeneralStats.numOfFlowsWithAlerts++; m_FlowTable[flowKey].seenAlertPacket = true; @@ -335,7 +339,7 @@ class SSLStatsCollector else if (recType == pcpp::SSL_APPLICATION_DATA) { // if it's the first app data message seen on this flow it means handshake was completed - if (m_FlowTable[flowKey].seenAppDataPacket == false) + if (!m_FlowTable[flowKey].seenAppDataPacket) { m_GeneralStats.numOfHandshakeCompleteFlows++; m_FlowTable[flowKey].seenAppDataPacket = true; @@ -345,13 +349,14 @@ class SSLStatsCollector // check if the layer is an handshake message else if (recType == pcpp::SSL_HANDSHAKE) { - pcpp::SSLHandshakeLayer* handshakeLayer = dynamic_cast(sslLayer); + auto* handshakeLayer = dynamic_cast(sslLayer); if (handshakeLayer == nullptr) + { continue; + } // try to find client-hello message - pcpp::SSLClientHelloMessage* clientHelloMessage = - handshakeLayer->getHandshakeMessageOfType(); + auto* clientHelloMessage = handshakeLayer->getHandshakeMessageOfType(); // collect client-hello stats if (clientHelloMessage != nullptr) @@ -360,8 +365,7 @@ class SSLStatsCollector } // try to find server-hello message - pcpp::SSLServerHelloMessage* serverHelloMessage = - handshakeLayer->getHandshakeMessageOfType(); + auto* serverHelloMessage = handshakeLayer->getHandshakeMessageOfType(); // collect server-hello stats if (serverHelloMessage != nullptr) @@ -382,10 +386,11 @@ class SSLStatsCollector { m_ClientHelloStats.numOfMessages++; - pcpp::SSLServerNameIndicationExtension* sniExt = - clientHelloMessage->getExtensionOfType(); + auto* sniExt = clientHelloMessage->getExtensionOfType(); if (sniExt != nullptr) + { m_ClientHelloStats.serverNameCount[sniExt->getHostName()]++; + } } /** @@ -397,16 +402,18 @@ class SSLStatsCollector pcpp::SSLCipherSuite* cipherSuite = serverHelloMessage->getCipherSuite(); if (cipherSuite != nullptr) + { m_ServerHelloStats.cipherSuiteCount[cipherSuite->asString()]++; + } } - double getCurTime(void) + static double getCurTime() { - struct timeval tv; + struct timeval tmVal{}; - gettimeofday(&tv, nullptr); + gettimeofday(&tmVal, nullptr); - return ((static_cast(tv.tv_sec)) + static_cast(tv.tv_usec / 1000000.0)); + return ((static_cast(tmVal.tv_sec)) + (static_cast(tmVal.tv_usec) / 1000000.0)); } SSLGeneralStats m_GeneralStats; @@ -418,6 +425,6 @@ class SSLStatsCollector std::unordered_map m_FlowTable; - double m_LastCalcRateTime; - double m_StartTime; + double m_LastCalcRateTime{}; + double m_StartTime{}; }; diff --git a/Examples/SSLAnalyzer/main.cpp b/Examples/SSLAnalyzer/main.cpp index e22f52d258..ed2fbd68fe 100644 --- a/Examples/SSLAnalyzer/main.cpp +++ b/Examples/SSLAnalyzer/main.cpp @@ -34,16 +34,16 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) #define PRINT_STAT_LINE(description, counter, measurement) \ std::cout << std::left << std::setw(46) << (std::string(description) + ":") << std::right << std::setw(15) \ << std::fixed << std::showpoint << std::setprecision(3) << counter << " [" << measurement << "]" \ - << std::endl; + << '\n'; -#define DEFAULT_CALC_RATES_PERIOD_SEC 2 +constexpr auto DEFAULT_CALC_RATES_PERIOD_SEC = 2; // clang-format off static struct option SSLAnalyzerOptions[] = { @@ -70,37 +70,36 @@ struct SSLPacketArrivedData */ void printUsage() { - std::cout << std::endl - << "Usage: PCAP file mode:" << std::endl - << "----------------------" << std::endl - << pcpp::AppName::get() << " [-hv] -f input_file" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" - << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl - << "Usage: Live traffic mode:" << std::endl - << "-------------------------" << std::endl - << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] -i interface" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl + std::cout << '\n' + << "Usage: PCAP file mode:" << '\n' + << "----------------------" << '\n' + << pcpp::AppName::get() << " [-hv] -f input_file" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Displays this help message and exits" << '\n' + << '\n' + << "Usage: Live traffic mode:" << '\n' + << "-------------------------" << '\n' + << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] -i interface" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " "address" - << std::endl + << '\n' << " -o output_file : Save all captured SSL packets to a pcap file. Notice this may cause performance " "degradation" - << std::endl + << '\n' << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" - << std::endl - << " -d : Disable periodic rates calculation" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << std::endl; + << '\n' + << " -d : Disable periodic rates calculation" << '\n' + << " -v : Displays the current version and exists" << '\n' + << " -h : Displays this help message and exits" << '\n' + << " -l : Print the list of interfaces and exists" << '\n' + << '\n'; } /** @@ -108,9 +107,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -122,11 +121,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -139,18 +138,18 @@ void printStatsHeadline(const std::string& description) underline += "-"; } - std::cout << std::endl << description << std::endl << underline << std::endl << std::endl; + std::cout << '\n' << description << '\n' << underline << '\n' << '\n'; } /** * packet capture callback - called whenever a packet arrives */ -void sslPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) +void sslPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* /*dev*/, void* cookie) { // parse the packet pcpp::Packet parsedPacket(packet); - SSLPacketArrivedData* data = static_cast(cookie); + auto* data = static_cast(cookie); // give the packet to the collector data->statsCollector->collectStats(&parsedPacket); @@ -193,8 +192,8 @@ void printServerNames(ClientHelloStats& clientHelloStatsCollector) { // create the table std::vector columnNames; - columnNames.push_back("Hostname"); - columnNames.push_back("Count"); + columnNames.emplace_back("Hostname"); + columnNames.emplace_back("Count"); std::vector columnsWidths; columnsWidths.push_back(40); columnsWidths.push_back(5); @@ -223,7 +222,7 @@ void printVersions(std::unordered_map& versionMap, const std::str // create the table std::vector columnNames; columnNames.push_back(headline); - columnNames.push_back("Count"); + columnNames.emplace_back("Count"); std::vector columnsWidths; columnsWidths.push_back(28); columnsWidths.push_back(5); @@ -250,8 +249,8 @@ void printCipherSuites(ServerHelloStats& serverHelloStats) { // create the table std::vector columnNames; - columnNames.push_back("Cipher-suite"); - columnNames.push_back("Count"); + columnNames.emplace_back("Cipher-suite"); + columnNames.emplace_back("Count"); std::vector columnsWidths; columnsWidths.push_back(50); columnsWidths.push_back(5); @@ -276,8 +275,8 @@ void printPorts(SSLGeneralStats& stats) { // create the table std::vector columnNames; - columnNames.push_back("SSL/TLS ports"); - columnNames.push_back("Count"); + columnNames.emplace_back("SSL/TLS ports"); + columnNames.emplace_back("Count"); std::vector columnsWidths; columnsWidths.push_back(13); columnsWidths.push_back(5); @@ -363,7 +362,9 @@ void analyzeSSLFromPcapFile(const std::string& pcapFileName) std::unique_ptr reader(pcpp::IFileReaderDevice::getReader(pcapFileName)); if (!reader->open()) + { EXIT_WITH_ERROR("Could not open input pcap file"); + } // read the input file packet by packet and give it to the SSLStatsCollector for collecting stats SSLStatsCollector collector; @@ -375,7 +376,7 @@ void analyzeSSLFromPcapFile(const std::string& pcapFileName) } // print stats summary - std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; + std::cout << '\n' << '\n' << "STATS SUMMARY" << '\n' << "=============" << '\n'; printStatsSummary(collector); // close input file @@ -390,7 +391,9 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi { // open the device if (!dev->open()) + { EXIT_WITH_ERROR("Could not open the device"); + } // set SSL/TLS ports filter on the live device to capture only SSL/TLS packets std::vector portFilterVec; @@ -399,8 +402,12 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi // The check is made for well known ports because currently SSLLayer does not support customizing of ports // considered as SSL/TLS. for (uint16_t port = 0; port < 1024; ++port) + { if (pcpp::SSLLayer::isSSLPort(port)) + { portFilterVec.push_back(new pcpp::PortFilter(port, pcpp::SRC_OR_DST)); + } + } // make an OR filter out of all port filters pcpp::OrFilter orFilter(portFilterVec); @@ -415,9 +422,9 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi // if needed to save the captured packets to file - open a writer device std::unique_ptr pcapWriter; - if (savePacketsToFileName != "") + if (!savePacketsToFileName.empty()) { - pcapWriter.reset(new pcpp::PcapFileWriterDevice(savePacketsToFileName)); + pcapWriter = std::make_unique(savePacketsToFileName); if (!pcapWriter->open()) { EXIT_WITH_ERROR("Could not open pcap file for writing"); @@ -425,7 +432,7 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi } // start capturing packets and collecting stats - SSLPacketArrivedData data; + SSLPacketArrivedData data{}; SSLStatsCollector collector; data.statsCollector = &collector; data.pcapWriter = pcapWriter.get(); @@ -455,7 +462,7 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi collector.calcRates(); // print stats summary - std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; + std::cout << '\n' << '\n' << "STATS SUMMARY" << '\n' << "=============" << '\n'; printStatsSummary(collector); // close and free the writer device @@ -472,12 +479,12 @@ int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - std::string interfaceNameOrIP = ""; + std::string interfaceNameOrIP; bool printRatesPeriodically = true; int printRatePeriod = DEFAULT_CALC_RATES_PERIOD_SEC; - std::string savePacketsToFileName = ""; + std::string savePacketsToFileName; - std::string readPacketsFromPcapFileName = ""; + std::string readPacketsFromPcapFileName; int optionIndex = 0; int opt = 0; @@ -498,7 +505,7 @@ int main(int argc, char* argv[]) savePacketsToFileName = optarg; break; case 'r': - printRatePeriod = atoi(optarg); + printRatePeriod = std::stoi(optarg); break; case 'd': printRatesPeriodically = false; @@ -520,11 +527,13 @@ int main(int argc, char* argv[]) } // if no interface nor input pcap file were provided - exit with error - if (readPacketsFromPcapFileName == "" && interfaceNameOrIP == "") + if (readPacketsFromPcapFileName.empty() && interfaceNameOrIP.empty()) + { EXIT_WITH_ERROR("Neither interface nor input pcap file were provided"); + } // analyze in pcap file mode - if (readPacketsFromPcapFileName != "") + if (!readPacketsFromPcapFileName.empty()) { analyzeSSLFromPcapFile(readPacketsFromPcapFileName); } @@ -533,7 +542,9 @@ int main(int argc, char* argv[]) // extract pcap live device by interface name or IP address pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } // start capturing and analyzing traffic analyzeSSLFromLiveTraffic(dev, printRatesPeriodically, printRatePeriod, savePacketsToFileName); diff --git a/Examples/TLSFingerprinting/main.cpp b/Examples/TLSFingerprinting/main.cpp index 1cdaf57828..2454914814 100644 --- a/Examples/TLSFingerprinting/main.cpp +++ b/Examples/TLSFingerprinting/main.cpp @@ -44,7 +44,7 @@ static struct option TLSFingerprintingOptions[] = { do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -52,9 +52,9 @@ static struct option TLSFingerprintingOptions[] = { #define TLS_FP_SH_ONLY "sh" #define TLS_FP_CH_AND_SH "ch_sh" -bool isNotAlphanumeric(char c) +bool isNotAlphanumeric(char chr) { - return std::isalnum(c) == 0; + return std::isalnum(chr) == 0; } /** @@ -75,55 +75,52 @@ bool stringCountComparer(const std::pair& first, const st void printUsage() { std::cout - << std::endl - << "Usage:" << std::endl - << "------" << std::endl + << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvlcms] [-r input_file] [-i interface] [-o output_file_name] [-s separator] [-t tls_fp_type] [-f " "bpf_filter]" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" - << std::endl + << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or IP address." - << std::endl - << " Required argument for capturing from live interface" << std::endl + << '\n' + << " Required argument for capturing from live interface" << '\n' << " -o output_file_name : Output file name. This is a csv file (where 'tab' is the default separator)" - << std::endl - << " which contains information about all of the TLS fingerprints found in the" - << std::endl - << " capture file or live interface. It includes the TLS fingerprint itself" - << std::endl + << '\n' + << " which contains information about all of the TLS fingerprints found in the" << '\n' + << " capture file or live interface. It includes the TLS fingerprint itself" << '\n' << " (raw string and MD5), IP addresses, TCP ports and SSL message type (ClientHello" - << std::endl + << '\n' << " or ServerHello). If this argument is not specified the output file name is the" - << std::endl + << '\n' << " name of capture file or the live interface and it is written to the current" - << std::endl - << " directory ('.')" << std::endl + << '\n' + << " directory ('.')" << '\n' << " -s separator : The separator to use in the csv output file. Valid values are a single character" - << std::endl + << '\n' << " which is not alphanumeric and not one of the following: '.', ',', ':', '-'." - << std::endl - << " If this argument is not specified the default separator is 'tab' ('\\t')" - << std::endl + << '\n' + << " If this argument is not specified the default separator is 'tab' ('\\t')" << '\n' << " -t tls_fp_type : Specify whether to calculate TLS fingerprints for ClientHello packets only " "('ch')," - << std::endl + << '\n' << " ServerHello packets only ('sh') or both ('ch_sh'). The only valid values are" - << std::endl + << '\n' << " 'ch', 'sh', 'ch_sh'. If this argument is not specified the default value is" - << std::endl - << " ClientHello ('ch')" << std::endl + << '\n' + << " ClientHello ('ch')" << '\n' << " -f bpf_filter : Apply a BPF filter to the capture file or live interface, meaning TLS fingerprint" - << std::endl - << " will only be generated for the filtered packets" << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << '\n' + << " will only be generated for the filtered packets" << '\n' + << " -l : Print the list of interfaces and exit" << '\n' + << " -v : Display the current version and exit" << '\n' + << " -h : Display this help message and exit" << '\n' + << '\n'; } /** @@ -131,9 +128,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -145,11 +142,11 @@ void listInterfaces() const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -159,7 +156,7 @@ void listInterfaces() */ static void onApplicationInterrupted(void* cookie) { - bool* shouldStop = (bool*)cookie; + bool* shouldStop = reinterpret_cast(cookie); *shouldStop = true; } @@ -168,14 +165,15 @@ static void onApplicationInterrupted(void* cookie) */ std::pair getIPs(const pcpp::Packet& packet) { - pcpp::IPAddress srcIP, dstIP; + pcpp::IPAddress srcIP; + pcpp::IPAddress dstIP; if (packet.isPacketOfType(pcpp::IP)) { const pcpp::IPLayer* ipLayer = packet.getLayerOfType(); srcIP = ipLayer->getSrcIPAddress(); dstIP = ipLayer->getDstIPAddress(); } - return std::pair(srcIP, dstIP); + return { srcIP, dstIP }; } /** @@ -183,15 +181,16 @@ std::pair getIPs(const pcpp::Packet& packet) */ std::pair getTcpPorts(const pcpp::Packet& packet) { - uint16_t srcPort = 0, dstPort = 0; + uint16_t srcPort = 0; + uint16_t dstPort = 0; if (packet.isPacketOfType(pcpp::TCP)) { - pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); + auto* tcpLayer = packet.getLayerOfType(); srcPort = tcpLayer->getSrcPort(); dstPort = tcpLayer->getDstPort(); } - return std::pair(srcPort, dstPort); + return { srcPort, dstPort }; } /** @@ -202,12 +201,12 @@ std::pair getTcpPorts(const pcpp::Packet& packet) void writeToOutputFile(std::ofstream* outputFile, const pcpp::Packet& parsedPacket, const std::string& tlsFPString, const std::string& tlsFP_MD5, const std::string& tlsFPType, const std::string& separator) { - std::pair ipSrcDest = getIPs(parsedPacket); - std::pair tcpPorts = getTcpPorts(parsedPacket); + const std::pair ipSrcDest = getIPs(parsedPacket); + const std::pair tcpPorts = getTcpPorts(parsedPacket); *outputFile << tlsFP_MD5 << separator << tlsFPString << separator << tlsFPType << separator << ipSrcDest.first.toString() << separator << tcpPorts.first << separator << ipSrcDest.second.toString() - << separator << tcpPorts.second << std::endl; + << separator << tcpPorts.second << '\n'; } /** @@ -217,27 +216,26 @@ void writeHeaderToOutputFile(std::ofstream& outputFile, const std::string& separ { outputFile << "TLS Fingerprint (MD5)" << separator << "TLS Fingerprint" << separator << "TLS Fingerprint type" << separator << "IP Source" << separator << "TCP Source Port" << separator << "IP Dest" << separator - << "TCP Dest Port" << std::endl; + << "TCP Dest Port" << '\n'; } struct TLSFingerprintingStats { - TLSFingerprintingStats() : numOfPacketsTotal(0), numOfCHPackets(0), numOfSHPackets(0) - {} - uint64_t numOfPacketsTotal; - uint64_t numOfCHPackets; - uint64_t numOfSHPackets; + TLSFingerprintingStats() = default; + uint64_t numOfPacketsTotal{ 0 }; + uint64_t numOfCHPackets{ 0 }; + uint64_t numOfSHPackets{ 0 }; std::unordered_map chFingerprints; std::unordered_map shFingerprints; }; struct HandlePacketData { - bool chFP; - bool shFP; - std::ofstream* outputFile; + bool chFP{}; + bool shFP{}; + std::ofstream* outputFile{}; std::string separator; - TLSFingerprintingStats* stats; + TLSFingerprintingStats* stats{}; }; /** @@ -247,8 +245,8 @@ void printCommonTLSFingerprints(const std::unordered_map& { // create the table std::vector columnNames; - columnNames.push_back("TLS Fingerprint"); - columnNames.push_back("Count"); + columnNames.emplace_back("TLS Fingerprint"); + columnNames.emplace_back("Count"); std::vector columnsWidths; columnsWidths.push_back(32); columnsWidths.push_back(7); @@ -263,7 +261,9 @@ void printCommonTLSFingerprints(const std::unordered_map& for (auto iter = map2vec.begin(); iter != map2vec.end(); ++iter) { if (iter - map2vec.begin() >= printCountItems) + { break; + } std::stringstream values; values << iter->first << "|" << iter->second; @@ -277,47 +277,51 @@ void printCommonTLSFingerprints(const std::unordered_map& void printStats(const TLSFingerprintingStats& stats, bool chFP, bool shFP) { std::stringstream stream; - stream << std::endl; - stream << "Summary:" << std::endl; - stream << "========" << std::endl; - stream << "Total packets read: " << stats.numOfPacketsTotal << std::endl; + stream << '\n'; + stream << "Summary:" << '\n'; + stream << "========" << '\n'; + stream << "Total packets read: " << stats.numOfPacketsTotal << '\n'; if (chFP) { - stream << "TLS ClientHello packets: " << stats.numOfCHPackets << std::endl; - stream << "Unique ClientHello TLS fingerprints: " << stats.chFingerprints.size() << std::endl; + stream << "TLS ClientHello packets: " << stats.numOfCHPackets << '\n'; + stream << "Unique ClientHello TLS fingerprints: " << stats.chFingerprints.size() << '\n'; } if (shFP) { - stream << "TLS ServerHello packets: " << stats.numOfSHPackets << std::endl; - stream << "Unique ServerHello TLS fingerprints: " << stats.shFingerprints.size() << std::endl; + stream << "TLS ServerHello packets: " << stats.numOfSHPackets << '\n'; + stream << "Unique ServerHello TLS fingerprints: " << stats.shFingerprints.size() << '\n'; } - std::cout << stream.str() << std::endl; + std::cout << stream.str() << '\n'; // write a table of the 10 most common TLS fingerprints // if user requested to extract ClientHello TLS fingerprints and there is data to show - if (chFP && stats.chFingerprints.size() > 0) + if (chFP && !stats.chFingerprints.empty()) { if (stats.chFingerprints.size() > 10) + { std::cout << "Top 10 "; - std::cout << "ClientHello TLS fingerprints:" << std::endl; + } + std::cout << "ClientHello TLS fingerprints:" << '\n'; // write no more than 10 most common TLS fingerprints printCommonTLSFingerprints(stats.chFingerprints, 10); - std::cout << std::endl; + std::cout << '\n'; } // if user requested to extract ServerHello TLS fingerprints and there is data to show - if (shFP && stats.shFingerprints.size() > 0) + if (shFP && !stats.shFingerprints.empty()) { if (stats.shFingerprints.size() > 10) + { std::cout << "Top 10 "; - std::cout << "ServerHello TLS fingerprints:" << std::endl; + } + std::cout << "ServerHello TLS fingerprints:" << '\n'; // write no more than 10 most common TLS fingerprints printCommonTLSFingerprints(stats.shFingerprints, 10); - std::cout << std::endl; + std::cout << '\n'; } } @@ -327,20 +331,19 @@ void printStats(const TLSFingerprintingStats& stats, bool chFP, bool shFP) */ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) { - pcpp::Packet parsedPacket(rawPacket); + const pcpp::Packet parsedPacket(rawPacket); data->stats->numOfPacketsTotal++; if (parsedPacket.isPacketOfType(pcpp::SSL)) { // extract the SSL/TLS handhsake layer - pcpp::SSLHandshakeLayer* sslHandshakeLayer = parsedPacket.getLayerOfType(); + auto* sslHandshakeLayer = parsedPacket.getLayerOfType(); if (sslHandshakeLayer != nullptr) { // if user requested to extract ClientHello TLS fingerprint if (data->chFP) { // check if the SSL/TLS handhsake layer contains a ClientHello message - pcpp::SSLClientHelloMessage* clientHelloMessage = - sslHandshakeLayer->getHandshakeMessageOfType(); + auto* clientHelloMessage = sslHandshakeLayer->getHandshakeMessageOfType(); if (clientHelloMessage != nullptr) { data->stats->numOfCHPackets++; @@ -348,7 +351,8 @@ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) // extract the TLS fingerprint pcpp::SSLClientHelloMessage::ClientHelloTLSFingerprint tlsFingerprint = clientHelloMessage->generateTLSFingerprint(); - std::pair tlsFingerprintStringAndMD5 = tlsFingerprint.toStringAndMD5(); + std::pair const tlsFingerprintStringAndMD5 = + tlsFingerprint.toStringAndMD5(); data->stats->chFingerprints[tlsFingerprintStringAndMD5.second]++; // write data to output file writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, @@ -360,8 +364,7 @@ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) if (data->shFP) { // check if the SSL/TLS handhsake layer contains a ServerHello message - pcpp::SSLServerHelloMessage* servertHelloMessage = - sslHandshakeLayer->getHandshakeMessageOfType(); + auto* servertHelloMessage = sslHandshakeLayer->getHandshakeMessageOfType(); if (servertHelloMessage != nullptr) { data->stats->numOfSHPackets++; @@ -369,7 +372,8 @@ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) // extract the TLS fingerprint pcpp::SSLServerHelloMessage::ServerHelloTLSFingerprint tlsFingerprint = servertHelloMessage->generateTLSFingerprint(); - std::pair tlsFingerprintStringAndMD5 = tlsFingerprint.toStringAndMD5(); + std::pair const tlsFingerprintStringAndMD5 = + tlsFingerprint.toStringAndMD5(); data->stats->shFingerprints[tlsFingerprintStringAndMD5.second]++; // write data to output file writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, @@ -387,18 +391,20 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st const std::string& separator, bool chFP, bool shFP, const std::string& bpfFilter) { // open input file (pcap or pcapng file) - pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader(inputPcapFileName.c_str()); + pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader(inputPcapFileName); // try to open the file device if (!reader->open()) + { EXIT_WITH_ERROR("Cannot open pcap/pcapng file"); + } // set output file name to input file name if not provided by the user if (outputFileName.empty()) { - size_t fileNameOffset = inputPcapFileName.find_last_of("\\/") + 1; - size_t extensionOffset = inputPcapFileName.find_last_of("."); - std::string fileNameWithoutExtension = + const size_t fileNameOffset = inputPcapFileName.find_last_of("\\/") + 1; + const size_t extensionOffset = inputPcapFileName.find_last_of('.'); + const std::string fileNameWithoutExtension = inputPcapFileName.substr(fileNameOffset, extensionOffset - fileNameOffset); outputFileName = fileNameWithoutExtension + ".txt"; } @@ -417,10 +423,12 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st if (!bpfFilter.empty()) { if (!reader->setFilter(bpfFilter)) + { EXIT_WITH_ERROR("Error in setting BPF filter to the pcap file"); + } } - std::cout << "Start reading '" << inputPcapFileName << "'..." << std::endl; + std::cout << "Start reading '" << inputPcapFileName << "'..." << '\n'; TLSFingerprintingStats stats; HandlePacketData data; @@ -444,15 +452,15 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st printStats(stats, chFP, shFP); - std::cout << "Output file was written to: '" << outputFileName << "'" << std::endl; + std::cout << "Output file was written to: '" << outputFileName << "'" << '\n'; } /** * packet capture callback - called whenever a packet arrives on the live interface (in live device capturing mode) */ -static void onPacketArrives(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* cookie) +static void onPacketArrives(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* /*dev*/, void* cookie) { - HandlePacketData* data = static_cast(cookie); + auto* data = static_cast(cookie); handlePacket(rawPacket, data); } @@ -465,10 +473,14 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: // extract pcap live device by interface name or IP address pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by given IP address or name"); + } if (!dev->open()) + { EXIT_WITH_ERROR("Couldn't open interface"); + } // set output file name to interface name if not provided by the user if (outputFileName.empty()) @@ -495,10 +507,12 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: if (!bpfFilter.empty()) { if (!dev->setFilter(bpfFilter)) + { EXIT_WITH_ERROR("Error in setting BPF filter to interface"); + } } - std::cout << "Start capturing packets from '" << interfaceNameOrIP << "'..." << std::endl; + std::cout << "Start capturing packets from '" << interfaceNameOrIP << "'..." << '\n'; TLSFingerprintingStats stats; HandlePacketData data; @@ -517,7 +531,9 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: // run in an endless loop until the user press ctrl+c while (!shouldStop) + { std::this_thread::sleep_for(std::chrono::seconds(1)); + } // stop capturing and close the live device dev->stopCapture(); @@ -525,7 +541,7 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: printStats(stats, chFP, shFP); - std::cout << "Output file was written to: '" << outputFileName << "'" << std::endl; + std::cout << "Output file was written to: '" << outputFileName << "'" << '\n'; } /** @@ -596,7 +612,7 @@ int main(int argc, char* argv[]) std::vector disallowedSeparatorsVec(disallowedSeparatorsArr, disallowedSeparatorsArr + sizeof(disallowedSeparatorsArr) / sizeof(disallowedSeparatorsArr[0])); - if (separator.empty() || separator.size() > 1 || std::isalnum(separator[0]) || + if (separator.empty() || separator.size() > 1 || (std::isalnum(separator[0]) != 0) || std::find(disallowedSeparatorsVec.begin(), disallowedSeparatorsVec.end(), separator) != disallowedSeparatorsVec.end()) { @@ -612,7 +628,8 @@ int main(int argc, char* argv[]) "'ch_sh' (Client Hello & Server Hello)\n"); } - bool chFP = true, shFP = true; + bool chFP = true; + bool shFP = true; if (tlsFingerprintType == TLS_FP_CH_ONLY) { shFP = false; diff --git a/Examples/TcpReassembly/main.cpp b/Examples/TcpReassembly/main.cpp index 69e5c69b1e..e381e70d84 100644 --- a/Examples/TcpReassembly/main.cpp +++ b/Examples/TcpReassembly/main.cpp @@ -39,7 +39,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -77,29 +77,27 @@ class GlobalConfig /** * A private c'tor (as this is a singleton) */ - GlobalConfig() - : m_RecentConnsWithActivity(nullptr), writeMetadata(false), writeToConsole(false), separateSides(false), - maxOpenFiles(DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) + GlobalConfig() : maxOpenFiles(DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) {} // A least-recently-used (LRU) list of all connections seen so far. Each connection is represented by its flow key. // This LRU list is used to decide which connection was seen least recently in case we reached max number of open // file descriptors and we need to decide which files to close - pcpp::LRUList* m_RecentConnsWithActivity; + pcpp::LRUList* m_RecentConnsWithActivity{ nullptr }; public: // a flag indicating whether to write a metadata file for each connection (containing several stats) - bool writeMetadata; + bool writeMetadata{ false }; // the directory to write files to (default is current directory) std::string outputDir; // a flag indicating whether to write TCP data to actual files or to console - bool writeToConsole; + bool writeToConsole{ false }; // a flag indicating whether to write both side of a connection to the same file (which is the default) or write // each side to a separate file - bool separateSides; + bool separateSides{ false }; // max number of allowed open files in each point in time size_t maxOpenFiles; @@ -115,7 +113,9 @@ class GlobalConfig // if user chooses to write to a directory other than the current directory - add the dir path to the return // value if (!outputDir.empty()) + { stream << outputDir << SEPARATOR; + } std::string sourceIP = connData.srcIP.toString(); std::string destIP = connData.dstIP.toString(); @@ -126,9 +126,13 @@ class GlobalConfig // side == 0 means data is sent from client->server if (side <= 0 || !useSeparateSides) + { stream << sourceIP << '.' << connData.srcPort << '-' << destIP << '.' << connData.dstPort; - else // side == 1 means data is sent from server->client + } + else + { // side == 1 means data is sent from server->client stream << destIP << '.' << connData.dstPort << '-' << sourceIP << '.' << connData.srcPort; + } // return the file path return stream.str(); @@ -142,13 +146,16 @@ class GlobalConfig { // if the user chooses to write only to console, don't open anything and return std::cout if (writeToConsole) + { return &std::cout; + } // open the file on the disk (with append or overwrite mode) if (reopen) + { return new std::ofstream(fileName.c_str(), std::ios_base::binary | std::ios_base::app); - else - return new std::ofstream(fileName.c_str(), std::ios_base::binary); + } + return new std::ofstream(fileName.c_str(), std::ios_base::binary); } /** @@ -160,7 +167,7 @@ class GlobalConfig if (!writeToConsole) { // close the file stream - auto fstream = (std::ofstream*)fileStream; + auto* fstream = dynamic_cast(fileStream); fstream->close(); // free the memory of the file stream @@ -177,7 +184,9 @@ class GlobalConfig // the side of the LRU list is determined by the max number of allowed open files at any point in time. Default // is DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES but the user can choose another number if (m_RecentConnsWithActivity == nullptr) + { m_RecentConnsWithActivity = new pcpp::LRUList(maxOpenFiles); + } // return the pointer return m_RecentConnsWithActivity; @@ -209,19 +218,19 @@ struct TcpReassemblyData { // pointer to 2 file stream - one for each side of the connection. If the user chooses to write both sides to the // same file (which is the default), only one file stream is used (index 0) - std::ostream* fileStreams[2]; + std::ostream* fileStreams[2]{}; // flags indicating whether the file in each side was already opened before. If the answer is yes, next time it'll // be opened in append mode (and not in overwrite mode) - bool reopenFileStreams[2]; + bool reopenFileStreams[2]{}; // a flag indicating on which side was the latest message on this connection - int8_t curSide; + int8_t curSide{}; // stats data: num of data packets on each side, bytes seen on each side and messages seen on each side - int numOfDataPackets[2]; - int numOfMessagesFromSide[2]; - int bytesFromSide[2]; + int numOfDataPackets[2]{}; + int numOfMessagesFromSide[2]{}; + int bytesFromSide[2]{}; /** * the default c'tor @@ -240,10 +249,14 @@ struct TcpReassemblyData { // close files on both sides if open if (fileStreams[0] != nullptr) + { GlobalConfig::getInstance().closeFileSteam(fileStreams[0]); + } if (fileStreams[1] != nullptr) + { GlobalConfig::getInstance().closeFileSteam(fileStreams[1]); + } } /** @@ -277,40 +290,40 @@ struct TcpReassemblyData }; // typedef representing the connection manager -typedef std::unordered_map TcpReassemblyConnMgr; +using TcpReassemblyConnMgr = std::unordered_map; /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() - << " [-hvlcms] [-r input_file] [-i interface] [-o output_dir] [-e bpf_filter] [-f max_files]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl + << " [-hvlcms] [-r input_file] [-i interface] [-o output_dir] [-e bpf_filter] [-f max_files]" << '\n' + << '\n' + << "Options:" << '\n' + << '\n' << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" - << std::endl + << '\n' << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " "address. Required argument for capturing from live interface" - << std::endl - << " -o output_dir : Specify output directory (default is '.')" << std::endl + << '\n' + << " -o output_dir : Specify output directory (default is '.')" << '\n' << " -e bpf_filter : Apply a BPF filter to capture file or live interface, meaning TCP reassembly " "will only work on filtered packets" - << std::endl - << " -f max_files : Maximum number of file descriptors to use" << std::endl - << " -c : Write all output to console (nothing will be written to files)" << std::endl - << " -m : Write a metadata file for each connection" << std::endl + << '\n' + << " -f max_files : Maximum number of file descriptors to use" << '\n' + << " -c : Write all output to console (nothing will be written to files)" << '\n' + << " -m : Write a metadata file for each connection" << '\n' << " -s : Write each side of each connection to a separate file (default is writing both " "sides of each connection to the same file)" - << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << '\n' + << " -l : Print the list of interfaces and exit" << '\n' + << " -v : Display the current version and exit" << '\n' + << " -h : Display this help message and exit" << '\n' + << '\n'; } /** @@ -318,9 +331,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -331,12 +344,12 @@ void listInterfaces() { auto const& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; - for (auto dev : devList) + for (auto* dev : devList) { std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() - << std::endl; + << '\n'; } exit(0); } @@ -347,7 +360,7 @@ void listInterfaces() static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::TcpStreamData& tcpData, void* userCookie) { // extract the connection manager from the user cookie - auto connMgr = (TcpReassemblyConnMgr*)userCookie; + auto* connMgr = reinterpret_cast(userCookie); // check if this flow already appears in the connection manager. If not add it auto flow = connMgr->find(tcpData.getConnectionData().flowKey); @@ -357,14 +370,18 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc flow = connMgr->find(tcpData.getConnectionData().flowKey); } - int8_t side; + int8_t side = 0; // if the user wants to write each side in a different file - set side as the sideIndex, otherwise write everything // to the same file ("side 0") if (GlobalConfig::getInstance().separateSides) + { side = sideIndex; + } else + { side = 0; + } // if the file stream on the relevant side isn't open yet (meaning it's the first data on this connection) if (flow->second.fileStreams[side] == nullptr) @@ -372,9 +389,9 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc // add the flow key of this connection to the list of open connections. If the return value isn't nullptr it // means that there are too many open files and we need to close the connection with least recently used file(s) // in order to open a new one. The connection with the least recently used file is the return value - uint32_t flowKeyToCloseFiles; - int result = GlobalConfig::getInstance().getRecentConnsWithActivity()->put(tcpData.getConnectionData().flowKey, - &flowKeyToCloseFiles); + uint32_t flowKeyToCloseFiles = 0; + const int result = GlobalConfig::getInstance().getRecentConnsWithActivity()->put( + tcpData.getConnectionData().flowKey, &flowKeyToCloseFiles); // if result equals to 1 it means we need to close the open files in this connection (the one with the least // recently used files) @@ -403,7 +420,7 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc // clang-format off // get the file name according to the 5-tuple etc. - std::string fileName = GlobalConfig::getInstance().getFileName(tcpData.getConnectionData(), sideIndex, GlobalConfig::getInstance().separateSides) + const std::string fileName = GlobalConfig::getInstance().getFileName(tcpData.getConnectionData(), sideIndex, GlobalConfig::getInstance().separateSides) + ".txt"; // clang-format on @@ -428,7 +445,8 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc flow->second.bytesFromSide[sideIndex] += (int)tcpData.getDataLength(); // write the new data to the file - flow->second.fileStreams[side]->write((char*)tcpData.getData(), tcpData.getDataLength()); + flow->second.fileStreams[side]->write(reinterpret_cast(tcpData.getData()), + static_cast(tcpData.getDataLength())); } /** @@ -438,7 +456,7 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& connectionData, void* userCookie) { // get a pointer to the connection manager - auto connMgr = (TcpReassemblyConnMgr*)userCookie; + auto* connMgr = reinterpret_cast(userCookie); // look for the connection in the connection manager auto connectionMngr = connMgr->find(connectionData.flowKey); @@ -456,37 +474,38 @@ static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& con * connection from the connection manager and writes the metadata file if requested by the user */ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& connectionData, - pcpp::TcpReassembly::ConnectionEndReason reason, void* userCookie) + pcpp::TcpReassembly::ConnectionEndReason /*reason*/, void* userCookie) { // get a pointer to the connection manager - auto connMgr = (TcpReassemblyConnMgr*)userCookie; + auto* connMgr = reinterpret_cast(userCookie); // find the connection in the connection manager by the flow key auto connection = connMgr->find(connectionData.flowKey); // connection wasn't found - shouldn't get here if (connection == connMgr->end()) + { return; + } // write a metadata file if required by the user if (GlobalConfig::getInstance().writeMetadata) { - std::string fileName = GlobalConfig::getInstance().getFileName(connectionData, 0, false) + "-metadata.txt"; + const std::string fileName = + GlobalConfig::getInstance().getFileName(connectionData, 0, false) + "-metadata.txt"; std::ofstream metadataFile(fileName.c_str()); - metadataFile << "Number of data packets in side 0: " << connection->second.numOfDataPackets[0] << std::endl; - metadataFile << "Number of data packets in side 1: " << connection->second.numOfDataPackets[1] << std::endl; + metadataFile << "Number of data packets in side 0: " << connection->second.numOfDataPackets[0] << '\n'; + metadataFile << "Number of data packets in side 1: " << connection->second.numOfDataPackets[1] << '\n'; metadataFile << "Total number of data packets: " - << (connection->second.numOfDataPackets[0] + connection->second.numOfDataPackets[1]) << std::endl; - metadataFile << std::endl; - metadataFile << "Number of bytes in side 0: " << connection->second.bytesFromSide[0] << std::endl; - metadataFile << "Number of bytes in side 1: " << connection->second.bytesFromSide[1] << std::endl; + << (connection->second.numOfDataPackets[0] + connection->second.numOfDataPackets[1]) << '\n'; + metadataFile << '\n'; + metadataFile << "Number of bytes in side 0: " << connection->second.bytesFromSide[0] << '\n'; + metadataFile << "Number of bytes in side 1: " << connection->second.bytesFromSide[1] << '\n'; metadataFile << "Total number of bytes: " - << (connection->second.bytesFromSide[0] + connection->second.bytesFromSide[1]) << std::endl; - metadataFile << std::endl; - metadataFile << "Number of messages in side 0: " << connection->second.numOfMessagesFromSide[0] - << std::endl; - metadataFile << "Number of messages in side 1: " << connection->second.numOfMessagesFromSide[1] - << std::endl; + << (connection->second.bytesFromSide[0] + connection->second.bytesFromSide[1]) << '\n'; + metadataFile << '\n'; + metadataFile << "Number of messages in side 0: " << connection->second.numOfMessagesFromSide[0] << '\n'; + metadataFile << "Number of messages in side 1: " << connection->second.numOfMessagesFromSide[1] << '\n'; metadataFile.close(); } @@ -499,17 +518,17 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne */ static void onApplicationInterrupted(void* cookie) { - bool* shouldStop = (bool*)cookie; + bool* shouldStop = reinterpret_cast(cookie); *shouldStop = true; } /** * packet capture callback - called whenever a packet arrives on the live device (in live device capturing mode) */ -static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* tcpReassemblyCookie) +static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* /*dev*/, void* tcpReassemblyCookie) { // get a pointer to the TCP reassembly instance and feed the packet arrived to it - auto tcpReassembly = (pcpp::TcpReassembly*)tcpReassemblyCookie; + auto* tcpReassembly = reinterpret_cast(tcpReassemblyCookie); tcpReassembly->reassemblePacket(packet); } @@ -524,16 +543,20 @@ void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& // try to open the file device if (!reader->open()) + { EXIT_WITH_ERROR("Cannot open pcap/pcapng file"); + } // set BPF filter if set by the user if (!bpfFilter.empty()) { if (!reader->setFilter(bpfFilter)) + { EXIT_WITH_ERROR("Cannot set BPF filter to pcap file"); + } } - std::cout << "Starting reading '" << fileName << "'..." << std::endl; + std::cout << "Starting reading '" << fileName << "'..." << '\n'; // run in a loop that reads one packet from the file in each iteration and feeds it to the TCP reassembly instance pcpp::RawPacket rawPacket; @@ -543,7 +566,7 @@ void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& } // extract number of connections before closing all of them - size_t numOfConnectionsProcessed = tcpReassembly.getConnectionInformation().size(); + const size_t numOfConnectionsProcessed = tcpReassembly.getConnectionInformation().size(); // after all packets have been read - close the connections which are still opened tcpReassembly.closeAllConnections(); @@ -552,7 +575,7 @@ void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& reader->close(); delete reader; - std::cout << "Done! processed " << numOfConnectionsProcessed << " connections" << std::endl; + std::cout << "Done! processed " << numOfConnectionsProcessed << " connections" << '\n'; } /** @@ -563,16 +586,20 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly { // try to open device if (!dev->open()) + { EXIT_WITH_ERROR("Cannot open interface"); + } // set BPF filter if set by the user if (!bpfFilter.empty()) { if (!dev->setFilter(bpfFilter)) + { EXIT_WITH_ERROR("Cannot set BPF filter to interface"); + } } - std::cout << "Starting packet capture on '" << dev->getIPv4Address() << "'..." << std::endl; + std::cout << "Starting packet capture on '" << dev->getIPv4Address() << "'..." << '\n'; // start capturing packets. Each packet arrived will be handled by onPacketArrives method dev->startCapture(onPacketArrives, &tcpReassembly); @@ -583,7 +610,9 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly // run in an endless loop until the user presses ctrl+c while (!shouldStop) + { std::this_thread::sleep_for(std::chrono::seconds(1)); + } // stop capturing and close the live device dev->stopCapture(); @@ -592,7 +621,7 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly // close all connections which are still opened tcpReassembly.closeAllConnections(); - std::cout << "Done! processed " << tcpReassembly.getConnectionInformation().size() << " connections" << std::endl; + std::cout << "Done! processed " << tcpReassembly.getConnectionInformation().size() << " connections" << '\n'; } /** @@ -612,7 +641,7 @@ int main(int argc, char* argv[]) size_t maxOpenFiles = DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES; int optionIndex = 0; - int opt; + int opt = 0; while ((opt = getopt_long(argc, argv, "i:r:o:e:f:mcsvhl", TcpAssemblyOptions, &optionIndex)) != -1) { @@ -642,7 +671,7 @@ int main(int argc, char* argv[]) writeToConsole = true; break; case 'f': - maxOpenFiles = (size_t)atoi(optarg); + maxOpenFiles = std::stoull(optarg); break; case 'h': printUsage(); @@ -661,11 +690,15 @@ int main(int argc, char* argv[]) // if no interface nor input pcap file were provided - exit with error if (inputPcapFileName.empty() && interfaceNameOrIP.empty()) + { EXIT_WITH_ERROR("Neither interface nor input pcap file were provided"); + } // verify output dir exists if (!outputDir.empty() && !pcpp::directoryExists(outputDir)) + { EXIT_WITH_ERROR("Output directory doesn't exist"); + } // set global config singleton with input configuration GlobalConfig::getInstance().outputDir = outputDir; @@ -691,7 +724,9 @@ int main(int argc, char* argv[]) // extract pcap live device by interface name or IP address pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) + { EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); + } // start capturing packets and do TCP reassembly doTcpReassemblyOnLiveTraffic(dev, tcpReassembly, bpfFilter); diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp index 0260cd7cb1..64f9fe26f4 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp @@ -18,7 +18,7 @@ bool L2FwdWorkerThread::run(uint32_t coreId) while (!m_Stop) { // receive packets from RX device - uint16_t numOfPackets = m_RxDevice->receivePackets(mbufArr, 64, 0); + const uint16_t numOfPackets = m_RxDevice->receivePackets(mbufArr, 64, 0); if (numOfPackets > 0) { diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h index aff9e96933..a5421f64ee 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h @@ -16,17 +16,16 @@ class L2FwdWorkerThread : public pcpp::DpdkWorkerThread L2FwdWorkerThread(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice); // d'tor (does nothing) - ~L2FwdWorkerThread() - {} + ~L2FwdWorkerThread() override = default; // implement abstract method // start running the worker thread - bool run(uint32_t coreId); + bool run(uint32_t coreId) override; // ask the worker thread to stop - void stop(); + void stop() override; // get worker thread core ID - uint32_t getCoreId() const; + uint32_t getCoreId() const override; }; diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp index 59459614f6..11c260c222 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp @@ -1,34 +1,35 @@ #include #include +#include #include #include "SystemUtils.h" #include "DpdkDeviceList.h" #include "TablePrinter.h" #include "WorkerThread.h" -#define MBUF_POOL_SIZE 16 * 1024 - 1 -#define DEVICE_ID_1 0 -#define DEVICE_ID_2 1 -#define COLLECT_STATS_EVERY_SEC 2 +constexpr auto MBUF_POOL_SIZE = 16 * 1024 - 1; +constexpr auto DEVICE_ID_1 = 0; +constexpr auto DEVICE_ID_2 = 1; +constexpr auto COLLECT_STATS_EVERY_SEC = 2; // Keep running flag bool keepRunning = true; -void onApplicationInterrupted(void* cookie) +void onApplicationInterrupted(void* /*cookie*/) { keepRunning = false; - std::cout << std::endl << "Shutting down..." << std::endl; + std::cout << '\n' << "Shutting down..." << '\n'; } void printStats(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) { - pcpp::DpdkDevice::DpdkDeviceStats rxStats; - pcpp::DpdkDevice::DpdkDeviceStats txStats; + pcpp::DpdkDevice::DpdkDeviceStats rxStats{}; + pcpp::DpdkDevice::DpdkDeviceStats txStats{}; rxDevice->getStatistics(rxStats); txDevice->getStatistics(txStats); - std::vector columnNames = { " ", "Total Packets", "Packets/sec", "Bytes", "Bits/sec" }; - std::vector columnLengths = { 10, 15, 15, 15, 15 }; + const std::vector columnNames = { " ", "Total Packets", "Packets/sec", "Bytes", "Bits/sec" }; + const std::vector columnLengths = { 10, 15, 15, 15, 15 }; pcpp::TablePrinter printer(columnNames, columnLengths); @@ -45,27 +46,27 @@ void printStats(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) printer.printRow(totalTx.str(), '|'); } -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // Register the on app close event handler pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, nullptr); // Initialize DPDK - pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); + const pcpp::CoreMask coreMaskToUse = pcpp::getCoreMaskForAllMachineCores(); pcpp::DpdkDeviceList::initDpdk(coreMaskToUse, MBUF_POOL_SIZE); // Find DPDK devices pcpp::DpdkDevice* device1 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_1); if (device1 == nullptr) { - std::cerr << "Cannot find device1 with port '" << DEVICE_ID_1 << "'" << std::endl; + std::cerr << "Cannot find device1 with port '" << DEVICE_ID_1 << "'" << '\n'; return 1; } pcpp::DpdkDevice* device2 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_2); if (device2 == nullptr) { - std::cerr << "Cannot find device2 with port '" << DEVICE_ID_2 << "'" << std::endl; + std::cerr << "Cannot find device2 with port '" << DEVICE_ID_2 << "'" << '\n'; return 1; } @@ -73,14 +74,14 @@ int main(int argc, char* argv[]) if (!device1->openMultiQueues(1, 1)) { std::cerr << "Couldn't open device1 #" << device1->getDeviceId() << ", PMD '" << device1->getPMDName() << "'" - << std::endl; + << '\n'; return 1; } if (!device2->openMultiQueues(1, 1)) { std::cerr << "Couldn't open device2 #" << device2->getDeviceId() << ", PMD '" << device2->getPMDName() << "'" - << std::endl; + << '\n'; return 1; } @@ -100,7 +101,7 @@ int main(int argc, char* argv[]) // Start capture in async mode if (!pcpp::DpdkDeviceList::getInstance().startDpdkWorkerThreads(workersCoreMask, workers)) { - std::cerr << "Couldn't start worker threads" << std::endl; + std::cerr << "Couldn't start worker threads" << '\n'; return 1; } @@ -119,14 +120,14 @@ int main(int argc, char* argv[]) // Clear screen and move to top left std::cout << "\033[2J\033[1;1H"; - std::cout << "Stats #" << statsCounter++ << std::endl << "==========" << std::endl << std::endl; + std::cout << "Stats #" << statsCounter++ << '\n' << "==========" << '\n' << '\n'; // Print stats of traffic going from Device1 to Device2 - std::cout << std::endl << "Device1->Device2 stats:" << std::endl << std::endl; + std::cout << '\n' << "Device1->Device2 stats:" << '\n' << '\n'; printStats(device1, device2); // Print stats of traffic going from Device2 to Device1 - std::cout << std::endl << "Device2->Device1 stats:" << std::endl << std::endl; + std::cout << '\n' << "Device2->Device1 stats:" << '\n' << '\n'; printStats(device2, device1); } counter++; diff --git a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp index 89f3bdf6d2..af362a9168 100644 --- a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp +++ b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp @@ -3,13 +3,13 @@ #include #include -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // open a pcap file for reading pcpp::PcapFileReaderDevice reader("1_packet.pcap"); if (!reader.open()) { - std::cerr << "Error opening the pcap file" << std::endl; + std::cerr << "Error opening the pcap file" << '\n'; return 1; } @@ -17,23 +17,23 @@ int main(int argc, char* argv[]) pcpp::RawPacket rawPacket; if (!reader.getNextPacket(rawPacket)) { - std::cerr << "Couldn't read the first packet in the file" << std::endl; + std::cerr << "Couldn't read the first packet in the file" << '\n'; return 1; } // parse the raw packet into a parsed packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // verify the packet is IPv4 if (parsedPacket.isPacketOfType(pcpp::IPv4)) { // extract source and dest IPs - pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); - pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); + const pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); + const pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // print source and dest IPs std::cout << "Source IP is '" << srcIP << "'; " - << "Dest IP is '" << destIP << "'" << std::endl; + << "Dest IP is '" << destIP << "'" << '\n'; } // close the file diff --git a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp index 5d330e8875..816ce2ac27 100644 --- a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp +++ b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp @@ -35,43 +35,59 @@ struct PacketStats void consumePacket(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::Ethernet)) + { ethPacketCount++; + } if (packet.isPacketOfType(pcpp::IPv4)) + { ipv4PacketCount++; + } if (packet.isPacketOfType(pcpp::IPv6)) + { ipv6PacketCount++; + } if (packet.isPacketOfType(pcpp::TCP)) + { tcpPacketCount++; + } if (packet.isPacketOfType(pcpp::UDP)) + { udpPacketCount++; + } if (packet.isPacketOfType(pcpp::DNS)) + { dnsPacketCount++; + } if (packet.isPacketOfType(pcpp::HTTP)) + { httpPacketCount++; + } if (packet.isPacketOfType(pcpp::SSL)) + { sslPacketCount++; + } } /** * Print stats to console */ - void printToConsole() + void printToConsole() const { - std::cout << "Ethernet packet count: " << ethPacketCount << std::endl - << "IPv4 packet count: " << ipv4PacketCount << std::endl - << "IPv6 packet count: " << ipv6PacketCount << std::endl - << "TCP packet count: " << tcpPacketCount << std::endl - << "UDP packet count: " << udpPacketCount << std::endl - << "DNS packet count: " << dnsPacketCount << std::endl - << "HTTP packet count: " << httpPacketCount << std::endl - << "SSL packet count: " << sslPacketCount << std::endl; + std::cout << "Ethernet packet count: " << ethPacketCount << '\n' + << "IPv4 packet count: " << ipv4PacketCount << '\n' + << "IPv6 packet count: " << ipv6PacketCount << '\n' + << "TCP packet count: " << tcpPacketCount << '\n' + << "UDP packet count: " << udpPacketCount << '\n' + << "DNS packet count: " << dnsPacketCount << '\n' + << "HTTP packet count: " << httpPacketCount << '\n' + << "SSL packet count: " << sslPacketCount << '\n'; } }; /** * A callback function for the async capture which is called each time a packet is captured */ -static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) +static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* /*dev*/, void* cookie) { // extract the stats object form the cookie auto* stats = static_cast(cookie); @@ -86,7 +102,7 @@ static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, /** * a callback function for the blocking mode capture which is called each time a packet is captured */ -static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) +static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* /*dev*/, void* cookie) { // extract the stats object from the cookie auto* stats = static_cast(cookie); @@ -104,16 +120,16 @@ static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveD /** * main method of the application */ -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // IPv4 address of the interface we want to sniff - std::string interfaceIPAddr = "10.0.0.1"; + std::string const interfaceIPAddr = "10.0.0.1"; // find the interface by IP address auto* dev = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); if (dev == nullptr) { - std::cerr << "Cannot find interface with IPv4 address of '" << interfaceIPAddr << "'" << std::endl; + std::cerr << "Cannot find interface with IPv4 address of '" << interfaceIPAddr << "'" << '\n'; return 1; } @@ -121,22 +137,22 @@ int main(int argc, char* argv[]) // ~~~~~~~~~~~~~~~ // before capturing packets let's print some info about this interface - std::cout << "Interface info:" << std::endl - << " Interface name: " << dev->getName() << std::endl // get interface name - << " Interface description: " << dev->getDesc() << std::endl // get interface description - << " MAC address: " << dev->getMacAddress() << std::endl // get interface MAC address - << " Default gateway: " << dev->getDefaultGateway() << std::endl // get default gateway - << " Interface MTU: " << dev->getMtu() << std::endl; // get interface MTU + std::cout << "Interface info:" << '\n' + << " Interface name: " << dev->getName() << '\n' // get interface name + << " Interface description: " << dev->getDesc() << '\n' // get interface description + << " MAC address: " << dev->getMacAddress() << '\n' // get interface MAC address + << " Default gateway: " << dev->getDefaultGateway() << '\n' // get default gateway + << " Interface MTU: " << dev->getMtu() << '\n'; // get interface MTU if (!dev->getDnsServers().empty()) { - std::cout << " DNS server: " << dev->getDnsServers().front() << std::endl; + std::cout << " DNS server: " << dev->getDnsServers().front() << '\n'; } // open the device before start capturing/sending packets if (!dev->open()) { - std::cerr << "Cannot open device" << std::endl; + std::cerr << "Cannot open device" << '\n'; return 1; } @@ -146,7 +162,7 @@ int main(int argc, char* argv[]) // Async packet capture with a callback function // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - std::cout << std::endl << "Starting async capture..." << std::endl; + std::cout << '\n' << "Starting async capture..." << '\n'; // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats // object as the cookie @@ -159,7 +175,7 @@ int main(int argc, char* argv[]) dev->stopCapture(); // print results - std::cout << "Results:" << std::endl; + std::cout << "Results:" << '\n'; stats.printToConsole(); // clear stats @@ -168,7 +184,7 @@ int main(int argc, char* argv[]) // Capturing packets in a packet vector // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - std::cout << std::endl << "Starting capture with packet vector..." << std::endl; + std::cout << '\n' << "Starting capture with packet vector..." << '\n'; // create an empty packet vector object pcpp::RawPacketVector packetVec; @@ -190,7 +206,7 @@ int main(int argc, char* argv[]) } // print results - std::cout << "Results:" << std::endl; + std::cout << "Results:" << '\n'; stats.printToConsole(); // clear stats @@ -199,7 +215,7 @@ int main(int argc, char* argv[]) // Capturing packets in blocking mode // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - std::cout << std::endl << "Starting capture in blocking mode..." << std::endl; + std::cout << '\n' << "Starting capture in blocking mode..." << '\n'; // start capturing in blocking mode. Give a callback function to call to whenever a packet is captured, the stats // object as the cookie and a 10 seconds timeout @@ -208,7 +224,7 @@ int main(int argc, char* argv[]) // thread is blocked until capture is finished // capture is finished, print results - std::cout << "Results:" << std::endl; + std::cout << "Results:" << '\n'; stats.printToConsole(); stats.clear(); @@ -216,30 +232,30 @@ int main(int argc, char* argv[]) // Sending single packets // ~~~~~~~~~~~~~~~~~~~~~~ - std::cout << std::endl << "Sending " << packetVec.size() << " packets one by one..." << std::endl; + std::cout << '\n' << "Sending " << packetVec.size() << " packets one by one..." << '\n'; // go over the vector of packets and send them one by one - bool allSent = std::all_of(packetVec.begin(), packetVec.end(), - [dev](pcpp::RawPacket* packet) { return dev->sendPacket(*packet); }); + const bool allSent = std::all_of(packetVec.begin(), packetVec.end(), + [dev](pcpp::RawPacket* packet) { return dev->sendPacket(*packet); }); if (!allSent) { - std::cerr << "Couldn't send packet" << std::endl; + std::cerr << "Couldn't send packet" << '\n'; return 1; } - std::cout << packetVec.size() << " packets sent" << std::endl; + std::cout << packetVec.size() << " packets sent" << '\n'; // Sending batch of packets // ~~~~~~~~~~~~~~~~~~~~~~~~ - std::cout << std::endl << "Sending " << packetVec.size() << " packets..." << std::endl; + std::cout << '\n' << "Sending " << packetVec.size() << " packets..." << '\n'; // send all packets in the vector. The returned number shows how many packets were actually sent (expected to be // equal to vector size) - int packetsSent = dev->sendPackets(packetVec); + const int packetsSent = dev->sendPackets(packetVec); - std::cout << packetsSent << " packets sent" << std::endl; + std::cout << packetsSent << " packets sent" << '\n'; // Using filters // ~~~~~~~~~~~~~ @@ -258,7 +274,7 @@ int main(int argc, char* argv[]) // set the filter on the device dev->setFilter(andFilter); - std::cout << std::endl << "Starting packet capture with a filter in place..." << std::endl; + std::cout << '\n' << "Starting packet capture with a filter in place..." << '\n'; // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats // object as the cookie @@ -271,7 +287,7 @@ int main(int argc, char* argv[]) dev->stopCapture(); // print results - should capture only packets which match the filter (which is TCP port 80) - std::cout << "Results:" << std::endl; + std::cout << "Results:" << '\n'; stats.printToConsole(); // close the device before application ends diff --git a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp index b3e9ee247c..32c109b271 100644 --- a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp +++ b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp @@ -11,7 +11,7 @@ #include "DnsLayer.h" #include "PcapFileDevice.h" -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // Packet Editing // ~~~~~~~~~~~~~~ @@ -23,14 +23,14 @@ int main(int argc, char* argv[]) // verify that a reader interface was indeed created if (reader == nullptr) { - std::cerr << "Cannot determine reader for file type" << std::endl; + std::cerr << "Cannot determine reader for file type" << '\n'; return 1; } // open the reader for reading if (!reader->open()) { - std::cerr << "Cannot open input.pcap for reading" << std::endl; + std::cerr << "Cannot open input.pcap for reading" << '\n'; return 1; } @@ -38,7 +38,7 @@ int main(int argc, char* argv[]) pcpp::RawPacket rawPacket; if (!reader->getNextPacket(rawPacket)) { - std::cerr << "Couldn't read the first packet in the file" << std::endl; + std::cerr << "Couldn't read the first packet in the file" << '\n'; return 1; } diff --git a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp index edfbfe1f81..469cfad96d 100644 --- a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp +++ b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp @@ -31,21 +31,37 @@ std::string printTcpFlags(pcpp::TcpLayer* tcpLayer) std::string result; auto* tcpHeader = tcpLayer->getTcpHeader(); if (tcpHeader->synFlag) + { result += "SYN "; + } if (tcpHeader->ackFlag) + { result += "ACK "; + } if (tcpHeader->pshFlag) + { result += "PSH "; + } if (tcpHeader->cwrFlag) + { result += "CWR "; + } if (tcpHeader->urgFlag) + { result += "URG "; + } if (tcpHeader->eceFlag) + { result += "ECE "; + } if (tcpHeader->rstFlag) + { result += "RST "; + } if (tcpHeader->finFlag) + { result += "FIN "; + } return result; } @@ -75,7 +91,7 @@ std::string printHttpMethod(pcpp::HttpRequestLayer::HttpMethod httpMethod) } } -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng) // and create an interface instance that both readers implement @@ -84,14 +100,14 @@ int main(int argc, char* argv[]) // verify that a reader interface was indeed created if (reader == nullptr) { - std::cerr << "Cannot determine reader for file type" << std::endl; + std::cerr << "Cannot determine reader for file type" << '\n'; return 1; } // open the reader for reading if (!reader->open()) { - std::cerr << "Cannot open input.pcap for reading" << std::endl; + std::cerr << "Cannot open input.pcap for reading" << '\n'; return 1; } @@ -99,7 +115,7 @@ int main(int argc, char* argv[]) pcpp::RawPacket rawPacket; if (!reader->getNextPacket(rawPacket)) { - std::cerr << "Couldn't read the first packet in the file" << std::endl; + std::cerr << "Couldn't read the first packet in the file" << '\n'; return 1; } @@ -107,7 +123,7 @@ int main(int argc, char* argv[]) reader->close(); // parse the raw packet into a parsed packet - pcpp::Packet parsedPacket(&rawPacket); + const pcpp::Packet parsedPacket(&rawPacket); // first let's go over the layers one by one and find out its type, its total length, its header length and its // payload length @@ -119,53 +135,52 @@ int main(int argc, char* argv[]) << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of // the layer (equals total // length minus header length) - << std::endl; + << '\n'; } // now let's get the Ethernet layer auto* ethernetLayer = parsedPacket.getLayerOfType(); if (ethernetLayer == nullptr) { - std::cerr << "Something went wrong, couldn't find Ethernet layer" << std::endl; + std::cerr << "Something went wrong, couldn't find Ethernet layer" << '\n'; return 1; } // print the source and dest MAC addresses and the Ether type - std::cout << std::endl - << "Source MAC address: " << ethernetLayer->getSourceMac() << std::endl - << "Destination MAC address: " << ethernetLayer->getDestMac() << std::endl - << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) - << std::endl; + std::cout << '\n' + << "Source MAC address: " << ethernetLayer->getSourceMac() << '\n' + << "Destination MAC address: " << ethernetLayer->getDestMac() << '\n' + << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) << '\n'; // let's get the IPv4 layer auto* ipLayer = parsedPacket.getLayerOfType(); if (ipLayer == nullptr) { - std::cerr << "Something went wrong, couldn't find IPv4 layer" << std::endl; + std::cerr << "Something went wrong, couldn't find IPv4 layer" << '\n'; return 1; } // print source and dest IP addresses, IP ID and TTL - std::cout << std::endl - << "Source IP address: " << ipLayer->getSrcIPAddress() << std::endl - << "Destination IP address: " << ipLayer->getDstIPAddress() << std::endl - << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::endl - << "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << std::endl; + std::cout << '\n' + << "Source IP address: " << ipLayer->getSrcIPAddress() << '\n' + << "Destination IP address: " << ipLayer->getDstIPAddress() << '\n' + << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << '\n' + << "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << '\n'; // let's get the TCP layer auto* tcpLayer = parsedPacket.getLayerOfType(); if (tcpLayer == nullptr) { - std::cerr << "Something went wrong, couldn't find TCP layer" << std::endl; + std::cerr << "Something went wrong, couldn't find TCP layer" << '\n'; return 1; } // print TCP source and dest ports, window size, and the TCP flags that are set in this layer - std::cout << std::endl - << "Source TCP port: " << tcpLayer->getSrcPort() << std::endl - << "Destination TCP port: " << tcpLayer->getDstPort() << std::endl - << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << std::endl - << "TCP flags: " << printTcpFlags(tcpLayer) << std::endl; + std::cout << '\n' + << "Source TCP port: " << tcpLayer->getSrcPort() << '\n' + << "Destination TCP port: " << tcpLayer->getDstPort() << '\n' + << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << '\n' + << "TCP flags: " << printTcpFlags(tcpLayer) << '\n'; std::cout << "TCP options: "; for (pcpp::TcpOption tcpOption = tcpLayer->getFirstTcpOption(); tcpOption.isNotNull(); @@ -173,28 +188,27 @@ int main(int argc, char* argv[]) { std::cout << printTcpOptionType(tcpOption.getTcpOptionEnumType()) << " "; } - std::cout << std::endl; + std::cout << '\n'; // let's get the HTTP request layer auto* httpRequestLayer = parsedPacket.getLayerOfType(); if (httpRequestLayer == nullptr) { - std::cerr << "Something went wrong, couldn't find HTTP request layer" << std::endl; + std::cerr << "Something went wrong, couldn't find HTTP request layer" << '\n'; return 1; } // print HTTP method and URI. Both appear in the first line of the HTTP request - std::cout << std::endl - << "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << std::endl - << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << std::endl; + std::cout << '\n' + << "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << '\n' + << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << '\n'; // print values of the following HTTP field: Host, User-Agent and Cookie - std::cout << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << std::endl + std::cout << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << '\n' << "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() - << std::endl - << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() - << std::endl; + << '\n' + << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() << '\n'; // print the full URL of this request - std::cout << "HTTP full URL: " << httpRequestLayer->getUrl() << std::endl; + std::cout << "HTTP full URL: " << httpRequestLayer->getUrl() << '\n'; } diff --git a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp index 54e6087793..cb9d113e3c 100644 --- a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp +++ b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp @@ -5,7 +5,7 @@ /** * main method of the application */ -int main(int argc, char* argv[]) +int main(int /*argc*/, char* /*argv*/[]) { // use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng) // and create an interface instance that both readers implement @@ -14,14 +14,14 @@ int main(int argc, char* argv[]) // verify that a reader interface was indeed created if (reader == nullptr) { - std::cerr << "Cannot determine reader for file type" << std::endl; + std::cerr << "Cannot determine reader for file type" << '\n'; return 1; } // open the reader for reading if (!reader->open()) { - std::cerr << "Cannot open input.pcap for reading" << std::endl; + std::cerr << "Cannot open input.pcap for reading" << '\n'; return 1; } @@ -32,7 +32,7 @@ int main(int argc, char* argv[]) // try to open the file for writing if (!pcapWriter.open()) { - std::cerr << "Cannot open output.pcap for writing" << std::endl; + std::cerr << "Cannot open output.pcap for writing" << '\n'; return 1; } @@ -43,14 +43,14 @@ int main(int argc, char* argv[]) // try to open the file for writing if (!pcapNgWriter.open()) { - std::cerr << "Cannot open output.pcapng for writing" << std::endl; + std::cerr << "Cannot open output.pcapng for writing" << '\n'; return 1; } // set a BPF filter for the reader - only packets that match the filter will be read if (!reader->setFilter("net 98.138.19.88")) { - std::cerr << "Cannot set filter for file reader" << std::endl; + std::cerr << "Cannot set filter for file reader" << '\n'; return 1; } @@ -69,7 +69,7 @@ int main(int argc, char* argv[]) // Use lambda to simplify statistics output auto printStats = [](const std::string& writerName, const pcpp::IPcapDevice::PcapStats& stats) { std::cout << "Written " << stats.packetsRecv << " packets successfully to " << writerName << " and " - << stats.packetsDrop << " packets could not be written" << std::endl; + << stats.packetsDrop << " packets could not be written" << '\n'; }; // create the stats object @@ -78,7 +78,7 @@ int main(int argc, char* argv[]) // read stats from reader and print them reader->getStatistics(stats); std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop - << " packets could not be read" << std::endl; + << " packets could not be read" << '\n'; // read stats from pcap writer and print them pcapWriter.getStatistics(stats); diff --git a/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h b/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h index e5354898ed..d4ec77d413 100644 --- a/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h @@ -17,27 +17,36 @@ class PacketMatchingEngine pcpp::IPv4Address m_SrcIpToMatch, m_DstIpToMatch; uint16_t m_SrcPortToMatch, m_DstPortToMatch; pcpp::ProtocolType m_ProtocolToMatch; - bool m_MatchSrcIp, m_MatchDstIp; - bool m_MatchSrcPort, m_MatchDstPort; - bool m_MatchProtocol; + bool m_MatchSrcIp{ false }, m_MatchDstIp{ false }; + bool m_MatchSrcPort{ false }, m_MatchDstPort{ false }; + bool m_MatchProtocol{ false }; public: PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), - m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), - m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchSrcIp = true; + } if (m_DstIpToMatch != pcpp::IPv4Address::Zero) + { m_MatchDstIp = true; + } if (m_SrcPortToMatch != 0) + { m_MatchSrcPort = true; + } if (m_DstPortToMatch != 0) + { m_MatchDstPort = true; + } if (m_ProtocolToMatch == pcpp::TCP || m_ProtocolToMatch == pcpp::UDP) + { m_MatchProtocol = true; + } } bool isMatched(pcpp::Packet& packet) @@ -49,7 +58,7 @@ class PacketMatchingEngine return false; } - pcpp::IPv4Layer* ip4Layer = packet.getLayerOfType(); + auto* ip4Layer = packet.getLayerOfType(); if (m_MatchSrcIp && (ip4Layer->getSrcIPv4Address() != m_SrcIpToMatch)) { return false; @@ -63,7 +72,8 @@ class PacketMatchingEngine if (m_MatchSrcPort || m_MatchDstPort) { - uint16_t srcPort, dstPort; + uint16_t srcPort = 0; + uint16_t dstPort = 0; if (packet.isPacketOfType(pcpp::TCP)) { srcPort = packet.getLayerOfType()->getSrcPort(); diff --git a/Examples/XdpExample-FilterTraffic/main.cpp b/Examples/XdpExample-FilterTraffic/main.cpp index f08b180c44..7916be4f29 100644 --- a/Examples/XdpExample-FilterTraffic/main.cpp +++ b/Examples/XdpExample-FilterTraffic/main.cpp @@ -25,7 +25,7 @@ #define EXIT_WITH_ERROR(reason) \ do \ { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -33,7 +33,7 @@ do \ { \ printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + std::cout << '\n' << "ERROR: " << reason << '\n' << '\n'; \ exit(1); \ } while (0) @@ -43,27 +43,23 @@ struct PacketStats { public: - int packetCount; - int ethCount; - int arpCount; - int ip4Count; - int ip6Count; - int tcpCount; - int udpCount; - int httpCount; - int dnsCount; - int sslCount; - int totalTcpFlows; - int totalUdpFlows; - int matchedTcpFlows; - int matchedUdpFlows; - int matchedPacketCount; - - PacketStats() - : packetCount(0), ethCount(0), arpCount(0), ip4Count(0), ip6Count(0), tcpCount(0), udpCount(0), httpCount(0), - dnsCount(0), sslCount(0), totalTcpFlows(0), totalUdpFlows(0), matchedTcpFlows(0), matchedUdpFlows(0), - matchedPacketCount(0) - {} + int packetCount{ 0 }; + int ethCount{ 0 }; + int arpCount{ 0 }; + int ip4Count{ 0 }; + int ip6Count{ 0 }; + int tcpCount{ 0 }; + int udpCount{ 0 }; + int httpCount{ 0 }; + int dnsCount{ 0 }; + int sslCount{ 0 }; + int totalTcpFlows{ 0 }; + int totalUdpFlows{ 0 }; + int matchedTcpFlows{ 0 }; + int matchedUdpFlows{ 0 }; + int matchedPacketCount{ 0 }; + + PacketStats() = default; /** * Collect stats per packet @@ -72,23 +68,41 @@ struct PacketStats { packetCount++; if (packet.isPacketOfType(pcpp::Ethernet)) + { ethCount++; + } if (packet.isPacketOfType(pcpp::ARP)) + { arpCount++; + } if (packet.isPacketOfType(pcpp::IPv4)) + { ip4Count++; + } if (packet.isPacketOfType(pcpp::IPv6)) + { ip6Count++; + } if (packet.isPacketOfType(pcpp::TCP)) + { tcpCount++; + } if (packet.isPacketOfType(pcpp::UDP)) + { udpCount++; + } if (packet.isPacketOfType(pcpp::HTTP)) + { httpCount++; + } if (packet.isPacketOfType(pcpp::DNS)) + { dnsCount++; + } if (packet.isPacketOfType(pcpp::SSL)) + { sslCount++; + } } }; @@ -97,16 +111,14 @@ struct PacketStats */ struct PacketCaptureArgs { - PacketStats* packetStats; - PacketMatchingEngine* matchingEngine; + PacketStats* packetStats{ nullptr }; + PacketMatchingEngine* matchingEngine{ nullptr }; std::unordered_map flowTable; - pcpp::XdpDevice* sendPacketsTo; - pcpp::PcapFileWriterDevice* pcapWriter; - bool stopCapture; + pcpp::XdpDevice* sendPacketsTo{ nullptr }; + pcpp::PcapFileWriterDevice* pcapWriter{ nullptr }; + bool stopCapture{ false }; - PacketCaptureArgs() - : packetStats(nullptr), matchingEngine(nullptr), sendPacketsTo(nullptr), pcapWriter(nullptr), stopCapture(false) - {} + PacketCaptureArgs() = default; }; // clang-format off @@ -130,7 +142,7 @@ static struct option XdpFilterTrafficOptions[] = { */ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpDevice* device, void* userCookie) { - auto args = reinterpret_cast(userCookie); + auto* args = reinterpret_cast(userCookie); // if the user asked to interrupt the app, stop receiving packets if (args->stopCapture) @@ -152,10 +164,10 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or // new flow - uint32_t hash = pcpp::hash5Tuple(&packet); + const uint32_t hash = pcpp::hash5Tuple(&packet); auto iter = args->flowTable.find(hash); - bool packetMatched; + bool packetMatched = false; // if packet belongs to an already existing flow if (iter != args->flowTable.end()) @@ -224,8 +236,8 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD void printStats(PacketStats* packetStats, pcpp::XdpDevice::XdpDeviceStats* rxDeviceStats, pcpp::XdpDevice::XdpDeviceStats* txDeviceStats) { - std::vector columnNames = { "Stat", "Count" }; - std::vector columnsWidths = { 21, 10 }; + const std::vector columnNames = { "Stat", "Count" }; + const std::vector columnsWidths = { 21, 10 }; pcpp::TablePrinter printer(columnNames, columnsWidths); printer.printRow("Eth count|" + std::to_string(packetStats->ethCount), '|'); @@ -250,7 +262,7 @@ void printStats(PacketStats* packetStats, pcpp::XdpDevice::XdpDeviceStats* rxDev printer.printRow("RX packets/sec|" + std::to_string(rxDeviceStats->rxPacketsPerSec), '|'); printer.printRow("RX bytes|" + std::to_string(rxDeviceStats->rxBytes), '|'); printer.printRow("RX bytes/sec|" + std::to_string(rxDeviceStats->rxBytesPerSec), '|'); - if (txDeviceStats) + if (txDeviceStats != nullptr) { printer.printRow("TX packets|" + std::to_string(txDeviceStats->txCompletedPackets), '|'); printer.printRow("TX packets/sec|" + std::to_string(txDeviceStats->txCompletedPacketsPerSec), '|'); @@ -273,7 +285,7 @@ void collectStats(std::future futureObj, PacketStats* packetStats, pcpp::X pcpp::XdpDevice::XdpDeviceStats* txStats = nullptr; - if (sendDev) + if (sendDev != nullptr) { // if send socket is different from receive socket, collect stats from the send socket if (sendDev != dev) @@ -301,42 +313,42 @@ void collectStats(std::future futureObj, PacketStats* packetStats, pcpp::X */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl + std::cout << '\n' + << "Usage:" << '\n' + << "------" << '\n' << pcpp::AppName::get() << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r " "PROTOCOL] -n INTERFACE_NAME" - << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl + << '\n' + << '\n' + << "Options:" << '\n' + << '\n' + << " -h|--help : Displays this help message and exits" << '\n' + << " -v|--version : Displays the current version and exits" << '\n' << " -l|--list : Print the list of network interfaces and exit" - << std::endl + << '\n' << " -n|--interface-name INTERFACE_NAME : An interface name to open AF_XDP socket and receive " "packets from." - << std::endl + << '\n' << " To see all available interfaces use the -l switch" - << std::endl + << '\n' << " -s|--send-matched-packets INTERFACE_NAME : Network interface name to send matched packets to." - << std::endl + << '\n' << " The app will open another AF_XDP socket for sending " "packets." - << std::endl + << '\n' << " Note: this interface can be the same one used to " "receive packets." - << std::endl + << '\n' << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." - << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl + << '\n' + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << '\n' + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << '\n' + << " -p|--match-source-port PORT : Match source TCP/UDP port" << '\n' + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << '\n' << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" - << std::endl - << std::endl; + << '\n' + << '\n'; } /** @@ -344,9 +356,9 @@ void printUsage() */ void printAppVersion() { - std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << '\n' + << "Built: " << pcpp::getBuildDateTime() << '\n' + << "Built from: " << pcpp::getGitInfo() << '\n'; exit(0); } @@ -355,13 +367,13 @@ void printAppVersion() */ void listInterfaces() { - std::cout << std::endl << "Network interfaces:" << std::endl; + std::cout << '\n' << "Network interfaces:" << '\n'; for (const auto& device : pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList()) { if (device->getIPv4Address() != pcpp::IPv4Address::Zero) { std::cout << " -> Name: '" << device->getName() - << "' IP address: " << device->getIPv4Address().toString() << std::endl; + << "' IP address: " << device->getIPv4Address().toString() << '\n'; } } exit(0); @@ -372,7 +384,7 @@ int main(int argc, char* argv[]) pcpp::AppName::init(argc, argv); int optionIndex = 0; - int opt; + int opt = 0; std::string interfaceName; @@ -434,7 +446,7 @@ int main(int argc, char* argv[]) } case 'p': { - int ret = std::stoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); @@ -444,7 +456,7 @@ int main(int argc, char* argv[]) } case 'P': { - int ret = std::stoi(optarg); + const int ret = std::stoi(optarg); if (ret <= 0 || ret > 65535) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); @@ -454,7 +466,7 @@ int main(int argc, char* argv[]) } case 'r': { - std::string protocol = std::string(optarg); + const std::string protocol = std::string(optarg); if (protocol == "TCP") { protocolToMatch = pcpp::TCP; @@ -571,7 +583,7 @@ int main(int argc, char* argv[]) // close the pcap writer if needed std::vector additionalStats; - if (pcapWriter) + if (pcapWriter != nullptr) { pcpp::IPcapDevice::PcapStats stats; pcapWriter->getStatistics(stats); @@ -609,7 +621,7 @@ int main(int argc, char* argv[]) for (const auto& additionalStat : additionalStats) { - std::cout << additionalStat << std::endl; + std::cout << additionalStat << '\n'; } // exit with an error if there was an error receiving packets