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