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