getnameinfo.c

説明を見る。
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 #ifdef INET6
00093         u_char pfx;
00094 #endif
00095         int h_error;
00096         char numserv[512];
00097         char numaddr[512];
00098 
00099         if (sa == NULL)
00100                 return ENI_NOSOCKET;
00101 
00102 #ifdef HAVE_SOCKADDR_LEN
00103         if (sa->sa_len != salen) return ENI_SALEN;
00104 #endif
00105         
00106         family = sa->sa_family;
00107         for (i = 0; afdl[i].a_af; i++)
00108                 if (afdl[i].a_af == family) {
00109                         afd = &afdl[i];
00110                         goto found;
00111                 }
00112         return ENI_FAMILY;
00113         
00114  found:
00115         if (salen != afd->a_socklen) return ENI_SALEN;
00116         
00117         port = ((struct sockinet *)sa)->si_port; /* network byte order */
00118         addr = (char *)sa + afd->a_off;
00119 
00120         if (serv == NULL || servlen == 0) {
00121                 /* what we should do? */
00122         } else if (flags & NI_NUMERICSERV) {
00123                 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
00124                 if (strlen(numserv) > servlen)
00125                         return ENI_MEMORY;
00126                 strcpy(serv, numserv);
00127         } else {
00128                 sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
00129                 if (sp) {
00130                         if (strlen(sp->s_name) > servlen)
00131                                 return ENI_MEMORY;
00132                         strcpy(serv, sp->s_name);
00133                 } else
00134                         return ENI_NOSERVNAME;
00135         }
00136 
00137         switch (sa->sa_family) {
00138         case AF_INET:
00139                 v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
00140                 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
00141                         flags |= NI_NUMERICHOST;
00142                 v4a >>= IN_CLASSA_NSHIFT;
00143                 if (v4a == 0 || v4a == IN_LOOPBACKNET)
00144                         flags |= NI_NUMERICHOST;                        
00145                 break;
00146 #ifdef INET6
00147         case AF_INET6:
00148                 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
00149                 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
00150                         flags |= NI_NUMERICHOST;
00151                 break;
00152 #endif
00153         }
00154         if (host == NULL || hostlen == 0) {
00155                 /* what should we do? */
00156         } else if (flags & NI_NUMERICHOST) {
00157                 if (!inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)))
00158                         return ENI_SYSTEM;
00159                 if (strlen(numaddr) > hostlen)
00160                         return ENI_MEMORY;
00161                 strcpy(host, numaddr);
00162         } else {
00163 #ifdef INET6
00164                 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
00165 #else
00166                 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
00167                 h_error = h_errno;
00168 #endif
00169 
00170                 if (hp) {
00171                         if (flags & NI_NOFQDN) {
00172                                 p = strchr(hp->h_name, '.');
00173                                 if (p) *p = '\0';
00174                         }
00175                         if (strlen(hp->h_name) > hostlen) {
00176 #ifdef INET6
00177                                 freehostent(hp);
00178 #endif
00179                                 return ENI_MEMORY;
00180                         }
00181                         strcpy(host, hp->h_name);
00182 #ifdef INET6
00183                         freehostent(hp);
00184 #endif
00185                 } else {
00186                         if (flags & NI_NAMEREQD)
00187                                 return ENI_NOHOSTNAME;
00188                         if (!inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)))
00189                                 return ENI_NOHOSTNAME;
00190                         if (strlen(numaddr) > hostlen)
00191                                 return ENI_MEMORY;
00192                         strcpy(host, numaddr);
00193                 }
00194         }
00195         return SUCCESS;
00196 }

rsyncに対してSat Dec 5 19:45:41 2009に生成されました。  doxygen 1.4.7