Merge branch 'vendor/GREP'
[dragonfly.git] / sys / netinet6 / in6_rmx.c
1 /*      $FreeBSD: src/sys/netinet6/in6_rmx.c,v 1.1.2.4 2004/10/06 02:35:17 suz Exp $    */
2 /*      $DragonFly: src/sys/netinet6/in6_rmx.c,v 1.15 2006/12/22 23:57:53 swildner Exp $        */
3 /*      $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $        */
4
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * Copyright 1994, 1995 Massachusetts Institute of Technology
36  *
37  * Permission to use, copy, modify, and distribute this software and
38  * its documentation for any purpose and without fee is hereby
39  * granted, provided that both the above copyright notice and this
40  * permission notice appear in all copies, that both the above
41  * copyright notice and this permission notice appear in all
42  * supporting documentation, and that the name of M.I.T. not be used
43  * in advertising or publicity pertaining to distribution of the
44  * software without specific, written prior permission.  M.I.T. makes
45  * no representations about the suitability of this software for any
46  * purpose.  It is provided "as is" without express or implied
47  * warranty.
48  *
49  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
50  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
51  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
52  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
53  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
56  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
59  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60  * SUCH DAMAGE.
61  *
62  */
63
64 /*
65  * This code does two things necessary for the enhanced TCP metrics to
66  * function in a useful manner:
67  *  1) It marks all non-host routes as `cloning', thus ensuring that
68  *     every actual reference to such a route actually gets turned
69  *     into a reference to a host route to the specific destination
70  *     requested.
71  *  2) When such routes lose all their references, it arranges for them
72  *     to be deleted in some random collection of circumstances, so that
73  *     a large quantity of stale routing data is not kept in kernel memory
74  *     indefinitely.  See in6_rtqtimo() below for the exact mechanism.
75  */
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/kernel.h>
80 #include <sys/sysctl.h>
81 #include <sys/queue.h>
82 #include <sys/socket.h>
83 #include <sys/socketvar.h>
84 #include <sys/mbuf.h>
85 #include <sys/syslog.h>
86 #include <sys/globaldata.h>
87 #include <sys/thread2.h>
88
89 #include <net/if.h>
90 #include <net/route.h>
91 #include <net/netisr2.h>
92 #include <net/netmsg2.h>
93 #include <netinet/in.h>
94 #include <netinet/ip_var.h>
95 #include <netinet/in_var.h>
96
97 #include <netinet/ip6.h>
98 #include <netinet6/ip6_var.h>
99
100 #include <netinet/icmp6.h>
101 #include <netinet6/nd6.h>
102
103 #include <netinet/tcp.h>
104 #include <netinet/tcp_seq.h>
105 #include <netinet/tcp_timer.h>
106 #include <netinet/tcp_var.h>
107
108 struct in6_rttimo_ctx {
109         struct callout          timo_ch;
110         struct netmsg_base      timo_nmsg;
111         struct radix_node_head  *timo_rnh;
112 } __cachealign;
113
114 static struct in6_rttimo_ctx    in6_rtqtimo_ctx[MAXCPU];
115 static struct in6_rttimo_ctx    in6_mtutimo_ctx[MAXCPU];
116
117 extern int      in6_inithead (void **head, int off);
118
119 #define RTPRF_OURS              RTF_PROTO3      /* set on routes we manage */
120
121 /*
122  * Do what we need to do when inserting a route.
123  */
124 static struct radix_node *
125 in6_addroute(char *key, char *mask, struct radix_node_head *head,
126              struct radix_node *treenodes)
127 {
128         struct rtentry *rt = (struct rtentry *)treenodes;
129         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
130         struct radix_node *ret;
131
132         /*
133          * For IPv6, all unicast non-host routes are automatically cloning.
134          */
135         if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
136                 rt->rt_flags |= RTF_MULTICAST;
137
138         if (!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
139                 rt->rt_flags |= RTF_PRCLONING;
140         }
141
142         /*
143          * A little bit of help for both IPv6 output and input:
144          *   For local addresses, we make sure that RTF_LOCAL is set,
145          *   with the thought that this might one day be used to speed up
146          *   ip_input().
147          *
148          * We also mark routes to multicast addresses as such, because
149          * it's easy to do and might be useful (but this is much more
150          * dubious since it's so easy to inspect the address).  (This
151          * is done above.)
152          *
153          * XXX
154          * should elaborate the code.
155          */
156         if (rt->rt_flags & RTF_HOST) {
157                 if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr)
158                                         ->sin6_addr,
159                                        &sin6->sin6_addr)) {
160                         rt->rt_flags |= RTF_LOCAL;
161                 }
162         }
163
164         if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) &&
165             rt->rt_ifp != NULL)
166                 rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);
167
168         ret = rn_addroute(key, mask, head, treenodes);
169         if (ret == NULL && rt->rt_flags & RTF_HOST) {
170                 struct rtentry *rt2;
171
172                 /*
173                  * We are trying to add a host route, but can't.
174                  * Find out if it is because of an
175                  * ARP entry and delete it if so.
176                  */
177                 rt2 = rtpurelookup((struct sockaddr *)sin6);
178                 if (rt2 != NULL) {
179                         --rt2->rt_refcnt;
180                         if (rt2->rt_flags & RTF_LLINFO &&
181                             rt2->rt_flags & RTF_HOST &&
182                             rt2->rt_gateway &&
183                             rt2->rt_gateway->sa_family == AF_LINK) {
184                                 rtrequest(RTM_DELETE, rt_key(rt2),
185                                           rt2->rt_gateway, rt_mask(rt2),
186                                           rt2->rt_flags, NULL);
187                                 ret = rn_addroute(key, mask, head, treenodes);
188                         }
189                 }
190         } else if (ret == NULL && rt->rt_flags & RTF_CLONING) {
191                 struct rtentry *rt2;
192
193                 /*
194                  * We are trying to add a net route, but can't.
195                  * The following case should be allowed, so we'll make a
196                  * special check for this:
197                  *      Two IPv6 addresses with the same prefix is assigned
198                  *      to a single interrface.
199                  *      # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1)
200                  *      # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2)
201                  *      In this case, (*1) and (*2) want to add the same
202                  *      net route entry, 3ffe:0501:: -> if0.
203                  *      This case should not raise an error.
204                  */
205                 rt2 = rtpurelookup((struct sockaddr *)sin6);
206                 if (rt2 != NULL) {
207                         if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY))
208                                         == RTF_CLONING &&
209                             rt2->rt_gateway &&
210                             rt2->rt_gateway->sa_family == AF_LINK &&
211                             rt2->rt_ifp == rt->rt_ifp) {
212                                 ret = rt2->rt_nodes;
213                         }
214                         --rt2->rt_refcnt;
215                 }
216         }
217         return ret;
218 }
219
220 /*
221  * This code is the inverse of in6_clsroute: on first reference, if we
222  * were managing the route, stop doing so and set the expiration timer
223  * back off again.
224  */
225 static struct radix_node *
226 in6_matchroute(char *key, struct radix_node_head *head)
227 {
228         struct radix_node *rn = rn_match(key, head);
229         struct rtentry *rt = (struct rtentry *)rn;
230
231         if (rt != NULL && rt->rt_refcnt == 0) { /* this is first reference */
232                 if (rt->rt_flags & RTPRF_OURS) {
233                         rt->rt_flags &= ~RTPRF_OURS;
234                         rt->rt_rmx.rmx_expire = 0;
235                 }
236         }
237         return rn;
238 }
239
240 SYSCTL_DECL(_net_inet6_ip6);
241
242 static int rtq_reallyold = 60*60;
243         /* one hour is ``really old'' */
244 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire,
245     CTLFLAG_RW, &rtq_reallyold , 0, "Default expiration time on cloned routes");
246
247 static int rtq_minreallyold = 10;
248         /* never automatically crank down to less */
249 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
250     &rtq_minreallyold , 0, "Minimum time to attempt to hold onto cloned routes");
251
252 static int rtq_toomany = 128;
253         /* 128 cached routes is ``too many'' */
254 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache,
255     CTLFLAG_RW, &rtq_toomany , 0, "Upper limit on cloned routes");
256
257
258 /*
259  * On last reference drop, mark the route as belong to us so that it can be
260  * timed out.
261  */
262 static void
263 in6_clsroute(struct radix_node *rn, struct radix_node_head *head)
264 {
265         struct rtentry *rt = (struct rtentry *)rn;
266
267         if (!(rt->rt_flags & RTF_UP))
268                 return;         /* prophylactic measures */
269
270         if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
271                 return;
272
273         if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS)) != RTF_WASCLONED)
274                 return;
275
276         /*
277          * As requested by David Greenman:
278          * If rtq_reallyold is 0, just delete the route without
279          * waiting for a timeout cycle to kill it.
280          */
281         if (rtq_reallyold != 0) {
282                 rt->rt_flags |= RTPRF_OURS;
283                 rt->rt_rmx.rmx_expire = time_uptime + rtq_reallyold;
284         } else {
285                 /*
286                  * Remove route from the radix tree, but defer deallocation
287                  * until we return to rtfree().
288                  */
289                 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
290                           rt->rt_flags, &rt);
291         }
292 }
293
294 struct rtqk_arg {
295         struct radix_node_head *rnh;
296         int mode;
297         int updating;
298         int draining;
299         int killed;
300         int found;
301         time_t nextstop;
302 };
303
304 /*
305  * Get rid of old routes.  When draining, this deletes everything, even when
306  * the timeout is not expired yet.  When updating, this makes sure that
307  * nothing has a timeout longer than the current value of rtq_reallyold.
308  */
309 static int
310 in6_rtqkill(struct radix_node *rn, void *rock)
311 {
312         struct rtqk_arg *ap = rock;
313         struct rtentry *rt = (struct rtentry *)rn;
314         int err;
315
316         if (rt->rt_flags & RTPRF_OURS) {
317                 ap->found++;
318
319                 if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) {
320                         if (rt->rt_refcnt > 0)
321                                 panic("rtqkill route really not free");
322
323                         err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
324                                         rt_mask(rt), rt->rt_flags, NULL);
325                         if (err)
326                                 log(LOG_WARNING, "in6_rtqkill: error %d", err);
327                         else
328                                 ap->killed++;
329                 } else {
330                         if (ap->updating &&
331                             (rt->rt_rmx.rmx_expire - time_uptime >
332                              rtq_reallyold)) {
333                                 rt->rt_rmx.rmx_expire =
334                                     time_uptime + rtq_reallyold;
335                         }
336                         ap->nextstop = lmin(ap->nextstop,
337                                             rt->rt_rmx.rmx_expire);
338                 }
339         }
340
341         return 0;
342 }
343
344 #define RTQ_TIMEOUT     60*10   /* run no less than once every ten minutes */
345 static int rtq_timeout = RTQ_TIMEOUT;
346
347 static void
348 in6_rtqtimo(void *arg __unused)
349 {
350         int cpuid = mycpuid;
351         struct lwkt_msg *lmsg = &in6_rtqtimo_ctx[cpuid].timo_nmsg.lmsg;
352
353         crit_enter();
354         if (lmsg->ms_flags & MSGF_DONE)
355                 lwkt_sendmsg_oncpu(netisr_cpuport(cpuid), lmsg);
356         crit_exit();
357 }
358
359 static void
360 in6_rtqtimo_dispatch(netmsg_t nmsg)
361 {
362         struct in6_rttimo_ctx *ctx = &in6_rtqtimo_ctx[mycpuid];
363         struct radix_node_head *rnh = ctx->timo_rnh;
364         struct rtqk_arg arg;
365         struct timeval atv;
366         static time_t last_adjusted_timeout = 0;
367
368         /* Reply ASAP */
369         crit_enter();
370         lwkt_replymsg(&nmsg->lmsg, 0);
371         crit_exit();
372
373         arg.found = arg.killed = 0;
374         arg.rnh = rnh;
375         arg.nextstop = time_uptime + rtq_timeout;
376         arg.draining = arg.updating = 0;
377         rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
378
379         /*
380          * Attempt to be somewhat dynamic about this:
381          * If there are ``too many'' routes sitting around taking up space,
382          * then crank down the timeout, and see if we can't make some more
383          * go away.  However, we make sure that we will never adjust more
384          * than once in rtq_timeout seconds, to keep from cranking down too
385          * hard.
386          */
387         if ((arg.found - arg.killed > rtq_toomany)
388            && (int)(time_uptime - last_adjusted_timeout) >= rtq_timeout
389            && rtq_reallyold > rtq_minreallyold) {
390                 rtq_reallyold = 2*rtq_reallyold / 3;
391                 if (rtq_reallyold < rtq_minreallyold) {
392                         rtq_reallyold = rtq_minreallyold;
393                 }
394
395                 last_adjusted_timeout = time_uptime;
396 #ifdef DIAGNOSTIC
397                 log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold to %d",
398                     rtq_reallyold);
399 #endif
400                 arg.found = arg.killed = 0;
401                 arg.updating = 1;
402                 rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
403         }
404
405         atv.tv_usec = 0;
406         atv.tv_sec = arg.nextstop - time_uptime;
407         if ((int)atv.tv_sec < 1) {              /* time shift safety */
408                 atv.tv_sec = 1;
409                 arg.nextstop = time_uptime + atv.tv_sec;
410         }
411         if ((int)atv.tv_sec > rtq_timeout) {    /* time shift safety */
412                 atv.tv_sec = rtq_timeout;
413                 arg.nextstop = time_uptime + atv.tv_sec;
414         }
415         callout_reset(&ctx->timo_ch, tvtohz_high(&atv), in6_rtqtimo, NULL);
416 }
417
418 /*
419  * Age old PMTUs.
420  */
421 struct mtuex_arg {
422         struct radix_node_head *rnh;
423         time_t nextstop;
424 };
425
426 static int
427 in6_mtuexpire(struct radix_node *rn, void *rock)
428 {
429         struct rtentry *rt = (struct rtentry *)rn;
430         struct mtuex_arg *ap = rock;
431
432         /* sanity */
433         if (!rt)
434                 panic("rt == NULL in in6_mtuexpire");
435
436         if (rt->rt_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) {
437                 if (rt->rt_rmx.rmx_expire <= time_uptime) {
438                         rt->rt_flags |= RTF_PROBEMTU;
439                 } else {
440                         ap->nextstop = lmin(ap->nextstop,
441                                         rt->rt_rmx.rmx_expire);
442                 }
443         }
444
445         return 0;
446 }
447
448 #define MTUTIMO_DEFAULT (60*1)
449
450 static void
451 in6_mtutimo(void *arg __unused)
452 {
453         int cpuid = mycpuid;
454         struct lwkt_msg *lmsg = &in6_mtutimo_ctx[cpuid].timo_nmsg.lmsg;
455
456         crit_enter();
457         if (lmsg->ms_flags & MSGF_DONE)
458                 lwkt_sendmsg_oncpu(netisr_cpuport(cpuid), lmsg);
459         crit_exit();
460 }
461
462 static void
463 in6_mtutimo_dispatch(netmsg_t nmsg)
464 {
465         struct in6_rttimo_ctx *ctx = &in6_mtutimo_ctx[mycpuid];
466         struct radix_node_head *rnh = ctx->timo_rnh;
467         struct mtuex_arg arg;
468         struct timeval atv;
469
470         /* Reply ASAP */
471         crit_enter();
472         lwkt_replymsg(&nmsg->lmsg, 0);
473         crit_exit();
474
475         arg.rnh = rnh;
476         arg.nextstop = time_uptime + MTUTIMO_DEFAULT;
477         rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
478
479         atv.tv_usec = 0;
480         atv.tv_sec = arg.nextstop - time_uptime;
481         if ((int)atv.tv_sec < 1) {              /* time shift safety */
482                 atv.tv_sec = 1;
483                 arg.nextstop = time_uptime + atv.tv_sec;
484         }
485         if ((int)atv.tv_sec > rtq_timeout) {    /* time shift safety */
486                 atv.tv_sec = rtq_timeout;
487                 arg.nextstop = time_uptime + atv.tv_sec;
488         }
489         callout_reset(&ctx->timo_ch, tvtohz_high(&atv), in6_mtutimo, NULL);
490 }
491
492 #if 0
493 void
494 in6_rtqdrain(void)
495 {
496         struct radix_node_head *rnh = rt_tables[mycpuid][AF_INET6];
497         struct rtqk_arg arg;
498
499         arg.found = arg.killed = 0;
500         arg.rnh = rnh;
501         arg.nextstop = 0;
502         arg.draining = 1;
503         arg.updating = 0;
504         crit_enter();
505         rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
506         crit_exit();
507 }
508 #endif
509
510 /*
511  * Initialize our routing tree.
512  */
513 int
514 in6_inithead(void **head, int off)
515 {
516         struct radix_node_head *rnh;
517         struct in6_rttimo_ctx *ctx;
518         int cpuid = mycpuid;
519
520         KKASSERT(head == (void **)&rt_tables[cpuid][AF_INET6]);
521
522         if (!rn_inithead(head, rn_cpumaskhead(cpuid), off))
523                 return 0;
524
525         rnh = *head;
526         rnh->rnh_addaddr = in6_addroute;
527         rnh->rnh_matchaddr = in6_matchroute;
528         rnh->rnh_close = in6_clsroute;
529
530         ctx = &in6_rtqtimo_ctx[cpuid];
531         ctx->timo_rnh = rnh;
532         callout_init_mp(&ctx->timo_ch);
533         netmsg_init(&ctx->timo_nmsg, NULL, &netisr_adone_rport, MSGF_PRIORITY,
534             in6_rtqtimo_dispatch);
535
536         ctx = &in6_mtutimo_ctx[cpuid];
537         ctx->timo_rnh = rnh;
538         callout_init_mp(&ctx->timo_ch);
539         netmsg_init(&ctx->timo_nmsg, NULL, &netisr_adone_rport, MSGF_PRIORITY,
540             in6_mtutimo_dispatch);
541
542         in6_rtqtimo(NULL);      /* kick off timeout first time */
543         in6_mtutimo(NULL);      /* kick off timeout first time */
544
545         return 1;
546 }