linuxnetwork-programmingipv6loopbackgetaddrinfo

Is ::ffff:127.0.0.1 localhost?


I'm getting introduced into IPv6 and I've read that IPv4 addresses can be mapped to IPv6 by using the ::ffff: prefix. This led me to think whether address ::ffff:127.0.0.1 refers to localhost, so I wrote a simple C program that uses getaddrinfo() and IN6_IS_ADDR_LOOPBACK macro for checking if the returned address is the loopback one.

I have tested the program with ::1 and other variations of the loopback address and, as expected, the program says that it's loopback. But, to my surprise, when I try ::ffff:127.0.0.1 the program says that it's not! How is this possible? Am I missing anything?

Here's the simplified version of the source code of my program:

struct addrinfo hints, *servinfo;
int rv;

memset(&hints, 0, sizeof(hints));

hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;

/* hostname_or_ip is entered from the command line */
if ( (rv = getaddrinfo(hostname_or_ip, NULL, &hints, &servinfo)) != 0) {
    exit(1);
}

struct addrinfo *p = servinfo;
struct sockaddr_in6 *h = (struct sockaddr_in6 *) p->ai_addr;
int is_loopback = IN6_IS_ADDR_LOOPBACK(&h->sin6_addr) ? 1 : 0;

printf("%s\n", is_loopback ? "YES!" : "NO!");

Solution

  • If you accept incoming IPv4 connections on an IPv6 socket then the IPv4 address has to be padded to 128 bits. That is done by prepending ::ffff:. So what you are seeing is the IPv4 loopback address.

    When checking if the address is the IPv6 loopback address then the answer will be no, because ::1 is the IPv6 loopback address. The address you see is classified as an IPv4-mapped IPv6 address. The mapped IPv4 address just happens to be the IPv4 loopback address, but from the point of view of the IPv6 stack it's just a mapped address.