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 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
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;
00116 addr = (char *)sa + afd->a_off;
00117
00118 if (serv == NULL || servlen == 0) {
00119
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
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 }