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