c-列出IPv4和IPv6的适配器地址和掩码/前缀(GetAdaptersAddresses)



我的任务是列出本地机器上的所有单播接口(通过网络掩码(IPv4(或前缀长度(IPv6(的IP地址和子网(。作为win32 API的新手,我正在阅读GetAdaptersAddress文档。有一个例子很清楚:

  • 随着缓冲区大小的增加调用GetAdaptersAddresses,直到结果适合分配的内存块
  • 迭代返回的PIP_ADAPTER_ADDRESSES(pCurrAddresses(链接列表:
    • 迭代PIP_ADAPTER_UNICAST_ADDRESS*pCurrAddresses->FirstUnicastAddresses链表以检索所有IP地址(SOCKET_ADDRESS及其LPSOCKADDRAddress->lpSockAddr成员(;它是sockaddr_in*sockaddr_in6*,取决于lpSockAddr.sa_family(AF_INETAF_INET6(

此时此刻,我有了IP地址。

网络掩码/前缀怎么样?这似乎就是PIP_ADAPTER_PREFIX_XP(及其SOCKET_ADDRESS Address字段(的意义所在。这是另一个链表,可从PIP_ADAPTER_ADDRESSES->FirstPrefix访问。

遗憾的是,文档指出前缀的排序可能与地址不同:

此外,链接的IP_ADAPTER_UNICAST_ADDRESS结构指向由FirstUnicastAddress成员和链接的FirstPrefix成员指向的IP_ADAPTER_PRIIX结构为由操作系统作为单独的内部链表进行维护。因此,链接的IP_ADAPTER_UNICAST_ADDRESS结构的顺序FirstUnicastAddress成员指向的没有与链接的IP_ADAPTER_PREFIX结构的顺序的关系由FirstPrefix成员指向。

解决方案是什么?我是不是错过了一些显而易见的东西?

某些代码(例如,zeroMQ(仅为每个适配器使用第一个单播地址和第一个前缀。这种方法安全吗?我会错过接口吗?

IP_ADAPTER_ADDRESSES::FirstPrefix字段为您提供了分配给适配器的子网/前缀列表,但正如文档所述,GetAdaptersAddresses()不会告诉您适配器上的哪个特定IP地址对应于哪个子网/后缀。因此,要确定每个IP地址的特定子网/前缀,您必须查看IP_ADAPTER_ADDRESSES::FirstUnicastAddresses列表中的各个条目。

在Windows Vista及更高版本上,IP_ADAPTER_UNICAST_ADDRESS::OnLinkPrefixLength字段为AF_INET地址提供IPv4子网掩码的长度,为AF_INET6地址提供IPv6前缀的长度。对于IPv4,如果需要实际的子网掩码,则可以将长度传递给ConvertLengthToIpv4Mask()函数。

在Windows XP上,OnLinkPrefixLength字段不存在。幸运的是,可以通过调用GetIpAddrTable()函数,然后在表中查找IP地址(在MIB_IPADDRROW::dwAddr字段中-子网掩码将在MIB_IPADDRROW::dwMask字段中(来检索AF_INET地址的IPv4子网掩码。

如果你需要的话,我不知道如何在XP上获得AF_INET6地址的IPv6前缀长度。

最新更新