getaddrinfo and IPv6/IPv4 addresses
Hello,
In an application, I use getaddrinfo() with PF_INET6 in the hints
structure to look up addresses for a host that only has an IPv4 address
specified in /etc/hosts.
Sometimes, getaddrinfo() returns a proper IPv6 address of the form
::ffff:xx.xx.xx.xx, with the x'es being the IPv4 address. At other times,
the call to getaddrinfo() fails with the error EAI_NODATA, "No address
associated with hostname".
I can show some output from my home-written wrapper for getaddrinfo()
that also shows the problem:
h83% getaddrinfo -n h90
IPv4 130.236.239.90
h83% getaddrinfo -n h83
IPv6 ::ffff:130.236.239.83
IPv4 130.236.239.83
UNIX localhost
h83% getaddrinfo -n h90
IPv6 ::ffff:130.236.239.90
IPv4 130.236.239.90
h83%
The commands were entered in the above sequence. Why does it give a
different result the first and last time? I have attached the source to
the getaddrinfo command in case it would help.
Both systems are debian potato using glibc 2.1.2. h90 runs a name server
and my 6bone tunnel.
I'd appreciate any input at all that could help me with this problem.
Regards,
Pontus
--
Pontus Lidman, pontus@mathcore.com, Software Engineer
No matter how cynical you get, it's impossible to keep up.
Scene: www.dc-s.com | MUD: tyme.envy.com 6969 | irc: irc.quakenet.eu.org
/* getaddrinfo, a wrapper for the system call getaddrinfo(3)
Version: 0.1
Copyright (C) 2000 Pontus Lidman, pontus@lysator.liu.se
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <netinet/in.h>
#include <sys/un.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
int numeric=0,verbose=0;
struct option options[]={
{ "passive", no_argument,0,0 },
{ "canonical",no_argument,0,0 },
{ "verbose", no_argument,&verbose,1 },
{ "numeric", no_argument,&numeric,1 },
{ 0,0,0,0 }
};
int option_index=0;
const char *proto_arr[]={
"IPv4","IPv6","UNIX"
};
int main(int argc, char **argv) {
struct addrinfo hints;
struct addrinfo *resultp;
char c;
char *host=NULL;
char *service=NULL;
int err;
struct sockaddr *sa;
int size;
int proto;
int nameinfoflags=0;
char hostbuf[NI_MAXHOST];
char servbuf[NI_MAXSERV];
while (1) {
c=getopt_long(argc,argv,"pcvn",options,&option_index);
if (c==-1) break;
switch(c) {
case 0:
case 'n':
numeric=1;
break;
case 'v':
verbose=1;
break;
}
}
if (argc-optind < 1) {
fprintf(stderr,"You must provide a hostname");
exit(1);
}
host=argv[optind];
if (argc-optind==2) {
service=argv[optind+1];
}
if (numeric) nameinfoflags |= (NI_NUMERICHOST | NI_NUMERICSERV);
bzero(&hints,sizeof(hints));
hints.ai_family=PF_UNSPEC;
if ((err=getaddrinfo(host,service,&hints,&resultp))) {
fprintf(stderr,"%s\n",gai_strerror(err));
exit(1);
}
while (resultp) {
sa=resultp->ai_addr;
size=0;
switch(sa->sa_family) {
case PF_INET:
size=sizeof(struct sockaddr_in);
proto=0;
break;
case PF_INET6:
size=sizeof(struct sockaddr_in6);
proto=1;
break;
case PF_LOCAL:
size=sizeof(struct sockaddr_un);
proto=2;
break;
default:
fprintf(stderr,"Unknown protocol family in result: %d\n",sa->sa_family);
}
if (size) {
if ((err=getnameinfo(sa,size,hostbuf,sizeof(hostbuf),servbuf,sizeof(servbuf),nameinfoflags))) {
fprintf(stderr,"%s\n",gai_strerror(err));
} else {
if (service)
printf("%s %s %s\n",proto_arr[proto],hostbuf,servbuf);
else
printf("%s %s\n",proto_arr[proto],hostbuf);
}
}
resultp=resultp->ai_next;
}
freeaddrinfo(resultp);
return 0;
}
Reply to: