Source-Changes-HG archive

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

[src/trunk]: src implement upper limit to icmp6 redirects (experimental, turn...



details:   https://anonhg.NetBSD.org/src/rev/14b9deabd097
branches:  trunk
changeset: 503549:14b9deabd097
user:      itojun <itojun%NetBSD.org@localhost>
date:      Thu Feb 08 16:07:39 2001 +0000

description:
implement upper limit to icmp6 redirects (experimental, turned off)
negative value to {mtudisc,redirect}_{hi,lo}wat will turn off the limitation.
sync with kame.

diffstat:

 lib/libc/gen/sysctl.3 |    3 +-
 sys/netinet6/icmp6.c  |  120 +++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 97 insertions(+), 26 deletions(-)

diffs (230 lines):

diff -r 584617def951 -r 14b9deabd097 lib/libc/gen/sysctl.3
--- a/lib/libc/gen/sysctl.3     Thu Feb 08 15:19:14 2001 +0000
+++ b/lib/libc/gen/sysctl.3     Thu Feb 08 16:07:39 2001 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sysctl.3,v 1.73 2001/02/07 08:59:47 itojun Exp $
+.\"    $NetBSD: sysctl.3,v 1.74 2001/02/08 16:07:39 itojun Exp $
 .\"
 .\" Copyright (c) 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -1072,6 +1072,7 @@
 .Li icmp6.mtudisc_lowat
 is used when we have unverified ICMPv6 too big messages.
 Verification is performed by using address/port pairs kept in connected pcbs.
+Negative value disables the upper limit.
 .It Li icmp6.nd6_debug
 If set to non-zero, kernel IPv6 neighbor discovery code will generate
 debugging messages.
diff -r 584617def951 -r 14b9deabd097 sys/netinet6/icmp6.c
--- a/sys/netinet6/icmp6.c      Thu Feb 08 15:19:14 2001 +0000
+++ b/sys/netinet6/icmp6.c      Thu Feb 08 16:07:39 2001 +0000
@@ -1,5 +1,4 @@
-/*     $NetBSD: icmp6.c,v 1.54 2001/02/07 10:56:38 itojun Exp $        */
-/*     $KAME: icmp6.c,v 1.191 2001/02/07 08:07:38 itojun Exp $ */
+/*     $KAME: icmp6.c,v 1.194 2001/02/08 15:19:12 itojun Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -131,8 +130,17 @@
 extern int pmtu_expire;
 
 /* XXX do these values make any sense? */
-int icmp6_mtudisc_hiwat = 1280;
-int icmp6_mtudisc_lowat = 256;
+static int icmp6_mtudisc_hiwat = 1280;
+static int icmp6_mtudisc_lowat = 256;
+
+/*
+ * keep track of # of redirect routes.
+ */
+static struct rttimer_queue *icmp6_redirect_timeout_q = NULL;
+
+/* XXX experimental, turned off */
+static int icmp6_redirect_hiwat = -1;
+static int icmp6_redirect_lowat = -1;
 
 static void icmp6_errcount __P((struct icmp6errstat *, int, int));
 static int icmp6_rip6_input __P((struct mbuf **, int));
@@ -148,6 +156,7 @@
                                struct ifnet *, int));
 static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *));
 static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
+static void icmp6_redirect_timeout __P((struct rtentry *, struct rttimer *));
 
 #ifdef COMPAT_RFC1885
 static struct route_in6 icmp6_reflect_rt;
@@ -158,6 +167,7 @@
 {
        mld6_init();
        icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire);
+       icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout);
 }
 
 static void
@@ -1054,15 +1064,16 @@
         */
        rtcount = rt_timer_count(icmp6_mtudisc_timeout_q);
        if (validated) {
-               if (rtcount > icmp6_mtudisc_hiwat)
+               if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat)
                        return;
-               else if (rtcount > icmp6_mtudisc_lowat) {
+               else if (0 <= icmp6_mtudisc_lowat &&
+                   rtcount > icmp6_mtudisc_lowat) {
                        /*
                         * XXX nuke a victim, install the new one.
                         */
                }
        } else {
-               if (rtcount > icmp6_mtudisc_lowat)
+               if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat)
                        return;
        }
 
@@ -1906,6 +1917,7 @@
        int plen;
        int type, code;
        struct ifnet *outif = NULL;
+       struct sockaddr_in6 sa6_src, sa6_dst;
 #ifdef COMPAT_RFC1885
        int mtu = IPV6_MMTU;
        struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst;
@@ -1963,12 +1975,24 @@
         */
        ip6->ip6_dst = ip6->ip6_src;
 
