summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritojun <>2000-02-09 12:22:09 +0000
committeritojun <>2000-02-09 12:22:09 +0000
commite198d71e66f565f1b105993a32008bab5c57e8e1 (patch)
treef29e4fda4e3e94b78fbed3641620d51be04592c6
parent4d2790bdcdf21e6500928a62b17cfc7e296d4a5a (diff)
downloadopenbsd-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.c255
-rw-r--r--src/lib/libc/net/getnameinfo.c77
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
75static int translate = NO;
76static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
77#endif
78
79static const char in_addrany[] = { 0, 0, 0, 0 }; 79static const char in_addrany[] = { 0, 0, 0, 0 };
80static const char in6_addrany[] = { 80static 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[] = {
150static int str_isnumber __P((const char *)); 150static int str_isnumber __P((const char *));
151static int explore_fqdn __P((const struct addrinfo *, const char *, 151static int explore_fqdn __P((const struct addrinfo *, const char *,
152 const char *, struct addrinfo **)); 152 const char *, struct addrinfo **));
153static int explore_null __P((const struct addrinfo *, const char *, 153static int explore_null __P((const struct addrinfo *,
154 const char *, struct addrinfo **)); 154 const char *, struct addrinfo **));
155static int explore_numeric __P((const struct addrinfo *, const char *, 155static 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 *,
163static int get_portmatch __P((const struct addrinfo *, const char *)); 163static int get_portmatch __P((const struct addrinfo *, const char *));
164static int get_port __P((struct addrinfo *, const char *, int)); 164static int get_port __P((struct addrinfo *, const char *, int));
165static const struct afd *find_afd __P((int)); 165static const struct afd *find_afd __P((int));
166#ifdef AI_ADDRCONFIG
167static int addrconfig __P((const struct addrinfo *));
168#endif
169#ifdef INET6
170static 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) \
180do { \ 186do { \
@@ -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) \
188do { \ 194do { \
@@ -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) \
196do { \ 202do { \
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
207static int 213static int
208str_isnumber(p) 214str_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 */
589static int 575static int
590explore_null(pai, hostname, servname, res) 576explore_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 */
918static int
919addrconfig(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 */
939static int
940ip6_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
82static 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 */
280static char *
281ip6_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