I am currently working on an IPv6 class and use inet_pton to retrieve the actual binary representation of the IP from a string i.e.:
AdressV6::AdressV6(const String & _ip)
{
int result = inet_pton(AF_INET6, _ip.c_str(), &(m_nativeAdress));
if(result <= 0)
//throw...
//How can I retrieve the sope ID from that?
}
Is there a common way to do that? Do you just manually parse the string and look for the “%” that does not sound very bullet proof 🙁
Thank you!
I tried manual parsing for now which seems to work. Still, if there is a better way please let me know:
//retrieve scope ID
uint32 scopeId = 0;
size_t pos = _ip.find("%");
if(pos != String::npos)
{
String theId = _ip.substr(pos+1);
scopeId = atoi(theId.c_str());
}
m_scopeId = scopeId;
On BSD and BSD based systems (this includes MacOS X for example), the scope ID is embedded into the address itself for link local addresses as the second 16 bit word. Please refer to the FreeBSD Handbook and search for "8.1.1.3 Scope Index" (without the quotes).
So assuming that intf1 has scope ID 1 and intf2 has scope ID 2,
inet_pton()will convert the strings as follows on these platforms:The last address is simply unscoped and thus cannot be really used for sending out data.
Please note that this is non-standard;
inet_pton()does not work that way on Linux or Windows based systems. However, I think even on Linux and Windows based systems,inet_pton()allows a scope ID at the end, it will simply ignore it, though.For non-link-local address, this trick doesn’t work, of course, yet those addresses are usually not scoped. They can be scoped, but usually every interface has an own, unique interface IPv6 address, based on its interface identifier (even if you use DHCPv6, in which case it has a DHCP address assigned by the DHCP server, as well as the auto generated IPv6 interface address, unless this auto generation has been forbidden).
The
struct sockaddr_in6structure has a field for the scope ID but the RFC that defines this field (RFC 2553 – Section 3.3) does not really give much detail how this field is to be interpreted. It only says:So this field is entirely implementation specific.
If you want this field to be filled in correctly, and your code should be as cross-platform as possible, you should use
getaddrinfo():One extra tip: If you want to use the returned
getaddrinfo()for a server socket (a socket that you want to bind locally and then callaccept()on it), you should also set the passive flag:Not that it will play a role in most case but that is the correct way of using
getaddrinfo().