diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 3e1af69ed0b8..8b567bf98141 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -94,6 +94,11 @@ static const char rcsid[] = #include "ifconfig.h" +/* wrapper for KAME-special getnameinfo() */ +#ifndef NI_WITHSCOPEID +#define NI_WITHSCOPEID 0 +#endif + struct ifreq ifr, ridreq; struct ifaliasreq addreq; #ifdef INET6 @@ -119,7 +124,7 @@ static int ip6lifetime; struct afswtch; #ifdef INET6 -char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/ +char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ #endif void Perror __P((const char *cmd)); @@ -969,6 +974,7 @@ in6_status(s, info) u_int32_t flags6; struct in6_addrlifetime lifetime; time_t t = time(NULL); + int error; memset(&null_sin, 0, sizeof(null_sin)); @@ -995,9 +1001,24 @@ in6_status(s, info) lifetime = ifr6.ifr_ifru.ifru_lifetime; close(s6); - printf("\tinet6 %s ", inet_ntop(AF_INET6, &sin->sin6_addr, - ntop_buf, sizeof(ntop_buf))); + /* XXX: embedded link local addr check */ + if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && + *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { + u_short index; + index = *(u_short *)&sin->sin6_addr.s6_addr[2]; + *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; + if (sin->sin6_scope_id == 0) + sin->sin6_scope_id = ntohs(index); + } + + error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, + sizeof(addr_buf), NULL, 0, + NI_NUMERICHOST|NI_WITHSCOPEID); + if (error != 0) + inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, + sizeof(addr_buf)); + printf("\tinet6 %s ", addr_buf); if (flags & IFF_POINTOPOINT) { /* note RTAX_BRD overlap with IFF_BROADCAST */ @@ -1007,8 +1028,27 @@ in6_status(s, info) * address. */ if (sin && sin->sin6_family == AF_INET6) { - printf("--> %s ", inet_ntop(AF_INET6, &sin->sin6_addr, - ntop_buf, sizeof(ntop_buf))); + int error; + + /* XXX: embedded link local addr check */ + if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && + *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { + u_short index; + + index = *(u_short *)&sin->sin6_addr.s6_addr[2]; + *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; + if (sin->sin6_scope_id == 0) + sin->sin6_scope_id = ntohs(index); + } + + error = getnameinfo((struct sockaddr *)sin, + sin->sin6_len, addr_buf, + sizeof(addr_buf), NULL, 0, + NI_NUMERICHOST|NI_WITHSCOPEID); + if (error != 0) + inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, + sizeof(addr_buf)); + printf("--> %s ", addr_buf); } } @@ -1213,6 +1253,8 @@ in6_getaddr(s, which) int which; { register struct sockaddr_in6 *sin = sin6tab[which]; + struct addrinfo hints, *res; + int error = -1; newaddr &= 1; @@ -1220,8 +1262,16 @@ in6_getaddr(s, which) if (which != MASK) sin->sin6_family = AF_INET6; - if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) - errx(1, "%s: bad value", s); + if (sin->sin6_family == AF_INET6) { + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + error = getaddrinfo(s, NULL, &hints, &res); + } + if (error != 0) { + if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) + errx(1, "%s: bad value", s); + } else + bcopy(res->ai_addr, sin, res->ai_addrlen); } void diff --git a/sbin/route/route.c b/sbin/route/route.c index 3a87f5135efa..6e67c404824a 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -72,6 +72,11 @@ static const char rcsid[] = #include #include +/* wrapper for KAME-special getnameinfo() */ +#ifndef NI_WITHSCOPEID +#define NI_WITHSCOPEID 0 +#endif + struct keytab { char *kt_cp; int kt_i; @@ -104,6 +109,9 @@ struct rt_metrics rt_metrics; u_long rtm_inits; int atalk_aton __P((const char *, struct at_addr *)); char *atalk_ntoa __P((struct at_addr)); +#ifdef INET6 +char *inet6_ntoa __P((struct sockaddr *sa)); +#endif char *routename(), *netname(); void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf(); void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr(); @@ -114,7 +122,7 @@ extern char *iso_ntoa(); void usage __P((const char *)) __dead2; #ifdef INET6 -char ntop_buf[INET6_ADDRSTRLEN]; /*for inet_ntop()*/ +char name_buf[MAXHOSTNAMELEN * 2 + 1]; /*for getnameinfo()*/ #endif void @@ -361,17 +369,8 @@ routename(sa) #ifdef INET6 case AF_INET6: - { struct sockaddr_in6 *sin6; - int gap; - - sin6 = (struct sockaddr_in6 *)sa; - gap = sizeof(struct sockaddr_in6) - sin6->sin6_len; - if (gap > 0) - bzero((char *)(sin6) + sin6->sin6_len, gap); - (void) snprintf(line, sizeof(line), "%s", - inet_ntop(AF_INET6, &sin6->sin6_addr, - ntop_buf, sizeof(ntop_buf))); - } + (void) snprintf(line, sizeof(line), "%s", inet6_ntoa(sa)); + break; #endif case AF_APPLETALK: @@ -473,17 +472,8 @@ netname(sa) #ifdef INET6 case AF_INET6: - { struct in6_addr in6; - int gap; - - in6 = ((struct sockaddr_in6 *)sa)->sin6_addr; - gap = sizeof(struct sockaddr_in6) - sa->sa_len; - if (gap > 0) - bzero((char *)(&in6 + 1) - gap, gap); - (void)snprintf(line, sizeof(line), "%s", - inet_ntop(AF_INET6, &in6, ntop_buf, - sizeof(ntop_buf))); - } + (void) snprintf(line, sizeof(line), "%s", inet6_ntoa(sa)); + break; #endif case AF_APPLETALK: @@ -917,11 +907,25 @@ getaddr(which, s, hpp) switch (afamily) { #ifdef INET6 case AF_INET6: - if (inet_pton(AF_INET6, s, (void *)&su->sin6.sin6_addr) != 1) { - (void) fprintf(stderr, "%s: bad value\n", s); + { + struct addrinfo hints, *res; + int error; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + + error = getaddrinfo(s, NULL, &hints, &res); + if (error != 0) { + (void) fprintf(stderr, "%s: bad value\n", + gai_strerror(error)); + if (error == EAI_SYSTEM) + (void) fprintf(stderr, "%s\n", + strerror(errno)); exit(1); } + bcopy(res->ai_addr, &su->sa, res->ai_addrlen); return 0; + } #endif #ifdef NS @@ -1613,3 +1617,45 @@ atalk_ntoa(struct at_addr at) (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); return(buf); } + +#ifdef INET6 +char * +inet6_ntoa(struct sockaddr *sa) +{ + char *cp; + struct sockaddr_in6 *sin6; + int error = -1, gap; + + cp = NULL; + sin6 = (struct sockaddr_in6 *)sa; + gap = sizeof(struct sockaddr_in6) - sin6->sin6_len; + if (gap > 0) + bzero((char *)(sin6) + sin6->sin6_len, gap); + + /* XXX: embedded link local addr check */ + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && + *(u_short *)&sin6->sin6_addr.s6_addr[2] != 0) { + u_short index; + + index = *(u_short *)&sin6->sin6_addr.s6_addr[2]; + *(u_short *)&sin6->sin6_addr.s6_addr[2] = 0; + if (sin6->sin6_scope_id == 0) + sin6->sin6_scope_id = ntohs(index); + } + + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || sa->sa_len < 4) + cp = "default"; + if (cp == 0 && !nflag) + error = getnameinfo(sa, sa->sa_len, name_buf, sizeof(name_buf), + NULL, 0, NI_NAMEREQD); + if (error != 0) + error = getnameinfo(sa, sa->sa_len, name_buf, + sizeof(name_buf), NULL, 0, + NI_NUMERICHOST|NI_WITHSCOPEID); + if (error != 0) + inet_ntop(AF_INET6, &sin6->sin6_addr, name_buf, + sizeof(name_buf)); + + return (cp != NULL) ? cp : name_buf; +} +#endif