2

i am using pcap_findalldevs to get the device list in the computer. I get it successfully, with the name of the device, and description, but I don't know why, I get Netmask 0.0.0.0 and the ip address also 0.0.0.0. here is my code to generate the list:

/* get the devices list */
if (pcap_findalldevs(&devList, errbuf) == -1)
{
    fprintf(stderr, "There is a problem with pcap_findalldevs: %s\n", errbuf);
    return -1;
}

/* scan the list for a suitable device to capture from */
for (dev = devList; dev != NULL; dev = dev->next)
{

    pcap_addr_t *dev_addr; //interface address that used by pcap_findalldevs()

    /* check if the device captureble*/
    if ((dev_addr = dev->addresses) != NULL && dev_addr->addr->sa_family == AF_INET && dev_addr->addr && dev_addr->netmask) {
        printf("Found a device %s on address %s with netmask %s\n", dev->name, iptos(((struct sockaddr_in *)dev_addr->addr)->sin_addr.s_addr), iptos(((struct sockaddr_in *)dev_addr->netmask)->sin_addr.s_addr));
        break;
    }
}
Benny Isaacs
  • 105
  • 1
  • 8
  • You're not walking all the addresses for the interface - is it possible that there's some strangeness in the way winpcap returns the list of addresses. You should enumerate all the addresses listed in the dev->addresses list. – Anya Shenanigans Jun 17 '14 at 19:55
  • I searched on the internet and everyone doing like I did.. I don't know why it doesn't work.. – Benny Isaacs Jun 17 '14 at 21:18
  • "I searched on the internet and everyone doing like I did." Well, they're all doing it wrong; maybe they're lucky, and an IPv4 address *happens* to be at the beginning of the list when their code runs, but code that assumes that the list will always have an IPv4 address at the beginning of the list is incorrect code. –  Jun 18 '14 at 03:07

5 Answers5

6

Here's what you should be doing:

/* get the devices list */
if (pcap_findalldevs(&devList, errbuf) == -1)
{
    fprintf(stderr, "There is a problem with pcap_findalldevs: %s\n", errbuf);
    return -1;
}

/* scan the list for a suitable device to capture from */
for (dev = devList; dev != NULL; dev = dev->next)
{

    pcap_addr_t *dev_addr; //interface address that used by pcap_findalldevs()

    /* check if the device captureble*/
    for (dev_addr = dev->addresses; dev_addr != NULL; dev_addr = dev_addr->next) {
        if (dev_addr->addr->sa_family == AF_INET && dev_addr->addr && dev_addr->netmask) {
            printf("Found a device %s on address %s with netmask %s\n", dev->name, iptos(((struct sockaddr_in *)dev_addr->addr)->sin_addr.s_addr), iptos(((struct sockaddr_in *)dev_addr->netmask)->sin_addr.s_addr));
            goto found;
        }
    }
}

found:

That way, you check the entire address list, not just the first address in the list. If, when you reach found, dev is non-null, it points to a device with at least one IPv4 address, and dev_addr points to that address. If dev is null, there are no devices with IPv4 addresses.

1

The post from Anrew Medico brought me to this solution:

At first I used const auto to initialize. This was a const char*. And I also got the subnetmask for ip-address. As the iptos() doesnt worked for me, I changed the deklaration to const string.

const string interface_ip = inet_ntoa(reinterpret_cast<struct sockaddr_in*>(address->addr)->sin_addr);
const string interface_netmask = inet_ntoa(reinterpret_cast<struct sockaddr_in*>(address->netmask)->sin_addr);

Hope this helps others, as it helped me.

Community
  • 1
  • 1
CanO
  • 111
  • 1
  • 4
0

You are exiting the loop after the first interface you find, which probably is the loopback interface.

Here is the code I used in the past (I skip the loopback which has address 0.0.0.0):

    for(pcap_if_t* pInterface(m_pAllDevices); pInterface != 0; pInterface = pInterface->next)
    {
        if((pInterface->flags & PCAP_IF_LOOPBACK) != 0) // Skip loopback interfaces
        {
            continue;
        }
        std::string address;
        if(pInterface->addresses != 0)
        {
#if defined(WIN32)
            static char tempChar[1] = {0};
            DWORD stringSize(0);
            if(pInterface->addresses != 0 && WSAAddressToStringA(pInterface->addresses->addr, sizeof(*(pInterface->addresses->addr)), 0, tempChar, &stringSize) == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT)
            {
                address.resize((size_t)stringSize);
                WSAAddressToStringA(pInterface->addresses->addr, sizeof(*(pInterface->addresses->addr)), 0, &(address[0]), &stringSize);
            }
#else
            char tempBuffer[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, pInterface->addresses->addr, tempBuffer, sizeof(tempBuffer));
            address = tempBuffer;
#endif
        }

    }
Paolo Brandoli
  • 4,681
  • 26
  • 38
  • Even after I delete the break and debug it, I get the right interface but it shows me address and netmask as 0.0.0.0.. – Benny Isaacs Jun 17 '14 at 20:04
  • You can see the debug here:http://prntscr.com/3ttlck Why the sa_family is 23(AF_INET6)? it should be 2(AF_INET) no? Thanks – Benny Isaacs Jun 17 '14 at 20:19
  • In the debug I see that you have dev->addresses->next, which contains in IPv4 address. Try to expand it and see if the IPv4 address is in there. Probably your card has two addresses (one for IPv6 and one for IPv4) – Paolo Brandoli Jun 17 '14 at 20:35
0

The iptos example from WinPcap uses a single static buffer to produce its result. This means that when you call it twice, the result of the second call overwrites the result of the first call.

Thus your code:

printf("Found a device %s on address %s with netmask %s\n",
       dev->name, iptos(<addr-expr>), iptos(<mask-expr>));

will always print the same value (either address or netmask, depending on your compiler's order of argument evaluation) in both the address and netmask positions.

To correct this, you can duplicate the result strings and save them to separate variables, like so:

char* addr = strdup(iptos(<addr-expr>));
char* mask = stdrup(iptos(<mask-expr>));
printf("Found a device %s on address %s with netmask %s\n",
       dev->name, addr, mask>);
free(addr);
free(mask);
nobody
  • 19,814
  • 17
  • 56
  • 77
  • It doesn't work.. http://prntscr.com/3ttu2o the problem is that when I generate the list I get 0.0.0.0.. Please see my other comment to see the debug.. thanks! – Benny Isaacs Jun 17 '14 at 20:42
-1

This worked for me.. Open Network connection settings.Right click on ur connection and select properties. Now Uncheck Internet protocol version 6(TCP/IPV6). Now run your application,You will get the proper IP address.

  • I don't think a local configuration can overcome a programming question. Are you also going to asking everyone installing your c++ application to change the settings on their own computer too ? – β.εηοιτ.βε Feb 02 '15 at 10:08
  • This is one of the way u can get a temporary solution for above issue.I had my program written for windows XP which was working fine,Now when i tried to port my code to windows 7 ,i faced the above issue(Since for a single interface there is both IPv6 and IPv4 in W7 whereas XP have only IPV4 ).This can be sorted out either by negleting IPv6 address in code(as desribed earlier) or by disabling the IPV6 ,if u dont want to change the code. Both are working fine.Am I clear... – Midhun C E Feb 03 '15 at 06:51