A well-known way is to use getaddrinfo() such like:
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include <iostream>
#include <netdb.h>
#include <string>
#include <sys/socket.h>
#include <sysexits.h>
int main(void)
{
    struct addrinfo hints;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET6;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_protocol = IPPROTO_UDP;
    struct addrinfo* result_addrinfo = nullptr;
    auto result = getaddrinfo("fe80::dabb:c1ff:fe0a:17f2%enp39s0", std::to_string(12345).c_str(), &hints, &result_addrinfo);
    if( result != 0 ){
        std::cout << "`getaddrinfo()` failed: " << gai_strerror(errno) << std::endl;
        return result;
    }
    for(
        struct addrinfo* info = result_addrinfo;
        info != nullptr;
        info = info->ai_next
    ){
        char ipv6addr_human_readable_form[INET6_ADDRSTRLEN] = {0, };
        inet_ntop(info->ai_family, &((struct sockaddr_in6*)(info->ai_addr))->sin6_addr, ipv6addr_human_readable_form, info->ai_addrlen);
        auto ipv6_scope_id = ((struct sockaddr_in6*)(info->ai_addr))->sin6_scope_id;
        std::cout << "IPv6 address = " << ipv6addr_human_readable_form << std::endl;
        std::cout << "Scope-ID = " << std::to_string(ipv6_scope_id) << std::endl;
    }
    freeaddrinfo(result_addrinfo);
    return EX_OK;
}
Of course, the Scope-ID can also be obtained as previously. But is there an easier and shorter?
  
  
  Solution using if_nametoindex()
Fortunately, Linux provides a function called if_nametoindex(). It returns the index number of the network interface, which is currently equal to the Scope-ID.
#include <net/if.h>
#include <iostream>
#include <sysexits.h>
int main(void)
{
    auto scope_id = if_nametoindex("enp39s0");
    std::cout << scope_id << std::endl;
    return EX_OK;
}
Now, the code became much shorter and easier. Also, there is no need to care to free memory!
 

 
    
Top comments (0)