Module Name:    src
Committed By:   spz
Date:           Tue May 24 18:07:12 UTC 2011

Modified Files:
        src/sys/netinet: icmp6.h
        src/sys/netinet6: in6.h in6_proto.c ip6_input.c ip6_var.h nd6.h
            nd6_rtr.c
        src/sys/sys: param.h
        src/usr.bin/netstat: inet6.c

Log Message:
RA flood mitigation via a limit on accepted routes:
- introduce a limit for the routes accepted via IPv6 Router Advertisement:
  a common 2 interface client will have 6, the default limit is 100 and
  can be adjusted via sysctl
- report the current number of routes installed via RA via sysctl
- count discarded route additions. Note that one RA message is two routes.
  This is at present only across all interfaces even though per-interface
  would be more useful, since the per-interface structure complies to RFC2466
- bump kernel version due to the previous change
- adjust netstat to use the new value (with netstat -p icmp6)


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/netinet/icmp6.h
cvs rdiff -u -r1.68 -r1.69 src/sys/netinet6/in6.h
cvs rdiff -u -r1.91 -r1.92 src/sys/netinet6/in6_proto.c
cvs rdiff -u -r1.130 -r1.131 src/sys/netinet6/ip6_input.c
cvs rdiff -u -r1.54 -r1.55 src/sys/netinet6/ip6_var.h
cvs rdiff -u -r1.53 -r1.54 src/sys/netinet6/nd6.h
cvs rdiff -u -r1.80 -r1.81 src/sys/netinet6/nd6_rtr.c
cvs rdiff -u -r1.388 -r1.389 src/sys/sys/param.h
cvs rdiff -u -r1.58 -r1.59 src/usr.bin/netstat/inet6.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet/icmp6.h
diff -u src/sys/netinet/icmp6.h:1.41 src/sys/netinet/icmp6.h:1.42
--- src/sys/netinet/icmp6.h:1.41	Sun May  8 18:42:53 2011
+++ src/sys/netinet/icmp6.h	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: icmp6.h,v 1.41 2011/05/08 18:42:53 spz Exp $	*/
+/*	$NetBSD: icmp6.h,v 1.42 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $	*/
 
 
@@ -569,8 +569,9 @@
 #define	ICMP6_STAT_BADRS	538	/* bad router solicitiation */
 #define	ICMP6_STAT_BADRA	539	/* bad router advertisement */
 #define	ICMP6_STAT_BADREDIRECT	540	/* bad redirect message */
+#define ICMP6_STAT_DROPPED_RAROUTE 541	/* discarded routes from router advertisement */
 
-#define	ICMP6_NSTATS		541
+#define	ICMP6_NSTATS		542
 
 #define	ICMP6_ERRSTAT_DST_UNREACH_NOROUTE	0
 #define	ICMP6_ERRSTAT_DST_UNREACH_ADMIN		1

Index: src/sys/netinet6/in6.h
diff -u src/sys/netinet6/in6.h:1.68 src/sys/netinet6/in6.h:1.69
--- src/sys/netinet6/in6.h:1.68	Fri Sep 11 22:06:29 2009
+++ src/sys/netinet6/in6.h	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.h,v 1.68 2009/09/11 22:06:29 dyoung Exp $	*/
+/*	$NetBSD: in6.h,v 1.69 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $	*/
 
 /*
@@ -575,9 +575,13 @@
 /* 40: reserved */
 #define IPV6CTL_MAXFRAGS	41	/* max fragments */
 #define IPV6CTL_IFQ		42	/* ip6intrq node */
+#define IPV6CTL_RTADV_MAXROUTES 43	/* maximum number of routes */
+					/* via router advertisement */
+#define IPV6CTL_RTADV_NUMROUTES 44	/* current number of routes */
+					/* via router advertisement */
 /* New entries should be added here from current IPV6CTL_MAXID value. */
 /* to define items, should talk with KAME guys first, for *BSD compatibility */
-#define IPV6CTL_MAXID		43
+#define IPV6CTL_MAXID		45
 
 #define IPV6CTL_NAMES { \
 	{ 0, 0 }, \
@@ -623,6 +627,8 @@
 	{ 0, 0 }, \
 	{ "maxfrags", CTLTYPE_INT }, \
 	{ "ifq", CTLTYPE_NODE }, \
+	{ "rtadv_maxroutes", CTLTYPE_INT }, \
+	{ "rtadv_numroutes", CTLTYPE_INT }, \
 }
 
 #endif /* _NETBSD_SOURCE */

