diff options
Diffstat (limited to 'src/lib/libc')
| -rw-r--r-- | src/lib/libc/net/getaddrinfo.c | 255 | ||||
| -rw-r--r-- | src/lib/libc/net/getnameinfo.c | 77 |
2 files changed, 221 insertions, 111 deletions
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c index 47b298f9c5..ff3131388e 100644 --- a/src/lib/libc/net/getaddrinfo.c +++ b/src/lib/libc/net/getaddrinfo.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: getaddrinfo.c,v 1.9 2000/01/26 06:51:26 itojun Exp $ */ | 1 | /* $OpenBSD: getaddrinfo.c,v 1.10 2000/02/09 12:22:09 itojun Exp $ */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| @@ -30,13 +30,18 @@ | |||
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| 33 | * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. | ||
| 34 | * | ||
| 35 | * Issues to be discussed: | 33 | * Issues to be discussed: |
| 36 | * - Thread safe-ness must be checked. | 34 | * - Thread safe-ness must be checked. |
| 37 | * - Return values. There are nonstandard return values defined and used | 35 | * - Return values. There are nonstandard return values defined and used |
| 38 | * in the source code. This is because RFC2553 is silent about which error | 36 | * in the source code. This is because RFC2553 is silent about which error |
| 39 | * code must be returned for which situation. | 37 | * code must be returned for which situation. |
| 38 | * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 | ||
| 39 | * says to use inet_aton() to convert IPv4 numeric to binary (alows | ||
| 40 | * classful form as a result). | ||
| 41 | * current code - disallow classful form for IPv4 (due to use of inet_pton). | ||
| 42 | * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is | ||
| 43 | * invalid. | ||
| 44 | * current code - SEGV on freeaddrinfo(NULL) | ||
| 40 | * Note: | 45 | * Note: |
| 41 | * - We use getipnodebyname() just for thread-safeness. There's no intent | 46 | * - We use getipnodebyname() just for thread-safeness. There's no intent |
| 42 | * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to | 47 | * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to |
| @@ -71,11 +76,6 @@ | |||
| 71 | #define YES 1 | 76 | #define YES 1 |
| 72 | #define NO 0 | 77 | #define NO 0 |
| 73 | 78 | ||
| 74 | #ifdef FAITH | ||
| 75 | static int translate = NO; | ||
| 76 | static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT; | ||
| 77 | #endif | ||
| 78 | |||
| 79 | static const char in_addrany[] = { 0, 0, 0, 0 }; | 79 | static const char in_addrany[] = { 0, 0, 0, 0 }; |
| 80 | static const char in6_addrany[] = { | 80 | static const char in6_addrany[] = { |
| 81 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 81 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| @@ -150,7 +150,7 @@ static const struct explore explore[] = { | |||
| 150 | static int str_isnumber __P((const char *)); | 150 | static int str_isnumber __P((const char *)); |
| 151 | static int explore_fqdn __P((const struct addrinfo *, const char *, | 151 | static int explore_fqdn __P((const struct addrinfo *, const char *, |
| 152 | const char *, struct addrinfo **)); | 152 | const char *, struct addrinfo **)); |
| 153 | static int explore_null __P((const struct addrinfo *, const char *, | 153 | static int explore_null __P((const struct addrinfo *, |
| 154 | const char *, struct addrinfo **)); | 154 | const char *, struct addrinfo **)); |
| 155 | static int explore_numeric __P((const struct addrinfo *, const char *, | 155 | static int explore_numeric __P((const struct addrinfo *, const char *, |
| 156 | const char *, struct addrinfo **)); | 156 | const char *, struct addrinfo **)); |
| @@ -163,6 +163,12 @@ static struct addrinfo *get_ai __P((const struct addrinfo *, | |||
| 163 | static int get_portmatch __P((const struct addrinfo *, const char *)); | 163 | static int get_portmatch __P((const struct addrinfo *, const char *)); |
| 164 | static int get_port __P((struct addrinfo *, const char *, int)); | 164 | static int get_port __P((struct addrinfo *, const char *, int)); |
| 165 | static const struct afd *find_afd __P((int)); | 165 | static const struct afd *find_afd __P((int)); |
| 166 | #ifdef AI_ADDRCONFIG | ||
| 167 | static int addrconfig __P((const struct addrinfo *)); | ||
| 168 | #endif | ||
| 169 | #ifdef INET6 | ||
| 170 | static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *)); | ||
| 171 | #endif | ||
| 166 | 172 | ||
| 167 | /* XXX macros that make external reference is BAD. */ | 173 | /* XXX macros that make external reference is BAD. */ |
| 168 | 174 | ||
| @@ -174,7 +180,7 @@ do { \ | |||
| 174 | error = EAI_MEMORY; \ | 180 | error = EAI_MEMORY; \ |
| 175 | goto free; \ | 181 | goto free; \ |
| 176 | } \ | 182 | } \ |
| 177 | } while (0) | 183 | } while (/*CONSTCOND*/0) |
| 178 | 184 | ||
| 179 | #define GET_PORT(ai, serv) \ | 185 | #define GET_PORT(ai, serv) \ |
| 180 | do { \ | 186 | do { \ |
| @@ -182,7 +188,7 @@ do { \ | |||
| 182 | error = get_port((ai), (serv), 0); \ | 188 | error = get_port((ai), (serv), 0); \ |
| 183 | if (error != 0) \ | 189 | if (error != 0) \ |
| 184 | goto free; \ | 190 | goto free; \ |
| 185 | } while (0) | 191 | } while (/*CONSTCOND*/0) |
| 186 | 192 | ||
| 187 | #define GET_CANONNAME(ai, str) \ | 193 | #define GET_CANONNAME(ai, str) \ |
| 188 | do { \ | 194 | do { \ |
| @@ -190,27 +196,27 @@ do { \ | |||
| 190 | error = get_canonname(pai, (ai), (str)); \ | 196 | error = get_canonname(pai, (ai), (str)); \ |
| 191 | if (error != 0) \ | 197 | if (error != 0) \ |
| 192 | goto free; \ | 198 | goto free; \ |
| 193 | } while (0) | 199 | } while (/*CONSTCOND*/0) |
| 194 | 200 | ||
| 195 | #define ERR(err) \ | 201 | #define ERR(err) \ |
| 196 | do { \ | 202 | do { \ |
| 197 | /* external reference: error, and label bad */ \ | 203 | /* external reference: error, and label bad */ \ |
| 198 | error = (err); \ | 204 | error = (err); \ |
| 199 | goto bad; \ | 205 | goto bad; \ |
| 200 | } while (0) | 206 | } while (/*CONSTCOND*/0) |
| 201 | 207 | ||
| 202 | #define MATCH_FAMILY(x, y, w) \ | 208 | #define MATCH_FAMILY(x, y, w) \ |
| 203 | ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) | 209 | ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) |
| 204 | #define MATCH(x, y, w) \ | 210 | #define MATCH(x, y, w) \ |
| 205 | ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY))) | 211 | ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) |
| 206 | 212 | ||
| 207 | static int | 213 | static int |
| 208 | str_isnumber(p) | 214 | str_isnumber(p) |
| 209 | const char *p; | 215 | const char *p; |
| 210 | { | 216 | { |
| 211 | char *q = (char *)p; | 217 | const char *q = (const char *)p; |
| 212 | while (*q) { | 218 | while (*q) { |
| 213 | if (! isdigit(*q)) | 219 | if (!isdigit(*q)) |
| 214 | return NO; | 220 | return NO; |
| 215 | q++; | 221 | q++; |
| 216 | } | 222 | } |
| @@ -231,21 +237,6 @@ getaddrinfo(hostname, servname, hints, res) | |||
| 231 | struct addrinfo *pai; | 237 | struct addrinfo *pai; |
| 232 | const struct afd *afd; | 238 | const struct afd *afd; |
| 233 | const struct explore *ex; | 239 | const struct explore *ex; |
| 234 | #ifndef AI_MASK | ||
| 235 | #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) | ||
| 236 | #endif | ||
| 237 | |||
| 238 | #ifdef FAITH | ||
| 239 | static int firsttime = 1; | ||
| 240 | |||
| 241 | if (firsttime) { | ||
| 242 | /* translator hack */ | ||
| 243 | char *q = getenv("GAI"); | ||
| 244 | if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) | ||
| 245 | translate = YES; | ||
| 246 | firsttime = 0; | ||
| 247 | } | ||
| 248 | #endif | ||
| 249 | 240 | ||
| 250 | sentinel.ai_next = NULL; | 241 | sentinel.ai_next = NULL; |
| 251 | cur = &sentinel; | 242 | cur = &sentinel; |
| @@ -306,11 +297,19 @@ getaddrinfo(hostname, servname, hints, res) | |||
| 306 | * for raw and other inet{,6} sockets. | 297 | * for raw and other inet{,6} sockets. |
| 307 | */ | 298 | */ |
| 308 | if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) | 299 | if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) |
| 309 | || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)) { | 300 | #ifdef PF_INET6 |
| 310 | ai0 = *pai; | 301 | || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) |
| 302 | #endif | ||
| 303 | ) { | ||
| 304 | ai0 = *pai; /* backup *pai */ | ||
| 311 | 305 | ||
| 312 | if (pai->ai_family == PF_UNSPEC) | 306 | if (pai->ai_family == PF_UNSPEC) { |
| 307 | #ifdef PF_INET6 | ||
| 313 | pai->ai_family = PF_INET6; | 308 | pai->ai_family = PF_INET6; |
| 309 | #else | ||
| 310 | pai->ai_family = PF_INET; | ||
| 311 | #endif | ||
| 312 | } | ||
| 314 | error = get_portmatch(pai, servname); | 313 | error = get_portmatch(pai, servname); |
| 315 | if (error) | 314 | if (error) |
| 316 | ERR(error); | 315 | ERR(error); |
| @@ -339,7 +338,7 @@ getaddrinfo(hostname, servname, hints, res) | |||
| 339 | pai->ai_protocol = ex->e_protocol; | 338 | pai->ai_protocol = ex->e_protocol; |
| 340 | 339 | ||
| 341 | if (hostname == NULL) | 340 | if (hostname == NULL) |
| 342 | error = explore_null(pai, hostname, servname, &cur->ai_next); | 341 | error = explore_null(pai, servname, &cur->ai_next); |
| 343 | else | 342 | else |
| 344 | error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); | 343 | error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); |
| 345 | 344 | ||
| @@ -445,21 +444,22 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 445 | char *ap; | 444 | char *ap; |
| 446 | struct addrinfo sentinel, *cur; | 445 | struct addrinfo sentinel, *cur; |
| 447 | int i; | 446 | int i; |
| 448 | #ifndef USE_GETIPNODEBY | ||
| 449 | int naddrs; | 447 | int naddrs; |
| 450 | #endif | ||
| 451 | const struct afd *afd; | 448 | const struct afd *afd; |
| 452 | int error; | 449 | int error = 0; |
| 453 | 450 | ||
| 454 | *res = NULL; | 451 | *res = NULL; |
| 455 | sentinel.ai_next = NULL; | 452 | sentinel.ai_next = NULL; |
| 456 | cur = &sentinel; | 453 | cur = &sentinel; |
| 457 | 454 | ||
| 455 | #ifdef AI_ADDRCONFIG | ||
| 458 | /* | 456 | /* |
| 459 | * Do not filter unsupported AFs here. We need to honor content of | 457 | * If AI_ADDRCONFIG is specified, check if we are expected to |
| 460 | * databases (/etc/hosts, DNS and others). Otherwise we cannot | 458 | * return the address family or not. |
| 461 | * replace gethostbyname() by getaddrinfo(). | ||
| 462 | */ | 459 | */ |
| 460 | if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) | ||
| 461 | return 0; | ||
| 462 | #endif | ||
| 463 | 463 | ||
| 464 | /* | 464 | /* |
| 465 | * if the servname does not match socktype/protocol, ignore it. | 465 | * if the servname does not match socktype/protocol, ignore it. |
| @@ -469,17 +469,8 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 469 | 469 | ||
| 470 | afd = find_afd(pai->ai_family); | 470 | afd = find_afd(pai->ai_family); |
| 471 | 471 | ||
| 472 | /* | ||
| 473 | * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG) | ||
| 474 | * rather than hardcoding it. we may need to add AI_ADDRCONFIG | ||
| 475 | * handling code by ourselves in case we don't have getipnodebyname(). | ||
| 476 | */ | ||
| 477 | #ifdef USE_GETIPNODEBY | ||
| 478 | hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error); | ||
| 479 | #else | ||
| 480 | hp = gethostbyname2(hostname, pai->ai_family); | 472 | hp = gethostbyname2(hostname, pai->ai_family); |
| 481 | h_error = h_errno; | 473 | h_error = h_errno; |
| 482 | #endif | ||
| 483 | 474 | ||
| 484 | if (hp == NULL) { | 475 | if (hp == NULL) { |
| 485 | switch (h_error) { | 476 | switch (h_error) { |
| @@ -498,9 +489,6 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 498 | } | 489 | } |
| 499 | } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) | 490 | } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) |
| 500 | || (hp->h_addr_list[0] == NULL)) { | 491 | || (hp->h_addr_list[0] == NULL)) { |
| 501 | #ifdef USE_GETIPNODEBY | ||
| 502 | freehostent(hp); | ||
| 503 | #endif | ||
| 504 | hp = NULL; | 492 | hp = NULL; |
| 505 | error = EAI_FAIL; | 493 | error = EAI_FAIL; |
| 506 | } | 494 | } |
| @@ -508,9 +496,6 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 508 | if (hp == NULL) | 496 | if (hp == NULL) |
| 509 | goto free; | 497 | goto free; |
| 510 | 498 | ||
| 511 | #ifdef USE_GETIPNODEBY | ||
| 512 | aplist = hp->h_addr_list; | ||
| 513 | #else | ||
| 514 | /* | 499 | /* |
| 515 | * hp will be overwritten if we use gethostbyname2(). | 500 | * hp will be overwritten if we use gethostbyname2(). |
| 516 | * always deep copy for simplification. | 501 | * always deep copy for simplification. |
| @@ -519,7 +504,7 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 519 | ; | 504 | ; |
| 520 | naddrs++; | 505 | naddrs++; |
| 521 | aplist = (char **)malloc(sizeof(aplist[0]) * naddrs); | 506 | aplist = (char **)malloc(sizeof(aplist[0]) * naddrs); |
| 522 | apbuf = (char *)malloc(hp->h_length * naddrs); | 507 | apbuf = (char *)malloc((size_t)hp->h_length * naddrs); |
| 523 | if (aplist == NULL || apbuf == NULL) { | 508 | if (aplist == NULL || apbuf == NULL) { |
| 524 | error = EAI_MEMORY; | 509 | error = EAI_MEMORY; |
| 525 | goto free; | 510 | goto free; |
| @@ -531,20 +516,21 @@ explore_fqdn(pai, hostname, servname, res) | |||
| 531 | continue; | 516 | continue; |
| 532 | } | 517 | } |
| 533 | memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i], | 518 | memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i], |
| 534 | hp->h_length); | 519 | (size_t)hp->h_length); |
| 535 | aplist[i] = &apbuf[i * hp->h_length]; | 520 | aplist[i] = &apbuf[i * hp->h_length]; |
| 536 | } | 521 | } |
| 537 | #endif | ||
| 538 | 522 | ||
| 539 | for (i = 0; aplist[i] != NULL; i++) { | 523 | for (i = 0; aplist[i] != NULL; i++) { |
| 540 | af = hp->h_addrtype; | 524 | af = hp->h_addrtype; |
| 541 | ap = aplist[i]; | 525 | ap = aplist[i]; |
| 526 | #ifdef AF_INET6 | ||
| 542 | if (af == AF_INET6 | 527 | if (af == AF_INET6 |
| 543 | && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { | 528 | && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { |
| 544 | af = AF_INET; | 529 | af = AF_INET; |
| 545 | ap = ap + sizeof(struct in6_addr) | 530 | ap = ap + sizeof(struct in6_addr) |
| 546 | - sizeof(struct in_addr); | 531 | - sizeof(struct in_addr); |
| 547 | } | 532 | } |
| 533 | #endif | ||
| 548 | 534 | ||
| 549 | if (af != pai->ai_family) | 535 | if (af != pai->ai_family) |
| 550 | continue; | 536 | continue; |
| @@ -587,9 +573,8 @@ free: | |||
| 587 | * non-passive socket -> localhost (127.0.0.1 or ::1) | 573 | * non-passive socket -> localhost (127.0.0.1 or ::1) |
| 588 | */ | 574 | */ |
| 589 | static int | 575 | static int |
| 590 | explore_null(pai, hostname, servname, res) | 576 | explore_null(pai, servname, res) |
| 591 | const struct addrinfo *pai; | 577 | const struct addrinfo *pai; |
| 592 | const char *hostname; | ||
| 593 | const char *servname; | 578 | const char *servname; |
| 594 | struct addrinfo **res; | 579 | struct addrinfo **res; |
| 595 | { | 580 | { |
| @@ -676,15 +661,33 @@ explore_numeric(pai, hostname, servname, res) | |||
| 676 | afd = find_afd(pai->ai_family); | 661 | afd = find_afd(pai->ai_family); |
| 677 | flags = pai->ai_flags; | 662 | flags = pai->ai_flags; |
| 678 | 663 | ||
| 679 | if (inet_pton(afd->a_af, hostname, pton) == 1) { | 664 | switch (afd->a_af) { |
| 680 | if (pai->ai_family == afd->a_af || | 665 | #if 0 /*X/Open spec*/ |
| 681 | pai->ai_family == PF_UNSPEC /*?*/) { | 666 | case AF_INET: |
| 682 | GET_AI(cur->ai_next, afd, pton); | 667 | if (inet_aton(hostname, (struct in_addr *)pton) == 1) { |
| 683 | GET_PORT(cur->ai_next, servname); | 668 | if (pai->ai_family == afd->a_af || |
| 684 | while (cur && cur->ai_next) | 669 | pai->ai_family == PF_UNSPEC /*?*/) { |
| 685 | cur = cur->ai_next; | 670 | GET_AI(cur->ai_next, afd, pton); |
| 686 | } else | 671 | GET_PORT(cur->ai_next, servname); |
| 687 | ERR(EAI_FAMILY); /*xxx*/ | 672 | while (cur && cur->ai_next) |
| 673 | cur = cur->ai_next; | ||
| 674 | } else | ||
| 675 | ERR(EAI_FAMILY); /*xxx*/ | ||
| 676 | } | ||
| 677 | break; | ||
| 678 | #endif | ||
| 679 | default: | ||
| 680 | if (inet_pton(afd->a_af, hostname, pton) == 1) { | ||
| 681 | if (pai->ai_family == afd->a_af || | ||
| 682 | pai->ai_family == PF_UNSPEC /*?*/) { | ||
| 683 | GET_AI(cur->ai_next, afd, pton); | ||
| 684 | GET_PORT(cur->ai_next, servname); | ||
| 685 | while (cur && cur->ai_next) | ||
| 686 | cur = cur->ai_next; | ||
| 687 | } else | ||
| 688 | ERR(EAI_FAMILY); /*xxx*/ | ||
| 689 | } | ||
| 690 | break; | ||
| 688 | } | 691 | } |
| 689 | 692 | ||
| 690 | *res = sentinel.ai_next; | 693 | *res = sentinel.ai_next; |
| @@ -713,8 +716,7 @@ explore_numeric_scope(pai, hostname, servname, res) | |||
| 713 | const struct afd *afd; | 716 | const struct afd *afd; |
| 714 | struct addrinfo *cur; | 717 | struct addrinfo *cur; |
| 715 | int error; | 718 | int error; |
| 716 | char *cp, *hostname2 = NULL; | 719 | char *cp, *hostname2 = NULL, *scope; |
| 717 | int scope; | ||
| 718 | struct sockaddr_in6 *sin6; | 720 | struct sockaddr_in6 *sin6; |
| 719 | 721 | ||
| 720 | /* | 722 | /* |
| @@ -732,36 +734,29 @@ explore_numeric_scope(pai, hostname, servname, res) | |||
| 732 | return explore_numeric(pai, hostname, servname, res); | 734 | return explore_numeric(pai, hostname, servname, res); |
| 733 | 735 | ||
| 734 | /* | 736 | /* |
| 735 | * Handle special case of <scoped_address><delimiter><scope id> | 737 | * Handle special case of <scope id><delimiter><scoped_address> |
| 736 | */ | 738 | */ |
| 737 | hostname2 = strdup(hostname); | 739 | hostname2 = strdup(hostname); |
| 738 | if (hostname2 == NULL) | 740 | if (hostname2 == NULL) |
| 739 | return EAI_MEMORY; | 741 | return EAI_MEMORY; |
| 740 | /* terminate at the delimiter */ | 742 | /* terminate at the delimiter */ |
| 741 | hostname2[cp - hostname] = '\0'; | 743 | hostname2[cp - hostname] = '\0'; |
| 742 | 744 | scope = hostname2; | |
| 743 | cp++; | 745 | cp++; |
| 744 | switch (pai->ai_family) { | ||
| 745 | #ifdef INET6 | ||
| 746 | case AF_INET6: | ||
| 747 | scope = if_nametoindex(cp); | ||
| 748 | if (scope == 0) { | ||
| 749 | free(hostname2); | ||
| 750 | return (EAI_NONAME); | ||
| 751 | } | ||
| 752 | break; | ||
| 753 | #endif | ||
| 754 | } | ||
| 755 | 746 | ||
| 756 | error = explore_numeric(pai, hostname2, servname, res); | 747 | error = explore_numeric(pai, cp, servname, res); |
| 757 | if (error == 0) { | 748 | if (error == 0) { |
| 749 | int scopeid; | ||
| 750 | |||
| 758 | for (cur = *res; cur; cur = cur->ai_next) { | 751 | for (cur = *res; cur; cur = cur->ai_next) { |
| 759 | if (cur->ai_family != AF_INET6) | 752 | if (cur->ai_family != AF_INET6) |
| 760 | continue; | 753 | continue; |
| 761 | sin6 = (struct sockaddr_in6 *)cur->ai_addr; | 754 | sin6 = (struct sockaddr_in6 *)cur->ai_addr; |
| 762 | if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || | 755 | if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) { |
| 763 | IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) | 756 | free(hostname2); |
| 764 | sin6->sin6_scope_id = scope; | 757 | return(EAI_NONAME); /* XXX: is return OK? */ |
| 758 | } | ||
| 759 | sin6->sin6_scope_id = scopeid; | ||
| 765 | } | 760 | } |
| 766 | } | 761 | } |
| 767 | 762 | ||
| @@ -802,12 +797,12 @@ get_ai(pai, afd, addr) | |||
| 802 | 797 | ||
| 803 | memcpy(ai, pai, sizeof(struct addrinfo)); | 798 | memcpy(ai, pai, sizeof(struct addrinfo)); |
| 804 | ai->ai_addr = (struct sockaddr *)(ai + 1); | 799 | ai->ai_addr = (struct sockaddr *)(ai + 1); |
| 805 | memset(ai->ai_addr, 0, afd->a_socklen); | 800 | memset(ai->ai_addr, 0, (size_t)afd->a_socklen); |
| 806 | ai->ai_addr->sa_len = afd->a_socklen; | 801 | ai->ai_addr->sa_len = afd->a_socklen; |
| 807 | ai->ai_addrlen = afd->a_socklen; | 802 | ai->ai_addrlen = afd->a_socklen; |
| 808 | ai->ai_addr->sa_family = ai->ai_family = afd->a_af; | 803 | ai->ai_addr->sa_family = ai->ai_family = afd->a_af; |
| 809 | p = (char *)(ai->ai_addr); | 804 | p = (char *)(ai->ai_addr); |
| 810 | memcpy(p + afd->a_off, addr, afd->a_addrlen); | 805 | memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); |
| 811 | return ai; | 806 | return ai; |
| 812 | } | 807 | } |
| 813 | 808 | ||
| @@ -834,8 +829,15 @@ get_port(ai, servname, matchonly) | |||
| 834 | 829 | ||
| 835 | if (servname == NULL) | 830 | if (servname == NULL) |
| 836 | return 0; | 831 | return 0; |
| 837 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 832 | switch (ai->ai_family) { |
| 833 | case AF_INET: | ||
| 834 | #ifdef AF_INET6 | ||
| 835 | case AF_INET6: | ||
| 836 | #endif | ||
| 837 | break; | ||
| 838 | default: | ||
| 838 | return 0; | 839 | return 0; |
| 840 | } | ||
| 839 | 841 | ||
| 840 | switch (ai->ai_socktype) { | 842 | switch (ai->ai_socktype) { |
| 841 | case SOCK_RAW: | 843 | case SOCK_RAW: |
| @@ -905,3 +907,70 @@ find_afd(af) | |||
| 905 | } | 907 | } |
| 906 | return NULL; | 908 | return NULL; |
| 907 | } | 909 | } |
| 910 | |||
| 911 | #ifdef AI_ADDRCONFIG | ||
| 912 | /* | ||
| 913 | * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend | ||
| 914 | * will take care of it. | ||
| 915 | * the semantics of AI_ADDRCONFIG is not defined well. we are not sure | ||
| 916 | * if the code is right or not. | ||
| 917 | */ | ||
| 918 | static int | ||
| 919 | addrconfig(pai) | ||
| 920 | const struct addrinfo *pai; | ||
| 921 | { | ||
| 922 | #ifdef USE_GETIPNODEBY | ||
| 923 | return 1; | ||
| 924 | #else | ||
| 925 | int s; | ||
| 926 | |||
| 927 | /* XXX errno */ | ||
| 928 | s = socket(pai->ai_family, SOCK_DGRAM, 0); | ||
| 929 | if (s < 0) | ||
| 930 | return 0; | ||
| 931 | close(s); | ||
| 932 | return 1; | ||
| 933 | #endif | ||
| 934 | } | ||
| 935 | #endif | ||
| 936 | |||
| 937 | #ifdef INET6 | ||
| 938 | /* convert a string to a scope identifier. XXX: IPv6 specific */ | ||
| 939 | static int | ||
| 940 | ip6_str2scopeid(scope, sin6) | ||
| 941 | char *scope; | ||
| 942 | struct sockaddr_in6 *sin6; | ||
| 943 | { | ||
| 944 | int scopeid; | ||
| 945 | struct in6_addr *a6 = &sin6->sin6_addr; | ||
| 946 | char *ep; | ||
| 947 | |||
| 948 | if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { | ||
| 949 | /* | ||
| 950 | * We currently assume a one-to-one mapping between links | ||
| 951 | * and interfaces, so we simply use interface indices for | ||
| 952 | * like-local scopes. | ||
| 953 | */ | ||
| 954 | scopeid = if_nametoindex(scope); | ||
| 955 | if (scopeid == 0) | ||
| 956 | goto trynumeric; | ||
| 957 | return(scopeid); | ||
| 958 | } | ||
| 959 | |||
| 960 | /* still unclear about literal, allow numeric only - placeholder */ | ||
| 961 | if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) | ||
| 962 | goto trynumeric; | ||
| 963 | if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) | ||
| 964 | goto trynumeric; | ||
| 965 | else | ||
| 966 | goto trynumeric; /* global */ | ||
| 967 | |||
| 968 | /* try to convert to a numeric id as a last resort */ | ||
| 969 | trynumeric: | ||
| 970 | scopeid = (int)strtoul(scope, &ep, 10); | ||
| 971 | if (*ep == '\0') | ||
| 972 | return scopeid; | ||
| 973 | else | ||
| 974 | return -1; | ||
| 975 | } | ||
| 976 | #endif | ||
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c index 8b2ca299ef..e203cd5d16 100644 --- a/src/lib/libc/net/getnameinfo.c +++ b/src/lib/libc/net/getnameinfo.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: getnameinfo.c,v 1.7 2000/01/17 08:15:27 itojun Exp $ */ | 1 | /* $OpenBSD: getnameinfo.c,v 1.8 2000/02/09 12:22:09 itojun Exp $ */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| @@ -78,6 +78,10 @@ struct sockinet { | |||
| 78 | u_short si_port; | 78 | u_short si_port; |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | #ifdef INET6 | ||
| 82 | static char *ip6_sa2str __P((struct sockaddr_in6 *, char *, int)); | ||
| 83 | #endif | ||
| 84 | |||
| 81 | #define ENI_NOSOCKET 0 | 85 | #define ENI_NOSOCKET 0 |
| 82 | #define ENI_NOSERVNAME 1 | 86 | #define ENI_NOSERVNAME 1 |
| 83 | #define ENI_NOHOSTNAME 2 | 87 | #define ENI_NOHOSTNAME 2 |
| @@ -198,13 +202,16 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 198 | * means that the caller does not want the result. | 202 | * means that the caller does not want the result. |
| 199 | */ | 203 | */ |
| 200 | } else if (flags & NI_NUMERICHOST) { | 204 | } else if (flags & NI_NUMERICHOST) { |
| 205 | int numaddrlen; | ||
| 206 | |||
| 201 | /* NUMERICHOST and NAMEREQD conflicts with each other */ | 207 | /* NUMERICHOST and NAMEREQD conflicts with each other */ |
| 202 | if (flags & NI_NAMEREQD) | 208 | if (flags & NI_NAMEREQD) |
| 203 | return ENI_NOHOSTNAME; | 209 | return ENI_NOHOSTNAME; |
| 204 | if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) | 210 | if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) |
| 205 | == NULL) | 211 | == NULL) |
| 206 | return ENI_SYSTEM; | 212 | return ENI_SYSTEM; |
| 207 | if (strlen(numaddr) > hostlen) | 213 | numaddrlen = strlen(numaddr); |
| 214 | if (numaddrlen + 1 > hostlen) /* don't forget terminator */ | ||
| 208 | return ENI_MEMORY; | 215 | return ENI_MEMORY; |
| 209 | strcpy(host, numaddr); | 216 | strcpy(host, numaddr); |
| 210 | #if defined(INET6) && defined(NI_WITHSCOPEID) | 217 | #if defined(INET6) && defined(NI_WITHSCOPEID) |
| @@ -216,24 +223,34 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 216 | if (flags & NI_WITHSCOPEID) | 223 | if (flags & NI_WITHSCOPEID) |
| 217 | #endif /* !ALWAYS_WITHSCOPE */ | 224 | #endif /* !ALWAYS_WITHSCOPE */ |
| 218 | { | 225 | { |
| 219 | char *ep = strchr(host, '\0'); | 226 | char scopebuf[MAXHOSTNAMELEN], *s; |
| 220 | unsigned int ifindex = | 227 | int scopelen; |
| 221 | ((struct sockaddr_in6 *)sa)->sin6_scope_id; | ||
| 222 | 228 | ||
| 223 | *ep = SCOPE_DELIMITER; | 229 | if ((s = ip6_sa2str((struct sockaddr_in6 *)sa, |
| 224 | if ((if_indextoname(ifindex, ep + 1)) == NULL) | 230 | scopebuf, 0)) == NULL) |
| 225 | /* XXX what should we do? */ | 231 | /* XXX what should we do? */ |
| 226 | strncpy(ep + 1, "???", 3); | 232 | strcpy(scopebuf, "0"); |
| 233 | |||
| 234 | scopelen = strlen(scopebuf); | ||
| 235 | if (scopelen + 1 + numaddrlen + 1 > hostlen) | ||
| 236 | return ENI_MEMORY; | ||
| 237 | |||
| 238 | /* | ||
| 239 | * Shift the host string to allocate | ||
| 240 | * space for the scope ID part. | ||
| 241 | */ | ||
| 242 | memmove(host + scopelen + 1, host, | ||
| 243 | numaddrlen); | ||
| 244 | /* copy the scope ID and the delimiter */ | ||
| 245 | memcpy(host, scopebuf, scopelen); | ||
| 246 | host[scopelen] = SCOPE_DELIMITER; | ||
| 247 | host[scopelen + 1 + numaddrlen] = '\0'; | ||
| 227 | } | 248 | } |
| 228 | } | 249 | } |
| 229 | #endif /* INET6 */ | 250 | #endif /* INET6 */ |
| 230 | } else { | 251 | } else { |
| 231 | #ifdef USE_GETIPNODEBY | ||
| 232 | hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); | ||
| 233 | #else | ||
| 234 | hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); | 252 | hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); |
| 235 | h_error = h_errno; | 253 | h_error = h_errno; |
| 236 | #endif | ||
| 237 | 254 | ||
| 238 | if (hp) { | 255 | if (hp) { |
| 239 | if (flags & NI_NOFQDN) { | 256 | if (flags & NI_NOFQDN) { |
| @@ -241,15 +258,9 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 241 | if (p) *p = '\0'; | 258 | if (p) *p = '\0'; |
| 242 | } | 259 | } |
| 243 | if (strlen(hp->h_name) > hostlen) { | 260 | if (strlen(hp->h_name) > hostlen) { |
| 244 | #ifdef USE_GETIPNODEBY | ||
| 245 | freehostent(hp); | ||
| 246 | #endif | ||
| 247 | return ENI_MEMORY; | 261 | return ENI_MEMORY; |
| 248 | } | 262 | } |
| 249 | strcpy(host, hp->h_name); | 263 | strcpy(host, hp->h_name); |
| 250 | #ifdef USE_GETIPNODEBY | ||
| 251 | freehostent(hp); | ||
| 252 | #endif | ||
| 253 | } else { | 264 | } else { |
| 254 | if (flags & NI_NAMEREQD) | 265 | if (flags & NI_NAMEREQD) |
| 255 | return ENI_NOHOSTNAME; | 266 | return ENI_NOHOSTNAME; |
| @@ -263,3 +274,33 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 263 | } | 274 | } |
| 264 | return SUCCESS; | 275 | return SUCCESS; |
| 265 | } | 276 | } |
| 277 | |||
| 278 | #ifdef INET6 | ||
| 279 | /* ARGSUSED */ | ||
| 280 | static char * | ||
| 281 | ip6_sa2str(sa6, buf, flags) | ||
| 282 | struct sockaddr_in6 *sa6; | ||
| 283 | char *buf; | ||
| 284 | int flags; | ||
| 285 | { | ||
| 286 | unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; | ||
| 287 | struct in6_addr *a6 = &sa6->sin6_addr; | ||
| 288 | |||
| 289 | #ifdef notyet | ||
| 290 | if (flags & NI_NUMERICSCOPE) { | ||
| 291 | sprintf(buf, "%d", sa6->sin6_scope_id); | ||
| 292 | return(buf); | ||
| 293 | } | ||
| 294 | #endif | ||
| 295 | |||
| 296 | if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) | ||
| 297 | return(if_indextoname(ifindex, buf)); | ||
| 298 | |||
| 299 | if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) | ||
| 300 | return(NULL); /* XXX */ | ||
| 301 | if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) | ||
| 302 | return(NULL); /* XXX */ | ||
| 303 | |||
| 304 | return(NULL); /* XXX */ | ||
| 305 | } | ||
| 306 | #endif | ||
