Search code examples
c++libpcaplibtins

Why is my program having problems opening a Network Device


I took a look at libtins and at the Examples I found the ARP Monitor example. The Code of the Example is this here:

#include <tins/tins.h>
#include <map>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::map;
using std::bind;

using namespace Tins;

class arp_monitor {
public:
    void run(Sniffer& sniffer);
private:
    bool callback(const PDU& pdu);

    map<IPv4Address, HWAddress<6>> addresses;
};

void arp_monitor::run(Sniffer& sniffer) {
    sniffer.sniff_loop(
        bind(
            &arp_monitor::callback,
            this,
            std::placeholders::_1
        )
    );
}

bool arp_monitor::callback(const PDU& pdu) {
    // Retrieve the ARP layer
    const ARP& arp = pdu.rfind_pdu<ARP>();
    // Is it an ARP reply?
    if (arp.opcode() == ARP::REPLY) {
        // Let's check if there's already an entry for this address
        auto iter = addresses.find(arp.sender_ip_addr());
        if (iter == addresses.end()) {
            // We haven't seen this address. Save it.
            addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
            cout << "[INFO] " << arp.sender_ip_addr() << " is at "
                 << arp.sender_hw_addr() << std::endl;
        }
        else {
            // We've seen this address. If it's not the same HW address, inform it
            if (arp.sender_hw_addr() != iter->second) {
                cout << "[WARNING] " << arp.sender_ip_addr() << " is at " 
                     << iter->second << " but also at " << arp.sender_hw_addr() 
                     << endl;
            }
        }
    }
    return true;
}

int main(int argc, char* argv[]) {
    if(argc != 2) {
        cout << "Usage: " <<* argv << " <interface>" << endl;
        return 1;
    }
    arp_monitor monitor;
    // Sniffer configuration
    SnifferConfiguration config;
    config.set_promisc_mode(true);
    config.set_filter("arp");

    try {
        // Sniff on the provided interface in promiscuous mode
        Sniffer sniffer(argv[1], config);
        
        // Only capture arp packets
        monitor.run(sniffer);
    }
    catch (std::exception& ex) {
        std::cerr << "Error: " << ex.what() << std::endl;
    }
}

I ran this Code as this here:

myprogram.exe eth0

The Result was:

Error: Error opening adapter: The System could not find the given Device. (20)

Definition of the words above:

eth0: My Network Device

libtins: high-level, multiplatform C++ network packet sniffing and crafting library

ARP: Address Resolution Protocol

I ran it at only one User named "Shadow" on Windows

Image of the Users Directory


Solution

  • Based on the image that te OP uploaded, I can only conclude that I was right about him running the program on Windows so I'll just copy from libtins's documentation:

    In order to capture packets on Windows, you could first list all network interfaces. You can do that easily by using the NetworkInterface class:

    // First fetch all network interfaces
    vector<NetworkInterface> interfaces = NetworkInterface::all();
    
    // Now iterate them
    for (const NetworkInterface& iface : interfaces) {
        // First print the name (GUID)
        cout << "Interface name: " << iface.name();
    
        // Now print the friendly name, a wstring that will contain something like 
        // "Local Area Connection 2"
        wcout << " (" << iface.friendly_name() << ")" << endl;
    }
    

    That small code snippet should provide an output like the following:

    Interface name: {6527cc7d-c647-4986-ac10-7784dc1f2439} (Local Area Connection 1)
    Interface name: {309d733f-79bb-41ef-aaec-8a7b83d2adcf} (Local Area Connection 2)
    Interface name: {55ab969f-80df-4d51-8130-291d54a752a3} (Local Area Connection 3)
    

    This might be enough for you to recognize which is the interface you want to use. You can also resort to getting the default interface, which is very likely the one you want to use, or show the IP addresses of each of them until you recognize them:

    // Get the default interface (where the default gateway route is)
    NetworkInterface iface = NetworkInterface::default_interface();
    
    // Print the name and the IP address
    cout << "Default interface: " << iface.name() 
         << " (" << iface.addresses().ip_addr() << ")" << endl;