Windows 为什么OnLinkPrefixLength与适配器PrefixLength不同?

Windows 为什么OnLinkPrefixLength与适配器PrefixLength不同?,windows,winsock,ipv6,Windows,Winsock,Ipv6,如果以Windows 7 SP1中的MSDN示例为例,则展开单播地址的枚举: char s[1024]; for (i = 0; pUnicast != NULL; i++) { inet_ntop (pUnicast->Address.lpSockaddr->sa_family, pUnicast->Address.lpSockaddr->sa_family == AF_INET ? (PVOID)&((struct sockaddr

如果以Windows 7 SP1中的MSDN示例为例,则展开单播地址的枚举:

char s[1024];
for (i = 0; pUnicast != NULL; i++) {
  inet_ntop (pUnicast->Address.lpSockaddr->sa_family,
      pUnicast->Address.lpSockaddr->sa_family == AF_INET ?
      (PVOID)&((struct sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr :
      (PVOID)&((struct sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr,
      s, sizeof (s));
  printf ("\t#%lu %s/%u\n",
      i, s, (unsigned)pUnicast->OnLinkPrefixLength);
  pUnicast = pUnicast->Next;
}
和前缀详细信息:

char s[1024];
for (i = 0; pPrefix != NULL; i++) {
  inet_ntop (pPrefix->Address.lpSockaddr->sa_family,
      pPrefix->Address.lpSockaddr->sa_family == AF_INET ?
      (PVOID)&((struct sockaddr_in*)pPrefix->Address.lpSockaddr)->sin_addr :
      (PVOID)&((struct sockaddr_in6*)pPrefix->Address.lpSockaddr)->sin6_addr,
      s, sizeof (s));
  printf ("\t#%lu %s/%u\n",
      i, s, pPrefix->PrefixLength);
  pPrefix = pPrefix->Next;
}
但一个适配器显示以下输出:

Length of the IP_ADAPTER_ADDRESS struct: 376
IfIndex (IPv4 interface): 15
Adapter name: {84C25EC1-7ABB-4D6E-B8C7-8DEE08961EE2}
#0 2001:0:4137:9e76:2443:d6:ba87:1a2a/64
#1 fe80::2443:d6:ba87:1a2a/64
Number of Unicast Addresses: 2
...
#0 ::/0
#1 2001::/32
#2 2001:0:4137:9e76:2443:d6:ba87:1a2a/128
#3 fe80::/64
#4 fe80::2443:d6:ba87:1a2a/128
#5 ff00::/8
Number of IP Adapter Prefix entries: 6
前缀列表是正确的,尽管略高于MSDN对3个地址的描述:

char s[1024];
for (i = 0; pUnicast != NULL; i++) {
  inet_ntop (pUnicast->Address.lpSockaddr->sa_family,
      pUnicast->Address.lpSockaddr->sa_family == AF_INET ?
      (PVOID)&((struct sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr :
      (PVOID)&((struct sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr,
      s, sizeof (s));
  printf ("\t#%lu %s/%u\n",
      i, s, (unsigned)pUnicast->OnLinkPrefixLength);
  pUnicast = pUnicast->Next;
}
在Windows Vista及更高版本上,链接 IP_适配器_前缀结构指向 由FirstPrefix成员包括 每个IP有三个IP适配器前缀 分配给适配器的地址。这些 包括主机IP地址前缀, 子网IP地址前缀,以及 子网广播IP地址前缀。在里面 此外,每个适配器都有一个 多播地址前缀和 广播地址前缀

通过与
netstat-r
的输出进行比较,我确定列表是正确的:

IPv6 Route Table
==================================================
Active Routes:
 If Metric Network Destination      Gateway
 15     58 ::/0                     On-link
  1    306 ::1/128                  On-link
 15     58 2001::/32                On-link
 15    306 2001:0:4137:9e76:2443:d6:ba87:1a2a/128
                                    On-link
 14    281 fe80::/64                On-link
 15    306 fe80::/64                On-link
 15    306 fe80::2443:d6:ba87:1a2a/128
                                    On-link
 14    281 fe80::6153:a573:f691:8167/128
                                    On-link
  1    306 ff00::/8                 On-link
 15    306 ff00::/8                 On-link
 14    281 ff00::/8                 On-link
==================================================

然而,我对API的解释是,
OnLinkPrefixLength
应该为全局范围单播地址返回32,但是Vista+only API返回64,为什么?

一点背景信息: IPv6有一些默认前缀长度。局域网的前缀长度通常为64。您看到的链接本地地址(fe80::/64)就是这样的例子。您自己系统的地址在路由表(/128)中显示为单个地址。多播地址是特殊的(ff00::/8),因为它们不对应于一个主机的一个地址,而是对应于潜在多个网络上的一组多个主机

您看到的/32是Teredo地址块(2001:0000::/32==2001::/32)。Teredo是Windows自动配置的IPv6-in-IPv4隧道协议。路由表显示默认IPv6路由(::/0)通过Teredo适配器。您的系统似乎没有“正常”的IPv6全局单播

摘要: 链路前缀长度通常为/64。Teredo是一个特例,使用固定的'special'/32。您自己的IPv6地址已完成,前缀长度为/128

你说得对,2001:0:4137:9e76:2443:d6:ba87:1a2a/64没有意义。它是Teredo,因此它的网络前缀长度应为/32。如果是单个IPv6地址,则其前缀长度应为/128。对于Teredo来说/64没有意义,似乎是一个bug