Subject: problems with using getnameinfo()?
To: NetBSD Networking Technical Discussion List <tech-net@NetBSD.ORG>
From: Greg A. Woods <woods@weird.com>
List: tech-net
Date: 05/07/2001 19:41:32
Can anyone see anything glaringly wrong with the following code?  (other
than perhaps my overly simplistic way of identifying an IPv6 address
string?)  I'm trying to learn to use IPv6 names and addresses, and while
I'm at it to test getnameinfo(), but unforunately it's not working for
me.  For example:

$ ./tgetnameinfo 127.0.0.1 
gethostbyaddr()
        Hostname:       localhost
        Aliases:
        Addresses:      127.0.0.1 

./tgetnameinfo: getnameinfo(AF_INET[127.0.0.1], 16): address family was not recognized, or address length invalid

$ ./tgetnameinfo fe80::1      
./tgetnameinfo: getnameinfo(AF_INET6[fe80::1], 28): address family was not recognized, or address length invalid

$ ./tgetnameinfo 204.92.254.2 
gethostbyaddr()
        Hostname:       mail.weird.com
        Aliases:        most.weird.com 
        Addresses:      204.92.254.2 

./tgetnameinfo: getnameinfo(AF_INET[204.92.254.2], 16): address family was not recognized, or address length invalid

 /*
  * getnameinfo tester. compile with:
  * 
  * run as: tgetnameinfo address
  *
  * Copyright hereby placed in the Public Domain.
  */

#define INET6	1				/* set this if you can.... */

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

char *
streiaret(eia, err)
	int eia;
	int err;
{
	switch (eia) {
	case EAI_AGAIN:
		return "name could not be resolved at this time";
	case EAI_BADFLAGS:
		return "invalid flags value";
	case EAI_FAIL:
		return "some non-recoverable error occurred";
	case EAI_FAMILY:	/* ??? why can't we separate these errors!?!?!? */
		return "address family was not recognized, or address length invalid";
	case EAI_MEMORY:
		return "memory allocation failure";
	case EAI_NONAME:
		return "host name not found";
	case EAI_SYSTEM:
		return strerror(err);
	}
}

int
main(argc, argv)
	int argc;
	char *argv[];
{
	union peer_sockunion {
		struct sockaddr peer_un;
#define sa		p_un.peer_un
		struct sockaddr_in peer_un4;
#define sin		p_un.peer_un4
#define sinaddr		p_un.peer_un4.sin_addr
#ifdef INET6
		struct sockaddr_in6 peer_un6;
# define sin6		p_un.peer_un6
# define sin6addr	p_un.peer_un6.sin6_addr
#endif
	} p_un;
	char hbuf[NI_MAXHOST];
	struct hostent *hp;
	int len = sizeof(p_un);
	int ret;

	if (argc != 2) {
		fprintf(stderr, "Usage: %s address\n", argv[0]);
		exit(2);
	}
#ifdef INET6
	if (strchr(argv[1], ':')) {
		sa.sa_len = sizeof(sin6addr);
		sa.sa_family = AF_INET6;
		len = sizeof(sin6);
		ret = inet_pton(sa.sa_family, argv[1], &sin6addr);
	} else
#endif
	{
		sa.sa_len = sizeof(sinaddr);
		sa.sa_family = AF_INET;
		len = sizeof(sin);
		ret = inet_pton(sa.sa_family, argv[1], &sinaddr);

	}
	if (ret != 1) {
		fprintf(stderr, "%s: error with '%s': %s\n", argv[0], argv[1], (ret == 0) ? "unparsable address" : strerror(errno));
		exit(1);
		/* NOTREACHED */
	}
	if (sa.sa_family == AF_INET) {
		if (hp = gethostbyaddr((char *) &(sinaddr), sizeof(sinaddr), AF_INET)) {
			printf("gethostbyaddr()\n\tHostname:\t%s\n", hp->h_name);
			printf("\tAliases:\t");
			while (hp->h_aliases[0])
				printf("%s ", *hp->h_aliases++);
			printf("\n");
			printf("\tAddresses:\t");
			while (hp->h_addr_list[0])
				printf("%s ", inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
			printf("\n\n");
		} else {	
			fprintf(stderr, "%s: gethostbyaddr(): %s\n", argv[0], hstrerror(h_errno));
		}
	}
	if ((ret = getnameinfo(&sa, len, hbuf, sizeof(hbuf), (char *) NULL, 0, NI_NAMEREQD)) != 0) {
		int oerr = errno;
		char abuf[NI_MAXHOST];
		const char *addr;

#ifdef INET6
		if (sa.sa_family == AF_INET6) {
			addr = inet_ntop(AF_INET6, &sin6addr, abuf, sizeof(abuf));
		} else
#endif
		{
			addr = inet_ntop(AF_INET, &sinaddr, abuf, sizeof(abuf));
		}
		if (!addr)
			asprintf((char **) &addr, "(%s)", strerror(errno));
		fprintf(stderr,
			"%s: getnameinfo(%s[%s], %d): %s\n",
			argv[0],
			(sa.sa_family == AF_INET6) ? "AF_INET6" : "AF_INET",
			addr,
			len,
			streiaret(ret, oerr));
		exit(1);
		/* NOTREACHED */
	}
	printf("getnameinfo()\n\tHostname:\t%s\n", hbuf);

	exit(0);
	/* NOTREACHED */
}

-- 
							Greg A. Woods

+1 416 218-0098      VE3TCP      <gwoods@acm.org>     <woods@robohack.ca>
Planix, Inc. <woods@planix.com>;   Secrets of the Weird <woods@weird.com>