route.c revision 1.128 1 /* $NetBSD: route.c,v 1.128 2014/02/25 18:30:12 pooka 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 #include "opt_route.h"
94
95 #include <sys/cdefs.h>
96 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.128 2014/02/25 18:30:12 pooka Exp $");
97
98 #include <sys/param.h>
99 #include <sys/kmem.h>
100 #include <sys/sysctl.h>
101 #include <sys/systm.h>
102 #include <sys/callout.h>
103 #include <sys/proc.h>
104 #include <sys/mbuf.h>
105 #include <sys/socket.h>
106 #include <sys/socketvar.h>
107 #include <sys/domain.h>
108 #include <sys/protosw.h>
109 #include <sys/kernel.h>
110 #include <sys/ioctl.h>
111 #include <sys/pool.h>
112 #include <sys/kauth.h>
113
114 #include <net/if.h>
115 #include <net/if_dl.h>
116 #include <net/route.h>
117 #include <net/raw_cb.h>
118
119 #include <netinet/in.h>
120 #include <netinet/in_var.h>
121
122 #ifdef RTFLUSH_DEBUG
123 #define rtcache_debug() __predict_false(_rtcache_debug)
124 #else /* RTFLUSH_DEBUG */
125 #define rtcache_debug() 0
126 #endif /* RTFLUSH_DEBUG */
127
128 struct rtstat rtstat;
129
130 int rttrash; /* routes not in table but not freed */
131
132 struct pool rtentry_pool;
133 struct pool rttimer_pool;
134
135 struct callout rt_timer_ch; /* callout for rt_timer_timer() */
136
137 #ifdef RTFLUSH_DEBUG
138 static int _rtcache_debug = 0;
139 #endif /* RTFLUSH_DEBUG */
140
141 static kauth_listener_t route_listener;
142
143 static int rtdeletemsg(struct rtentry *);
144 static int rtflushclone1(struct rtentry *, void *);
145 static void rtflushclone(sa_family_t family, struct rtentry *);
146
147 #ifdef RTFLUSH_DEBUG
148 static void sysctl_net_rtcache_setup(struct sysctllog **);
149 static void
150 sysctl_net_rtcache_setup(struct sysctllog **clog)
151 {
152 const struct sysctlnode *rnode;
153
154 if (sysctl_createv(clog, 0, NULL, &rnode, CTLFLAG_PERMANENT,
155 CTLTYPE_NODE,
156 "rtcache", SYSCTL_DESCR("Route cache related settings"),
157 NULL, 0, NULL, 0, CTL_NET, CTL_CREATE, CTL_EOL) != 0)
158 return;
159 if (sysctl_createv(clog, 0, &rnode, &rnode,
160 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
161 "debug", SYSCTL_DESCR("Debug route caches"),
162 NULL, 0, &_rtcache_debug, 0, CTL_CREATE, CTL_EOL) != 0)
163 return;
164 }
165 #endif /* RTFLUSH_DEBUG */
166
167 struct ifaddr *
168 rt_get_ifa(struct rtentry *rt)
169 {
170 struct ifaddr *ifa;
171
172 if ((ifa = rt->rt_ifa) == NULL)
173 return ifa;
174 else if (ifa->ifa_getifa == NULL)
175 return ifa;
176 #if 0
177 else if (ifa->ifa_seqno != NULL && *ifa->ifa_seqno == rt->rt_ifa_seqno)
178 return ifa;
179 #endif
180 else {
181 ifa = (*ifa->ifa_getifa)(ifa, rt_getkey(rt));
182 rt_replace_ifa(rt, ifa);
183 return ifa;
184 }
185 }
186
187 static void
188 rt_set_ifa1(struct rtentry *rt, struct ifaddr *ifa)
189 {
190 rt->rt_ifa = ifa;
191 if (ifa->ifa_seqno != NULL)
192 rt->rt_ifa_seqno = *ifa->ifa_seqno;
193 }
194
195 /*
196 * Is this route the connected route for the ifa?
197 */
198 static int
199 rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa)
200 {
201 const struct sockaddr *key, *dst, *odst;
202 struct sockaddr_storage maskeddst;
203
204 key = rt_getkey(rt);
205 dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
206 if (dst == NULL ||
207 dst->sa_family != key->sa_family ||
208 dst->sa_len != key->sa_len)
209 return 0;
210 if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
211 odst = dst;
212 dst = (struct sockaddr *)&maskeddst;
213 rt_maskedcopy(odst, (struct sockaddr *)&maskeddst,
214 ifa->ifa_netmask);
215 }
216 return (memcmp(dst, key, dst->sa_len) == 0);
217 }
218
219 void
220 rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa)
221 {
222 if (rt->rt_ifa &&
223 rt->rt_ifa != ifa &&
224 rt->rt_ifa->ifa_flags & IFA_ROUTE &&
225 rt_ifa_connected(rt, rt->rt_ifa))
226 {
227 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
228 "replace deleted IFA_ROUTE\n",
229 (void *)rt->_rt_key, (void *)rt->rt_ifa);
230 rt->rt_ifa->ifa_flags &= ~IFA_ROUTE;
231 if (rt_ifa_connected(rt, ifa)) {
232 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
233 "replace added IFA_ROUTE\n",
234 (void *)rt->_rt_key, (void *)ifa);
235 ifa->ifa_flags |= IFA_ROUTE;
236 }
237 }
238
239 IFAREF(ifa);
240 IFAFREE(rt->rt_ifa);
241 rt_set_ifa1(rt, ifa);
242 }
243
244 static void
245 rt_set_ifa(struct rtentry *rt, struct ifaddr *ifa)
246 {
247 IFAREF(ifa);
248 rt_set_ifa1(rt, ifa);
249 }
250
251 static int
252 route_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
253 void *arg0, void *arg1, void *arg2, void *arg3)
254 {
255 struct rt_msghdr *rtm;
256 int result;
257
258 result = KAUTH_RESULT_DEFER;
259 rtm = arg1;
260
261 if (action != KAUTH_NETWORK_ROUTE)
262 return result;
263
264 if (rtm->rtm_type == RTM_GET)
265 result = KAUTH_RESULT_ALLOW;
266
267 return result;
268 }
269
270 void
271 rt_init(void)
272 {
273
274 #ifdef RTFLUSH_DEBUG
275 sysctl_net_rtcache_setup(NULL);
276 #endif
277
278 pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl",
279 NULL, IPL_SOFTNET);
280 pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl",
281 NULL, IPL_SOFTNET);
282
283 rn_init(); /* initialize all zeroes, all ones, mask table */
284 rtbl_init();
285
286 route_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
287 route_listener_cb, NULL);
288 }
289
290 void
291 rtflushall(int family)
292 {
293 struct domain *dom;
294
295 if (rtcache_debug())
296 printf("%s: enter\n", __func__);
297
298 if ((dom = pffinddomain(family)) == NULL)
299 return;
300
301 rtcache_invalidate(&dom->dom_rtcache);
302 }
303
304 void
305 rtcache(struct route *ro)
306 {
307 struct domain *dom;
308
309 rtcache_invariants(ro);
310 KASSERT(ro->_ro_rt != NULL);
311 KASSERT(ro->ro_invalid == false);
312 KASSERT(rtcache_getdst(ro) != NULL);
313
314 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) == NULL)
315 return;
316
317 LIST_INSERT_HEAD(&dom->dom_rtcache, ro, ro_rtcache_next);
318 rtcache_invariants(ro);
319 }
320
321 /*
322 * Packet routing routines.
323 */
324 struct rtentry *
325 rtalloc1(const struct sockaddr *dst, int report)
326 {
327 rtbl_t *rtbl = rt_gettable(dst->sa_family);
328 struct rtentry *rt;
329 struct rtentry *newrt = NULL;
330 struct rt_addrinfo info;
331 int s = splsoftnet(), err = 0, msgtype = RTM_MISS;
332
333 if (rtbl != NULL && (rt = rt_matchaddr(rtbl, dst)) != NULL) {
334 newrt = rt;
335 if (report && (rt->rt_flags & RTF_CLONING)) {
336 err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0,
337 &newrt);
338 if (err) {
339 newrt = rt;
340 rt->rt_refcnt++;
341 goto miss;
342 }
343 KASSERT(newrt != NULL);
344 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
345 msgtype = RTM_RESOLVE;
346 goto miss;
347 }
348 /* Inform listeners of the new route */
349 memset(&info, 0, sizeof(info));
350 info.rti_info[RTAX_DST] = rt_getkey(rt);
351 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
352 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
353 if (rt->rt_ifp != NULL) {
354 info.rti_info[RTAX_IFP] =
355 rt->rt_ifp->if_dl->ifa_addr;
356 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
357 }
358 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0);
359 } else
360 rt->rt_refcnt++;
361 } else {
362 rtstat.rts_unreach++;
363 miss: if (report) {
364 memset((void *)&info, 0, sizeof(info));
365 info.rti_info[RTAX_DST] = dst;
366 rt_missmsg(msgtype, &info, 0, err);
367 }
368 }
369 splx(s);
370 return newrt;
371 }
372
373 void
374 rtfree(struct rtentry *rt)
375 {
376 struct ifaddr *ifa;
377
378 if (rt == NULL)
379 panic("rtfree");
380 rt->rt_refcnt--;
381 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
382 rt_assert_inactive(rt);
383 rttrash--;
384 if (rt->rt_refcnt < 0) {
385 printf("rtfree: %p not freed (neg refs)\n", rt);
386 return;
387 }
388 rt_timer_remove_all(rt, 0);
389 ifa = rt->rt_ifa;
390 rt->rt_ifa = NULL;
391 IFAFREE(ifa);
392 rt->rt_ifp = NULL;
393 rt_destroy(rt);
394 pool_put(&rtentry_pool, rt);
395 }
396 }
397
398 void
399 ifafree(struct ifaddr *ifa)
400 {
401
402 #ifdef DIAGNOSTIC
403 if (ifa == NULL)
404 panic("ifafree: null ifa");
405 if (ifa->ifa_refcnt != 0)
406 panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt);
407 #endif
408 #ifdef IFAREF_DEBUG
409 printf("ifafree: freeing ifaddr %p\n", ifa);
410 #endif
411 free(ifa, M_IFADDR);
412 }
413
414 /*
415 * Force a routing table entry to the specified
416 * destination to go through the given gateway.
417 * Normally called as a result of a routing redirect
418 * message from the network layer.
419 *
420 * N.B.: must be called at splsoftnet
421 */
422 void
423 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway,
424 const struct sockaddr *netmask, int flags, const struct sockaddr *src,
425 struct rtentry **rtp)
426 {
427 struct rtentry *rt;
428 int error = 0;
429 uint64_t *stat = NULL;
430 struct rt_addrinfo info;
431 struct ifaddr *ifa;
432
433 /* verify the gateway is directly reachable */
434 if ((ifa = ifa_ifwithnet(gateway)) == NULL) {
435 error = ENETUNREACH;
436 goto out;
437 }
438 rt = rtalloc1(dst, 0);
439 /*
440 * If the redirect isn't from our current router for this dst,
441 * it's either old or wrong. If it redirects us to ourselves,
442 * we have a routing loop, perhaps as a result of an interface
443 * going down recently.
444 */
445 if (!(flags & RTF_DONE) && rt &&
446 (sockaddr_cmp(src, rt->rt_gateway) != 0 || rt->rt_ifa != ifa))
447 error = EINVAL;
448 else if (ifa_ifwithaddr(gateway))
449 error = EHOSTUNREACH;
450 if (error)
451 goto done;
452 /*
453 * Create a new entry if we just got back a wildcard entry
454 * or the lookup failed. This is necessary for hosts
455 * which use routing redirects generated by smart gateways
456 * to dynamically build the routing tables.
457 */
458 if (rt == NULL || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
459 goto create;
460 /*
461 * Don't listen to the redirect if it's
462 * for a route to an interface.
463 */
464 if (rt->rt_flags & RTF_GATEWAY) {
465 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
466 /*
467 * Changing from route to net => route to host.
468 * Create new route, rather than smashing route to net.
469 */
470 create:
471 if (rt != NULL)
472 rtfree(rt);
473 flags |= RTF_GATEWAY | RTF_DYNAMIC;
474 memset(&info, 0, sizeof(info));
475 info.rti_info[RTAX_DST] = dst;
476 info.rti_info[RTAX_GATEWAY] = gateway;
477 info.rti_info[RTAX_NETMASK] = netmask;
478 info.rti_ifa = ifa;
479 info.rti_flags = flags;
480 rt = NULL;
481 error = rtrequest1(RTM_ADD, &info, &rt);
482 if (rt != NULL)
483 flags = rt->rt_flags;
484 stat = &rtstat.rts_dynamic;
485 } else {
486 /*
487 * Smash the current notion of the gateway to
488 * this destination. Should check about netmask!!!
489 */
490 rt->rt_flags |= RTF_MODIFIED;
491 flags |= RTF_MODIFIED;
492 stat = &rtstat.rts_newgateway;
493 rt_setgate(rt, gateway);
494 }
495 } else
496 error = EHOSTUNREACH;
497 done:
498 if (rt) {
499 if (rtp != NULL && !error)
500 *rtp = rt;
501 else
502 rtfree(rt);
503 }
504 out:
505 if (error)
506 rtstat.rts_badredirect++;
507 else if (stat != NULL)
508 (*stat)++;
509 memset(&info, 0, sizeof(info));
510 info.rti_info[RTAX_DST] = dst;
511 info.rti_info[RTAX_GATEWAY] = gateway;
512 info.rti_info[RTAX_NETMASK] = netmask;
513 info.rti_info[RTAX_AUTHOR] = src;
514 rt_missmsg(RTM_REDIRECT, &info, flags, error);
515 }
516
517 /*
518 * Delete a route and generate a message
519 */
520 static int
521 rtdeletemsg(struct rtentry *rt)
522 {
523 int error;
524 struct rt_addrinfo info;
525
526 /*
527 * Request the new route so that the entry is not actually
528 * deleted. That will allow the information being reported to
529 * be accurate (and consistent with route_output()).
530 */
531 memset(&info, 0, sizeof(info));
532 info.rti_info[RTAX_DST] = rt_getkey(rt);
533 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
534 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
535 info.rti_flags = rt->rt_flags;
536 error = rtrequest1(RTM_DELETE, &info, &rt);
537
538 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error);
539
540 /* Adjust the refcount */
541 if (error == 0 && rt->rt_refcnt <= 0) {
542 rt->rt_refcnt++;
543 rtfree(rt);
544 }
545 return error;
546 }
547
548 static int
549 rtflushclone1(struct rtentry *rt, void *arg)
550 {
551 struct rtentry *parent;
552
553 parent = (struct rtentry *)arg;
554 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent)
555 rtdeletemsg(rt);
556 return 0;
557 }
558
559 static void
560 rtflushclone(sa_family_t family, struct rtentry *parent)
561 {
562
563 #ifdef DIAGNOSTIC
564 if (!parent || (parent->rt_flags & RTF_CLONING) == 0)
565 panic("rtflushclone: called with a non-cloning route");
566 #endif
567 rt_walktree(family, rtflushclone1, (void *)parent);
568 }
569
570 /*
571 * Routing table ioctl interface.
572 */
573 int
574 rtioctl(u_long req, void *data, struct lwp *l)
575 {
576 return EOPNOTSUPP;
577 }
578
579 struct ifaddr *
580 ifa_ifwithroute(int flags, const struct sockaddr *dst,
581 const struct sockaddr *gateway)
582 {
583 struct ifaddr *ifa;
584 if ((flags & RTF_GATEWAY) == 0) {
585 /*
586 * If we are adding a route to an interface,
587 * and the interface is a pt to pt link
588 * we should search for the destination
589 * as our clue to the interface. Otherwise
590 * we can use the local address.
591 */
592 ifa = NULL;
593 if ((flags & RTF_HOST) && gateway->sa_family != AF_LINK)
594 ifa = ifa_ifwithdstaddr(dst);
595 if (ifa == NULL)
596 ifa = ifa_ifwithaddr(gateway);
597 } else {
598 /*
599 * If we are adding a route to a remote net
600 * or host, the gateway may still be on the
601 * other end of a pt to pt link.
602 */
603 ifa = ifa_ifwithdstaddr(gateway);
604 }
605 if (ifa == NULL)
606 ifa = ifa_ifwithnet(gateway);
607 if (ifa == NULL) {
608 struct rtentry *rt = rtalloc1(dst, 0);
609 if (rt == NULL)
610 return NULL;
611 rt->rt_refcnt--;
612 if ((ifa = rt->rt_ifa) == NULL)
613 return NULL;
614 }
615 if (ifa->ifa_addr->sa_family != dst->sa_family) {
616 struct ifaddr *oifa = ifa;
617 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
618 if (ifa == NULL)
619 ifa = oifa;
620 }
621 return ifa;
622 }
623
624 int
625 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway,
626 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt)
627 {
628 struct rt_addrinfo info;
629
630 memset(&info, 0, sizeof(info));
631 info.rti_flags = flags;
632 info.rti_info[RTAX_DST] = dst;
633 info.rti_info[RTAX_GATEWAY] = gateway;
634 info.rti_info[RTAX_NETMASK] = netmask;
635 return rtrequest1(req, &info, ret_nrt);
636 }
637
638 int
639 rt_getifa(struct rt_addrinfo *info)
640 {
641 struct ifaddr *ifa;
642 const struct sockaddr *dst = info->rti_info[RTAX_DST];
643 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
644 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA];
645 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
646 int flags = info->rti_flags;
647
648 /*
649 * ifp may be specified by sockaddr_dl when protocol address
650 * is ambiguous
651 */
652 if (info->rti_ifp == NULL && ifpaddr != NULL
653 && ifpaddr->sa_family == AF_LINK &&
654 (ifa = ifa_ifwithnet(ifpaddr)) != NULL)
655 info->rti_ifp = ifa->ifa_ifp;
656 if (info->rti_ifa == NULL && ifaaddr != NULL)
657 info->rti_ifa = ifa_ifwithaddr(ifaaddr);
658 if (info->rti_ifa == NULL) {
659 const struct sockaddr *sa;
660
661 sa = ifaaddr != NULL ? ifaaddr :
662 (gateway != NULL ? gateway : dst);
663 if (sa != NULL && info->rti_ifp != NULL)
664 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
665 else if (dst != NULL && gateway != NULL)
666 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
667 else if (sa != NULL)
668 info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
669 }
670 if ((ifa = info->rti_ifa) == NULL)
671 return ENETUNREACH;
672 if (ifa->ifa_getifa != NULL)
673 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst);
674 if (info->rti_ifp == NULL)
675 info->rti_ifp = ifa->ifa_ifp;
676 return 0;
677 }
678
679 int
680 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
681 {
682 int s = splsoftnet();
683 int error = 0, rc;
684 struct rtentry *rt, *crt;
685 rtbl_t *rtbl;
686 struct ifaddr *ifa, *ifa2;
687 struct sockaddr_storage maskeddst;
688 const struct sockaddr *dst = info->rti_info[RTAX_DST];
689 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
690 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK];
691 int flags = info->rti_flags;
692 #define senderr(x) { error = x ; goto bad; }
693
694 if ((rtbl = rt_gettable(dst->sa_family)) == NULL)
695 senderr(ESRCH);
696 if (flags & RTF_HOST)
697 netmask = NULL;
698 switch (req) {
699 case RTM_DELETE:
700 if (netmask) {
701 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
702 netmask);
703 dst = (struct sockaddr *)&maskeddst;
704 }
705 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
706 senderr(ESRCH);
707 if ((rt->rt_flags & RTF_CLONING) != 0) {
708 /* clean up any cloned children */
709 rtflushclone(dst->sa_family, rt);
710 }
711 if ((rt = rt_deladdr(rtbl, dst, netmask)) == NULL)
712 senderr(ESRCH);
713 if (rt->rt_gwroute) {
714 RTFREE(rt->rt_gwroute);
715 rt->rt_gwroute = NULL;
716 }
717 if (rt->rt_parent) {
718 rt->rt_parent->rt_refcnt--;
719 rt->rt_parent = NULL;
720 }
721 rt->rt_flags &= ~RTF_UP;
722 if ((ifa = rt->rt_ifa)) {
723 if (ifa->ifa_flags & IFA_ROUTE &&
724 rt_ifa_connected(rt, ifa)) {
725 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
726 "deleted IFA_ROUTE\n",
727 (void *)rt->_rt_key, (void *)ifa);
728 ifa->ifa_flags &= ~IFA_ROUTE;
729 }
730 if (ifa->ifa_rtrequest)
731 ifa->ifa_rtrequest(RTM_DELETE, rt, info);
732 }
733 rttrash++;
734 if (ret_nrt)
735 *ret_nrt = rt;
736 else if (rt->rt_refcnt <= 0) {
737 rt->rt_refcnt++;
738 rtfree(rt);
739 }
740 break;
741
742 case RTM_RESOLVE:
743 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
744 senderr(EINVAL);
745 if ((rt->rt_flags & RTF_CLONING) == 0)
746 senderr(EINVAL);
747 ifa = rt->rt_ifa;
748 flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC);
749 flags |= RTF_CLONED;
750 gateway = rt->rt_gateway;
751 flags |= RTF_HOST;
752 goto makeroute;
753
754 case RTM_ADD:
755 if (info->rti_ifa == NULL && (error = rt_getifa(info)))
756 senderr(error);
757 ifa = info->rti_ifa;
758 makeroute:
759 /* Already at splsoftnet() so pool_get/pool_put are safe */
760 rt = pool_get(&rtentry_pool, PR_NOWAIT);
761 if (rt == NULL)
762 senderr(ENOBUFS);
763 memset(rt, 0, sizeof(*rt));
764 rt->rt_flags = RTF_UP | flags;
765 LIST_INIT(&rt->rt_timer);
766 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
767 if (rt_setkey(rt, dst, M_NOWAIT) == NULL ||
768 rt_setgate(rt, gateway) != 0) {
769 pool_put(&rtentry_pool, rt);
770 senderr(ENOBUFS);
771 }
772 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
773 if (netmask) {
774 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
775 netmask);
776 rt_setkey(rt, (struct sockaddr *)&maskeddst, M_NOWAIT);
777 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
778 } else {
779 rt_setkey(rt, dst, M_NOWAIT);
780 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
781 }
782 rt_set_ifa(rt, ifa);
783 if (info->rti_info[RTAX_TAG] != NULL)
784 rt_settag(rt, info->rti_info[RTAX_TAG]);
785 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
786 if (info->rti_info[RTAX_IFP] != NULL &&
787 (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL &&
788 ifa2->ifa_ifp != NULL)
789 rt->rt_ifp = ifa2->ifa_ifp;
790 else
791 rt->rt_ifp = ifa->ifa_ifp;
792 if (req == RTM_RESOLVE) {
793 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
794 rt->rt_parent = *ret_nrt;
795 rt->rt_parent->rt_refcnt++;
796 }
797 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
798 rc = rt_addaddr(rtbl, rt, netmask);
799 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
800 if (rc != 0 && (crt = rtalloc1(rt_getkey(rt), 0)) != NULL) {
801 /* overwrite cloned route */
802 if ((crt->rt_flags & RTF_CLONED) != 0) {
803 rtdeletemsg(crt);
804 rc = rt_addaddr(rtbl, rt, netmask);
805 }
806 RTFREE(crt);
807 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
808 }
809 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
810 if (rc != 0) {
811 IFAFREE(ifa);
812 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent)
813 rtfree(rt->rt_parent);
814 if (rt->rt_gwroute)
815 rtfree(rt->rt_gwroute);
816 rt_destroy(rt);
817 pool_put(&rtentry_pool, rt);
818 senderr(rc);
819 }
820 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
821 if (ifa->ifa_rtrequest)
822 ifa->ifa_rtrequest(req, rt, info);
823 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
824 if (ret_nrt) {
825 *ret_nrt = rt;
826 rt->rt_refcnt++;
827 }
828 if ((rt->rt_flags & RTF_CLONING) != 0) {
829 /* clean up any cloned children */
830 rtflushclone(dst->sa_family, rt);
831 }
832 rtflushall(dst->sa_family);
833 break;
834 case RTM_GET:
835 if (netmask != NULL) {
836 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst,
837 netmask);
838 dst = (struct sockaddr *)&maskeddst;
839 }
840 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
841 senderr(ESRCH);
842 if (ret_nrt != NULL) {
843 *ret_nrt = rt;
844 rt->rt_refcnt++;
845 }
846 break;
847 }
848 bad:
849 splx(s);
850 return error;
851 }
852
853 int
854 rt_setgate(struct rtentry *rt, const struct sockaddr *gate)
855 {
856 KASSERT(rt != rt->rt_gwroute);
857
858 KASSERT(rt->_rt_key != NULL);
859 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
860
861 if (rt->rt_gwroute) {
862 RTFREE(rt->rt_gwroute);
863 rt->rt_gwroute = NULL;
864 }
865 KASSERT(rt->_rt_key != NULL);
866 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
867 if (rt->rt_gateway != NULL)
868 sockaddr_free(rt->rt_gateway);
869 KASSERT(rt->_rt_key != NULL);
870 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
871 if ((rt->rt_gateway = sockaddr_dup(gate, M_NOWAIT)) == NULL)
872 return ENOMEM;
873 KASSERT(rt->_rt_key != NULL);
874 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
875
876 if (rt->rt_flags & RTF_GATEWAY) {
877 KASSERT(rt->_rt_key != NULL);
878 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
879 rt->rt_gwroute = rtalloc1(gate, 1);
880 /*
881 * If we switched gateways, grab the MTU from the new
882 * gateway route if the current MTU, if the current MTU is
883 * greater than the MTU of gateway.
884 * Note that, if the MTU of gateway is 0, we will reset the
885 * MTU of the route to run PMTUD again from scratch. XXX
886 */
887 KASSERT(rt->_rt_key != NULL);
888 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
889 if (rt->rt_gwroute
890 && !(rt->rt_rmx.rmx_locks & RTV_MTU)
891 && rt->rt_rmx.rmx_mtu
892 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) {
893 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu;
894 }
895 }
896 KASSERT(rt->_rt_key != NULL);
897 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
898 return 0;
899 }
900
901 void
902 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst,
903 const struct sockaddr *netmask)
904 {
905 const char *netmaskp = &netmask->sa_data[0],
906 *srcp = &src->sa_data[0];
907 char *dstp = &dst->sa_data[0];
908 const char *maskend = (char *)dst + MIN(netmask->sa_len, src->sa_len);
909 const char *srcend = (char *)dst + src->sa_len;
910
911 dst->sa_len = src->sa_len;
912 dst->sa_family = src->sa_family;
913
914 while (dstp < maskend)
915 *dstp++ = *srcp++ & *netmaskp++;
916 if (dstp < srcend)
917 memset(dstp, 0, (size_t)(srcend - dstp));
918 }
919
920 /*
921 * Set up or tear down a routing table entry, normally
922 * for an interface.
923 */
924 int
925 rtinit(struct ifaddr *ifa, int cmd, int flags)
926 {
927 struct rtentry *rt;
928 struct sockaddr *dst, *odst;
929 struct sockaddr_storage maskeddst;
930 struct rtentry *nrt = NULL;
931 int error;
932 struct rt_addrinfo info;
933 struct sockaddr_dl *sdl;
934 const struct sockaddr_dl *ifsdl;
935
936 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
937 if (cmd == RTM_DELETE) {
938 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
939 /* Delete subnet route for this interface */
940 odst = dst;
941 dst = (struct sockaddr *)&maskeddst;
942 rt_maskedcopy(odst, dst, ifa->ifa_netmask);
943 }
944 if ((rt = rtalloc1(dst, 0)) != NULL) {
945 rt->rt_refcnt--;
946 if (rt->rt_ifa != ifa)
947 return (flags & RTF_HOST) ? EHOSTUNREACH
948 : ENETUNREACH;
949 }
950 }
951 memset(&info, 0, sizeof(info));
952 info.rti_ifa = ifa;
953 info.rti_flags = flags | ifa->ifa_flags;
954 info.rti_info[RTAX_DST] = dst;
955 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
956 /*
957 * XXX here, it seems that we are assuming that ifa_netmask is NULL
958 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate
959 * variable) when RTF_HOST is 1. still not sure if i can safely
960 * change it to meet bsdi4 behavior.
961 */
962 if (cmd != RTM_LLINFO_UPD)
963 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
964 error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info,
965 &nrt);
966 if (error != 0 || (rt = nrt) == NULL)
967 ;
968 else switch (cmd) {
969 case RTM_DELETE:
970 rt_newaddrmsg(cmd, ifa, error, nrt);
971 if (rt->rt_refcnt <= 0) {
972 rt->rt_refcnt++;
973 rtfree(rt);
974 }
975 break;
976 case RTM_LLINFO_UPD:
977 rt->rt_refcnt--;
978 RT_DPRINTF("%s: updating%s\n", __func__,
979 ((rt->rt_flags & RTF_LLINFO) == 0) ? " (no llinfo)" : "");
980
981 ifsdl = ifa->ifa_ifp->if_sadl;
982
983 if ((rt->rt_flags & RTF_LLINFO) != 0 &&
984 (sdl = satosdl(rt->rt_gateway)) != NULL &&
985 sdl->sdl_family == AF_LINK &&
986 sockaddr_dl_setaddr(sdl, sdl->sdl_len, CLLADDR(ifsdl),
987 ifa->ifa_ifp->if_addrlen) == NULL) {
988 error = EINVAL;
989 break;
990 }
991
992 if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL)
993 ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info);
994 rt_newaddrmsg(RTM_CHANGE, ifa, error, nrt);
995 break;
996 case RTM_ADD:
997 rt->rt_refcnt--;
998 if (rt->rt_ifa != ifa) {
999 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
1000 rt->rt_ifa);
1001 if (rt->rt_ifa->ifa_rtrequest != NULL) {
1002 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
1003 &info);
1004 }
1005 rt_replace_ifa(rt, ifa);
1006 rt->rt_ifp = ifa->ifa_ifp;
1007 if (ifa->ifa_rtrequest != NULL)
1008 ifa->ifa_rtrequest(RTM_ADD, rt, &info);
1009 }
1010 rt_newaddrmsg(cmd, ifa, error, nrt);
1011 break;
1012 }
1013 return error;
1014 }
1015
1016 /*
1017 * Route timer routines. These routes allow functions to be called
1018 * for various routes at any time. This is useful in supporting
1019 * path MTU discovery and redirect route deletion.
1020 *
1021 * This is similar to some BSDI internal functions, but it provides
1022 * for multiple queues for efficiency's sake...
1023 */
1024
1025 LIST_HEAD(, rttimer_queue) rttimer_queue_head;
1026 static int rt_init_done = 0;
1027
1028 #define RTTIMER_CALLOUT(r) do { \
1029 if (r->rtt_func != NULL) { \
1030 (*r->rtt_func)(r->rtt_rt, r); \
1031 } else { \
1032 rtrequest((int) RTM_DELETE, \
1033 rt_getkey(r->rtt_rt), \
1034 0, 0, 0, 0); \
1035 } \
1036 } while (/*CONSTCOND*/0)
1037
1038 /*
1039 * Some subtle order problems with domain initialization mean that
1040 * we cannot count on this being run from rt_init before various
1041 * protocol initializations are done. Therefore, we make sure
1042 * that this is run when the first queue is added...
1043 */
1044
1045 void
1046 rt_timer_init(void)
1047 {
1048 assert(rt_init_done == 0);
1049
1050 LIST_INIT(&rttimer_queue_head);
1051 callout_init(&rt_timer_ch, 0);
1052 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
1053 rt_init_done = 1;
1054 }
1055
1056 struct rttimer_queue *
1057 rt_timer_queue_create(u_int timeout)
1058 {
1059 struct rttimer_queue *rtq;
1060
1061 if (rt_init_done == 0)
1062 rt_timer_init();
1063
1064 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq);
1065 if (rtq == NULL)
1066 return NULL;
1067 memset(rtq, 0, sizeof(*rtq));
1068
1069 rtq->rtq_timeout = timeout;
1070 TAILQ_INIT(&rtq->rtq_head);
1071 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link);
1072
1073 return rtq;
1074 }
1075
1076 void
1077 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout)
1078 {
1079
1080 rtq->rtq_timeout = timeout;
1081 }
1082
1083 void
1084 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy)
1085 {
1086 struct rttimer *r;
1087
1088 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) {
1089 LIST_REMOVE(r, rtt_link);
1090 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
1091 if (destroy)
1092 RTTIMER_CALLOUT(r);
1093 /* we are already at splsoftnet */
1094 pool_put(&rttimer_pool, r);
1095 if (rtq->rtq_count > 0)
1096 rtq->rtq_count--;
1097 else
1098 printf("rt_timer_queue_remove_all: "
1099 "rtq_count reached 0\n");
1100 }
1101 }
1102
1103 void
1104 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy)
1105 {
1106
1107 rt_timer_queue_remove_all(rtq, destroy);
1108
1109 LIST_REMOVE(rtq, rtq_link);
1110
1111 /*
1112 * Caller is responsible for freeing the rttimer_queue structure.
1113 */
1114 }
1115
1116 unsigned long
1117 rt_timer_count(struct rttimer_queue *rtq)
1118 {
1119 return rtq->rtq_count;
1120 }
1121
1122 void
1123 rt_timer_remove_all(struct rtentry *rt, int destroy)
1124 {
1125 struct rttimer *r;
1126
1127 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) {
1128 LIST_REMOVE(r, rtt_link);
1129 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1130 if (destroy)
1131 RTTIMER_CALLOUT(r);
1132 if (r->rtt_queue->rtq_count > 0)
1133 r->rtt_queue->rtq_count--;
1134 else
1135 printf("rt_timer_remove_all: rtq_count reached 0\n");
1136 /* we are already at splsoftnet */
1137 pool_put(&rttimer_pool, r);
1138 }
1139 }
1140
1141 int
1142 rt_timer_add(struct rtentry *rt,
1143 void (*func)(struct rtentry *, struct rttimer *),
1144 struct rttimer_queue *queue)
1145 {
1146 struct rttimer *r;
1147 int s;
1148
1149 /*
1150 * If there's already a timer with this action, destroy it before
1151 * we add a new one.
1152 */
1153 LIST_FOREACH(r, &rt->rt_timer, rtt_link) {
1154 if (r->rtt_func == func)
1155 break;
1156 }
1157 if (r != NULL) {
1158 LIST_REMOVE(r, rtt_link);
1159 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1160 if (r->rtt_queue->rtq_count > 0)
1161 r->rtt_queue->rtq_count--;
1162 else
1163 printf("rt_timer_add: rtq_count reached 0\n");
1164 } else {
1165 s = splsoftnet();
1166 r = pool_get(&rttimer_pool, PR_NOWAIT);
1167 splx(s);
1168 if (r == NULL)
1169 return ENOBUFS;
1170 }
1171
1172 memset(r, 0, sizeof(*r));
1173
1174 r->rtt_rt = rt;
1175 r->rtt_time = time_uptime;
1176 r->rtt_func = func;
1177 r->rtt_queue = queue;
1178 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link);
1179 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next);
1180 r->rtt_queue->rtq_count++;
1181
1182 return 0;
1183 }
1184
1185 /* ARGSUSED */
1186 void
1187 rt_timer_timer(void *arg)
1188 {
1189 struct rttimer_queue *rtq;
1190 struct rttimer *r;
1191 int s;
1192
1193 s = splsoftnet();
1194 LIST_FOREACH(rtq, &rttimer_queue_head, rtq_link) {
1195 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL &&
1196 (r->rtt_time + rtq->rtq_timeout) < time_uptime) {
1197 LIST_REMOVE(r, rtt_link);
1198 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
1199 RTTIMER_CALLOUT(r);
1200 pool_put(&rttimer_pool, r);
1201 if (rtq->rtq_count > 0)
1202 rtq->rtq_count--;
1203 else
1204 printf("rt_timer_timer: rtq_count reached 0\n");
1205 }
1206 }
1207 splx(s);
1208
1209 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
1210 }
1211
1212 static struct rtentry *
1213 _rtcache_init(struct route *ro, int flag)
1214 {
1215 rtcache_invariants(ro);
1216 KASSERT(ro->_ro_rt == NULL);
1217
1218 if (rtcache_getdst(ro) == NULL)
1219 return NULL;
1220 ro->ro_invalid = false;
1221 if ((ro->_ro_rt = rtalloc1(rtcache_getdst(ro), flag)) != NULL)
1222 rtcache(ro);
1223
1224 rtcache_invariants(ro);
1225 return ro->_ro_rt;
1226 }
1227
1228 struct rtentry *
1229 rtcache_init(struct route *ro)
1230 {
1231 return _rtcache_init(ro, 1);
1232 }
1233
1234 struct rtentry *
1235 rtcache_init_noclone(struct route *ro)
1236 {
1237 return _rtcache_init(ro, 0);
1238 }
1239
1240 struct rtentry *
1241 rtcache_update(struct route *ro, int clone)
1242 {
1243 rtcache_clear(ro);
1244 return _rtcache_init(ro, clone);
1245 }
1246
1247 void
1248 rtcache_copy(struct route *new_ro, const struct route *old_ro)
1249 {
1250 struct rtentry *rt;
1251
1252 KASSERT(new_ro != old_ro);
1253 rtcache_invariants(new_ro);
1254 rtcache_invariants(old_ro);
1255
1256 if ((rt = rtcache_validate(old_ro)) != NULL)
1257 rt->rt_refcnt++;
1258
1259 if (rtcache_getdst(old_ro) == NULL ||
1260 rtcache_setdst(new_ro, rtcache_getdst(old_ro)) != 0)
1261 return;
1262
1263 new_ro->ro_invalid = false;
1264 if ((new_ro->_ro_rt = rt) != NULL)
1265 rtcache(new_ro);
1266 rtcache_invariants(new_ro);
1267 }
1268
1269 static struct dom_rtlist invalid_routes = LIST_HEAD_INITIALIZER(dom_rtlist);
1270
1271 void
1272 rtcache_invalidate(struct dom_rtlist *rtlist)
1273 {
1274 struct route *ro;
1275
1276 while ((ro = LIST_FIRST(rtlist)) != NULL) {
1277 rtcache_invariants(ro);
1278 KASSERT(ro->_ro_rt != NULL);
1279 ro->ro_invalid = true;
1280 LIST_REMOVE(ro, ro_rtcache_next);
1281 LIST_INSERT_HEAD(&invalid_routes, ro, ro_rtcache_next);
1282 rtcache_invariants(ro);
1283 }
1284 }
1285
1286 void
1287 rtcache_clear(struct route *ro)
1288 {
1289 rtcache_invariants(ro);
1290 if (ro->_ro_rt == NULL)
1291 return;
1292
1293 LIST_REMOVE(ro, ro_rtcache_next);
1294
1295 RTFREE(ro->_ro_rt);
1296 ro->_ro_rt = NULL;
1297 ro->ro_invalid = false;
1298 rtcache_invariants(ro);
1299 }
1300
1301 struct rtentry *
1302 rtcache_lookup2(struct route *ro, const struct sockaddr *dst, int clone,
1303 int *hitp)
1304 {
1305 const struct sockaddr *odst;
1306 struct rtentry *rt = NULL;
1307
1308 rtcache_invariants(ro);
1309
1310 odst = rtcache_getdst(ro);
1311
1312 if (odst == NULL)
1313 ;
1314 else if (sockaddr_cmp(odst, dst) != 0)
1315 rtcache_free(ro);
1316 else if ((rt = rtcache_validate(ro)) == NULL)
1317 rtcache_clear(ro);
1318
1319 if (rt == NULL) {
1320 *hitp = 0;
1321 if (rtcache_setdst(ro, dst) == 0)
1322 rt = _rtcache_init(ro, clone);
1323 } else
1324 *hitp = 1;
1325
1326 rtcache_invariants(ro);
1327
1328 return rt;
1329 }
1330
1331 void
1332 rtcache_free(struct route *ro)
1333 {
1334 rtcache_clear(ro);
1335 if (ro->ro_sa != NULL) {
1336 sockaddr_free(ro->ro_sa);
1337 ro->ro_sa = NULL;
1338 }
1339 rtcache_invariants(ro);
1340 }
1341
1342 int
1343 rtcache_setdst(struct route *ro, const struct sockaddr *sa)
1344 {
1345 KASSERT(sa != NULL);
1346
1347 rtcache_invariants(ro);
1348 if (ro->ro_sa != NULL && ro->ro_sa->sa_family == sa->sa_family) {
1349 rtcache_clear(ro);
1350 if (sockaddr_copy(ro->ro_sa, ro->ro_sa->sa_len, sa) != NULL) {
1351 rtcache_invariants(ro);
1352 return 0;
1353 }
1354 sockaddr_free(ro->ro_sa);
1355 } else if (ro->ro_sa != NULL)
1356 rtcache_free(ro); /* free ro_sa, wrong family */
1357
1358 KASSERT(ro->_ro_rt == NULL);
1359
1360 if ((ro->ro_sa = sockaddr_dup(sa, M_NOWAIT)) == NULL) {
1361 rtcache_invariants(ro);
1362 return ENOMEM;
1363 }
1364 rtcache_invariants(ro);
1365 return 0;
1366 }
1367
1368 const struct sockaddr *
1369 rt_settag(struct rtentry *rt, const struct sockaddr *tag)
1370 {
1371 if (rt->rt_tag != tag) {
1372 if (rt->rt_tag != NULL)
1373 sockaddr_free(rt->rt_tag);
1374 rt->rt_tag = sockaddr_dup(tag, M_NOWAIT);
1375 }
1376 return rt->rt_tag;
1377 }
1378
1379 struct sockaddr *
1380 rt_gettag(struct rtentry *rt)
1381 {
1382 return rt->rt_tag;
1383 }
1384