-       /* XXX hack for link-local addresses */
-       if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
-               ip6->ip6_dst.s6_addr16[1] =
-                       htons(m->m_pkthdr.rcvif->if_index);
-       if (IN6_IS_ADDR_LINKLOCAL(&t))
-               t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
+       /*
+        * XXX: make sure to embed scope zone information, using
+        * already embedded IDs or the received interface (if any).
+        * Note that rcvif may be NULL.
+        * TODO: scoped routing case (XXX).
+        */
+       bzero(&sa6_src, sizeof(sa6_src));
+       sa6_src.sin6_family = AF_INET6;
+       sa6_src.sin6_len = sizeof(sa6_src);
+       sa6_src.sin6_addr = ip6->ip6_dst;
+       in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif);
+       in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL);
+       bzero(&sa6_dst, sizeof(sa6_dst));
+       sa6_dst.sin6_family = AF_INET6;
+       sa6_dst.sin6_len = sizeof(sa6_dst);
+       sa6_dst.sin6_addr = t;
+       in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif);
+       in6_embedscope(&t, &sa6_dst, NULL, NULL);
 
 #ifdef COMPAT_RFC1885
        /*
@@ -1980,6 +2004,7 @@
        if (icmp6_reflect_rt.ro_rt == 0 ||
            ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) {
                if (icmp6_reflect_rt.ro_rt) {
+                       RTFREE(icmp6_reflect_rt.ro_rt);
                        icmp6_reflect_rt.ro_rt = 0;
                }
                bzero(sin6, sizeof(*sin6));
@@ -2023,19 +2048,27 @@
                src = &t;
        }
 
-       if (src == 0)
+       if (src == 0) {
+               int e;
+               struct route_in6 ro;
+
                /*
                 * This case matches to multicasts, our anycast, or unicasts
-                * that we do not own. Select a source address which has the
-                * same scope.
-                * XXX: for (non link-local) multicast addresses, this might
-                * not be a good choice.
+                * that we do not own. Select a source address based on the
+                * source address of the erroneous packet.
                 */
-               if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0)
-                       src = &IA6_SIN6(ia)->sin6_addr;
-
-       if (src == 0)
-               goto bad;
+               bzero(&ro, sizeof(ro));
+               src = in6_selectsrc(&sa6_src, NULL, NULL, &ro, NULL, &e);
+               if (ro.ro_rt)
+                       RTFREE(ro.ro_rt); /* XXX: we could use this */
+               if (src == NULL) {
+                       nd6log((LOG_DEBUG,
+                           "icmp6_reflect: source can't be determined: "
+                           "dst=%s, error=%d\n",
+                           ip6_sprintf(&sa6_src.sin6_addr), e));
+                       goto bad;
+               }
+       }
 
        ip6->ip6_src = *src;
 
@@ -2260,6 +2293,24 @@
                struct sockaddr_in6 sdst;
                struct sockaddr_in6 sgw;
                struct sockaddr_in6 ssrc;
+               unsigned long rtcount;
+               struct rtentry *newrt = NULL;
+
+               /*
+                * do not install redirect route, if the number of entries
+                * is too much (> hiwat).  note that, the node (= host) will
+                * work just fine even if we do not install redirect route
+                * (there will be additional hops, though).
+                */
+               rtcount = rt_timer_count(icmp6_redirect_timeout_q);
+               if (0 <= icmp6_redirect_hiwat && rtcount > icmp6_redirect_hiwat)
+                       return;
+               else if (0 <= icmp6_redirect_lowat &&
+                   rtcount > icmp6_redirect_lowat) {
+                       /*
+                        * XXX nuke a victim, install the new one.
+                        */
+               }
 
                bzero(&sdst, sizeof(sdst));
                bzero(&sgw, sizeof(sgw));
@@ -2273,8 +2324,13 @@
                rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
                           (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
                           (struct sockaddr *)&ssrc,
-                          (struct rtentry **)NULL
-                          );
+                          &newrt);
+
+               if (newrt) {
+                       (void)rt_timer_add(newrt, icmp6_redirect_timeout,
+                           icmp6_redirect_timeout_q);
+                       rtfree(newrt);
+               }
        }
        /* finally update cached route in each socket via pfctlinput */
     {
@@ -2740,6 +2796,20 @@
        }
 }
 
+static void
+icmp6_redirect_timeout(rt, r)
+       struct rtentry *rt;
+       struct rttimer *r;
+{
+       if (rt == NULL)
+               panic("icmp6_redirect_timeout: bad route to timeout");
+       if ((rt->rt_flags & (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) ==
+           (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) {
+               rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
+                   rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
+       }
+}
+
 #include <uvm/uvm_extern.h>
 #include <sys/sysctl.h>
 



Home | Main Index | Thread Index | Old Index