Index: src/sys/netinet6/in6_proto.c
diff -u src/sys/netinet6/in6_proto.c:1.91 src/sys/netinet6/in6_proto.c:1.92
--- src/sys/netinet6/in6_proto.c:1.91	Tue May  3 17:44:30 2011
+++ src/sys/netinet6/in6_proto.c	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_proto.c,v 1.91 2011/05/03 17:44:30 dyoung Exp $	*/
+/*	$NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.91 2011/05/03 17:44:30 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $");
 
 #include "opt_gateway.h"
 #include "opt_inet.h"
@@ -482,6 +482,13 @@
 
 int	ip6_keepfaith = 0;
 time_t	ip6_log_time = (time_t)0L;
+int	ip6_rtadv_maxroutes = 100; /* (arbitrary) initial maximum number of
+                                    * routes via rtadv expected to be
+                                    * significantly larger than common use.
+                                    * if you need to count: 3 extra initial
+                                    * routes, plus 1 per interface after the
+                                    * first one, then one per non-linklocal
+                                    * prefix */
 
 /* icmp6 */
 /*

Index: src/sys/netinet6/ip6_input.c
diff -u src/sys/netinet6/ip6_input.c:1.130 src/sys/netinet6/ip6_input.c:1.131
--- src/sys/netinet6/ip6_input.c:1.130	Tue May  3 18:28:45 2011
+++ src/sys/netinet6/ip6_input.c	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_input.c,v 1.130 2011/05/03 18:28:45 dyoung Exp $	*/
+/*	$NetBSD: ip6_input.c,v 1.131 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.130 2011/05/03 18:28:45 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.131 2011/05/24 18:07:11 spz Exp $");
 
 #include "opt_gateway.h"
 #include "opt_inet.h"
@@ -1795,6 +1795,20 @@
 		       IPV6CTL_ACCEPT_RTADV, CTL_EOL);
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "rtadv_maxroutes",
+		       SYSCTL_DESCR("Maximum number of routes accepted via router advertisements"),
+		       NULL, 0, &ip6_rtadv_maxroutes, 0,
+		       CTL_NET, PF_INET6, IPPROTO_IPV6,
+		       IPV6CTL_RTADV_MAXROUTES, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_INT, "rtadv_numroutes",
+		       SYSCTL_DESCR("Current number of routes accepted via router advertisements"),
+		       NULL, 0, &nd6_numroutes, 0,
+		       CTL_NET, PF_INET6, IPPROTO_IPV6,
+		       IPV6CTL_RTADV_NUMROUTES, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 		       CTLTYPE_INT, "keepfaith",
 		       SYSCTL_DESCR("Activate faith interface"),
 		       NULL, 0, &ip6_keepfaith, 0,

Index: src/sys/netinet6/ip6_var.h
diff -u src/sys/netinet6/ip6_var.h:1.54 src/sys/netinet6/ip6_var.h:1.55
--- src/sys/netinet6/ip6_var.h:1.54	Tue May  3 17:44:30 2011
+++ src/sys/netinet6/ip6_var.h	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_var.h,v 1.54 2011/05/03 17:44:30 dyoung Exp $	*/
+/*	$NetBSD: ip6_var.h,v 1.55 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $	*/
 
 /*
@@ -281,6 +281,7 @@
 extern int	ip6_sourcecheck;	/* Verify source interface */
 extern int	ip6_sourcecheck_interval; /* Interval between log messages */
 extern int	ip6_accept_rtadv;	/* Acts as a host not a router */
+extern int	ip6_rtadv_maxroutes;	/* maximum number of routes via rtadv */
 extern int	ip6_keepfaith;		/* Firewall Aided Internet Translator */
 extern int	ip6_log_interval;
 extern time_t	ip6_log_time;

Index: src/sys/netinet6/nd6.h
diff -u src/sys/netinet6/nd6.h:1.53 src/sys/netinet6/nd6.h:1.54
--- src/sys/netinet6/nd6.h:1.53	Fri Nov  6 20:41:22 2009
+++ src/sys/netinet6/nd6.h	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.h,v 1.53 2009/11/06 20:41:22 dyoung Exp $	*/
+/*	$NetBSD: nd6.h,v 1.54 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $	*/
 
 /*
@@ -372,6 +372,7 @@
 extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */
 extern u_int32_t ip6_temp_valid_lifetime; /* seconds */
 extern int ip6_temp_regen_advance; /* seconds */
