support extended scoped address notation (fe80::1%de0).

it hides implementation detail (embedded ifid) from the users.
This commit is contained in:
itojun 2000-04-20 12:08:50 +00:00
parent 8bd19349a1
commit bfbec7cf43
1 changed files with 115 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: route.c,v 1.35 1999/12/03 05:43:00 itojun Exp $ */
/* $NetBSD: route.c,v 1.36 2000/04/20 12:08:50 itojun Exp $ */
/*
* Copyright (c) 1983, 1989, 1991, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
#if 0
static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: route.c,v 1.35 1999/12/03 05:43:00 itojun Exp $");
__RCSID("$NetBSD: route.c,v 1.36 2000/04/20 12:08:50 itojun Exp $");
#endif
#endif /* not lint */
@ -86,6 +86,9 @@ static char *any_ntoa __P((const struct sockaddr *));
static void set_metric __P((char *, int));
static void newroute __P((int, char **));
static void inet_makenetandmask __P((u_int32_t, struct sockaddr_in *));
#ifdef INET6
static void inet6_makenetandmask __P((struct sockaddr_in6 *));
#endif
static int getaddr __P((int, char *, struct hostent **));
static void flushroutes __P((int, char *[]));
#ifndef SMALL
@ -381,9 +384,6 @@ routename(sa)
static char domain[MAXHOSTNAMELEN + 1];
static int first = 1;
struct in_addr in;
#ifdef INET6
static char ntop_buf[NI_MAXHOST];
#endif
if (first) {
first = 0;
@ -429,14 +429,35 @@ routename(sa)
#ifndef SMALL
#ifdef INET6
case AF_INET6:
{ struct in6_addr in6;
int gap;
{
struct sockaddr_in6 sin6;
int niflags;
in6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
gap = 24 - sa->sa_len;
if (gap > 0)
bzero((char *)(&in6 + 1) - gap, gap);
return ((char *)inet_ntop(AF_INET6, &in6, ntop_buf, sizeof(ntop_buf)));
#ifdef NI_WITHSCOPEID
niflags = NI_WITHSCOPEID;
#else
niflags = 0;
#endif
if (nflag)
niflags |= NI_NUMERICHOST;
memset(&sin6, 0, sizeof(sin6));
memcpy(&sin6, sa, sa->sa_len);
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
sin6.sin6_addr.s6_addr[2] = 0;
sin6.sin6_addr.s6_addr[3] = 0;
}
#endif
if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
line, sizeof(line), NULL, 0, niflags) != 0)
strncpy(line, "invalid", sizeof(line));
break;
}
#endif
@ -479,9 +500,6 @@ netname(sa)
u_int32_t i;
int subnetshift;
struct in_addr in;
#ifdef INET6
static char ntop_buf[NI_MAXHOST];
#endif
switch (sa->sa_family) {
@ -547,14 +565,35 @@ netname(sa)
#ifndef SMALL
#ifdef INET6
case AF_INET6:
{ struct in6_addr in6;
int gap;
{
struct sockaddr_in6 sin6;
int niflags;
in6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
gap = 24 - sa->sa_len;
if (gap > 0)
bzero((char *)(&in6 + 1) - gap, gap);
return ((char *)inet_ntop(AF_INET6, &in6, ntop_buf, sizeof(ntop_buf)));
#ifdef NI_WITHSCOPEID
niflags = NI_WITHSCOPEID;
#else
niflags = 0;
#endif
if (nflag)
niflags |= NI_NUMERICHOST;
memset(&sin6, 0, sizeof(sin6));
memcpy(&sin6, sa, sa->sa_len);
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
sin6.sin6_addr.s6_addr[2] = 0;
sin6.sin6_addr.s6_addr[3] = 0;
}
#endif
if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
line, sizeof(line), NULL, 0, niflags) != 0)
strncpy(line, "invalid", sizeof(line));
break;
}
#endif
@ -903,6 +942,37 @@ inet_makenetandmask(net, sin)
sin->sin_len = 1 + cp - (char *)sin;
}
#ifdef INET6
/*
* XXX the function may need more improvement...
*/
static void
inet6_makenetandmask(sin6)
struct sockaddr_in6 *sin6;
{
char *plen;
struct in6_addr in6;
plen = NULL;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
sin6->sin6_scope_id == 0) {
plen = "0";
} else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
/* aggregatable global unicast - RFC2374 */
memset(&in6, 0, sizeof(in6));
if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8))
plen = "64";
else
plen = "128";
}
if (plen) {
rtm_addrs |= RTA_NETMASK;
prefixlen(plen);
}
}
#endif
/*
* Interpret an argument as a network address of some kind,
* returning 1 if a host address, 0 if a network address.
@ -970,11 +1040,33 @@ getaddr(which, s, hpp)
#ifndef SMALL
#ifdef INET6
case AF_INET6:
if (inet_pton(AF_INET6, s, (void *)&su->sin6.sin6_addr) != 1) {
{
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = afamily; /*AF_INET6*/
hints.ai_flags = AI_NUMERICHOST;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
if (getaddrinfo(s, "0", &hints, &res) != 0 ||
res->ai_family != AF_INET6 ||
res->ai_addrlen != sizeof(su->sin6)) {
(void) fprintf(stderr, "%s: bad value\n", s);
exit(1);
}
memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
#ifdef __KAME__
if (IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) &&
su->sin6.sin6_scope_id) {
*(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
htons(su->sin6.sin6_scope_id);
su->sin6.sin6_scope_id = 0;
}
#endif
if (which == RTA_DST)
inet6_makenetandmask(&su->sin6);
freeaddrinfo(res);
return 0;
}
#endif
case AF_NS: