Project

General

Profile

Bug #5096

getaddrinfo doesn't properly handle AI_ADDRCONFIG | AI_V4MAPPED

Added by Robert Mustacchi almost 6 years ago. Updated over 5 years ago.

Status:
Closed
Priority:
Normal
Category:
lib - userland libraries
Start date:
2014-08-14
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

When getaddrinfo() is invoked with AF_UNSPEC and flags set to AI_ADDRCONFIG | AI_V4MAPPED (aka AI_DEFAULT), and there are no IPv6 interfaces on the system (non-loopback), then getaddrinfo returns an IPv6 mapped IPv4 address. The following program can be used to demonstrate it:

#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <strings.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int
main(int argc, const char *argv[])
{
        struct addrinfo *addrs, *a, hints;
        int i;
        char buf[1024];
        const char *n;

        if (argc != 2) {
                fprintf(stderr, "give me a host, just one\\n");
                return (1);
        }

        bzero(&hints, sizeof (struct addrinfo));
        hints.ai_family = AF_UNSPEC;
        hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;

        if (getaddrinfo(argv[1], NULL, &hints, &addrs) != 0) {
                fprintf(stderr, "getaddrinfo failed: %s\\n",
                    strerror(errno));
                return (1);
        }

        for (a = addrs; a != NULL; a = a->ai_next) {
                void *addr;
                if (a->ai_family == AF_INET) {
                        addr = &((struct sockaddr_in *)a->ai_addr)->sin_addr;
                } else {
                        addr = &((struct sockaddr_in6 *)a->ai_addr)->sin6_addr;
                }
                n = inet_ntop(a->ai_family, addr, buf, sizeof (buf));
                if (n == NULL) {
                        fprintf(stderr, "inet_pton failed: %s\\n", strerror(errno));
                        freeaddrinfo(addrs);
                        return (1);
                }
                printf("%s\\n", n);
        }

        freeaddrinfo(addrs);
        return (0);
}

This ends up getting to getaddrinfo via getipnodebyname(). RFC 2553 explicitly describes the behavior of getipnodebyname() in the case of specifying V4MAPPED and ADDRCONFIG. In addition, because a closer reading of the SUS specification for getaddrinfo doesn't clarify this behavior. In this case getaddrinfo is calling getipnodebyname() in a reasonable way, therefore the fix cannot be in getipnodebyname().

Instead, the question is whether or not getaddrinfo is working incorrectly. In this case, because AF_UNSPEC was requested, it seems reasonable to get the address back in any format. However, the standard's wording isn't the clearest here. Instead, it seems like getaddrinfo() is supposed to actually allow ADDRCONFIG to trump V4MAPPED, which is also what happens on other platforms.

To implement this, I've gone and added a private flag between libnsl and libsocket's getipnodebyname which should allow us to convince getipnodebyname to have the getaddrinfo behavior.


Related issues

Related to illumos gate - Bug #6592: AI_ADDRCONFIG fails all resolutions when only loopback is presentClosed2016-02-01

Actions

History

#1

Updated by Electric Monk over 5 years ago

  • Status changed from New to Closed

git commit 2f443e27e5988131d8b57bec58ee15f9227e0899

commit  2f443e27e5988131d8b57bec58ee15f9227e0899
Author: Robert Mustacchi <rm@joyent.com>
Date:   2014-12-10T23:36:39.000Z

    5096 getaddrinfo doesn't properly handle AI_ADDRCONFIG | AI_V4MAPPED
    Reviewed by: Dan McDonald <danmcd@omniti.com>
    Reviewed by: Jason King <jason.brian.king@gmail.com>
    Approved by: Richard Lowe <richlowe@richlowe.net>

#2

Updated by Marcel Telka 3 months ago

  • Related to Bug #6592: AI_ADDRCONFIG fails all resolutions when only loopback is present added

Also available in: Atom PDF