/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Issues to be discussed: * - Thread safe-ness must be checked * - Return values. There seems to be no standard for return value (RFC2133) * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). */#if 0#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <netdb.h>#include <resolv.h>#include <string.h>#include <stddef.h>#include "addrinfo.h"#endif#define SUCCESS 0#define YES 1#define NO 0staticstructgni_afd{inta_af;inta_addrlen;inta_socklen;inta_off;}gni_afdl[]={#ifdef ENABLE_IPV6{PF_INET6,sizeof(structin6_addr),sizeof(structsockaddr_in6),offsetof(structsockaddr_in6,sin6_addr)},#endif{PF_INET,sizeof(structin_addr),sizeof(structsockaddr_in),offsetof(structsockaddr_in,sin_addr)},{0,0,0},};structgni_sockinet{u_charsi_len;u_charsi_family;u_shortsi_port;};#define ENI_NOSOCKET 0#define ENI_NOSERVNAME 1#define ENI_NOHOSTNAME 2#define ENI_MEMORY 3#define ENI_SYSTEM 4#define ENI_FAMILY 5#define ENI_SALEN 6/* forward declaration to make gcc happy */intgetnameinfo(conststructsockaddr*,size_t,char*,size_t,char*,size_t,int);intgetnameinfo(sa,salen,host,hostlen,serv,servlen,flags)conststructsockaddr*sa;size_tsalen;char*host;size_thostlen;char*serv;size_tservlen;intflags;{structgni_afd*gni_afd;structservent*sp;structhostent*hp;u_shortport;intfamily,len,i;char*addr,*p;u_longv4a;#ifdef ENABLE_IPV6u_charpfx;#endifinth_error;charnumserv[512];charnumaddr[512];if(sa==NULL)returnENI_NOSOCKET;#ifdef HAVE_SOCKADDR_SA_LENlen=sa->sa_len;if(len!=salen)returnENI_SALEN;#elselen=salen;#endiffamily=sa->sa_family;for(i=0;gni_afdl[i].a_af;i++)if(gni_afdl[i].a_af==family){gni_afd=&gni_afdl[i];gotofound;}returnENI_FAMILY;found:if(len!=gni_afd->a_socklen)returnENI_SALEN;port=((structgni_sockinet*)sa)->si_port;/* network byte order */addr=(char*)sa+gni_afd->a_off;if(serv==NULL||servlen==0){/* what we should do? */}elseif(flags&NI_NUMERICSERV){sprintf(numserv,"%d",ntohs(port));if(strlen(numserv)>servlen)returnENI_MEMORY;strcpy(serv,numserv);}else{sp=getservbyport(port,(flags&NI_DGRAM)?"udp":"tcp");if(sp){if(strlen(sp->s_name)>servlen)returnENI_MEMORY;strcpy(serv,sp->s_name);}elsereturnENI_NOSERVNAME;}switch(sa->sa_family){caseAF_INET:v4a=((structsockaddr_in*)sa)->sin_addr.s_addr;if(IN_MULTICAST(v4a)||IN_EXPERIMENTAL(v4a))flags|=NI_NUMERICHOST;v4a>>=IN_CLASSA_NSHIFT;if(v4a==0||v4a==IN_LOOPBACKNET)flags|=NI_NUMERICHOST;break;#ifdef ENABLE_IPV6caseAF_INET6:pfx=((structsockaddr_in6*)sa)->sin6_addr.s6_addr8[0];if(pfx==0||pfx==0xfe||pfx==0xff)flags|=NI_NUMERICHOST;break;#endif}if(host==NULL||hostlen==0){/* what should we do? */}elseif(flags&NI_NUMERICHOST){if(inet_ntop(gni_afd->a_af,addr,numaddr,sizeof(numaddr))==NULL)returnENI_SYSTEM;if(strlen(numaddr)>hostlen)returnENI_MEMORY;strcpy(host,numaddr);}else{#ifdef ENABLE_IPV6hp=getipnodebyaddr(addr,gni_afd->a_addrlen,gni_afd->a_af,&h_error);#elsehp=gethostbyaddr(addr,gni_afd->a_addrlen,gni_afd->a_af);h_error=h_errno;#endifif(hp){if(flags&NI_NOFQDN){p=strchr(hp->h_name,'.');if(p)*p='\0';}if(strlen(hp->h_name)>hostlen){#ifdef ENABLE_IPV6freehostent(hp);#endifreturnENI_MEMORY;}strcpy(host,hp->h_name);#ifdef ENABLE_IPV6freehostent(hp);#endif}else{if(flags&NI_NAMEREQD)returnENI_NOHOSTNAME;if(inet_ntop(gni_afd->a_af,addr,numaddr,sizeof(numaddr))==NULL)returnENI_NOHOSTNAME;if(strlen(numaddr)>hostlen)returnENI_MEMORY;strcpy(host,numaddr);}}returnSUCCESS;}