+extern int nd6_numroutes;
 
 union nd_opts {
 	struct nd_opt_hdr *nd_opt_array[8];

Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.80 src/sys/netinet6/nd6_rtr.c:1.81
--- src/sys/netinet6/nd6_rtr.c:1.80	Fri Nov  6 20:41:22 2009
+++ src/sys/netinet6/nd6_rtr.c	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_rtr.c,v 1.80 2009/11/06 20:41:22 dyoung Exp $	*/
+/*	$NetBSD: nd6_rtr.c,v 1.81 2011/05/24 18:07:11 spz Exp $	*/
 /*	$KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.80 2009/11/06 20:41:22 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.81 2011/05/24 18:07:11 spz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -95,6 +95,8 @@
 u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
 int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
 
+int nd6_numroutes = 0;
+
 /* RTPREF_MEDIUM has to be 0! */
 #define RTPREF_HIGH	1
 #define RTPREF_MEDIUM	0
@@ -104,7 +106,7 @@
 
 /*
  * Receive Router Solicitation Message - just for routers.
- * Router solicitation/advertisement is mostly managed by userland program
+ * Router solicitation/advertisement is mostly managed by a userland program
  * (rtadvd) so here we have no function like nd6_ra_output().
  *
  * Based on RFC 2461
@@ -206,8 +208,8 @@
 	struct nd_defrouter *dr;
 
 	/*
-	 * We only accept RAs only when
-	 * the system-wide variable allows the acceptance, and
+	 * We only accept RAs when
+	 * the system-wide variable allows the acceptance, and the
 	 * per-interface variable allows RAs on the receiving interface.
 	 */
 	if (!nd6_accepts_rtadv(ndi))
@@ -458,6 +460,7 @@
 	if (newrt) {
 		nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
 		newrt->rt_refcnt--;
+		nd6_numroutes++;
 	}
 	if (error == 0)
 		new->installed = 1;
@@ -561,6 +564,7 @@
 			 */
 			oldrt->rt_refcnt++;
 			rtfree(oldrt);
+			nd6_numroutes--;
 		}
 	}
 
@@ -778,6 +782,12 @@
 		return (NULL);
 	}
 
+	if (ip6_rtadv_maxroutes <= nd6_numroutes) {
+		ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
+		splx(s);
+		return (NULL);
+	}
+
 	n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
 	if (n == NULL) {
 		splx(s);
@@ -1045,6 +1055,11 @@
 		if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
 			goto end;
 
+		if (ip6_rtadv_maxroutes <= nd6_numroutes) {
+			ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
+			goto end;
+		}
+
 		error = nd6_prelist_add(new, dr, &newpr);
 		if (error != 0 || newpr == NULL) {
 			nd6log((LOG_NOTICE, "prelist_update: "
@@ -1603,8 +1618,10 @@
 	error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
 	    ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
 	if (error == 0) {
-		if (rt != NULL) /* this should be non NULL, though */
+		if (rt != NULL) { /* this should be non NULL, though */
 			nd6_rtmsg(RTM_ADD, rt);
+			nd6_numroutes++;
+		}
 		pr->ndpr_stateflags |= NDPRF_ONLINK;
 	} else {
 		nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
@@ -1647,8 +1664,10 @@
 		pr->ndpr_stateflags &= ~NDPRF_ONLINK;
 
 		/* report the route deletion to the routing socket. */
-		if (rt != NULL)
+		if (rt != NULL) {
 			nd6_rtmsg(RTM_DELETE, rt);
+			nd6_numroutes--;
+		}
 
 		/*
 		 * There might be the same prefix on another interface,

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.388 src/sys/sys/param.h:1.389
--- src/sys/sys/param.h:1.388	Tue Apr 26 11:32:39 2011
+++ src/sys/sys/param.h	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.388 2011/04/26 11:32:39 hannken Exp $	*/
+/*	$NetBSD: param.h,v 1.389 2011/05/24 18:07:11 spz Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -63,7 +63,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	599005100	/* NetBSD 5.99.51 */
+#define	__NetBSD_Version__	599005200	/* NetBSD 5.99.52 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Index: src/usr.bin/netstat/inet6.c
diff -u src/usr.bin/netstat/inet6.c:1.58 src/usr.bin/netstat/inet6.c:1.59
--- src/usr.bin/netstat/inet6.c:1.58	Wed May 11 22:21:59 2011
+++ src/usr.bin/netstat/inet6.c	Tue May 24 18:07:11 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: inet6.c,v 1.58 2011/05/11 22:21:59 dyoung Exp $	*/
+/*	$NetBSD: inet6.c,v 1.59 2011/05/24 18:07:11 spz Exp $	*/
 /*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
 
 /*
@@ -64,7 +64,7 @@
 #if 0
 static char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
 #else
-__RCSID("$NetBSD: inet6.c,v 1.58 2011/05/11 22:21:59 dyoung Exp $");
+__RCSID("$NetBSD: inet6.c,v 1.59 2011/05/24 18:07:11 spz Exp $");
 #endif
 #endif /* not lint */
 
@@ -1196,6 +1196,7 @@
 	p(ICMP6_STAT_BADNA, "\t%llu bad neighbor advertisement message%s\n");
 	p(ICMP6_STAT_BADRS, "\t%llu bad router solicitation message%s\n");
 	p(ICMP6_STAT_BADRA, "\t%llu bad router advertisement message%s\n");
+	p(ICMP6_STAT_DROPPED_RAROUTE, "\t%llu router advertisement route%s dropped\n");
 	p(ICMP6_STAT_BADREDIRECT, "\t%llu bad redirect message%s\n");
 	p(ICMP6_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
 #undef p

Reply via email to