If you take the MSDN example inside IP_ADAPTER_ADDRESSES Structure on Windows 7 SP1 then expand out enumeration of unicast addresses:
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;
}
and prefix details:
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;
}
But one adapter shows the following output:
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
The prefix list is correct, albeit slightly expanded over MSDN’s description of 3 addresses:
On Windows Vista and later, the linked
IP_ADAPTER_PREFIX structures pointed
to by the FirstPrefix member include
three IP adapter prefixes for each IP
address assigned to the adapter. These
include the host IP address prefix,
the subnet IP address prefix, and the
subnet broadcast IP address prefix. In
addition, for each adapter there is a
multicast address prefix and a
broadcast address prefix.
I determine the list is correct by comparing with the output of 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
==================================================
However my interpretation of the API is that OnLinkPrefixLength should return 32 for the global-scope unicast address but the Vista+ only API is returning 64, why?
A bit of background information:
There are a few default prefix lengths for IPv6. A LAN usually has a prefix length of 64. The link local addresses you see (fe80::/64) are examples of that. The addresses of your own system show up as single addresses in the routing table (/128). The multicast addresses are special (ff00::/8) as they don’t correspond to one address of one host but to a group of multiple hosts on potentially multiple networks.
The /32 you are seeing is the Teredo address block (2001:0000::/32 == 2001::/32). Teredo is a IPv6-in-IPv4 tunneling protocol that Windows automatically configures. The routing table shows that your default IPv6 route (::/0) is through the Teredo adapter. Your system doesn’t seem to have ‘normal’ IPv6 global unicast.
Summary:
The on-link-prefix-length is usually /64. Teredo is a special case and uses a fixed ‘special’ /32. Your own IPv6 addresses are complete and have a prefix length of /128.
You are right in that 2001:0:4137:9e76:2443:d6:ba87:1a2a/64 doesn’t make sense. It is Teredo so it should have a network prefix length of /32. If it is a single IPv6 address it should have a prefix length of /128. The /64 does not make sense for Teredo and seems to be a bug.