From b13a33f0be3b49fd6fe25c2057e9bc69df16fd73 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Tue, 15 Jun 2021 19:06:49 -0400 Subject: [PATCH 1/3] Windows: PCAP: Less verbose name for the interface Fixing some tabs/spaces formatting here as well --- include/icsneo/platform/windows/pcap.h | 2 +- platform/windows/pcap.cpp | 68 +++++++++++++------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/icsneo/platform/windows/pcap.h b/include/icsneo/platform/windows/pcap.h index 21c216f..39ebe7f 100644 --- a/include/icsneo/platform/windows/pcap.h +++ b/include/icsneo/platform/windows/pcap.h @@ -59,7 +59,7 @@ private: pcap_stat stats; }; static std::vector knownInterfaces; - NetworkInterface interfacevar; + NetworkInterface iface; }; } diff --git a/platform/windows/pcap.cpp b/platform/windows/pcap.cpp index 8cd8c4f..c8a65b1 100644 --- a/platform/windows/pcap.cpp +++ b/platform/windows/pcap.cpp @@ -33,7 +33,7 @@ std::vector PCAP::FindAll() { bool success = false; // Calling pcap.findalldevs_ex too quickly can cause various errors. Retry a few times in this case. for(auto retry = 0; retry < 10; retry++) { - auto ret = pcap.findalldevs_ex((char*)PCAP_SRC_IF_STRING, nullptr, &alldevs, errbuf); + auto ret = pcap.findalldevs_ex((char*)PCAP_SRC_IF_STRING, nullptr, &alldevs, errbuf); if(ret == 0) { success = true; break; @@ -69,48 +69,48 @@ std::vector PCAP::FindAll() { } // aa->AdapterName constains a unique name of the interface like "{3B1D2791-435A-456F-8A7B-9CB0EEE5DAB3}" - // interfacevar.nameFromWinPCAP has "rpcap://\Device\NPF_{3B1D2791-435A-456F-8A7B-9CB0EEE5DAB3}" + // iface.nameFromWinPCAP has "rpcap://\Device\NPF_{3B1D2791-435A-456F-8A7B-9CB0EEE5DAB3}" // We're comparing strings to match the Win32 info with the WinPCAP info for(IP_ADAPTER_ADDRESSES* aa = (IP_ADAPTER_ADDRESSES*)adapterAddressBuffer.data(); aa != nullptr; aa = aa->Next) { - for(auto& interfacevar : interfaces) { - if(interfacevar.nameFromWinPCAP.find(aa->AdapterName) == std::string::npos) + for(auto& iface : interfaces) { + if(iface.nameFromWinPCAP.find(aa->AdapterName) == std::string::npos) continue; // This is not the interface that corresponds - memcpy(interfacevar.macAddress, aa->PhysicalAddress, sizeof(interfacevar.macAddress)); - interfacevar.nameFromWin32API = aa->AdapterName; - interfacevar.descriptionFromWin32API = converter.to_bytes(aa->Description); - interfacevar.friendlyNameFromWin32API = converter.to_bytes(aa->FriendlyName); - if(interfacevar.descriptionFromWin32API.find("LAN9512/LAN9514") != std::string::npos) { + memcpy(iface.macAddress, aa->PhysicalAddress, sizeof(iface.macAddress)); + iface.nameFromWin32API = aa->AdapterName; + iface.descriptionFromWin32API = converter.to_bytes(aa->Description); + iface.friendlyNameFromWin32API = converter.to_bytes(aa->FriendlyName); + if(iface.descriptionFromWin32API.find("LAN9512/LAN9514") != std::string::npos) { // This is an Ethernet EVB device - interfacevar.fullName = "Intrepid Ethernet EVB ( " + interfacevar.friendlyNameFromWin32API + " : " + interfacevar.descriptionFromWin32API + " )"; + iface.fullName = "Intrepid Ethernet EVB ( " + iface.friendlyNameFromWin32API + " : " + iface.descriptionFromWin32API + " )"; } else { - interfacevar.fullName = interfacevar.friendlyNameFromWin32API + " : " + interfacevar.descriptionFromWin32API; + iface.fullName = iface.friendlyNameFromWin32API + " : " + iface.descriptionFromWin32API; } } } - for(auto& interfacevar : interfaces) { + for(auto& iface : interfaces) { bool exists = false; for(auto& known : knownInterfaces) - if(memcmp(interfacevar.macAddress, known.macAddress, sizeof(interfacevar.macAddress)) == 0) + if(memcmp(iface.macAddress, known.macAddress, sizeof(iface.macAddress)) == 0) exists = true; if(!exists) - knownInterfaces.emplace_back(interfacevar); + knownInterfaces.emplace_back(iface); } constexpr auto openflags = (PCAP_OPENFLAG_MAX_RESPONSIVENESS | PCAP_OPENFLAG_NOCAPTURE_LOCAL); for(size_t i = 0; i < knownInterfaces.size(); i++) { - auto& interfacevar = knownInterfaces[i]; - if(interfacevar.fullName.length() == 0) + auto& iface = knownInterfaces[i]; + if(iface.fullName.length() == 0) continue; // Win32 did not find this interface in the previous step - interfacevar.fp = pcap.open(interfacevar.nameFromWinPCAP.c_str(), 1518, openflags, 1, nullptr, errbuf); + iface.fp = pcap.open(iface.nameFromWinPCAP.c_str(), 1518, openflags, 1, nullptr, errbuf); - if(interfacevar.fp == nullptr) + if(iface.fp == nullptr) continue; // Could not open the interface EthernetPacketizer::EthernetPacket requestPacket; - memcpy(requestPacket.srcMAC, interfacevar.macAddress, sizeof(requestPacket.srcMAC)); + memcpy(requestPacket.srcMAC, iface.macAddress, sizeof(requestPacket.srcMAC)); requestPacket.payload.reserve(4); requestPacket.payload = { ((1 << 4) | (uint8_t)Network::NetID::Main51), // Packet size of 1 on NETID_MAIN51 @@ -120,13 +120,13 @@ std::vector PCAP::FindAll() { requestPacket.payload.insert(requestPacket.payload.begin(), 0xAA); auto bs = requestPacket.getBytestream(); - pcap.sendpacket(interfacevar.fp, bs.data(), (int)bs.size()); + pcap.sendpacket(iface.fp, bs.data(), (int)bs.size()); auto timeout = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(5); while(std::chrono::high_resolution_clock::now() <= timeout) { // Wait up to 5ms for the response struct pcap_pkthdr* header; const uint8_t* data; - auto res = pcap.next_ex(interfacevar.fp, &header, &data); + auto res = pcap.next_ex(iface.fp, &header, &data); if(res < 0) { //std::cout << "pcapnextex failed with " << res << std::endl; break; @@ -137,7 +137,7 @@ std::vector PCAP::FindAll() { EthernetPacketizer::EthernetPacket packet(data, header->caplen); // Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us? if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && ( - memcmp(packet.destMAC, interfacevar.macAddress, sizeof(packet.destMAC)) == 0 || + memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 || memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0 )) { /* We have received a packet from a device. We don't know if this is the device we're @@ -169,8 +169,8 @@ std::vector PCAP::FindAll() { } } - pcap.close(interfacevar.fp); - interfacevar.fp = nullptr; + pcap.close(iface.fp); + iface.fp = nullptr; } return foundDevices; @@ -183,8 +183,8 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) { PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice), pcap(PCAPDLL::getInstance()), ethPacketizer(err) { if(IsHandleValid(device.handle)) { - interfacevar = knownInterfaces[(device.handle >> 24) & 0xFF]; - interfacevar.fp = nullptr; // We're going to open our own connection to the interfacevar. This should already be nullptr but just in case. + iface = knownInterfaces[(device.handle >> 24) & 0xFF]; + iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case. deviceMAC[0] = 0x00; deviceMAC[1] = 0xFC; @@ -193,7 +193,7 @@ PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(er deviceMAC[4] = (device.handle >> 8) & 0xFF; deviceMAC[5] = device.handle & 0xFF; memcpy(ethPacketizer.deviceMAC, deviceMAC, 6); - memcpy(ethPacketizer.hostMAC, interfacevar.macAddress, 6); + memcpy(ethPacketizer.hostMAC, iface.macAddress, 6); } else { openable = false; } @@ -216,8 +216,8 @@ bool PCAP::open() { } // Open the interface - interfacevar.fp = pcap.open(interfacevar.nameFromWinPCAP.c_str(), 65536, PCAP_OPENFLAG_MAX_RESPONSIVENESS | PCAP_OPENFLAG_NOCAPTURE_LOCAL, 50, nullptr, errbuf); - if(interfacevar.fp == nullptr) { + iface.fp = pcap.open(iface.nameFromWinPCAP.c_str(), 65536, PCAP_OPENFLAG_MAX_RESPONSIVENESS | PCAP_OPENFLAG_NOCAPTURE_LOCAL, 50, nullptr, errbuf); + if(iface.fp == nullptr) { report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; } @@ -231,7 +231,7 @@ bool PCAP::open() { } bool PCAP::isOpen() { - return interfacevar.fp != nullptr; + return iface.fp != nullptr; } bool PCAP::close() { @@ -246,8 +246,8 @@ bool PCAP::close() { transmitThread.join(); closing = false; - pcap.close(interfacevar.fp); - interfacevar.fp = nullptr; + pcap.close(iface.fp); + iface.fp = nullptr; uint8_t flush; WriteOperation flushop; @@ -263,7 +263,7 @@ void PCAP::readTask() { const uint8_t* data; EventManager::GetInstance().downgradeErrorsOnCurrentThread(); while(!closing) { - auto readBytes = pcap.next_ex(interfacevar.fp, &header, &data); + auto readBytes = pcap.next_ex(iface.fp, &header, &data); if(readBytes < 0) { report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error); break; @@ -334,7 +334,7 @@ void PCAP::transmitTask() { if(transmitQueueCV.wait_for(lk, std::chrono::milliseconds(100), [this] { return !!transmitQueue; }) && !closing && transmitQueue) { pcap_send_queue* current = transmitQueue; lk.unlock(); - pcap.sendqueue_transmit(interfacevar.fp, current, 0); + pcap.sendqueue_transmit(iface.fp, current, 0); { std::lock_guard lk2(transmitQueueMutex); transmitQueue = nullptr; From 37d06807e497acc743c17453efc5f0488cc1d1b2 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Tue, 15 Jun 2021 19:08:19 -0400 Subject: [PATCH 2/3] POSIX: PCAP: Update inferface name to match Windows implementation --- include/icsneo/platform/posix/pcap.h | 6 +-- platform/posix/pcap.cpp | 64 ++++++++++++++-------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/icsneo/platform/posix/pcap.h b/include/icsneo/platform/posix/pcap.h index 3b44366..e221c68 100644 --- a/include/icsneo/platform/posix/pcap.h +++ b/include/icsneo/platform/posix/pcap.h @@ -39,14 +39,14 @@ private: public: uint8_t uuid; uint8_t macAddress[8]; - std::string nameFromWinPCAP; - std::string descriptionFromWinPCAP; + std::string nameFromPCAP; + std::string descriptionFromPCAP; std::string fullName; pcap_t* fp = nullptr; pcap_stat stats; }; static std::vector knownInterfaces; - NetworkInterface interface; + NetworkInterface iface; class EthernetPacket { public: // Don't worry about endian when setting fields, this is all taken care of in getBytestream diff --git a/platform/posix/pcap.cpp b/platform/posix/pcap.cpp index 67ffc27..3594476 100644 --- a/platform/posix/pcap.cpp +++ b/platform/posix/pcap.cpp @@ -22,7 +22,7 @@ std::vector PCAP::FindAll() { static bool warned = false; // Only warn once for failure to open devices std::vector foundDevices; - // First we ask WinPCAP to give us all of the devices + // First we ask PCAP to give us all of the devices pcap_if_t* alldevs; char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; bool success = false; @@ -49,9 +49,9 @@ std::vector PCAP::FindAll() { continue; } NetworkInterface netif; - netif.nameFromWinPCAP = dev->name; + netif.nameFromPCAP = dev->name; if(dev->description) - netif.descriptionFromWinPCAP = dev->description; + netif.descriptionFromPCAP = dev->description; pcap_addr* currentAddress = dev->addresses; bool hasAddress = false; while(!hasAddress && currentAddress != nullptr) { @@ -76,40 +76,40 @@ std::vector PCAP::FindAll() { pcap_freealldevs(alldevs); - for(auto& interface : interfaces) { + for(auto& iface : interfaces) { bool exists = false; for(auto& known : knownInterfaces) - if(memcmp(interface.macAddress, known.macAddress, sizeof(interface.macAddress)) == 0) + if(memcmp(iface.macAddress, known.macAddress, sizeof(iface.macAddress)) == 0) exists = true; if(!exists) - knownInterfaces.emplace_back(interface); + knownInterfaces.emplace_back(iface); } for(size_t i = 0; i < knownInterfaces.size(); i++) { - auto& interface = knownInterfaces[i]; - // if(interface.fullName.length() == 0) + auto& iface = knownInterfaces[i]; + // if(iface.fullName.length() == 0) // continue; // Win32 did not find this interface in the previous step errbuf[0] = '\0'; - interface.fp = pcap_open_live(interface.nameFromWinPCAP.c_str(), 65536, 1, -1, errbuf); + iface.fp = pcap_open_live(iface.nameFromPCAP.c_str(), 65536, 1, -1, errbuf); // TODO Handle warnings // if(strlen(errbuf) != 0) { // This means a warning - // std::cout << "Warning for " << interface.nameFromWinPCAP << " " << errbuf << std::endl; + // std::cout << "Warning for " << iface.nameFromPCAP << " " << errbuf << std::endl; // } - if(interface.fp == nullptr) { + if(iface.fp == nullptr) { if (!warned) { warned = true; EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::EventWarning); - // std::cout << "pcap_open_live failed for " << interface.nameFromWinPCAP << " with " << errbuf << std::endl; + // std::cout << "pcap_open_live failed for " << iface.nameFromPCAP << " with " << errbuf << std::endl; } continue; // Could not open the interface } - pcap_setnonblock(interface.fp, 1, errbuf); + pcap_setnonblock(iface.fp, 1, errbuf); EthernetPacket requestPacket; - memcpy(requestPacket.srcMAC, interface.macAddress, sizeof(requestPacket.srcMAC)); + memcpy(requestPacket.srcMAC, iface.macAddress, sizeof(requestPacket.srcMAC)); requestPacket.payload.reserve(4); requestPacket.payload = { ((1 << 4) | (uint8_t)Network::NetID::Main51), // Packet size of 1 on NETID_MAIN51 @@ -119,13 +119,13 @@ std::vector PCAP::FindAll() { requestPacket.payload.insert(requestPacket.payload.begin(), 0xAA); auto bs = requestPacket.getBytestream(); - pcap_sendpacket(interface.fp, bs.data(), (int)bs.size()); + pcap_sendpacket(iface.fp, bs.data(), (int)bs.size()); auto timeout = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(50); while(std::chrono::high_resolution_clock::now() <= timeout) { // Wait up to 5ms for the response struct pcap_pkthdr* header; const uint8_t* data; - auto res = pcap_next_ex(interface.fp, &header, &data); + auto res = pcap_next_ex(iface.fp, &header, &data); if(res < 0) { if (!warned) { warned = true; @@ -140,7 +140,7 @@ std::vector PCAP::FindAll() { EthernetPacket packet(data, header->caplen); // Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us? if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && ( - memcmp(packet.destMAC, interface.macAddress, sizeof(packet.destMAC)) == 0 || + memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 || memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0 || memcmp(packet.destMAC, ICS_UNSET_MAC, sizeof(packet.destMAC)) == 0 )) { @@ -173,8 +173,8 @@ std::vector PCAP::FindAll() { } } - pcap_close(interface.fp); - interface.fp = nullptr; + pcap_close(iface.fp); + iface.fp = nullptr; } return foundDevices; @@ -187,8 +187,8 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) { PCAP::PCAP(device_eventhandler_t err, neodevice_t& forDevice) : Driver(err), device(forDevice) { if(IsHandleValid(device.handle)) { - interface = knownInterfaces[(device.handle >> 24) & 0xFF]; - interface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case. + iface = knownInterfaces[(device.handle >> 24) & 0xFF]; + iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case. deviceMAC[0] = 0x00; deviceMAC[1] = 0xFC; @@ -209,13 +209,13 @@ bool PCAP::open() { return false; // Open the interface - interface.fp = pcap_open_live(interface.nameFromWinPCAP.c_str(), 65536, 1, -1, errbuf); - if(interface.fp == nullptr) { + iface.fp = pcap_open_live(iface.nameFromPCAP.c_str(), 65536, 1, -1, errbuf); + if(iface.fp == nullptr) { report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); return false; } - pcap_setnonblock(interface.fp, 0, errbuf); + pcap_setnonblock(iface.fp, 0, errbuf); // Create threads readThread = std::thread(&PCAP::readTask, this); @@ -225,7 +225,7 @@ bool PCAP::open() { } bool PCAP::isOpen() { - return interface.fp != nullptr; + return iface.fp != nullptr; } bool PCAP::close() { @@ -233,14 +233,14 @@ bool PCAP::close() { return false; closing = true; // Signal the threads that we are closing - pcap_breakloop(interface.fp); + pcap_breakloop(iface.fp); pthread_cancel(readThread.native_handle()); readThread.join(); writeThread.join(); closing = false; - pcap_close(interface.fp); - interface.fp = nullptr; + pcap_close(iface.fp); + iface.fp = nullptr; uint8_t flush; WriteOperation flushop; @@ -253,14 +253,14 @@ bool PCAP::close() { void PCAP::readTask() { EventManager::GetInstance().downgradeErrorsOnCurrentThread(); while (!closing) { - pcap_dispatch(interface.fp, -1, [](uint8_t* obj, const struct pcap_pkthdr* header, const uint8_t* data) { + pcap_dispatch(iface.fp, -1, [](uint8_t* obj, const struct pcap_pkthdr* header, const uint8_t* data) { PCAP* driver = (PCAP*)obj; EthernetPacket packet(data, header->caplen); if(packet.etherType != 0xCAB2) return; // Not a packet to host - if(memcmp(packet.destMAC, driver->interface.macAddress, sizeof(packet.destMAC)) != 0 && + if(memcmp(packet.destMAC, driver->iface.macAddress, sizeof(packet.destMAC)) != 0 && memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) != 0 && memcmp(packet.destMAC, ICS_UNSET_MAC, sizeof(packet.destMAC)) != 0) return; // Packet is not addressed to us or broadcast @@ -280,7 +280,7 @@ void PCAP::writeTask() { EventManager::GetInstance().downgradeErrorsOnCurrentThread(); // Set MAC address of packet - memcpy(sendPacket.srcMAC, interface.macAddress, sizeof(sendPacket.srcMAC)); + memcpy(sendPacket.srcMAC, iface.macAddress, sizeof(sendPacket.srcMAC)); memcpy(sendPacket.destMAC, deviceMAC, sizeof(deviceMAC)); while(!closing) { @@ -291,7 +291,7 @@ void PCAP::writeTask() { sendPacket.payload = std::move(writeOp.bytes); auto bs = sendPacket.getBytestream(); if(!closing) - pcap_sendpacket(interface.fp, bs.data(), (int)bs.size()); + pcap_sendpacket(iface.fp, bs.data(), (int)bs.size()); // TODO Handle packet send errors } } From 4da5f63e576d1278b1fa68f1ad71b2a1dcb424b4 Mon Sep 17 00:00:00 2001 From: sbo79 <56559706+sbo79@users.noreply.github.com> Date: Tue, 15 Jun 2021 20:18:43 +0200 Subject: [PATCH 3/3] Update README.md Just experienced list filters got introduced to cmake in 3.6.... still failed run trough in ubuntu 18.04. works above 3.12. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b008bb..ee6d9c2 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Building will require Microsoft Visual Studio 2017+ and CMake to be installed. Getting the dependencies is easiest with the Homebrew package manager. You will also need XCode installed. You can then install CMake, an up-to-date version of GCC or Clang, and `libusb-1.0`. ### Linux The dependencies are as follows - - CMake 3.2 or above + - CMake 3.12 or above - GCC 4.7 or above, 4.8+ recommended - `libusb-1.0-0-dev` - `libpcap0.8-dev`