00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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;
00118 addr = (char *)sa + afd->a_off;
00119
00120 if (serv == NULL || servlen == 0) {
00121
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
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 }