diff options
author | itojun <> | 2000-02-09 12:22:09 +0000 |
---|---|---|
committer | itojun <> | 2000-02-09 12:22:09 +0000 |
commit | e198d71e66f565f1b105993a32008bab5c57e8e1 (patch) | |
tree | f29e4fda4e3e94b78fbed3641620d51be04592c6 | |
parent | 4d2790bdcdf21e6500928a62b17cfc7e296d4a5a (diff) | |
download | openbsd-e198d71e66f565f1b105993a32008bab5c57e8e1.tar.gz openbsd-e198d71e66f565f1b105993a32008bab5c57e8e1.tar.bz2 openbsd-e198d71e66f565f1b105993a32008bab5c57e8e1.zip |
revise extended scoped address format support. delimiter and the order
is changed, based on discussion in ipngwg scoped address cabal.
past code: fe80::1@de0
now: de0%fe80::1
this will be in sync with next extended address format proposal
(which should be final - I don't want to make this kind of change again).
-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 | ||