Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

getnameinfo.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
00003  *
00004  * Changes Copyright (C) 2001 by Martin Pool <mbp@samba.org>
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the project nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  */
00030 
00031 /*
00032  * Issues to be discussed:
00033  * - Thread safe-ness must be checked
00034  * - Return values.  There seems to be no standard for return value (RFC2133)
00035  *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
00036  */
00037 
00038 #include "rsync.h"
00039 
00040 #define SUCCESS 0
00041 #define ANY 0
00042 #define YES 1
00043 #define NO  0
00044 
00045 static struct afd {
00046         int a_af;
00047         int a_addrlen;
00048         int a_socklen;
00049         int a_off;
00050 } afdl [] = {
00051 #ifdef INET6
00052         {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
00053                 offsetof(struct sockaddr_in6, sin6_addr)},
00054 #endif
00055         {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
00056                 offsetof(struct sockaddr_in, sin_addr)},
00057         {0, 0, 0, 0},
00058 };
00059 
00060 struct sockinet {
00061         u_char  si_len;
00062         u_char  si_family;
00063         u_short si_port;
00064 };
00065 
00066 #define ENI_NOSOCKET    0
00067 #define ENI_NOSERVNAME  1
00068 #define ENI_NOHOSTNAME  2
00069 #define ENI_MEMORY      3
00070 #define ENI_SYSTEM      4
00071 #define ENI_FAMILY      5
00072 #define ENI_SALEN       6
00073 
00074 int
00075 getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
00076         const struct sockaddr *sa;
00077         size_t salen;
00078         char *host;
00079         size_t hostlen;
00080         char *serv;
00081         size_t servlen;
00082         int flags;
00083 {
00084         extern int h_errno;
00085         struct afd *afd;
00086         struct servent *sp;
00087         struct hostent *hp;
00088         u_short port;
00089         int family, i;
00090         char *addr, *p;
00091         u_long v4a;
00092         u_char pfx;
00093         int h_error;
00094         char numserv[512];
00095         char numaddr[512];
00096 
00097         if (sa == NULL)
00098                 return ENI_NOSOCKET;
00099 
00100 #ifdef HAVE_SOCKADDR_LEN
00101         if (sa->sa_len != salen) return ENI_SALEN;
00102 #endif /* HAVE_SOCKADDR_LEN */
00103         
00104         family = sa->sa_family;
00105         for (i = 0; afdl[i].a_af; i++)
00106                 if (afdl[i].a_af == family) {
00107                         afd = &afdl[i];
00108                         goto found;
00109                 }
00110         return ENI_FAMILY;
00111         
00112  found:
00113         if (salen != afd->a_socklen) return ENI_SALEN;
00114         
00115         port = ((struct sockinet *)sa)->si_port; /* network byte order */
00116         addr = (char *)sa + afd->a_off;
00117 
00118         if (serv == NULL || servlen == 0) {
00119                 /* what we should do? */
00120         } else if (flags & NI_NUMERICSERV) {
00121                 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
00122                 if (strlen(numserv) > servlen)
00123                         return ENI_MEMORY;
00124                 strcpy(serv, numserv);
00125         } else {
00126                 sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
00127                 if (sp) {
00128                         if (strlen(sp->s_name) > servlen)
00129                                 return ENI_MEMORY;
00130                         strcpy(serv, sp->s_name);
00131                 } else
00132                         return ENI_NOSERVNAME;
00133         }
00134 
00135         switch (sa->sa_family) {
00136         case AF_INET:
00137                 v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
00138                 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
00139                         flags |= NI_NUMERICHOST;
00140                 v4a >>= IN_CLASSA_NSHIFT;
00141                 if (v4a == 0 || v4a == IN_LOOPBACKNET)
00142                         flags |= NI_NUMERICHOST;                        
00143                 break;
00144 #ifdef INET6
00145         case AF_INET6:
00146                 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
00147                 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
00148                         flags |= NI_NUMERICHOST;
00149                 break;
00150 #endif
00151         }
00152         if (host == NULL || hostlen == 0) {
00153                 /* what should we do? */
00154         } else if (flags & NI_NUMERICHOST) {
00155                 if (!inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)))
00156                         return ENI_SYSTEM;
00157                 if (strlen(numaddr) > hostlen)
00158                         return ENI_MEMORY;
00159                 strcpy(host, numaddr);
00160         } else {
00161 #ifdef INET6
00162                 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
00163 #else
00164                 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
00165                 h_error = h_errno;
00166 #endif
00167 
00168                 if (hp) {
00169                         if (flags & NI_NOFQDN) {
00170                                 p = strchr(hp->h_name, '.');
00171                                 if (p) *p = '\0';
00172                         }
00173                         if (strlen(hp->h_name) > hostlen) {
00174 #ifdef INET6
00175                                 freehostent(hp);
00176 #endif
00177                                 return ENI_MEMORY;
00178                         }
00179                         strcpy(host, hp->h_name);
00180 #ifdef INET6
00181                         freehostent(hp);
00182 #endif
00183                 } else {
00184                         if (flags & NI_NAMEREQD)
00185                                 return ENI_NOHOSTNAME;
00186                         if (!inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)))
00187                                 return ENI_NOHOSTNAME;
00188                         if (strlen(numaddr) > hostlen)
00189                                 return ENI_MEMORY;
00190                         strcpy(host, numaddr);
00191                 }
00192         }
00193         return SUCCESS;
00194 }

Generated on Tue Apr 16 12:37:36 2002 for rsync by doxygen1.2.15