Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

implemented "cached" routes management to prevent local/foreign DoS

(experimental, not tested)
  • Loading branch information...
commit 1701f910d8968152f68746d58b76e17771ed005a 1 parent 32897ca
authored March 29, 2002
57  openbsd/sys/net/route.c
@@ -110,7 +110,15 @@ extern struct ifnet encif;
110 110
 int	rttrash;		/* routes not in table but not freed */
111 111
 struct	sockaddr wildcard;	/* zero valued cookie for wildcard searches */
112 112
 
  113
+/* XXX do these values make any sense? */
  114
+static int rt_cache_hiwat = 4096;
  115
+static int rt_cache_lowat = 1024;
  116
+
  117
+static int rt_cachetimeout = 3600;	/* should be configurable */
  118
+static struct rttimer_queue *rt_cache_timeout_q = NULL;
  119
+
113 120
 static int okaytoclone __P((u_int, int));
  121
+static void rt_draincache __P((void));
114 122
 
115 123
 #ifdef IPSEC
116 124
 
@@ -142,6 +150,8 @@ route_init()
142 150
 	rn_art_init();	/* initialize all zeroes, all ones, mask table */
143 151
 #endif
144 152
 	rtable_init((void **)rt_tables);
  153
+
  154
+	rt_cache_timeout_q = rt_timer_queue_create(rt_cachetimeout);
145 155
 }
146 156
 
147 157
 void
@@ -183,8 +193,8 @@ rtalloc2(dst, report,howstrict)
183 193
 		newrt = rt = (struct rtentry *)rn;
184 194
 		if (report && (rt->rt_flags & RTF_CLONING) &&
185 195
 		    okaytoclone(rt->rt_flags, howstrict)) {
186  
-			err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0,
187  
-			    &newrt);
  196
+			err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0),
  197
+			    RTF_CACHE, &newrt);
188 198
 			if (err) {
189 199
 				newrt = rt;
190 200
 				rt->rt_refcnt++;
@@ -237,7 +247,7 @@ rtalloc1(dst, report)
237 247
 		newrt = rt = (struct rtentry *)rn;
238 248
 		if (report && (rt->rt_flags & RTF_CLONING)) {
239 249
 			err = rtrequest(RTM_RESOLVE, dst, SA(NULL),
240  
-			    SA(NULL), 0, &newrt);
  250
+			    SA(NULL), RTF_CACHE, &newrt);
241 251
 			if (err) {
242 252
 				newrt = rt;
243 253
 				rt->rt_refcnt++;
@@ -569,6 +579,7 @@ rtrequest1(req, info, ret_nrt)
569 579
 	struct rtentry **ret_nrt;
570 580
 {
571 581
 	int s = splsoftnet(); int error = 0;
  582
+	int cache = 0;
572 583
 	register struct rtentry *rt;
573 584
 	register struct radix_node *rn;
574 585
 	register struct radix_node_head *rnh;
@@ -580,6 +591,8 @@ rtrequest1(req, info, ret_nrt)
580 591
 		senderr(EAFNOSUPPORT);
581 592
 	if (flags & RTF_HOST)
582 593
 		netmask = 0;
  594
+	if (flags & RTF_CACHE)
  595
+		cache = 1;
583 596
 	switch (req) {
584 597
 	case RTM_DELETE:
585 598
 		if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL)
@@ -618,6 +631,18 @@ rtrequest1(req, info, ret_nrt)
618 631
 			senderr(error);
619 632
 		ifa = info->rti_ifa;
620 633
 	makeroute:
  634
+		if (cache) {
  635
+			unsigned long rtcount;
  636
+
  637
+			rtcount = rt_timer_count(rt_cache_timeout_q);
  638
+			if (0 <= rt_cache_hiwat && rtcount > rt_cache_hiwat) {
  639
+				senderr(ENOBUFS);
  640
+			} else if (0 <= rt_cache_lowat &&
  641
+				   rtcount > rt_cache_lowat) {
  642
+				/* remove stale routes */
  643
+				rt_draincache();
  644
+			}
  645
+		}
621 646
 		R_Malloc(rt, struct rtentry *, sizeof(*rt));
622 647
 		if (rt == NULL)
623 648
 			senderr(ENOBUFS);
@@ -667,6 +692,9 @@ rtrequest1(req, info, ret_nrt)
667 692
 			*ret_nrt = rt;
668 693
 			rt->rt_refcnt++;
669 694
 		}
  695
+
  696
+		if (cache)
  697
+			rt_timer_add(rt, NULL, rt_cache_timeout_q);
670 698
 		break;
671 699
 	}
672 700
 bad:
@@ -1055,3 +1083,26 @@ rt_timer_timer(arg)
1055 1083
 
1056 1084
 	timeout_add(to, hz);		/* every second */
1057 1085
 }
  1086
+
  1087
+static void
  1088
+rt_draincache()
  1089
+{
  1090
+	int s;
  1091
+	struct rttimer *r, *r_next;
  1092
+
  1093
+	s = splsoftnet();
  1094
+
  1095
+	for (r = TAILQ_FIRST(&rt_cache_timeout_q->rtq_head); r; r = r_next) {
  1096
+		r_next = TAILQ_NEXT(r, rtt_next);
  1097
+
  1098
+		if (r->rtt_rt->rt_refcnt == 0) {
  1099
+			/*
  1100
+			 * we expect RTTIMER_CALLOUT calls rtrequest(DELETE),
  1101
+			 * which will remove the associated route and unlink
  1102
+			 * the timer entry.
  1103
+			 */
  1104
+			RTTIMER_CALLOUT(r);
  1105
+		}
  1106
+	}
  1107
+	splx(s);
  1108
+}
2  openbsd/sys/net/route.h
@@ -158,6 +158,8 @@ struct ortentry {
158 158
 #define RTF_PROTO2	0x4000		/* protocol specific routing flag */
159 159
 #define RTF_PROTO1	0x8000		/* protocol specific routing flag */
160 160
 
  161
+#define RTF_CACHE	0x10000		/* cached route in general */
  162
+
161 163
 #ifndef _KERNEL
162 164
 /* obsoleted */
163 165
 #define	RTF_TUNNEL	0x100000	/* Tunnelling bit. */

0 notes on commit 1701f91

Please sign in to comment.
Something went wrong with that request. Please try again.