Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 27 Feb 2020 13:17:20 +0300
From: Alexander Scherbatiy <alexander.scherbatiy@...l-sw.com>
To: musl@...ts.openwall.com
Subject: getaddrinfo(3) with AI_V4MAPPED and AI_ALL flags

Hello,

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 '0.0.0.0'
AF_INET6 IPv6 addr '::'

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

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:0.0.0.0' and  IPv6 '::'

----------------

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

----------------

Is it expected behavior?

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

Thanks,

Alexander.


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, 
INET6_ADDRSTRLEN);
         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) {
         sockaddr_show(rp->ai_addr);
     }
     printf("\n");
}

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 | 
AI_ALL\n");
     show_addr_info(AF_INET6,  AI_PASSIVE | AI_V4MAPPED | AI_ALL);

     return EXIT_SUCCESS;
}

--------------------------------





Powered by blists - more mailing lists

Your e-mail address:

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