Blame src/tests/resolve/addrinfo-test.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* tests/resolve/addrinfo-test.c */
Packit fd8b60
/*
Packit fd8b60
 * Copyright 2004 by the Massachusetts Institute of Technology.
Packit fd8b60
 * All Rights Reserved.
Packit fd8b60
 *
Packit fd8b60
 * Export of this software from the United States of America may
Packit fd8b60
 *   require a specific license from the United States Government.
Packit fd8b60
 *   It is the responsibility of any person or organization contemplating
Packit fd8b60
 *   export to obtain such a license before exporting.
Packit fd8b60
 *
Packit fd8b60
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
Packit fd8b60
 * distribute this software and its documentation for any purpose and
Packit fd8b60
 * without fee is hereby granted, provided that the above copyright
Packit fd8b60
 * notice appear in all copies and that both that copyright notice and
Packit fd8b60
 * this permission notice appear in supporting documentation, and that
Packit fd8b60
 * the name of M.I.T. not be used in advertising or publicity pertaining
Packit fd8b60
 * to distribution of the software without specific, written prior
Packit fd8b60
 * permission.  Furthermore if you modify this software you must label
Packit fd8b60
 * your software as modified software and not distribute it in such a
Packit fd8b60
 * fashion that it might be confused with the original M.I.T. software.
Packit fd8b60
 * M.I.T. makes no representations about the suitability of
Packit fd8b60
 * this software for any purpose.  It is provided "as is" without express
Packit fd8b60
 * or implied warranty.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * A simple program to test the functionality of the getaddrinfo function.
Packit fd8b60
 *
Packit fd8b60
 * Usage:
Packit fd8b60
 *   addrinfo-test [-t|-u|-R|-I] [-d|-s|-r] [-p port] [-P] [hostname]
Packit fd8b60
 *
Packit fd8b60
 *   When invoked with no arguments, NULL is used for the node name,
Packit fd8b60
 *   which (at least with a non-null "port") means a socket address
Packit fd8b60
 *   is desired that can be used with connect() or bind() (depending
Packit fd8b60
 *   on whether "-P" is given).
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include <k5-platform.h>
Packit fd8b60
#include <sys/types.h>
Packit fd8b60
#include <sys/socket.h>
Packit fd8b60
#include <netdb.h>
Packit fd8b60
#include <netinet/in.h> /* needed for IPPROTO_* on NetBSD */
Packit fd8b60
#ifdef USE_FAKE_ADDRINFO
Packit fd8b60
#include "fake-addrinfo.h"
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
static const char *protoname (int p) {
Packit fd8b60
    static char buf[30];
Packit fd8b60
Packit fd8b60
#define X(N) if (p == IPPROTO_ ## N) return #N
Packit fd8b60
Packit fd8b60
    X(TCP);
Packit fd8b60
    X(UDP);
Packit fd8b60
    X(ICMP);
Packit fd8b60
#ifdef IPPROTO_IPV6
Packit fd8b60
    X(IPV6);
Packit fd8b60
#endif
Packit fd8b60
#ifdef IPPROTO_GRE
Packit fd8b60
    X(GRE);
Packit fd8b60
#endif
Packit fd8b60
#ifdef IPPROTO_NONE
Packit fd8b60
    X(NONE);
Packit fd8b60
#endif
Packit fd8b60
    X(RAW);
Packit fd8b60
#ifdef IPPROTO_COMP
Packit fd8b60
    X(COMP);
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
    snprintf(buf, sizeof(buf), " %-2d", p);
Packit fd8b60
    return buf;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static const char *socktypename (int t) {
Packit fd8b60
    static char buf[30];
Packit fd8b60
    switch (t) {
Packit fd8b60
    case SOCK_DGRAM: return "DGRAM";
Packit fd8b60
    case SOCK_STREAM: return "STREAM";
Packit fd8b60
    case SOCK_RAW: return "RAW";
Packit fd8b60
    case SOCK_RDM: return "RDM";
Packit fd8b60
    case SOCK_SEQPACKET: return "SEQPACKET";
Packit fd8b60
    }
Packit fd8b60
    snprintf(buf, sizeof(buf), " %-2d", t);
Packit fd8b60
    return buf;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static char *whoami;
Packit fd8b60
Packit fd8b60
static void usage () {
Packit fd8b60
    fprintf(stderr,
Packit fd8b60
            "usage:\n"
Packit fd8b60
            "\t%s [ options ] [host]\n"
Packit fd8b60
            "options:\n"
Packit fd8b60
            "\t-t\tspecify protocol IPPROTO_TCP\n"
Packit fd8b60
            "\t-u\tspecify protocol IPPROTO_UDP\n"
Packit fd8b60
            "\t-R\tspecify protocol IPPROTO_RAW\n"
Packit fd8b60
            "\t-I\tspecify protocol IPPROTO_ICMP\n"
Packit fd8b60
            "\n"
Packit fd8b60
            "\t-d\tspecify socket type SOCK_DGRAM\n"
Packit fd8b60
            "\t-s\tspecify socket type SOCK_STREAM\n"
Packit fd8b60
            "\t-r\tspecify socket type SOCK_RAW\n"
Packit fd8b60
            "\n"
Packit fd8b60
            "\t-4\tspecify address family AF_INET\n"
Packit fd8b60
#ifdef AF_INET6
Packit fd8b60
            "\t-6\tspecify address family AF_INET6\n"
Packit fd8b60
#endif
Packit fd8b60
            "\n"
Packit fd8b60
            "\t-p P\tspecify port P (service name or port number)\n"
Packit fd8b60
            "\t-N\thostname is numeric, skip DNS query\n"
Packit fd8b60
            "\t-n\tservice/port is numeric (sets AI_NUMERICSERV)\n"
Packit fd8b60
            "\t-P\tset AI_PASSIVE\n"
Packit fd8b60
            "\n"
Packit fd8b60
            "default: protocol 0, socket type 0, address family 0, null port\n"
Packit fd8b60
            ,
Packit fd8b60
            whoami);
Packit fd8b60
    /* [ -t | -u | -R | -I ] [ -d | -s | -r ] [ -p port ] */
Packit fd8b60
    exit (1);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static const char *familyname (int f) {
Packit fd8b60
    static char buf[30];
Packit fd8b60
    switch (f) {
Packit fd8b60
    default:
Packit fd8b60
        snprintf(buf, sizeof(buf), "AF %d", f);
Packit fd8b60
        return buf;
Packit fd8b60
    case AF_INET: return "AF_INET";
Packit fd8b60
#ifdef AF_INET6
Packit fd8b60
    case AF_INET6: return "AF_INET6";
Packit fd8b60
#endif
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#define eaistr(X) (X == EAI_SYSTEM ? strerror(errno) : gai_strerror(X))
Packit fd8b60
Packit fd8b60
int main (int argc, char *argv[])
Packit fd8b60
{
Packit fd8b60
    struct addrinfo *ap, *ap2;
Packit fd8b60
    int err, numerichost = 0, numericserv = 0;
Packit fd8b60
    char *hname, *port = 0, *sep;
Packit fd8b60
    struct addrinfo hints;
Packit fd8b60
Packit fd8b60
    whoami = strrchr(argv[0], '/');
Packit fd8b60
    if (whoami == 0)
Packit fd8b60
        whoami = argv[0];
Packit fd8b60
    else
Packit fd8b60
        whoami = whoami+1;
Packit fd8b60
Packit fd8b60
    memset(&hints, 0, sizeof(hints));
Packit fd8b60
    hints.ai_flags = 0;
Packit fd8b60
    hints.ai_socktype = 0;
Packit fd8b60
Packit fd8b60
    hname = 0;
Packit fd8b60
    hints.ai_family = 0;
Packit fd8b60
Packit fd8b60
    if (argc == 1)
Packit fd8b60
        usage ();
Packit fd8b60
Packit fd8b60
    while (++argv, --argc > 0) {
Packit fd8b60
        char *arg;
Packit fd8b60
        arg = *argv;
Packit fd8b60
Packit fd8b60
        if (*arg != '-')
Packit fd8b60
            hname = arg;
Packit fd8b60
        else if (arg[1] == 0 || arg[2] != 0)
Packit fd8b60
            usage ();
Packit fd8b60
        else
Packit fd8b60
            switch (arg[1]) {
Packit fd8b60
            case 'u':
Packit fd8b60
                hints.ai_protocol = IPPROTO_UDP;
Packit fd8b60
                break;
Packit fd8b60
            case 't':
Packit fd8b60
                hints.ai_protocol = IPPROTO_TCP;
Packit fd8b60
                break;
Packit fd8b60
            case 'R':
Packit fd8b60
                hints.ai_protocol = IPPROTO_RAW;
Packit fd8b60
                break;
Packit fd8b60
            case 'I':
Packit fd8b60
                hints.ai_protocol = IPPROTO_ICMP;
Packit fd8b60
                break;
Packit fd8b60
            case 'd':
Packit fd8b60
                hints.ai_socktype = SOCK_DGRAM;
Packit fd8b60
                break;
Packit fd8b60
            case 's':
Packit fd8b60
                hints.ai_socktype = SOCK_STREAM;
Packit fd8b60
                break;
Packit fd8b60
            case 'r':
Packit fd8b60
                hints.ai_socktype = SOCK_RAW;
Packit fd8b60
                break;
Packit fd8b60
            case 'p':
Packit fd8b60
                if (argv[1] == 0 || argv[1][0] == 0 || argv[1][0] == '-')
Packit fd8b60
                    usage ();
Packit fd8b60
                port = argv[1];
Packit fd8b60
                argc--, argv++;
Packit fd8b60
                break;
Packit fd8b60
            case '4':
Packit fd8b60
                hints.ai_family = AF_INET;
Packit fd8b60
                break;
Packit fd8b60
#ifdef AF_INET6
Packit fd8b60
            case '6':
Packit fd8b60
                hints.ai_family = AF_INET6;
Packit fd8b60
                break;
Packit fd8b60
#endif
Packit fd8b60
            case 'N':
Packit fd8b60
                numerichost = 1;
Packit fd8b60
                break;
Packit fd8b60
            case 'n':
Packit fd8b60
                numericserv = 1;
Packit fd8b60
                break;
Packit fd8b60
            case 'P':
Packit fd8b60
                hints.ai_flags |= AI_PASSIVE;
Packit fd8b60
                break;
Packit fd8b60
            default:
Packit fd8b60
                usage ();
Packit fd8b60
            }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (hname && !numerichost)
Packit fd8b60
        hints.ai_flags |= AI_CANONNAME;
Packit fd8b60
    if (numerichost) {
Packit fd8b60
#ifdef AI_NUMERICHOST
Packit fd8b60
        hints.ai_flags |= AI_NUMERICHOST;
Packit fd8b60
#else
Packit fd8b60
        fprintf(stderr, "AI_NUMERICHOST not defined on this platform\n");
Packit fd8b60
        exit(1);
Packit fd8b60
#endif
Packit fd8b60
    }
Packit fd8b60
    if (numericserv) {
Packit fd8b60
#ifdef AI_NUMERICSERV
Packit fd8b60
        hints.ai_flags |= AI_NUMERICSERV;
Packit fd8b60
#else
Packit fd8b60
        fprintf(stderr, "AI_NUMERICSERV not defined on this platform\n");
Packit fd8b60
        exit(1);
Packit fd8b60
#endif
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    printf("getaddrinfo(hostname %s, service %s,\n"
Packit fd8b60
           "            hints { ",
Packit fd8b60
           hname ? hname : "(null)", port ? port : "(null)");
Packit fd8b60
    sep = "";
Packit fd8b60
#define Z(FLAG) if (hints.ai_flags & AI_##FLAG) printf("%s%s", sep, #FLAG), sep = "|"
Packit fd8b60
    Z(CANONNAME);
Packit fd8b60
    Z(PASSIVE);
Packit fd8b60
#ifdef AI_NUMERICHOST
Packit fd8b60
    Z(NUMERICHOST);
Packit fd8b60
#endif
Packit fd8b60
#ifdef AI_NUMERICSERV
Packit fd8b60
    Z(NUMERICSERV);
Packit fd8b60
#endif
Packit fd8b60
    if (sep[0] == 0)
Packit fd8b60
        printf ("no-flags");
Packit fd8b60
    if (hints.ai_family)
Packit fd8b60
        printf(" %s", familyname(hints.ai_family));
Packit fd8b60
    if (hints.ai_socktype)
Packit fd8b60
        printf(" SOCK_%s", socktypename(hints.ai_socktype));
Packit fd8b60
    if (hints.ai_protocol)
Packit fd8b60
        printf(" IPPROTO_%s", protoname(hints.ai_protocol));
Packit fd8b60
    printf(" }):\n");
Packit fd8b60
Packit fd8b60
    err = getaddrinfo(hname, port, &hints, &ap);
Packit fd8b60
    if (err) {
Packit fd8b60
        printf("\terror => %s\n", eaistr(err));
Packit fd8b60
        return 1;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    for (ap2 = ap; ap2; ap2 = ap2->ai_next) {
Packit fd8b60
        char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
Packit fd8b60
        /* If we don't do this, even AIX's own getnameinfo will reject
Packit fd8b60
           the sockaddr structures.  The sa_len field doesn't get set
Packit fd8b60
           either, on AIX, but getnameinfo won't complain.  */
Packit fd8b60
        if (ap2->ai_addr->sa_family == 0) {
Packit fd8b60
            printf("BAD: sa_family zero! fixing...\n");
Packit fd8b60
            ap2->ai_addr->sa_family = ap2->ai_family;
Packit fd8b60
        } else if (ap2->ai_addr->sa_family != ap2->ai_family) {
Packit fd8b60
            printf("BAD: sa_family != ai_family! fixing...\n");
Packit fd8b60
            ap2->ai_addr->sa_family = ap2->ai_family;
Packit fd8b60
        }
Packit fd8b60
        if (getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof(hbuf),
Packit fd8b60
                        pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
Packit fd8b60
            strlcpy(hbuf, "...", sizeof(hbuf));
Packit fd8b60
            strlcpy(pbuf, "...", sizeof(pbuf));
Packit fd8b60
        }
Packit fd8b60
        printf("%p:\n"
Packit fd8b60
               "\tfamily = %s\tproto = %-4s\tsocktype = %s\n",
Packit fd8b60
               (void *) ap2, familyname(ap2->ai_family),
Packit fd8b60
               protoname (ap2->ai_protocol),
Packit fd8b60
               socktypename (ap2->ai_socktype));
Packit fd8b60
        if (ap2->ai_canonname) {
Packit fd8b60
            if (ap2->ai_canonname[0])
Packit fd8b60
                printf("\tcanonname = %s\n", ap2->ai_canonname);
Packit fd8b60
            else
Packit fd8b60
                printf("BAD: ai_canonname is set but empty!\n");
Packit fd8b60
        } else if (ap2 == ap && (hints.ai_flags & AI_CANONNAME)) {
Packit fd8b60
            printf("BAD: first ai_canonname is null!\n");
Packit fd8b60
        }
Packit fd8b60
        printf("\taddr = %-28s\tport = %s\n", hbuf, pbuf);
Packit fd8b60
Packit fd8b60
        err = getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof (hbuf),
Packit fd8b60
                          pbuf, sizeof(pbuf), NI_NAMEREQD);
Packit fd8b60
        if (err)
Packit fd8b60
            printf("\tgetnameinfo(NI_NAMEREQD): %s\n", eaistr(err));
Packit fd8b60
        else
Packit fd8b60
            printf("\tgetnameinfo => %s, %s\n", hbuf, pbuf);
Packit fd8b60
    }
Packit fd8b60
    freeaddrinfo(ap);
Packit fd8b60
    return 0;
Packit fd8b60
}