Subject: Re: IPv6 with gethostbyname2 and gethostbyaddr
To: Jeremy C. Reed <reed@reedmedia.net>
From: None <itojun@iijlab.net>
List: tech-net
Date: 07/05/2002 06:03:12
>(If this is the wrong list, please let me know about a better one.)
>
>I read that gethostbyname2 and gethostbyaddr for IPv6 is being deprecated
>and that I should use getaddrinfo or getnodebyname instead. And inet_aton
>manual recommends getaddrinfo and getnameinfo for IPv6.
>
>But how can I get gethostbyname2 and gethostbyaddr to work for IPv6?
>
>Here are some examples:
i see three problems in your code:
- use of inet_aton(3), which is IPv4 only. use inet_pton(3) instead.
- hardcoded use of sockaddr_in. sockaddr_in6 is bigger than
sockaddr_in, so it won't fit.
- misuse of strncpy - strncpy does not terminate copied buffer with \0
here's the working version so far, but i really recommend you to
use getaddrinfo/getnameinfo, it's easier and clean.
the code is not totally correct as it passes numeric form (::1)
to gethostbyname2(), which does not work.
itojun
#include <string.h>
#include <stdio.h>
#include <netdb.h> /* gethostbyname() and related */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h> /* AF_INET manifest constant */
#include <stdlib.h>
int main(argc, argv)
int argc;
char *argv[];
{
char *hostname = NULL;
int addrtype = AF_INET;
int rval = 0, reverse = 0, ipv6 = 0;
union {
struct in6_addr in6;
struct in_addr in;
} addrbuf;
char buf[128];
if (argc == 1) {
fprintf (stderr, "gethost: neither action flags nor hostname given.\n");
exit(1);
}
while (*++argv) {
if (*argv[0] == '-') {
if (!strcmp(*argv, "-x")) {
reverse = 1;
continue;
}
if (!strcmp(*argv, "-6")) {
ipv6 = 1;
addrtype = AF_INET6;
continue;
}
}
hostname = (char *)malloc(strlen(*argv) + 1);
if (hostname) {
strncpy(hostname, *argv, strlen(*argv));
hostname[strlen(*argv)] = '\0';
}
}
if (hostname) {
struct hostent *h;
if (reverse && 0 == inet_pton(addrtype, hostname, &addrbuf)) {
fprintf(stderr,
"Problem looking up \"%s\": %s\n", hostname, hstrerror(h_errno));
exit (1);
}
if (ipv6 || strchr(hostname, ':'))
if (reverse)
h = gethostbyaddr(addrtype == AF_INET ? &addrbuf.in : &addrbuf.in6,
addrtype == AF_INET ? sizeof(addrbuf.in) : sizeof(addrbuf.in6),
addrtype);
else h = gethostbyname2(hostname, addrtype);
if (h) {
int idx = 0;
printf("Hostname: %s\n", h->h_name);
while (h->h_aliases[idx])
printf("Alias: %s\n", h->h_aliases[idx++]);
switch (h->h_addrtype) {
case AF_INET:
case AF_INET6:
for (idx = 0; h->h_addr_list[idx]; ++idx) {
inet_ntop(addrtype, h->h_addr_list[idx], buf, sizeof(buf));
printf("Address: %s\n", buf);
}
break;
default:
break;
}
} else {
/* not all OSes have h_errno & hstrerror() - Solaris doesn't */
fprintf(stderr,
"Problem looking up \"%s\": %s\n", hostname, hstrerror(h_errno));
rval = 1;
}
}
free(hostname);
return(rval);
}