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
00039
00040
00041
00042 #include <rsync.h>
00043
00044 #if defined(__KAME__) && defined(INET6)
00045 # define FAITH
00046 #endif
00047
00048 #define SUCCESS 0
00049 #define ANY 0
00050 #define YES 1
00051 #define NO 0
00052
00053 #ifdef FAITH
00054 static int translate = NO;
00055 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
00056 #endif
00057
00058
00059
00060 #ifndef NO_DATA
00061 #ifdef NO_ADDRESS
00062 #define NO_DATA NO_ADDRESS
00063 #endif
00064 #endif
00065
00066 static const char in_addrany[] = { 0, 0, 0, 0 };
00067 static const char in6_addrany[] = {
00068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00069 };
00070 static const char in_loopback[] = { 127, 0, 0, 1 };
00071 static const char in6_loopback[] = {
00072 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
00073 };
00074
00075 struct sockinet {
00076 u_char si_len;
00077 u_char si_family;
00078 u_short si_port;
00079 };
00080
00081 static struct afd {
00082 int a_af;
00083 int a_addrlen;
00084 int a_socklen;
00085 int a_off;
00086 const char *a_addrany;
00087 const char *a_loopback;
00088 } afdl [] = {
00089 #ifdef INET6
00090 #define N_INET6 0
00091 {PF_INET6, sizeof(struct in6_addr),
00092 sizeof(struct sockaddr_in6),
00093 offsetof(struct sockaddr_in6, sin6_addr),
00094 in6_addrany, in6_loopback},
00095 #define N_INET 1
00096 #else
00097 #define N_INET 0
00098 #endif
00099 {PF_INET, sizeof(struct in_addr),
00100 sizeof(struct sockaddr_in),
00101 offsetof(struct sockaddr_in, sin_addr),
00102 in_addrany, in_loopback},
00103 {0, 0, 0, 0, NULL, NULL},
00104 };
00105
00106 #ifdef INET6
00107 #define PTON_MAX 16
00108 #else
00109 #define PTON_MAX 4
00110 #endif
00111
00112
00113 static int get_name (const char *, struct afd *,
00114 struct addrinfo **, char *, struct addrinfo *,
00115 int);
00116 static int get_addr (const char *, int, struct addrinfo **,
00117 struct addrinfo *, int);
00118 static int str_isnumber (const char *);
00119
00120 static char *ai_errlist[] = {
00121 "success.",
00122 "address family for hostname not supported.",
00123 "temporary failure in name resolution.",
00124 "invalid value for ai_flags.",
00125 "non-recoverable failure in name resolution.",
00126 "ai_family not supported.",
00127 "memory allocation failure.",
00128 "no address associated with hostname.",
00129 "hostname nor servname provided, or not known.",
00130 "servname not supported for ai_socktype.",
00131 "ai_socktype not supported.",
00132 "system error returned in errno.",
00133 "invalid value for hints.",
00134 "resolved protocol is unknown.",
00135 "unknown error.",
00136 };
00137
00138 #define GET_CANONNAME(ai, str) \
00139 if (pai->ai_flags & AI_CANONNAME) {\
00140 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
00141 strcpy((ai)->ai_canonname, (str));\
00142 } else {\
00143 error = EAI_MEMORY;\
00144 goto free;\
00145 }\
00146 }
00147
00148
00149 static int get_ai(struct addrinfo ** to_ai,
00150 struct addrinfo const * pai,
00151 struct afd *afd,
00152 const char *addr,
00153 short port)
00154 {
00155 char *p;
00156 if ((*to_ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
00157 ((afd)->a_socklen)))
00158 == NULL)
00159 return 0;
00160 memcpy(*to_ai, pai, sizeof(struct addrinfo));
00161 (*to_ai)->ai_addr = (struct sockaddr *)((*to_ai) + 1);
00162 memset((*to_ai)->ai_addr, 0, (afd)->a_socklen);
00163 (*to_ai)->ai_addrlen = (afd)->a_socklen;
00164 #if HAVE_SOCKADDR_LEN
00165 (*to_ai)->ai_addr->sa_len= (afd)->a_socklen;
00166 #endif
00167 (*to_ai)->ai_addr->sa_family = (*to_ai)->ai_family = (afd)->a_af;
00168 ((struct sockinet *)(*to_ai)->ai_addr)->si_port = port;
00169 p = (char *)((*to_ai)->ai_addr);
00170 memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);
00171 return 1;
00172 }
00173
00174 #define ERR(err) { error = (err); goto bad; }
00175
00176 char *
00177 gai_strerror(ecode)
00178 int ecode;
00179 {
00180 if (ecode < 0 || ecode > EAI_MAX)
00181 ecode = EAI_MAX;
00182 return ai_errlist[ecode];
00183 }
00184
00185 void
00186 freeaddrinfo(ai)
00187 struct addrinfo *ai;
00188 {
00189 struct addrinfo *next;
00190
00191 do {
00192 next = ai->ai_next;
00193 if (ai->ai_canonname)
00194 free(ai->ai_canonname);
00195
00196 free(ai);
00197 } while ((ai = next) != NULL);
00198 }
00199
00200 static int
00201 str_isnumber(p)
00202 const char *p;
00203 {
00204 char *q = (char *)p;
00205 while (*q) {
00206 if (! isdigit(*q))
00207 return NO;
00208 q++;
00209 }
00210 return YES;
00211 }
00212
00213 int
00214 getaddrinfo(hostname, servname, hints, res)
00215 const char *hostname, *servname;
00216 const struct addrinfo *hints;
00217 struct addrinfo **res;
00218 {
00219 struct addrinfo sentinel;
00220 struct addrinfo *top = NULL;
00221 struct addrinfo *cur;
00222 int i, error = 0;
00223 char pton[PTON_MAX];
00224 struct addrinfo ai;
00225 struct addrinfo *pai;
00226 u_short port;
00227
00228 #ifdef FAITH
00229 static int firsttime = 1;
00230
00231 if (firsttime) {
00232
00233 {
00234 char *q = getenv("GAI");
00235 if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
00236 translate = YES;
00237 }
00238 firsttime = 0;
00239 }
00240 #endif
00241
00242
00243 sentinel.ai_next = NULL;
00244 cur = &sentinel;
00245 pai = &ai;
00246 pai->ai_flags = 0;
00247 pai->ai_family = PF_UNSPEC;
00248 pai->ai_socktype = ANY;
00249 pai->ai_protocol = ANY;
00250 pai->ai_addrlen = 0;
00251 pai->ai_canonname = NULL;
00252 pai->ai_addr = NULL;
00253 pai->ai_next = NULL;
00254 port = ANY;
00255
00256 if (hostname == NULL && servname == NULL)
00257 return EAI_NONAME;
00258 if (hints) {
00259
00260 if (hints->ai_addrlen || hints->ai_canonname ||
00261 hints->ai_addr || hints->ai_next)
00262 ERR(EAI_BADHINTS);
00263 if (hints->ai_flags & ~AI_MASK)
00264 ERR(EAI_BADFLAGS);
00265 switch (hints->ai_family) {
00266 case PF_UNSPEC:
00267 case PF_INET:
00268 #ifdef INET6
00269 case PF_INET6:
00270 #endif
00271 break;
00272 default:
00273 ERR(EAI_FAMILY);
00274 }
00275 memcpy(pai, hints, sizeof(*pai));
00276 switch (pai->ai_socktype) {
00277 case ANY:
00278 switch (pai->ai_protocol) {
00279 case ANY:
00280 break;
00281 case IPPROTO_UDP:
00282 pai->ai_socktype = SOCK_DGRAM;
00283 break;
00284 case IPPROTO_TCP:
00285 pai->ai_socktype = SOCK_STREAM;
00286 break;
00287 default:
00288 pai->ai_socktype = SOCK_RAW;
00289 break;
00290 }
00291 break;
00292 case SOCK_RAW:
00293 break;
00294 case SOCK_DGRAM:
00295 if (pai->ai_protocol != IPPROTO_UDP &&
00296 pai->ai_protocol != ANY)
00297 ERR(EAI_BADHINTS);
00298 pai->ai_protocol = IPPROTO_UDP;
00299 break;
00300 case SOCK_STREAM:
00301 if (pai->ai_protocol != IPPROTO_TCP &&
00302 pai->ai_protocol != ANY)
00303 ERR(EAI_BADHINTS);
00304 pai->ai_protocol = IPPROTO_TCP;
00305 break;
00306 default:
00307 ERR(EAI_SOCKTYPE);
00308 break;
00309 }
00310 }
00311
00312
00313
00314
00315 if (servname) {
00316 if (str_isnumber(servname)) {
00317 if (pai->ai_socktype == ANY) {
00318
00319 pai->ai_socktype = SOCK_DGRAM;
00320 pai->ai_protocol = IPPROTO_UDP;
00321 }
00322 port = htons(atoi(servname));
00323 } else {
00324 struct servent *sp;
00325 char *proto;
00326
00327 proto = NULL;
00328 switch (pai->ai_socktype) {
00329 case ANY:
00330 proto = NULL;
00331 break;
00332 case SOCK_DGRAM:
00333 proto = "udp";
00334 break;
00335 case SOCK_STREAM:
00336 proto = "tcp";
00337 break;
00338 default:
00339 fprintf(stderr, "panic!\n");
00340 break;
00341 }
00342 if ((sp = getservbyname(servname, proto)) == NULL)
00343 ERR(EAI_SERVICE);
00344 port = sp->s_port;
00345 if (pai->ai_socktype == ANY) {
00346 if (strcmp(sp->s_proto, "udp") == 0) {
00347 pai->ai_socktype = SOCK_DGRAM;
00348 pai->ai_protocol = IPPROTO_UDP;
00349 } else if (strcmp(sp->s_proto, "tcp") == 0) {
00350 pai->ai_socktype = SOCK_STREAM;
00351 pai->ai_protocol = IPPROTO_TCP;
00352 } else
00353 ERR(EAI_PROTOCOL);
00354 }
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363 if (hostname == NULL) {
00364 struct afd *afd;
00365
00366 for (afd = &afdl[0]; afd->a_af; afd++) {
00367 if (!(pai->ai_family == PF_UNSPEC
00368 || pai->ai_family == afd->a_af)) {
00369 continue;
00370 }
00371
00372 if (pai->ai_flags & AI_PASSIVE) {
00373 if (!get_ai(&cur->ai_next, pai, afd, afd->a_addrany, port))
00374 goto free;
00375
00376
00377
00378 } else {
00379 if (!get_ai(&cur->ai_next, pai, afd, afd->a_loopback,
00380 port))
00381 goto free;
00382
00383
00384
00385 }
00386 cur = cur->ai_next;
00387 }
00388 top = sentinel.ai_next;
00389 if (top)
00390 goto good;
00391 else
00392 ERR(EAI_FAMILY);
00393 }
00394
00395
00396 for (i = 0; afdl[i].a_af; i++) {
00397 if (inet_pton(afdl[i].a_af, hostname, pton)) {
00398 u_long v4a;
00399
00400 switch (afdl[i].a_af) {
00401 case AF_INET:
00402 v4a = ((struct in_addr *)pton)->s_addr;
00403 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
00404 pai->ai_flags &= ~AI_CANONNAME;
00405 v4a >>= IN_CLASSA_NSHIFT;
00406 if (v4a == 0 || v4a == IN_LOOPBACKNET)
00407 pai->ai_flags &= ~AI_CANONNAME;
00408 break;
00409 #ifdef INET6
00410 case AF_INET6:
00411 {
00412 u_char pfx;
00413 pfx = ((struct in6_addr *)pton)->s6_addr[0];
00414 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
00415 pai->ai_flags &= ~AI_CANONNAME;
00416 break;
00417 }
00418 #endif
00419 }
00420
00421 if (pai->ai_family == afdl[i].a_af ||
00422 pai->ai_family == PF_UNSPEC) {
00423 if (! (pai->ai_flags & AI_CANONNAME)) {
00424 if (get_ai(&top, pai, &afdl[i], pton, port))
00425 goto good;
00426 else
00427 goto free;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 get_name(pton, &afdl[i], &top, pton, pai, port);
00439 goto good;
00440 } else
00441 ERR(EAI_FAMILY);
00442 }
00443 }
00444
00445 if (pai->ai_flags & AI_NUMERICHOST)
00446 ERR(EAI_NONAME);
00447
00448
00449 error = get_addr(hostname, pai->ai_family, &top, pai, port);
00450 if (error == 0) {
00451 if (top) {
00452 good:
00453 *res = top;
00454 return SUCCESS;
00455 } else
00456 error = EAI_FAIL;
00457 }
00458 free:
00459 if (top)
00460 freeaddrinfo(top);
00461 bad:
00462 *res = NULL;
00463 return error;
00464 }
00465
00466 static int
00467 get_name(addr, afd, res, numaddr, pai, port0)
00468 const char *addr;
00469 struct afd *afd;
00470 struct addrinfo **res;
00471 char *numaddr;
00472 struct addrinfo *pai;
00473 int port0;
00474 {
00475 u_short port = port0 & 0xffff;
00476 struct hostent *hp;
00477 struct addrinfo *cur;
00478 int error = 0;
00479
00480 #ifdef INET6
00481 {
00482 int h_error;
00483 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
00484 }
00485 #else
00486 hp = gethostbyaddr(addr, afd->a_addrlen, AF_INET);
00487 #endif
00488 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
00489 if (!get_ai(&cur, pai, afd, hp->h_addr_list[0], port))
00490 goto free;
00491 GET_CANONNAME(cur, hp->h_name);
00492 } else {
00493 if (!get_ai(&cur, pai, afd, numaddr, port))
00494 goto free;
00495 }
00496
00497 #ifdef INET6
00498 if (hp)
00499 freehostent(hp);
00500 #endif
00501 *res = cur;
00502 return SUCCESS;
00503 free:
00504 if (cur)
00505 freeaddrinfo(cur);
00506 #ifdef INET6
00507 if (hp)
00508 freehostent(hp);
00509 #endif
00510
00511 *res = NULL;
00512 return error;
00513 }
00514
00515 static int
00516 get_addr(hostname, af, res, pai, port0)
00517 const char *hostname;
00518 int af;
00519 struct addrinfo **res;
00520 struct addrinfo *pai;
00521 int port0;
00522 {
00523 u_short port = port0 & 0xffff;
00524 struct addrinfo sentinel;
00525 struct hostent *hp;
00526 struct addrinfo *top, *cur;
00527 struct afd *afd;
00528 int i, error = 0, h_error;
00529 char *ap;
00530 #ifndef INET6
00531 extern int h_errno;
00532 #endif
00533
00534 top = NULL;
00535 sentinel.ai_next = NULL;
00536 cur = &sentinel;
00537 #ifdef INET6
00538 if (af == AF_UNSPEC) {
00539 hp = getipnodebyname(hostname, AF_INET6,
00540 AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
00541 } else
00542 hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
00543 #else
00544 hp = gethostbyname(hostname);
00545 h_error = h_errno;
00546 #endif
00547 if (hp == NULL) {
00548 switch (h_error) {
00549 case HOST_NOT_FOUND:
00550 case NO_DATA:
00551 error = EAI_NODATA;
00552 break;
00553 case TRY_AGAIN:
00554 error = EAI_AGAIN;
00555 break;
00556 case NO_RECOVERY:
00557 default:
00558 error = EAI_FAIL;
00559 break;
00560 }
00561 goto bad;
00562 }
00563
00564 if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
00565 (hp->h_addr_list[0] == NULL))
00566 ERR(EAI_FAIL);
00567
00568 for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
00569 switch (af) {
00570 #ifdef INET6
00571 case AF_INET6:
00572 afd = &afdl[N_INET6];
00573 break;
00574 #endif
00575 #ifndef INET6
00576 default:
00577 #endif
00578 case AF_INET:
00579 afd = &afdl[N_INET];
00580 break;
00581 #ifdef INET6
00582 default:
00583 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
00584 ap += sizeof(struct in6_addr) -
00585 sizeof(struct in_addr);
00586 afd = &afdl[N_INET];
00587 } else
00588 afd = &afdl[N_INET6];
00589 break;
00590 #endif
00591 }
00592 #ifdef FAITH
00593 if (translate && afd->a_af == AF_INET) {
00594 struct in6_addr *in6;
00595
00596 if (!get_ai(&cur->ai_next, pai, &afdl[N_INET6], ap, port))
00597 goto free;
00598 in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
00599 memcpy(&in6->s6_addr32[0], &faith_prefix,
00600 sizeof(struct in6_addr) - sizeof(struct in_addr));
00601 memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
00602 } else
00603 #endif
00604 if (!get_ai(&cur->ai_next, pai, afd, ap, port))
00605 goto free;
00606 if (cur == &sentinel) {
00607 top = cur->ai_next;
00608 GET_CANONNAME(top, hp->h_name);
00609 }
00610 cur = cur->ai_next;
00611 }
00612 #ifdef INET6
00613 freehostent(hp);
00614 #endif
00615 *res = top;
00616 return SUCCESS;
00617 free:
00618 if (top)
00619 freeaddrinfo(top);
00620 #ifdef INET6
00621 if (hp)
00622 freehostent(hp);
00623 #endif
00624 bad:
00625 *res = NULL;
00626 return error;
00627 }