无法通过pcap_findalldevs获取IP地址

时间:2014-06-17 18:06:29

标签: c++ networking pcap libpcap winpcap

我正在使用pcap_findalldevs获取计算机中的设备列表。我成功了,设备的名称和描述,但我不知道为什么,我得到Netmask 0.0.0.0和IP地址也0.0.0.0。 这是我生成列表的代码:

/* 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;
    }
}

5 个答案:

答案 0 :(得分:5)

这是应该做的事情:

/* 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:

这样,您可以检查整个地址列表,而不仅仅是列表中的第一个地址。如果,当您到达found时,dev为非空,则它指向至少有一个IPv4地址的设备,dev_addr指向该地址。如果dev为空,则表示没有具有IPv4地址的设备。

答案 1 :(得分:1)

Anrew Medico的post让我想到了这个解决方案:

起初我使用const auto进行初始化。这是一个常见问题*。我还得到了ip-address的子网掩码。由于iptos()对我不起作用,我将deklaration更改为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);

希望这有助于其他人,因为它帮助了我。

答案 2 :(得分:0)

在您找到的第一个接口之后退出循环,这可能是环回接口。

这是我过去使用的代码(我跳过了地址为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
        }

    }

答案 3 :(得分:0)

iptos example from WinPcap使用单个静态缓冲区来生成结果。这意味着当你调用它两次时,第二次调用的结果会覆盖第一次调用的结果。

因此你的代码:

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

将始终在地址和网络掩码位置中打印相同的值(地址或网络掩码,具体取决于编译器的参数评估顺序)。

要更正此问题,您可以复制结果字符串并将其保存到单独的变量中,如下所示:

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);

答案 4 :(得分:-1)

这对我有用.. 打开网络连接设置。右键单击您的连接并选择属性。现在取消选中Internet协议版本6(TCP / IPV6)。 现在运行您的应用程序,您将获得正确的IP地址。