route.c revision 1.160 1 /* $NetBSD: route.c,v 1.160 2016/04/07 04:04:47 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Kevin M. Lahey of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the project nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62 /*
63 * Copyright (c) 1980, 1986, 1991, 1993
64 * The Regents of the University of California. All rights reserved.
65 *
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
68 * are met:
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 * 3. Neither the name of the University nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 *
90 * @(#)route.c 8.3 (Berkeley) 1/9/95
91 */
92
93 #ifdef _KERNEL_OPT
94 #include "opt_inet.h"
95 #include "opt_route.h"
96 #endif
97
98 #include <sys/cdefs.h>
99 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.160 2016/04/07 04:04:47 christos Exp $");
100
101 #include <sys/param.h>
102 #ifdef RTFLUSH_DEBUG
103 #include <sys/sysctl.h>
104 #endif
105 #include <sys/systm.h>
106 #include <sys/callout.h>
107 #include <sys/proc.h>
108 #include <sys/mbuf.h>
109 #include <sys/socket.h>
110 #include <sys/socketvar.h>
111 #include <sys/domain.h>
112 #include <sys/protosw.h>
113 #include <sys/kernel.h>
114 #include <sys/ioctl.h>
115 #include <sys/pool.h>
116 #include <sys/kauth.h>
117
118 #include <net/if.h>
119 #include <net/if_dl.h>
120 #include <net/route.h>
121
122 #include <netinet/in.h>
123 #include <netinet/in_var.h>
124
125 #ifdef RTFLUSH_DEBUG
126 #define rtcache_debug() __predict_false(_rtcache_debug)
127 #else /* RTFLUSH_DEBUG */
128 #define rtcache_debug() 0
129 #endif /* RTFLUSH_DEBUG */
130
131 struct rtstat rtstat;
132
133 static int rttrash; /* routes not in table but not freed */
134
135 static struct pool rtentry_pool;
136 static struct pool rttimer_pool;
137
138 static struct callout rt_timer_ch; /* callout for rt_timer_timer() */
139
140 #ifdef RTFLUSH_DEBUG
141 static int _rtcache_debug = 0;
142 #endif /* RTFLUSH_DEBUG */
143
144 static kauth_listener_t route_listener;
145
146 static int rtdeletemsg(struct rtentry *);
147 static void rtflushall(int);
148
149 static void rt_maskedcopy(const struct sockaddr *,
150 struct sockaddr *, const struct sockaddr *);
151
152 static void rtcache_clear(struct route *);
153 static void rtcache_invalidate(struct dom_rtlist *);
154
155 #ifdef RTFLUSH_DEBUG
156 static void sysctl_net_rtcache_setup(struct sysctllog **);
157 static void
158 sysctl_net_rtcache_setup(struct sysctllog **clog)
159 {
160 const struct sysctlnode *rnode;
161
162 if (sysctl_createv(clog, 0, NULL, &rnode, CTLFLAG_PERMANENT,
163 CTLTYPE_NODE,
164 "rtcache", SYSCTL_DESCR("Route cache related settings"),
165 NULL, 0, NULL, 0, CTL_NET, CTL_CREATE, CTL_EOL) != 0)
166 return;
167 if (sysctl_createv(clog, 0, &rnode, &rnode,
168 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
169 "debug", SYSCTL_DESCR("Debug route caches"),
170 NULL, 0, &_rtcache_debug, 0, CTL_CREATE, CTL_EOL) != 0)
171 return;
172 }
173 #endif /* RTFLUSH_DEBUG */
174
175 static inline void
176 rt_destroy(struct rtentry *rt)
177 {
178 if (rt->_rt_key != NULL)
179 sockaddr_free(rt->_rt_key);
180 if (rt->rt_gateway != NULL)
181 sockaddr_free(rt->rt_gateway);
182 if (rt_gettag(rt) != NULL)
183 sockaddr_free(rt_gettag(rt));
184 rt->_rt_key = rt->rt_gateway = rt->rt_tag = NULL;
185 }
186
187 static inline const struct sockaddr *
188 rt_setkey(struct rtentry *rt, const struct sockaddr *key, int flags)
189 {
190 if (rt->_rt_key == key)
191 goto out;
192
193 if (rt->_rt_key != NULL)
194 sockaddr_free(rt->_rt_key);
195 rt->_rt_key = sockaddr_dup(key, flags);
196 out:
197 rt->rt_nodes->rn_key = (const char *)rt->_rt_key;
198 return rt->_rt_key;
199 }
200
201 struct ifaddr *
202 rt_get_ifa(struct rtentry *rt)
203 {
204 struct ifaddr *ifa;
205
206 if ((ifa = rt->rt_ifa) == NULL)
207 return ifa;
208 else if (ifa->ifa_getifa == NULL)
209 return ifa;
210 #if 0
211 else if (ifa->ifa_seqno != NULL && *ifa->ifa_seqno == rt->rt_ifa_seqno)
212 return ifa;
213 #endif
214 else {
215 ifa = (*ifa->ifa_getifa)(ifa, rt_getkey(rt));
216 if (ifa == NULL)
217 return NULL;
218 rt_replace_ifa(rt, ifa);
219 return ifa;
220 }
221 }
222
223 static void
224 rt_set_ifa1(struct rtentry *rt, struct ifaddr *ifa)
225 {
226 rt->rt_ifa = ifa;
227 if (ifa->ifa_seqno != NULL)
228 rt->rt_ifa_seqno = *ifa->ifa_seqno;
229 }
230
231 /*
232 * Is this route the connected route for the ifa?
233 */
234 static int
235 rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa)
236 {
237 const struct sockaddr *key, *dst, *odst;
238 struct sockaddr_storage maskeddst;
239
240 key = rt_getkey(rt);
241 dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
242 if (dst == NULL ||
243 dst->sa_family != key->sa_family ||
244 dst->sa_len != key->sa_len)
245 return 0;
246 if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
247 odst = dst;
248 dst = (struct sockaddr *)&maskeddst;
249 rt_maskedcopy(odst, (struct sockaddr *)&maskeddst,
250 ifa->ifa_netmask);
251 }
252 return (memcmp(dst, key, dst->sa_len) == 0);
253 }
254
255 void
256 rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa)
257 {
258 if (rt->rt_ifa &&
259 rt->rt_ifa != ifa &&
260 rt->rt_ifa->ifa_flags & IFA_ROUTE &&
261 rt_ifa_connected(rt, rt->rt_ifa))
262 {
263 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
264 "replace deleted IFA_ROUTE\n",
265 (void *)rt->_rt_key, (void *)rt->rt_ifa);
266 rt->rt_ifa->ifa_flags &= ~IFA_ROUTE;
267 if (rt_ifa_connected(rt, ifa)) {
268 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
269 "replace added IFA_ROUTE\n",
270 (void *)rt->_rt_key, (void *)ifa);
271 ifa->ifa_flags |= IFA_ROUTE;
272 }
273 }
274
275 ifaref(ifa);
276 ifafree(rt->rt_ifa);
277 rt_set_ifa1(rt, ifa);
278 }
279
280 static void
281 rt_set_ifa(struct rtentry *rt, struct ifaddr *ifa)
282 {
283 ifaref(ifa);
284 rt_set_ifa1(rt, ifa);
285 }
286
287 static int
288 route_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
289 void *arg0, void *arg1, void *arg2, void *arg3)
290 {
291 struct rt_msghdr *rtm;
292 int result;
293
294 result = KAUTH_RESULT_DEFER;
295 rtm = arg1;
296
297 if (action != KAUTH_NETWORK_ROUTE)
298 return result;
299
300 if (rtm->rtm_type == RTM_GET)
301 result = KAUTH_RESULT_ALLOW;
302
303 return result;
304 }
305
306 void
307 rt_init(void)
308 {
309
310 #ifdef RTFLUSH_DEBUG
311 sysctl_net_rtcache_setup(NULL);
312 #endif
313
314 pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl",
315 NULL, IPL_SOFTNET);
316 pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl",
317 NULL, IPL_SOFTNET);
318
319 rn_init(); /* initialize all zeroes, all ones, mask table */
320 rtbl_init();
321
322 route_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
323 route_listener_cb, NULL);
324 }
325
326 static void
327 rtflushall(int family)
328 {
329 struct domain *dom;
330
331 if (rtcache_debug())
332 printf("%s: enter\n", __func__);
333
334 if ((dom = pffinddomain(family)) == NULL)
335 return;
336
337 rtcache_invalidate(&dom->dom_rtcache);
338 }
339
340 static void
341 rtcache(struct route *ro)
342 {
343 struct domain *dom;
344
345 rtcache_invariants(ro);
346 KASSERT(ro->_ro_rt != NULL);
347 KASSERT(ro->ro_invalid == false);
348 KASSERT(rtcache_getdst(ro) != NULL);
349
350 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) == NULL)
351 return;
352
353 LIST_INSERT_HEAD(&dom->dom_rtcache, ro, ro_rtcache_next);
354 rtcache_invariants(ro);
355 }
356
357 #ifdef RT_DEBUG
358 static void
359 dump_rt(const struct rtentry *rt)
360 {
361 char buf[512];
362
363 aprint_normal("rt: ");
364 aprint_normal("p=%p ", rt);
365 if (rt->_rt_key == NULL) {
366 aprint_normal("dst=(NULL) ");
367 } else {
368 sockaddr_format(rt->_rt_key, buf, sizeof(buf));
369 aprint_normal("dst=%s ", buf);
370 }
371 if (rt->rt_gateway == NULL) {
372 aprint_normal("gw=(NULL) ");
373 } else {
374 sockaddr_format(rt->_rt_key, buf, sizeof(buf));
375 aprint_normal("gw=%s ", buf);
376 }
377 aprint_normal("flags=%x ", rt->rt_flags);
378 if (rt->rt_ifp == NULL) {
379 aprint_normal("if=(NULL) ");
380 } else {
381 aprint_normal("if=%s ", rt->rt_ifp->if_xname);
382 }
383 aprint_normal("\n");
384 }
385 #endif /* RT_DEBUG */
386
387 /*
388 * Packet routing routines. If success, refcnt of a returned rtentry
389 * will be incremented. The caller has to rtfree it by itself.
390 */
391 struct rtentry *
392 rtalloc1(const struct sockaddr *dst, int report)
393 {
394 rtbl_t *rtbl;
395 struct rtentry *rt;
396 int s;
397
398 s = splsoftnet();
399 rtbl = rt_gettable(dst->sa_family);
400 if (rtbl == NULL)
401 goto miss;
402
403 rt = rt_matchaddr(rtbl, dst);
404 if (rt == NULL)
405 goto miss;
406
407 rt->rt_refcnt++;
408
409 splx(s);
410 return rt;
411 miss:
412 rtstat.rts_unreach++;
413 if (report) {
414 struct rt_addrinfo info;
415
416 memset(&info, 0, sizeof(info));
417 info.rti_info[RTAX_DST] = dst;
418 rt_missmsg(RTM_MISS, &info, 0, 0);
419 }
420 splx(s);
421 return NULL;
422 }
423
424 #ifdef DEBUG
425 /*
426 * Check the following constraint for each rtcache:
427 * if a rtcache holds a rtentry, the rtentry's refcnt is more than zero,
428 * i.e., the rtentry should be referenced at least by the rtcache.
429 */
430 static void
431 rtcache_check_rtrefcnt(int family)
432 {
433 struct domain *dom = pffinddomain(family);
434 struct route *ro;
435
436 if (dom == NULL)
437 return;
438
439 LIST_FOREACH(ro, &dom->dom_rtcache, ro_rtcache_next)
440 KDASSERT(ro->_ro_rt == NULL || ro->_ro_rt->rt_refcnt > 0);
441 }
442 #endif
443
444 void
445 rtfree(struct rtentry *rt)
446 {
447 struct ifaddr *ifa;
448
449 KASSERT(rt != NULL);
450 KASSERT(rt->rt_refcnt > 0);
451
452 rt->rt_refcnt--;
453 #ifdef DEBUG
454 if (rt_getkey(rt) != NULL)
455 rtcache_check_rtrefcnt(rt_getkey(rt)->sa_family);
456 #endif
457 if (rt->rt_refcnt == 0 && (rt->rt_flags & RTF_UP) == 0) {
458 rt_assert_inactive(rt);
459 rttrash--;
460 rt_timer_remove_all(rt, 0);
461 ifa = rt->rt_ifa;
462 rt->rt_ifa = NULL;
463 ifafree(ifa);
464 rt->rt_ifp = NULL;
465 rt_destroy(rt);
466 pool_put(&rtentry_pool, rt);
467 }
468 }
469
470 /*
471 * Force a routing table entry to the specified
472 * destination to go through the given gateway.
473 * Normally called as a result of a routing redirect
474 * message from the network layer.
475 *
476 * N.B.: must be called at splsoftnet
477 */
478 void
479 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway,
480 const struct sockaddr *netmask, int flags, const struct sockaddr *src,
481 struct rtentry **rtp)
482 {
483 struct rtentry *rt;
484 int error = 0;
485 uint64_t *stat = NULL;
486 struct rt_addrinfo info;
487 struct ifaddr *ifa;
488
489 /* verify the gateway is directly reachable */
490 if ((ifa = ifa_ifwithnet(gateway)) == NULL) {
491 error = ENETUNREACH;
492 goto out;
493 }
494 rt = rtalloc1(dst, 0);
495 /*
496 * If the redirect isn't from our current router for this dst,
497 * it's either old or wrong. If it redirects us to ourselves,
498 * we have a routing loop, perhaps as a result of an interface
499 * going down recently.
500 */
501 if (!(flags & RTF_DONE) && rt &&
502 (sockaddr_cmp(src, rt->rt_gateway) != 0 || rt->rt_ifa != ifa))
503 error = EINVAL;
504 else if (ifa_ifwithaddr(gateway))
505 error = EHOSTUNREACH;
506 if (error)
507 goto done;
508 /*
509 * Create a new entry if we just got back a wildcard entry
510 * or the lookup failed. This is necessary for hosts
511 * which use routing redirects generated by smart gateways
512 * to dynamically build the routing tables.
513 */
514 if (rt == NULL || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
515 goto create;
516 /*
517 * Don't listen to the redirect if it's
518 * for a route to an interface.
519 */
520 if (rt->rt_flags & RTF_GATEWAY) {
521 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
522 /*
523 * Changing from route to net => route to host.
524 * Create new route, rather than smashing route to net.
525 */
526 create:
527 if (rt != NULL)
528 rtfree(rt);
529 flags |= RTF_GATEWAY | RTF_DYNAMIC;
530 memset(&info, 0, sizeof(info));
531 info.rti_info[RTAX_DST] = dst;
532 info.rti_info[RTAX_GATEWAY] = gateway;
533 info.rti_info[RTAX_NETMASK] = netmask;
534 info.rti_ifa = ifa;
535 info.rti_flags = flags;
536 rt = NULL;
537 error = rtrequest1(RTM_ADD, &info, &rt);
538 if (rt != NULL)
539 flags = rt->rt_flags;
540 stat = &rtstat.rts_dynamic;
541 } else {
542 /*
543 * Smash the current notion of the gateway to
544 * this destination. Should check about netmask!!!
545 */
546 rt->rt_flags |= RTF_MODIFIED;
547 flags |= RTF_MODIFIED;
548 stat = &rtstat.rts_newgateway;
549 rt_setgate(rt, gateway);
550 }
551 } else
552 error = EHOSTUNREACH;
553 done:
554 if (rt) {
555 if (rtp != NULL && !error)
556 *rtp = rt;
557 else
558 rtfree(rt);
559 }
560 out:
561 if (error)
562 rtstat.rts_badredirect++;
563 else if (stat != NULL)
564 (*stat)++;
565 memset(&info, 0, sizeof(info));
566 info.rti_info[RTAX_DST] = dst;
567 info.rti_info[RTAX_GATEWAY] = gateway;
568 info.rti_info[RTAX_NETMASK] = netmask;
569 info.rti_info[RTAX_AUTHOR] = src;
570 rt_missmsg(RTM_REDIRECT, &info, flags, error);
571 }
572
573 /*
574 * Delete a route and generate a message.
575 * It doesn't free a passed rt.
576 */
577 static int
578 rtdeletemsg(struct rtentry *rt)
579 {
580 int error;
581 struct rt_addrinfo info;
582
583 /*
584 * Request the new route so that the entry is not actually
585 * deleted. That will allow the information being reported to
586 * be accurate (and consistent with route_output()).
587 */
588 memset(&info, 0, sizeof(info));
589 info.rti_info[RTAX_DST] = rt_getkey(rt);
590 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
591 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
592 info.rti_flags = rt->rt_flags;
593 error = rtrequest1(RTM_DELETE, &info, NULL);
594
595 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error);
596
597 return error;
598 }
599
600 struct ifaddr *
601 ifa_ifwithroute(int flags, const struct sockaddr *dst,
602 const struct sockaddr *gateway)
603 {
604 struct ifaddr *ifa;
605 if ((flags & RTF_GATEWAY) == 0) {
606 /*
607 * If we are adding a route to an interface,
608 * and the interface is a pt to pt link
609 * we should search for the destination
610 * as our clue to the interface. Otherwise
611 * we can use the local address.
612 */
613 ifa = NULL;
614 if ((flags & RTF_HOST) && gateway->sa_family != AF_LINK)
615 ifa = ifa_ifwithdstaddr(dst);
616 if (ifa == NULL)
617 ifa = ifa_ifwithaddr(gateway);
618 } else {
619 /*
620 * If we are adding a route to a remote net
621 * or host, the gateway may still be on the
622 * other end of a pt to pt link.
623 */
624 ifa = ifa_ifwithdstaddr(gateway);
625 }
626 if (ifa == NULL)
627 ifa = ifa_ifwithnet(gateway);
628 if (ifa == NULL) {
629 struct rtentry *rt = rtalloc1(dst, 0);
630 if (rt == NULL)
631 return NULL;
632 ifa = rt->rt_ifa;
633 rtfree(rt);
634 if (ifa == NULL)
635 return NULL;
636 }
637 if (ifa->ifa_addr->sa_family != dst->sa_family) {
638 struct ifaddr *oifa = ifa;
639 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
640 if (ifa == NULL)
641 ifa = oifa;
642 }
643 return ifa;
644 }
645
646 /*
647 * If it suceeds and ret_nrt isn't NULL, refcnt of ret_nrt is incremented.
648 * The caller has to rtfree it by itself.
649 */
650 int
651 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway,
652 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt)
653 {
654 struct rt_addrinfo info;
655
656 memset(&info, 0, sizeof(info));
657 info.rti_flags = flags;
658 info.rti_info[RTAX_DST] = dst;
659 info.rti_info[RTAX_GATEWAY] = gateway;
660 info.rti_info[RTAX_NETMASK] = netmask;
661 return rtrequest1(req, &info, ret_nrt);
662 }
663
664 /*
665 * It's a utility function to add/remove a route to/from the routing table
666 * and tell user processes the addition/removal on success.
667 */
668 int
669 rtrequest_newmsg(const int req, const struct sockaddr *dst,
670 const struct sockaddr *gateway, const struct sockaddr *netmask,
671 const int flags)
672 {
673 int error;
674 struct rtentry *ret_nrt = NULL;
675
676 KASSERT(req == RTM_ADD || req == RTM_DELETE);
677
678 error = rtrequest(req, dst, gateway, netmask, flags, &ret_nrt);
679 if (error != 0)
680 return error;
681
682 KASSERT(ret_nrt != NULL);
683
684 rt_newmsg(req, ret_nrt); /* tell user process */
685 rtfree(ret_nrt);
686
687 return 0;
688 }
689
690 int
691 rt_getifa(struct rt_addrinfo *info)
692 {
693 struct ifaddr *ifa;
694 const struct sockaddr *dst = info->rti_info[RTAX_DST];
695 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
696 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA];
697 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
698 int flags = info->rti_flags;
699
700 /*
701 * ifp may be specified by sockaddr_dl when protocol address
702 * is ambiguous
703 */
704 if (info->rti_ifp == NULL && ifpaddr != NULL
705 && ifpaddr->sa_family == AF_LINK &&
706 (ifa = ifa_ifwithnet(ifpaddr)) != NULL)
707 info->rti_ifp = ifa->ifa_ifp;
708 if (info->rti_ifa == NULL && ifaaddr != NULL)
709 info->rti_ifa = ifa_ifwithaddr(ifaaddr);
710 if (info->rti_ifa == NULL) {
711 const struct sockaddr *sa;
712
713 sa = ifaaddr != NULL ? ifaaddr :
714 (gateway != NULL ? gateway : dst);
715 if (sa != NULL && info->rti_ifp != NULL)
716 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
717 else if (dst != NULL && gateway != NULL)
718 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
719 else if (sa != NULL)
720 info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
721 }
722 if ((ifa = info->rti_ifa) == NULL)
723 return ENETUNREACH;
724 if (ifa->ifa_getifa != NULL) {
725 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst);
726 if (ifa == NULL)
727 return ENETUNREACH;
728 }
729 if (info->rti_ifp == NULL)
730 info->rti_ifp = ifa->ifa_ifp;
731 return 0;
732 }
733
734 /*
735 * If it suceeds and ret_nrt isn't NULL, refcnt of ret_nrt is incremented.
736 * The caller has to rtfree it by itself.
737 */
738 int
739 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
740 {
741 int s = splsoftnet();
742 int error = 0, rc;
743 struct rtentry *rt;
744 rtbl_t *rtbl;
745 struct ifaddr *ifa, *ifa2;
746 struct sockaddr_storage maskeddst;
747 const struct sockaddr *dst = info->rti_info[RTAX_DST];
748 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
749 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK];
750 int flags = info->rti_flags;
751 #define senderr(x) { error = x ; goto bad; }
752
753 if ((rtbl = rt_gettable(dst->sa_family)) == NULL)
754 senderr(ESRCH);
755 if (flags & RTF_HOST)
756 netmask = NULL;
757 switch (req) {
758 case RTM_DELETE:
759 if (netmask) {
760 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
761 netmask);
762 dst = (struct sockaddr *)&maskeddst;
763 }
764 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
765 senderr(ESRCH);
766 if ((rt = rt_deladdr(rtbl, dst, netmask)) == NULL)
767 senderr(ESRCH);
768 if (rt->rt_gwroute) {
769 rtfree(rt->rt_gwroute);
770 rt->rt_gwroute = NULL;
771 }
772 rt->rt_flags &= ~RTF_UP;
773 if ((ifa = rt->rt_ifa)) {
774 if (ifa->ifa_flags & IFA_ROUTE &&
775 rt_ifa_connected(rt, ifa)) {
776 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
777 "deleted IFA_ROUTE\n",
778 (void *)rt->_rt_key, (void *)ifa);
779 ifa->ifa_flags &= ~IFA_ROUTE;
780 }
781 if (ifa->ifa_rtrequest)
782 ifa->ifa_rtrequest(RTM_DELETE, rt, info);
783 }
784 rttrash++;
785 if (ret_nrt) {
786 *ret_nrt = rt;
787 rt->rt_refcnt++;
788 } else if (rt->rt_refcnt <= 0) {
789 /* Adjust the refcount */
790 rt->rt_refcnt++;
791 rtfree(rt);
792 }
793 break;
794
795 case RTM_ADD:
796 if (info->rti_ifa == NULL && (error = rt_getifa(info)))
797 senderr(error);
798 ifa = info->rti_ifa;
799 /* Already at splsoftnet() so pool_get/pool_put are safe */
800 rt = pool_get(&rtentry_pool, PR_NOWAIT);
801 if (rt == NULL)
802 senderr(ENOBUFS);
803 memset(rt, 0, sizeof(*rt));
804 rt->rt_flags = RTF_UP | flags;
805 LIST_INIT(&rt->rt_timer);
806 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
807 if (rt_setkey(rt, dst, M_NOWAIT) == NULL ||
808 rt_setgate(rt, gateway) != 0) {
809 pool_put(&rtentry_pool, rt);
810 senderr(ENOBUFS);
811 }
812 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
813 if (netmask) {
814 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
815 netmask);
816 rt_setkey(rt, (struct sockaddr *)&maskeddst, M_NOWAIT);
817 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
818 } else {
819 rt_setkey(rt, dst, M_NOWAIT);
820 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
821 }
822 rt_set_ifa(rt, ifa);
823 if (info->rti_info[RTAX_TAG] != NULL)
824 rt_settag(rt, info->rti_info[RTAX_TAG]);
825 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
826 if (info->rti_info[RTAX_IFP] != NULL &&
827 (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL &&
828 ifa2->ifa_ifp != NULL)
829 rt->rt_ifp = ifa2->ifa_ifp;
830 else
831 rt->rt_ifp = ifa->ifa_ifp;
832 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
833 rc = rt_addaddr(rtbl, rt, netmask);
834 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
835 if (rc != 0) {
836 ifafree(ifa);
837 if (rt->rt_gwroute)
838 rtfree(rt->rt_gwroute);
839 rt_destroy(rt);
840 pool_put(&rtentry_pool, rt);
841 senderr(rc);
842 }
843 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
844 if (ifa->ifa_rtrequest)
845 ifa->ifa_rtrequest(req, rt, info);
846 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
847 if (ret_nrt) {
848 *ret_nrt = rt;
849 rt->rt_refcnt++;
850 }
851 rtflushall(dst->sa_family);
852 break;
853 case RTM_GET:
854 if (netmask != NULL) {
855 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
856 netmask);
857 dst = (struct sockaddr *)&maskeddst;
858 }
859 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
860 senderr(ESRCH);
861 if (ret_nrt != NULL) {
862 *ret_nrt = rt;
863 rt->rt_refcnt++;
864 }
865 break;
866 }
867 bad:
868 splx(s);
869 return error;
870 }
871
872 int
873 rt_setgate(struct rtentry *rt, const struct sockaddr *gate)
874 {
875 KASSERT(rt != rt->rt_gwroute);
876
877 KASSERT(rt->_rt_key != NULL);
878 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
879
880 if (rt->rt_gwroute) {
881 rtfree(rt->rt_gwroute);
882 rt->rt_gwroute = NULL;
883 }
884 KASSERT(rt->_rt_key != NULL);
885 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
886 if (rt->rt_gateway != NULL)
887 sockaddr_free(rt->rt_gateway);
888 KASSERT(rt->_rt_key != NULL);
889 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
890 if ((rt->rt_gateway = sockaddr_dup(gate, M_ZERO | M_NOWAIT)) == NULL)
891 return ENOMEM;
892 KASSERT(rt->_rt_key != NULL);
893 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
894
895 if (rt->rt_flags & RTF_GATEWAY) {
896 KASSERT(rt->_rt_key != NULL);
897 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
898 rt->rt_gwroute = rtalloc1(gate, 1);
899 /*
900 * If we switched gateways, grab the MTU from the new
901 * gateway route if the current MTU, if the current MTU is
902 * greater than the MTU of gateway.
903 * Note that, if the MTU of gateway is 0, we will reset the
904 * MTU of the route to run PMTUD again from scratch. XXX
905 */
906 KASSERT(rt->_rt_key != NULL);
907 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
908 if (rt->rt_gwroute
909 && !(rt->rt_rmx.rmx_locks & RTV_MTU)
910 && rt->rt_rmx.rmx_mtu
911 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) {
912 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu;
913 }
914 }
915 KASSERT(rt->_rt_key != NULL);
916 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
917 return 0;
918 }
919
920 static void
921 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst,
922 const struct sockaddr *netmask)
923 {
924 const char *netmaskp = &netmask->sa_data[0],
925 *srcp = &src->sa_data[0];
926 char *dstp = &dst->sa_data[0];
927 const char *maskend = (char *)dst + MIN(netmask->sa_len, src->sa_len);
928 const char *srcend = (char *)dst + src->sa_len;
929
930 dst->sa_len = src->sa_len;
931 dst->sa_family = src->sa_family;
932
933 while (dstp < maskend)
934 *dstp++ = *srcp++ & *netmaskp++;
935 if (dstp < srcend)
936 memset(dstp, 0, (size_t)(srcend - dstp));
937 }
938
939 /*
940 * Inform the routing socket of a route change.
941 */
942 void
943 rt_newmsg(const int cmd, const struct rtentry *rt)
944 {
945 struct rt_addrinfo info;
946
947 memset((void *)&info, 0, sizeof(info));
948 info.rti_info[RTAX_DST] = rt_getkey(rt);
949 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
950 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
951 if (rt->rt_ifp) {
952 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr;
953 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
954 }
955
956 rt_missmsg(cmd, &info, rt->rt_flags, 0);
957 }
958
959 /*
960 * Set up or tear down a routing table entry, normally
961 * for an interface.
962 */
963 int
964 rtinit(struct ifaddr *ifa, int cmd, int flags)
965 {
966 struct rtentry *rt;
967 struct sockaddr *dst, *odst;
968 struct sockaddr_storage maskeddst;
969 struct rtentry *nrt = NULL;
970 int error;
971 struct rt_addrinfo info;
972
973 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
974 if (cmd == RTM_DELETE) {
975 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
976 /* Delete subnet route for this interface */
977 odst = dst;
978 dst = (struct sockaddr *)&maskeddst;
979 rt_maskedcopy(odst, dst, ifa->ifa_netmask);
980 }
981 if ((rt = rtalloc1(dst, 0)) != NULL) {
982 if (rt->rt_ifa != ifa) {
983 rtfree(rt);
984 return (flags & RTF_HOST) ? EHOSTUNREACH
985 : ENETUNREACH;
986 }
987 rtfree(rt);
988 }
989 }
990 memset(&info, 0, sizeof(info));
991 info.rti_ifa = ifa;
992 info.rti_flags = flags | ifa->ifa_flags;
993 info.rti_info[RTAX_DST] = dst;
994 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
995
996 /*
997 * XXX here, it seems that we are assuming that ifa_netmask is NULL
998 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate
999 * variable) when RTF_HOST is 1. still not sure if i can safely
1000 * change it to meet bsdi4 behavior.
1001 */
1002 if (cmd != RTM_LLINFO_UPD)
1003 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1004 error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info,
1005 &nrt);
1006 if (error != 0)
1007 return error;
1008
1009 rt = nrt;
1010 switch (cmd) {
1011 case RTM_DELETE:
1012 rt_newmsg(cmd, rt);
1013 break;
1014 case RTM_LLINFO_UPD:
1015 if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL)
1016 ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info);
1017 rt_newmsg(RTM_CHANGE, rt);
1018 break;
1019 case RTM_ADD:
1020 if (rt->rt_ifa != ifa) {
1021 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
1022 rt->rt_ifa);
1023 if (rt->rt_ifa->ifa_rtrequest != NULL) {
1024 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
1025 &info);
1026 }
1027 rt_replace_ifa(rt, ifa);
1028 rt->rt_ifp = ifa->ifa_ifp;
1029 if (ifa->ifa_rtrequest != NULL)
1030 ifa->ifa_rtrequest(RTM_ADD, rt, &info);
1031 }
1032 rt_newmsg(cmd, rt);
1033 break;
1034 }
1035 rtfree(rt);
1036 return error;
1037 }
1038
1039 /*
1040 * Create a local route entry for the address.
1041 * Announce the addition of the address and the route to the routing socket.
1042 */
1043 int
1044 rt_ifa_addlocal(struct ifaddr *ifa)
1045 {
1046 struct rtentry *rt;
1047 int e;
1048
1049 /* If there is no loopback entry, allocate one. */
1050 rt = rtalloc1(ifa->ifa_addr, 0);
1051 #ifdef RT_DEBUG
1052 if (rt != NULL)
1053 dump_rt(rt);
1054 #endif
1055 if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
1056 (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
1057 {
1058 struct rt_addrinfo info;
1059 struct rtentry *nrt;
1060
1061 memset(&info, 0, sizeof(info));
1062 info.rti_flags = RTF_HOST | RTF_LOCAL;
1063 if (!(ifa->ifa_ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)))
1064 info.rti_flags |= RTF_LLDATA;
1065 info.rti_info[RTAX_DST] = ifa->ifa_addr;
1066 info.rti_info[RTAX_GATEWAY] =
1067 (const struct sockaddr *)ifa->ifa_ifp->if_sadl;
1068 info.rti_ifa = ifa;
1069 nrt = NULL;
1070 e = rtrequest1(RTM_ADD, &info, &nrt);
1071 if (nrt && ifa != nrt->rt_ifa)
1072 rt_replace_ifa(nrt, ifa);
1073 rt_newaddrmsg(RTM_ADD, ifa, e, nrt);
1074 if (nrt != NULL) {
1075 #ifdef RT_DEBUG
1076 dump_rt(nrt);
1077 #endif
1078 rtfree(nrt);
1079 }
1080 } else {
1081 e = 0;
1082 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
1083 }
1084 if (rt != NULL)
1085 rtfree(rt);
1086 return e;
1087 }
1088
1089 /*
1090 * Remove the local route entry for the address.
1091 * Announce the removal of the address and the route to the routing socket.
1092 */
1093 int
1094 rt_ifa_remlocal(struct ifaddr *ifa, struct ifaddr *alt_ifa)
1095 {
1096 struct rtentry *rt;
1097 int e = 0;
1098
1099 rt = rtalloc1(ifa->ifa_addr, 0);
1100
1101 /*
1102 * Before deleting, check if a corresponding loopbacked
1103 * host route surely exists. With this check, we can avoid
1104 * deleting an interface direct route whose destination is
1105 * the same as the address being removed. This can happen
1106 * when removing a subnet-router anycast address on an
1107 * interface attached to a shared medium.
1108 */
1109 if (rt != NULL &&
1110 (rt->rt_flags & RTF_HOST) &&
1111 (rt->rt_ifp->if_flags & IFF_LOOPBACK))
1112 {
1113 /* If we cannot replace the route's ifaddr with the equivalent
1114 * ifaddr of another interface, I believe it is safest to
1115 * delete the route.
1116 */
1117 if (alt_ifa == NULL) {
1118 e = rtdeletemsg(rt);
1119 rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL);
1120 } else {
1121 rt_replace_ifa(rt, alt_ifa);
1122 rt_newmsg(RTM_CHANGE, rt);
1123 }
1124 } else
1125 rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL);
1126 if (rt != NULL)
1127 rtfree(rt);
1128 return e;
1129 }
1130
1131 /*
1132 * Route timer routines. These routes allow functions to be called
1133 * for various routes at any time. This is useful in supporting
1134 * path MTU discovery and redirect route deletion.
1135 *
1136 * This is similar to some BSDI internal functions, but it provides
1137 * for multiple queues for efficiency's sake...
1138 */
1139
1140 LIST_HEAD(, rttimer_queue) rttimer_queue_head;
1141 static int rt_init_done = 0;
1142
1143 /*
1144 * Some subtle order problems with domain initialization mean that
1145 * we cannot count on this being run from rt_init before various
1146 * protocol initializations are done. Therefore, we make sure
1147 * that this is run when the first queue is added...
1148 */
1149
1150 void
1151 rt_timer_init(void)
1152 {
1153 assert(rt_init_done == 0);
1154
1155 LIST_INIT(&rttimer_queue_head);
1156 callout_init(&rt_timer_ch, 0);
1157 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
1158 rt_init_done = 1;
1159 }
1160
1161 struct rttimer_queue *
1162 rt_timer_queue_create(u_int timeout)
1163 {
1164 struct rttimer_queue *rtq;
1165
1166 if (rt_init_done == 0)
1167 rt_timer_init();
1168
1169 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq);
1170 if (rtq == NULL)
1171 return NULL;
1172 memset(rtq, 0, sizeof(*rtq));
1173
1174 rtq->rtq_timeout = timeout;
1175 TAILQ_INIT(&rtq->rtq_head);
1176 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link);
1177
1178 return rtq;
1179 }
1180
1181 void
1182 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout)
1183 {
1184
1185 rtq->rtq_timeout = timeout;
1186 }
1187
1188 void
1189 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy)
1190 {
1191 struct rttimer *r;
1192
1193 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) {
1194 LIST_REMOVE(r, rtt_link);
1195 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
1196 if (destroy)
1197 (*r->rtt_func)(r->rtt_rt, r);
1198 rtfree(r->rtt_rt);
1199 /* we are already at splsoftnet */
1200 pool_put(&rttimer_pool, r);
1201 if (rtq->rtq_count > 0)
1202 rtq->rtq_count--;
1203 else
1204 printf("rt_timer_queue_remove_all: "
1205 "rtq_count reached 0\n");
1206 }
1207 }
1208
1209 void
1210 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy)
1211 {
1212
1213 rt_timer_queue_remove_all(rtq, destroy);
1214
1215 LIST_REMOVE(rtq, rtq_link);
1216
1217 /*
1218 * Caller is responsible for freeing the rttimer_queue structure.
1219 */
1220 }
1221
1222 unsigned long
1223 rt_timer_count(struct rttimer_queue *rtq)
1224 {
1225 return rtq->rtq_count;
1226 }
1227
1228 void
1229 rt_timer_remove_all(struct rtentry *rt, int destroy)
1230 {
1231 struct rttimer *r;
1232
1233 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) {
1234 LIST_REMOVE(r, rtt_link);
1235 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1236 if (destroy)
1237 (*r->rtt_func)(r->rtt_rt, r);
1238 if (r->rtt_queue->rtq_count > 0)
1239 r->rtt_queue->rtq_count--;
1240 else
1241 printf("rt_timer_remove_all: rtq_count reached 0\n");
1242 rtfree(r->rtt_rt);
1243 /* we are already at splsoftnet */
1244 pool_put(&rttimer_pool, r);
1245 }
1246 }
1247
1248 int
1249 rt_timer_add(struct rtentry *rt,
1250 void (*func)(struct rtentry *, struct rttimer *),
1251 struct rttimer_queue *queue)
1252 {
1253 struct rttimer *r;
1254 int s;
1255
1256 KASSERT(func != NULL);
1257 /*
1258 * If there's already a timer with this action, destroy it before
1259 * we add a new one.
1260 */
1261 LIST_FOREACH(r, &rt->rt_timer, rtt_link) {
1262 if (r->rtt_func == func)
1263 break;
1264 }
1265 if (r != NULL) {
1266 LIST_REMOVE(r, rtt_link);
1267 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1268 if (r->rtt_queue->rtq_count > 0)
1269 r->rtt_queue->rtq_count--;
1270 else
1271 printf("rt_timer_add: rtq_count reached 0\n");
1272 rtfree(r->rtt_rt);
1273 } else {
1274 s = splsoftnet();
1275 r = pool_get(&rttimer_pool, PR_NOWAIT);
1276 splx(s);
1277 if (r == NULL)
1278 return ENOBUFS;
1279 }
1280
1281 memset(r, 0, sizeof(*r));
1282
1283 rt->rt_refcnt++;
1284 r->rtt_rt = rt;
1285 r->rtt_time = time_uptime;
1286 r->rtt_func = func;
1287 r->rtt_queue = queue;
1288 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link);
1289 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next);
1290 r->rtt_queue->rtq_count++;
1291
1292 return 0;
1293 }
1294
1295 /* ARGSUSED */
1296 void
1297 rt_timer_timer(void *arg)
1298 {
1299 struct rttimer_queue *rtq;
1300 struct rttimer *r;
1301 int s;
1302
1303 s = splsoftnet();
1304 LIST_FOREACH(rtq, &rttimer_queue_head, rtq_link) {
1305 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL &&
1306 (r->rtt_time + rtq->rtq_timeout) < time_uptime) {
1307 LIST_REMOVE(r, rtt_link);
1308 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
1309 (*r->rtt_func)(r->rtt_rt, r);
1310 rtfree(r->rtt_rt);
1311 pool_put(&rttimer_pool, r);
1312 if (rtq->rtq_count > 0)
1313 rtq->rtq_count--;
1314 else
1315 printf("rt_timer_timer: rtq_count reached 0\n");
1316 }
1317 }
1318 splx(s);
1319
1320 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
1321 }
1322
1323 static struct rtentry *
1324 _rtcache_init(struct route *ro, int flag)
1325 {
1326 rtcache_invariants(ro);
1327 KASSERT(ro->_ro_rt == NULL);
1328
1329 if (rtcache_getdst(ro) == NULL)
1330 return NULL;
1331 ro->ro_invalid = false;
1332 if ((ro->_ro_rt = rtalloc1(rtcache_getdst(ro), flag)) != NULL)
1333 rtcache(ro);
1334
1335 rtcache_invariants(ro);
1336 return ro->_ro_rt;
1337 }
1338
1339 struct rtentry *
1340 rtcache_init(struct route *ro)
1341 {
1342 return _rtcache_init(ro, 1);
1343 }
1344
1345 struct rtentry *
1346 rtcache_init_noclone(struct route *ro)
1347 {
1348 return _rtcache_init(ro, 0);
1349 }
1350
1351 struct rtentry *
1352 rtcache_update(struct route *ro, int clone)
1353 {
1354 rtcache_clear(ro);
1355 return _rtcache_init(ro, clone);
1356 }
1357
1358 void
1359 rtcache_copy(struct route *new_ro, const struct route *old_ro)
1360 {
1361 struct rtentry *rt;
1362
1363 KASSERT(new_ro != old_ro);
1364 rtcache_invariants(new_ro);
1365 rtcache_invariants(old_ro);
1366
1367 if ((rt = rtcache_validate(old_ro)) != NULL)
1368 rt->rt_refcnt++;
1369
1370 if (rtcache_getdst(old_ro) == NULL ||
1371 rtcache_setdst(new_ro, rtcache_getdst(old_ro)) != 0)
1372 return;
1373
1374 new_ro->ro_invalid = false;
1375 if ((new_ro->_ro_rt = rt) != NULL)
1376 rtcache(new_ro);
1377 rtcache_invariants(new_ro);
1378 }
1379
1380 static struct dom_rtlist invalid_routes = LIST_HEAD_INITIALIZER(dom_rtlist);
1381
1382 static void
1383 rtcache_invalidate(struct dom_rtlist *rtlist)
1384 {
1385 struct route *ro;
1386
1387 while ((ro = LIST_FIRST(rtlist)) != NULL) {
1388 rtcache_invariants(ro);
1389 KASSERT(ro->_ro_rt != NULL);
1390 ro->ro_invalid = true;
1391 LIST_REMOVE(ro, ro_rtcache_next);
1392 LIST_INSERT_HEAD(&invalid_routes, ro, ro_rtcache_next);
1393 rtcache_invariants(ro);
1394 }
1395 }
1396
1397 static void
1398 rtcache_clear(struct route *ro)
1399 {
1400 rtcache_invariants(ro);
1401 if (ro->_ro_rt == NULL)
1402 return;
1403
1404 LIST_REMOVE(ro, ro_rtcache_next);
1405
1406 rtfree(ro->_ro_rt);
1407 ro->_ro_rt = NULL;
1408 ro->ro_invalid = false;
1409 rtcache_invariants(ro);
1410 }
1411
1412 struct rtentry *
1413 rtcache_lookup2(struct route *ro, const struct sockaddr *dst, int clone,
1414 int *hitp)
1415 {
1416 const struct sockaddr *odst;
1417 struct rtentry *rt = NULL;
1418
1419 odst = rtcache_getdst(ro);
1420 if (odst == NULL)
1421 goto miss;
1422
1423 if (sockaddr_cmp(odst, dst) != 0) {
1424 rtcache_free(ro);
1425 goto miss;
1426 }
1427
1428 rt = rtcache_validate(ro);
1429 if (rt == NULL) {
1430 rtcache_clear(ro);
1431 goto miss;
1432 }
1433
1434 *hitp = 1;
1435 rtcache_invariants(ro);
1436
1437 return rt;
1438 miss:
1439 *hitp = 0;
1440 if (rtcache_setdst(ro, dst) == 0)
1441 rt = _rtcache_init(ro, clone);
1442
1443 rtcache_invariants(ro);
1444
1445 return rt;
1446 }
1447
1448 void
1449 rtcache_free(struct route *ro)
1450 {
1451 rtcache_clear(ro);
1452 if (ro->ro_sa != NULL) {
1453 sockaddr_free(ro->ro_sa);
1454 ro->ro_sa = NULL;
1455 }
1456 rtcache_invariants(ro);
1457 }
1458
1459 int
1460 rtcache_setdst(struct route *ro, const struct sockaddr *sa)
1461 {
1462 KASSERT(sa != NULL);
1463
1464 rtcache_invariants(ro);
1465 if (ro->ro_sa != NULL) {
1466 if (ro->ro_sa->sa_family == sa->sa_family) {
1467 rtcache_clear(ro);
1468 sockaddr_copy(ro->ro_sa, ro->ro_sa->sa_len, sa);
1469 rtcache_invariants(ro);
1470 return 0;
1471 }
1472 /* free ro_sa, wrong family */
1473 rtcache_free(ro);
1474 }
1475
1476 KASSERT(ro->_ro_rt == NULL);
1477
1478 if ((ro->ro_sa = sockaddr_dup(sa, M_ZERO | M_NOWAIT)) == NULL) {
1479 rtcache_invariants(ro);
1480 return ENOMEM;
1481 }
1482 rtcache_invariants(ro);
1483 return 0;
1484 }
1485
1486 const struct sockaddr *
1487 rt_settag(struct rtentry *rt, const struct sockaddr *tag)
1488 {
1489 if (rt->rt_tag != tag) {
1490 if (rt->rt_tag != NULL)
1491 sockaddr_free(rt->rt_tag);
1492 rt->rt_tag = sockaddr_dup(tag, M_ZERO | M_NOWAIT);
1493 }
1494 return rt->rt_tag;
1495 }
1496
1497 struct sockaddr *
1498 rt_gettag(struct rtentry *rt)
1499 {
1500 return rt->rt_tag;
1501 }
1502