Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 27 Feb 2020 13:17:20 +0300
From: Alexander Scherbatiy <>
Subject: getaddrinfo(3) with AI_V4MAPPED and AI_ALL flags


When I call getaddrinfo() with different families, SOCK_STREAM socktype, 
IPPROTO_TCP protocol, and AI_PASSIVE flag the result is the same on the 
Alpine Linux 3.11.3 and Ubuntu 19.10 (the code sample is below):


family: AF_UNSPEC, flags: AI_PASSIVE
AF_INET  IPv4 addr ''
AF_INET6 IPv6 addr '::'

family: AF_INET,   flags: AI_PASSIVE
AF_INET  IPv4 addr ''

family: AF_INET6,  flags: AI_PASSIVE
AF_INET6 IPv6 addr '::'


When I use getaddrinfo() with AF_INET6 family and additional AI_V4MAPPED 
| AI_ALL (return both IPv6 and IPv4-mapped IPv6 addresses) flags the 
result on Ubuntu contains only IPv6 '::' address:


family: AF_INET6,  flags: AI_PASSIVE | AI_V4MAPPED | AI_ALL
AF_INET6 IPv6 addr '::'


whereas the result on Alpine Linux contains both IPv4-mapped IPv6 
addresses '::ffff:' and  IPv6 '::'


family: AF_INET6,  flags: AI_PASSIVE | AI_V4MAPPED | AI_ALL
AF_INET6 IPv6 addr '::ffff:'
AF_INET6 IPv6 addr '::'


Is it expected behavior?

I use Alpine Linux 3.11.3 from docker with musl libc (x86_64).



Code sample:

-------------  addr_info.c -----------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <netdb.h>
#include <arpa/inet.h>

void sockaddr_show(struct sockaddr *sa) {

     int family = sa->sa_family;

     if (family == AF_INET) {
         char buff[INET_ADDRSTRLEN];
         struct sockaddr_in server_addr = *((struct sockaddr_in*) sa);
         inet_ntop(AF_INET, &server_addr.sin_addr, buff, INET_ADDRSTRLEN);
         printf("AF_INET  IPv4 addr '%s'\n", buff);
     } else if (family == AF_INET6) {
         char buff[INET_ADDRSTRLEN];
         struct sockaddr_in6 server_addr = *((struct sockaddr_in6*) sa);
         inet_ntop(AF_INET6, &server_addr.sin6_addr, buff, 
         printf("AF_INET6 IPv6 addr '%s'\n", buff);
     } else {
         printf("family: %d\n", family);

void show_addr_info(int family, int flags) {

     char* hostname = NULL;
     char* service = "33833";

     struct addrinfo hints;
     struct addrinfo *result, *rp;

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

     hints.ai_family = family;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = IPPROTO_TCP;
     hints.ai_flags = flags;

     int res = getaddrinfo(hostname, service, &hints, &result);
     for (rp = result; rp != NULL; rp = rp->ai_next) {

int main(void) {

     printf("family: AF_UNSPEC, flags: AI_PASSIVE\n");
     show_addr_info(AF_UNSPEC, AI_PASSIVE);

     printf("family: AF_INET,   flags: AI_PASSIVE\n");
     show_addr_info(AF_INET,   AI_PASSIVE);

     printf("family: AF_INET6,  flags: AI_PASSIVE\n");
     show_addr_info(AF_INET6,  AI_PASSIVE);

     printf("family: AF_INET6,  flags: AI_PASSIVE | AI_V4MAPPED | 
     show_addr_info(AF_INET6,  AI_PASSIVE | AI_V4MAPPED | AI_ALL);

     return EXIT_SUCCESS;


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.