Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/route support extended scoped address notation (fe80::1...



details:   https://anonhg.NetBSD.org/src/rev/3580a5d6832d
branches:  trunk
changeset: 485140:3580a5d6832d
user:      itojun <itojun%NetBSD.org@localhost>
date:      Thu Apr 20 12:08:50 2000 +0000

description:
support extended scoped address notation (fe80::1%de0).
it hides implementation detail (embedded ifid) from the users.

diffstat:

 sbin/route/route.c |  138 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 115 insertions(+), 23 deletions(-)

diffs (207 lines):

diff -r dc17d45bed09 -r 3580a5d6832d sbin/route/route.c
--- a/sbin/route/route.c        Thu Apr 20 11:51:27 2000 +0000
+++ b/sbin/route/route.c        Thu Apr 20 12:08:50 2000 +0000
@@ -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 @@
 #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 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 @@
        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 @@
 #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 @@
        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 @@
 #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 @@
        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 @@
 #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:



Home | Main Index | Thread Index | Old Index