route.c revision 1.87 1 /* $NetBSD: route.c,v 1.87 2007/03/04 06:03:18 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1998 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 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. Neither the name of the project nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 */
68
69 /*
70 * Copyright (c) 1980, 1986, 1991, 1993
71 * The Regents of the University of California. All rights reserved.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions
75 * are met:
76 * 1. Redistributions of source code must retain the above copyright
77 * notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce the above copyright
79 * notice, this list of conditions and the following disclaimer in the
80 * documentation and/or other materials provided with the distribution.
81 * 3. Neither the name of the University nor the names of its contributors
82 * may be used to endorse or promote products derived from this software
83 * without specific prior written permission.
84 *
85 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
88 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
95 * SUCH DAMAGE.
96 *
97 * @(#)route.c 8.3 (Berkeley) 1/9/95
98 */
99
100 #include <sys/cdefs.h>
101 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.87 2007/03/04 06:03:18 christos Exp $");
102
103 #include <sys/param.h>
104 #include <sys/systm.h>
105 #include <sys/callout.h>
106 #include <sys/proc.h>
107 #include <sys/mbuf.h>
108 #include <sys/socket.h>
109 #include <sys/socketvar.h>
110 #include <sys/domain.h>
111 #include <sys/protosw.h>
112 #include <sys/kernel.h>
113 #include <sys/ioctl.h>
114 #include <sys/pool.h>
115
116 #include <net/if.h>
117 #include <net/route.h>
118 #include <net/raw_cb.h>
119
120 #include <netinet/in.h>
121 #include <netinet/in_var.h>
122
123
124 struct route_cb route_cb;
125 struct rtstat rtstat;
126 struct radix_node_head *rt_tables[AF_MAX+1];
127
128 int rttrash; /* routes not in table but not freed */
129 struct sockaddr wildcard; /* zero valued cookie for wildcard searches */
130
131 POOL_INIT(rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", NULL);
132 POOL_INIT(rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", NULL);
133
134 struct callout rt_timer_ch; /* callout for rt_timer_timer() */
135
136 static int rtdeletemsg(struct rtentry *);
137 static int rtflushclone1(struct radix_node *, void *);
138 static void rtflushclone(struct radix_node_head *, struct rtentry *);
139
140 struct ifaddr *
141 rt_get_ifa(struct rtentry *rt)
142 {
143 struct ifaddr *ifa;
144
145 if ((ifa = rt->rt_ifa) == NULL)
146 return ifa;
147 else if (ifa->ifa_getifa == NULL)
148 return ifa;
149 #if 0
150 else if (ifa->ifa_seqno != NULL && *ifa->ifa_seqno == rt->rt_ifa_seqno)
151 return ifa;
152 #endif
153 else {
154 ifa = (*ifa->ifa_getifa)(ifa, rt_key(rt));
155 rt_replace_ifa(rt, ifa);
156 return ifa;
157 }
158 }
159
160 static void
161 rt_set_ifa1(struct rtentry *rt, struct ifaddr *ifa)
162 {
163 rt->rt_ifa = ifa;
164 if (ifa->ifa_seqno != NULL)
165 rt->rt_ifa_seqno = *ifa->ifa_seqno;
166 }
167
168 void
169 rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa)
170 {
171 IFAREF(ifa);
172 IFAFREE(rt->rt_ifa);
173 rt_set_ifa1(rt, ifa);
174 }
175
176 static void
177 rt_set_ifa(struct rtentry *rt, struct ifaddr *ifa)
178 {
179 IFAREF(ifa);
180 rt_set_ifa1(rt, ifa);
181 }
182
183 void
184 rtable_init(void **table)
185 {
186 struct domain *dom;
187 DOMAIN_FOREACH(dom)
188 if (dom->dom_rtattach)
189 dom->dom_rtattach(&table[dom->dom_family],
190 dom->dom_rtoffset);
191 }
192
193 void
194 route_init(void)
195 {
196
197 rn_init(); /* initialize all zeroes, all ones, mask table */
198 rtable_init((void **)rt_tables);
199 }
200
201 void
202 rtflushall(int family)
203 {
204 const struct domain *dom;
205
206 if ((dom = pffinddomain(family)) != NULL && dom->dom_rtflushall != NULL)
207 (*dom->dom_rtflushall)();
208 }
209
210 void
211 rtflush(struct route *ro)
212 {
213 const struct domain *dom;
214
215 KASSERT(ro->ro_rt != NULL);
216
217 RTFREE(ro->ro_rt);
218 ro->ro_rt = NULL;
219
220 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) != NULL &&
221 dom->dom_rtflush != NULL)
222 (*dom->dom_rtflush)(ro);
223 }
224
225 void
226 rtcache(struct route *ro)
227 {
228 const struct domain *dom;
229
230 KASSERT(ro->ro_rt != NULL);
231
232 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) != NULL &&
233 dom->dom_rtcache != NULL)
234 (*dom->dom_rtcache)(ro);
235 }
236
237 /*
238 * Packet routing routines.
239 */
240 void
241 rtalloc(struct route *ro)
242 {
243 if (ro->ro_rt != NULL) {
244 if (ro->ro_rt->rt_ifp != NULL &&
245 (ro->ro_rt->rt_flags & RTF_UP) != 0)
246 return;
247 rtflush(ro);
248 }
249 if ((ro->ro_rt = rtalloc1(rtcache_getdst(ro), 1)) == NULL)
250 return;
251 rtcache(ro);
252 }
253
254 struct rtentry *
255 rtalloc1(const struct sockaddr *dst, int report)
256 {
257 struct radix_node_head *rnh = rt_tables[dst->sa_family];
258 struct rtentry *rt;
259 struct radix_node *rn;
260 struct rtentry *newrt = NULL;
261 struct rt_addrinfo info;
262 int s = splsoftnet(), err = 0, msgtype = RTM_MISS;
263
264 if (rnh && (rn = rnh->rnh_matchaddr(dst, rnh)) &&
265 ((rn->rn_flags & RNF_ROOT) == 0)) {
266 newrt = rt = (struct rtentry *)rn;
267 if (report && (rt->rt_flags & RTF_CLONING)) {
268 err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0,
269 &newrt);
270 if (err) {
271 newrt = rt;
272 rt->rt_refcnt++;
273 goto miss;
274 }
275 KASSERT(newrt != NULL);
276 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
277 msgtype = RTM_RESOLVE;
278 goto miss;
279 }
280 /* Inform listeners of the new route */
281 memset(&info, 0, sizeof(info));
282 info.rti_info[RTAX_DST] = rt_key(rt);
283 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
284 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
285 if (rt->rt_ifp != NULL) {
286 info.rti_info[RTAX_IFP] =
287 TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr;
288 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
289 }
290 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0);
291 } else
292 rt->rt_refcnt++;
293 } else {
294 rtstat.rts_unreach++;
295 miss: if (report) {
296 memset((void *)&info, 0, sizeof(info));
297 info.rti_info[RTAX_DST] = dst;
298 rt_missmsg(msgtype, &info, 0, err);
299 }
300 }
301 splx(s);
302 return (newrt);
303 }
304
305 void
306 rtfree(struct rtentry *rt)
307 {
308 struct ifaddr *ifa;
309
310 if (rt == NULL)
311 panic("rtfree");
312 rt->rt_refcnt--;
313 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
314 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
315 panic ("rtfree 2");
316 rttrash--;
317 if (rt->rt_refcnt < 0) {
318 printf("rtfree: %p not freed (neg refs)\n", rt);
319 return;
320 }
321 rt_timer_remove_all(rt, 0);
322 ifa = rt->rt_ifa;
323 rt->rt_ifa = NULL;
324 IFAFREE(ifa);
325 rt->rt_ifp = NULL;
326 Free(rt_key(rt));
327 pool_put(&rtentry_pool, rt);
328 }
329 }
330
331 void
332 ifafree(struct ifaddr *ifa)
333 {
334
335 #ifdef DIAGNOSTIC
336 if (ifa == NULL)
337 panic("ifafree: null ifa");
338 if (ifa->ifa_refcnt != 0)
339 panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt);
340 #endif
341 #ifdef IFAREF_DEBUG
342 printf("ifafree: freeing ifaddr %p\n", ifa);
343 #endif
344 free(ifa, M_IFADDR);
345 }
346
347 /*
348 * Force a routing table entry to the specified
349 * destination to go through the given gateway.
350 * Normally called as a result of a routing redirect
351 * message from the network layer.
352 *
353 * N.B.: must be called at splsoftnet
354 */
355 void
356 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway,
357 const struct sockaddr *netmask, int flags, const struct sockaddr *src,
358 struct rtentry **rtp)
359 {
360 struct rtentry *rt;
361 int error = 0;
362 u_quad_t *stat = NULL;
363 struct rt_addrinfo info;
364 struct ifaddr *ifa;
365
366 /* verify the gateway is directly reachable */
367 if ((ifa = ifa_ifwithnet(gateway)) == NULL) {
368 error = ENETUNREACH;
369 goto out;
370 }
371 rt = rtalloc1(dst, 0);
372 /*
373 * If the redirect isn't from our current router for this dst,
374 * it's either old or wrong. If it redirects us to ourselves,
375 * we have a routing loop, perhaps as a result of an interface
376 * going down recently.
377 */
378 #define equal(a1, a2) \
379 ((a1)->sa_len == (a2)->sa_len && \
380 memcmp((a1), (a2), (a1)->sa_len) == 0)
381 if (!(flags & RTF_DONE) && rt &&
382 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
383 error = EINVAL;
384 else if (ifa_ifwithaddr(gateway))
385 error = EHOSTUNREACH;
386 if (error)
387 goto done;
388 /*
389 * Create a new entry if we just got back a wildcard entry
390 * or the lookup failed. This is necessary for hosts
391 * which use routing redirects generated by smart gateways
392 * to dynamically build the routing tables.
393 */
394 if ((rt == NULL) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
395 goto create;
396 /*
397 * Don't listen to the redirect if it's
398 * for a route to an interface.
399 */
400 if (rt->rt_flags & RTF_GATEWAY) {
401 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
402 /*
403 * Changing from route to net => route to host.
404 * Create new route, rather than smashing route to net.
405 */
406 create:
407 if (rt)
408 rtfree(rt);
409 flags |= RTF_GATEWAY | RTF_DYNAMIC;
410 info.rti_info[RTAX_DST] = dst;
411 info.rti_info[RTAX_GATEWAY] = gateway;
412 info.rti_info[RTAX_NETMASK] = netmask;
413 info.rti_ifa = ifa;
414 info.rti_flags = flags;
415 rt = NULL;
416 error = rtrequest1(RTM_ADD, &info, &rt);
417 if (rt != NULL)
418 flags = rt->rt_flags;
419 stat = &rtstat.rts_dynamic;
420 } else {
421 /*
422 * Smash the current notion of the gateway to
423 * this destination. Should check about netmask!!!
424 */
425 rt->rt_flags |= RTF_MODIFIED;
426 flags |= RTF_MODIFIED;
427 stat = &rtstat.rts_newgateway;
428 rt_setgate(rt, rt_key(rt), gateway);
429 }
430 } else
431 error = EHOSTUNREACH;
432 done:
433 if (rt) {
434 if (rtp && !error)
435 *rtp = rt;
436 else
437 rtfree(rt);
438 }
439 out:
440 if (error)
441 rtstat.rts_badredirect++;
442 else if (stat != NULL)
443 (*stat)++;
444 memset((void *)&info, 0, sizeof(info));
445 info.rti_info[RTAX_DST] = dst;
446 info.rti_info[RTAX_GATEWAY] = gateway;
447 info.rti_info[RTAX_NETMASK] = netmask;
448 info.rti_info[RTAX_AUTHOR] = src;
449 rt_missmsg(RTM_REDIRECT, &info, flags, error);
450 }
451
452 /*
453 * Delete a route and generate a message
454 */
455 static int
456 rtdeletemsg(struct rtentry *rt)
457 {
458 int error;
459 struct rt_addrinfo info;
460
461 /*
462 * Request the new route so that the entry is not actually
463 * deleted. That will allow the information being reported to
464 * be accurate (and consistent with route_output()).
465 */
466 memset((void *)&info, 0, sizeof(info));
467 info.rti_info[RTAX_DST] = rt_key(rt);
468 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
469 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
470 info.rti_flags = rt->rt_flags;
471 error = rtrequest1(RTM_DELETE, &info, &rt);
472
473 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error);
474
475 /* Adjust the refcount */
476 if (error == 0 && rt->rt_refcnt <= 0) {
477 rt->rt_refcnt++;
478 rtfree(rt);
479 }
480 return (error);
481 }
482
483 static int
484 rtflushclone1(struct radix_node *rn, void *arg)
485 {
486 struct rtentry *rt, *parent;
487
488 rt = (struct rtentry *)rn;
489 parent = (struct rtentry *)arg;
490 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent)
491 rtdeletemsg(rt);
492 return 0;
493 }
494
495 static void
496 rtflushclone(struct radix_node_head *rnh, struct rtentry *parent)
497 {
498
499 #ifdef DIAGNOSTIC
500 if (!parent || (parent->rt_flags & RTF_CLONING) == 0)
501 panic("rtflushclone: called with a non-cloning route");
502 if (!rnh->rnh_walktree)
503 panic("rtflushclone: no rnh_walktree");
504 #endif
505 rnh->rnh_walktree(rnh, rtflushclone1, (void *)parent);
506 }
507
508 /*
509 * Routing table ioctl interface.
510 */
511 int
512 rtioctl(u_long req, void *data, struct lwp *l)
513 {
514 return (EOPNOTSUPP);
515 }
516
517 struct ifaddr *
518 ifa_ifwithroute(int flags, const struct sockaddr *dst,
519 const struct sockaddr *gateway)
520 {
521 struct ifaddr *ifa;
522 if ((flags & RTF_GATEWAY) == 0) {
523 /*
524 * If we are adding a route to an interface,
525 * and the interface is a pt to pt link
526 * we should search for the destination
527 * as our clue to the interface. Otherwise
528 * we can use the local address.
529 */
530 ifa = NULL;
531 if (flags & RTF_HOST)
532 ifa = ifa_ifwithdstaddr(dst);
533 if (ifa == NULL)
534 ifa = ifa_ifwithaddr(gateway);
535 } else {
536 /*
537 * If we are adding a route to a remote net
538 * or host, the gateway may still be on the
539 * other end of a pt to pt link.
540 */
541 ifa = ifa_ifwithdstaddr(gateway);
542 }
543 if (ifa == NULL)
544 ifa = ifa_ifwithnet(gateway);
545 if (ifa == NULL) {
546 struct rtentry *rt = rtalloc1(dst, 0);
547 if (rt == NULL)
548 return NULL;
549 rt->rt_refcnt--;
550 if ((ifa = rt->rt_ifa) == NULL)
551 return NULL;
552 }
553 if (ifa->ifa_addr->sa_family != dst->sa_family) {
554 struct ifaddr *oifa = ifa;
555 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
556 if (ifa == 0)
557 ifa = oifa;
558 }
559 return (ifa);
560 }
561
562 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
563
564 int
565 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway,
566 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt)
567 {
568 struct rt_addrinfo info;
569
570 memset(&info, 0, sizeof(info));
571 info.rti_flags = flags;
572 info.rti_info[RTAX_DST] = dst;
573 info.rti_info[RTAX_GATEWAY] = gateway;
574 info.rti_info[RTAX_NETMASK] = netmask;
575 return rtrequest1(req, &info, ret_nrt);
576 }
577
578 int
579 rt_getifa(struct rt_addrinfo *info)
580 {
581 struct ifaddr *ifa;
582 const struct sockaddr *dst = info->rti_info[RTAX_DST];
583 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
584 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA];
585 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
586 int flags = info->rti_flags;
587
588 /*
589 * ifp may be specified by sockaddr_dl when protocol address
590 * is ambiguous
591 */
592 if (info->rti_ifp == NULL && ifpaddr != NULL
593 && ifpaddr->sa_family == AF_LINK &&
594 (ifa = ifa_ifwithnet((const struct sockaddr *)ifpaddr)) != NULL)
595 info->rti_ifp = ifa->ifa_ifp;
596 if (info->rti_ifa == NULL && ifaaddr != NULL)
597 info->rti_ifa = ifa_ifwithaddr(ifaaddr);
598 if (info->rti_ifa == NULL) {
599 const struct sockaddr *sa;
600
601 sa = ifaaddr != NULL ? ifaaddr :
602 (gateway != NULL ? gateway : dst);
603 if (sa != NULL && info->rti_ifp != NULL)
604 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
605 else if (dst != NULL && gateway != NULL)
606 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
607 else if (sa != NULL)
608 info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
609 }
610 if ((ifa = info->rti_ifa) == NULL)
611 return ENETUNREACH;
612 if (ifa->ifa_getifa != NULL)
613 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst);
614 if (info->rti_ifp == NULL)
615 info->rti_ifp = ifa->ifa_ifp;
616 return 0;
617 }
618
619 int
620 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
621 {
622 int s = splsoftnet();
623 int error = 0;
624 struct rtentry *rt, *crt;
625 struct radix_node *rn;
626 struct radix_node_head *rnh;
627 struct ifaddr *ifa;
628 struct sockaddr_storage deldst;
629 const struct sockaddr *dst = info->rti_info[RTAX_DST];
630 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
631 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK];
632 int flags = info->rti_flags;
633 #define senderr(x) { error = x ; goto bad; }
634
635 if ((rnh = rt_tables[dst->sa_family]) == NULL)
636 senderr(ESRCH);
637 if (flags & RTF_HOST)
638 netmask = NULL;
639 switch (req) {
640 case RTM_DELETE:
641 if (netmask) {
642 rt_maskedcopy(dst, (struct sockaddr *)&deldst, netmask);
643 dst = (struct sockaddr *)&deldst;
644 }
645 if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL)
646 senderr(ESRCH);
647 rt = (struct rtentry *)rn;
648 if ((rt->rt_flags & RTF_CLONING) != 0) {
649 /* clean up any cloned children */
650 rtflushclone(rnh, rt);
651 }
652 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL)
653 senderr(ESRCH);
654 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
655 panic ("rtrequest delete");
656 rt = (struct rtentry *)rn;
657 if (rt->rt_gwroute) {
658 RTFREE(rt->rt_gwroute);
659 rt->rt_gwroute = NULL;
660 }
661 if (rt->rt_parent) {
662 rt->rt_parent->rt_refcnt--;
663 rt->rt_parent = NULL;
664 }
665 rt->rt_flags &= ~RTF_UP;
666 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
667 ifa->ifa_rtrequest(RTM_DELETE, rt, info);
668 rttrash++;
669 if (ret_nrt)
670 *ret_nrt = rt;
671 else if (rt->rt_refcnt <= 0) {
672 rt->rt_refcnt++;
673 rtfree(rt);
674 }
675 break;
676
677 case RTM_RESOLVE:
678 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
679 senderr(EINVAL);
680 if ((rt->rt_flags & RTF_CLONING) == 0)
681 senderr(EINVAL);
682 ifa = rt->rt_ifa;
683 flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC);
684 flags |= RTF_CLONED;
685 gateway = rt->rt_gateway;
686 if ((netmask = rt->rt_genmask) == NULL)
687 flags |= RTF_HOST;
688 goto makeroute;
689
690 case RTM_ADD:
691 if (info->rti_ifa == NULL && (error = rt_getifa(info)))
692 senderr(error);
693 ifa = info->rti_ifa;
694 makeroute:
695 /* Already at splsoftnet() so pool_get/pool_put are safe */
696 rt = pool_get(&rtentry_pool, PR_NOWAIT);
697 if (rt == NULL)
698 senderr(ENOBUFS);
699 Bzero(rt, sizeof(*rt));
700 rt->rt_flags = RTF_UP | flags;
701 LIST_INIT(&rt->rt_timer);
702 if (rt_setgate(rt, dst, gateway)) {
703 pool_put(&rtentry_pool, rt);
704 senderr(ENOBUFS);
705 }
706 if (netmask) {
707 rt_maskedcopy(dst, rt_key(rt), netmask);
708 } else
709 Bcopy(dst, rt_key(rt), dst->sa_len);
710 rt_set_ifa(rt, ifa);
711 rt->rt_ifp = ifa->ifa_ifp;
712 if (req == RTM_RESOLVE) {
713 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
714 rt->rt_parent = *ret_nrt;
715 rt->rt_parent->rt_refcnt++;
716 }
717 rn = rnh->rnh_addaddr(rt_key(rt), netmask, rnh, rt->rt_nodes);
718 if (rn == NULL && (crt = rtalloc1(rt_key(rt), 0)) != NULL) {
719 /* overwrite cloned route */
720 if ((crt->rt_flags & RTF_CLONED) != 0) {
721 rtdeletemsg(crt);
722 rn = rnh->rnh_addaddr(rt_key(rt),
723 netmask, rnh, rt->rt_nodes);
724 }
725 RTFREE(crt);
726 }
727 if (rn == NULL) {
728 IFAFREE(ifa);
729 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent)
730 rtfree(rt->rt_parent);
731 if (rt->rt_gwroute)
732 rtfree(rt->rt_gwroute);
733 Free(rt_key(rt));
734 pool_put(&rtentry_pool, rt);
735 senderr(EEXIST);
736 }
737 if (ifa->ifa_rtrequest)
738 ifa->ifa_rtrequest(req, rt, info);
739 if (ret_nrt) {
740 *ret_nrt = rt;
741 rt->rt_refcnt++;
742 }
743 if ((rt->rt_flags & RTF_CLONING) != 0) {
744 /* clean up any cloned children */
745 rtflushclone(rnh, rt);
746 }
747 rtflushall(dst->sa_family);
748 break;
749 }
750 bad:
751 splx(s);
752 return (error);
753 }
754
755 int
756 rt_setgate( struct rtentry *rt0, const struct sockaddr *dst,
757 const struct sockaddr *gate)
758 {
759 char *new, *old;
760 u_int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
761 struct rtentry *rt = rt0;
762
763 if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
764 old = (void *)rt_key(rt);
765 R_Malloc(new, void *, dlen + glen);
766 if (new == NULL)
767 return 1;
768 Bzero(new, dlen + glen);
769 rt->rt_nodes->rn_key = new;
770 } else {
771 new = __UNCONST(rt->rt_nodes->rn_key); /*XXXUNCONST*/
772 old = NULL;
773 }
774 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
775 if (old) {
776 Bcopy(dst, new, dlen);
777 Free(old);
778 }
779 if (rt->rt_gwroute) {
780 RTFREE(rt->rt_gwroute);
781 rt->rt_gwroute = NULL;
782 }
783 if (rt->rt_flags & RTF_GATEWAY) {
784 rt->rt_gwroute = rtalloc1(gate, 1);
785 /*
786 * If we switched gateways, grab the MTU from the new
787 * gateway route if the current MTU, if the current MTU is
788 * greater than the MTU of gateway.
789 * Note that, if the MTU of gateway is 0, we will reset the
790 * MTU of the route to run PMTUD again from scratch. XXX
791 */
792 if (rt->rt_gwroute
793 && !(rt->rt_rmx.rmx_locks & RTV_MTU)
794 && rt->rt_rmx.rmx_mtu
795 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) {
796 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu;
797 }
798 }
799 return 0;
800 }
801
802 void
803 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst,
804 const struct sockaddr *netmask)
805 {
806 const u_char *cp1 = (const u_char *)src;
807 u_char *cp2 = (u_char *)dst;
808 const u_char *cp3 = (const u_char *)netmask;
809 u_char *cplim = cp2 + *cp3;
810 u_char *cplim2 = cp2 + *cp1;
811
812 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
813 cp3 += 2;
814 if (cplim > cplim2)
815 cplim = cplim2;
816 while (cp2 < cplim)
817 *cp2++ = *cp1++ & *cp3++;
818 if (cp2 < cplim2)
819 memset(cp2, 0, (unsigned)(cplim2 - cp2));
820 }
821
822 /*
823 * Set up or tear down a routing table entry, normally
824 * for an interface.
825 */
826 int
827 rtinit(struct ifaddr *ifa, int cmd, int flags)
828 {
829 struct rtentry *rt;
830 struct sockaddr *dst, *odst;
831 struct sockaddr_storage deldst;
832 struct rtentry *nrt = NULL;
833 int error;
834 struct rt_addrinfo info;
835
836 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
837 if (cmd == RTM_DELETE) {
838 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
839 /* Delete subnet route for this interface */
840 odst = dst;
841 dst = (struct sockaddr *)&deldst;
842 rt_maskedcopy(odst, dst, ifa->ifa_netmask);
843 }
844 if ((rt = rtalloc1(dst, 0)) != NULL) {
845 rt->rt_refcnt--;
846 if (rt->rt_ifa != ifa)
847 return (flags & RTF_HOST) ? EHOSTUNREACH
848 : ENETUNREACH;
849 }
850 }
851 memset(&info, 0, sizeof(info));
852 info.rti_ifa = ifa;
853 info.rti_flags = flags | ifa->ifa_flags;
854 info.rti_info[RTAX_DST] = dst;
855 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
856 /*
857 * XXX here, it seems that we are assuming that ifa_netmask is NULL
858 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate
859 * variable) when RTF_HOST is 1. still not sure if i can safely
860 * change it to meet bsdi4 behavior.
861 */
862 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
863 error = rtrequest1(cmd, &info, &nrt);
864 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
865 rt_newaddrmsg(cmd, ifa, error, nrt);
866 if (rt->rt_refcnt <= 0) {
867 rt->rt_refcnt++;
868 rtfree(rt);
869 }
870 }
871 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
872 rt->rt_refcnt--;
873 if (rt->rt_ifa != ifa) {
874 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
875 rt->rt_ifa);
876 if (rt->rt_ifa->ifa_rtrequest)
877 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, NULL);
878 rt_replace_ifa(rt, ifa);
879 rt->rt_ifp = ifa->ifa_ifp;
880 if (ifa->ifa_rtrequest)
881 ifa->ifa_rtrequest(RTM_ADD, rt, NULL);
882 }
883 rt_newaddrmsg(cmd, ifa, error, nrt);
884 }
885 return error;
886 }
887
888 /*
889 * Route timer routines. These routes allow functions to be called
890 * for various routes at any time. This is useful in supporting
891 * path MTU discovery and redirect route deletion.
892 *
893 * This is similar to some BSDI internal functions, but it provides
894 * for multiple queues for efficiency's sake...
895 */
896
897 LIST_HEAD(, rttimer_queue) rttimer_queue_head;
898 static int rt_init_done = 0;
899
900 #define RTTIMER_CALLOUT(r) do { \
901 if (r->rtt_func != NULL) { \
902 (*r->rtt_func)(r->rtt_rt, r); \
903 } else { \
904 rtrequest((int) RTM_DELETE, \
905 (struct sockaddr *)rt_key(r->rtt_rt), \
906 0, 0, 0, 0); \
907 } \
908 } while (/*CONSTCOND*/0)
909
910 /*
911 * Some subtle order problems with domain initialization mean that
912 * we cannot count on this being run from rt_init before various
913 * protocol initializations are done. Therefore, we make sure
914 * that this is run when the first queue is added...
915 */
916
917 void
918 rt_timer_init(void)
919 {
920 assert(rt_init_done == 0);
921
922 LIST_INIT(&rttimer_queue_head);
923 callout_init(&rt_timer_ch);
924 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
925 rt_init_done = 1;
926 }
927
928 struct rttimer_queue *
929 rt_timer_queue_create(u_int timeout)
930 {
931 struct rttimer_queue *rtq;
932
933 if (rt_init_done == 0)
934 rt_timer_init();
935
936 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq);
937 if (rtq == NULL)
938 return NULL;
939 Bzero(rtq, sizeof *rtq);
940
941 rtq->rtq_timeout = timeout;
942 rtq->rtq_count = 0;
943 TAILQ_INIT(&rtq->rtq_head);
944 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link);
945
946 return rtq;
947 }
948
949 void
950 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout)
951 {
952
953 rtq->rtq_timeout = timeout;
954 }
955
956 void
957 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy)
958 {
959 struct rttimer *r;
960
961 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) {
962 LIST_REMOVE(r, rtt_link);
963 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
964 if (destroy)
965 RTTIMER_CALLOUT(r);
966 /* we are already at splsoftnet */
967 pool_put(&rttimer_pool, r);
968 if (rtq->rtq_count > 0)
969 rtq->rtq_count--;
970 else
971 printf("rt_timer_queue_remove_all: "
972 "rtq_count reached 0\n");
973 }
974 }
975
976 void
977 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy)
978 {
979
980 rt_timer_queue_remove_all(rtq, destroy);
981
982 LIST_REMOVE(rtq, rtq_link);
983
984 /*
985 * Caller is responsible for freeing the rttimer_queue structure.
986 */
987 }
988
989 unsigned long
990 rt_timer_count(struct rttimer_queue *rtq)
991 {
992 return rtq->rtq_count;
993 }
994
995 void
996 rt_timer_remove_all(struct rtentry *rt, int destroy)
997 {
998 struct rttimer *r;
999
1000 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) {
1001 LIST_REMOVE(r, rtt_link);
1002 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1003 if (destroy)
1004 RTTIMER_CALLOUT(r);
1005 if (r->rtt_queue->rtq_count > 0)
1006 r->rtt_queue->rtq_count--;
1007 else
1008 printf("rt_timer_remove_all: rtq_count reached 0\n");
1009 /* we are already at splsoftnet */
1010 pool_put(&rttimer_pool, r);
1011 }
1012 }
1013
1014 int
1015 rt_timer_add(struct rtentry *rt,
1016 void (*func)(struct rtentry *, struct rttimer *),
1017 struct rttimer_queue *queue)
1018 {
1019 struct rttimer *r;
1020 int s;
1021
1022 /*
1023 * If there's already a timer with this action, destroy it before
1024 * we add a new one.
1025 */
1026 LIST_FOREACH(r, &rt->rt_timer, rtt_link) {
1027 if (r->rtt_func == func)
1028 break;
1029 }
1030 if (r != NULL) {
1031 LIST_REMOVE(r, rtt_link);
1032 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1033 if (r->rtt_queue->rtq_count > 0)
1034 r->rtt_queue->rtq_count--;
1035 else
1036 printf("rt_timer_add: rtq_count reached 0\n");
1037 } else {
1038 s = splsoftnet();
1039 r = pool_get(&rttimer_pool, PR_NOWAIT);
1040 splx(s);
1041 if (r == NULL)
1042 return ENOBUFS;
1043 }
1044
1045 memset(r, 0, sizeof(*r));
1046
1047 r->rtt_rt = rt;
1048 r->rtt_time = time_uptime;
1049 r->rtt_func = func;
1050 r->rtt_queue = queue;
1051 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link);
1052 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next);
1053 r->rtt_queue->rtq_count++;
1054
1055 return (0);
1056 }
1057
1058 /* ARGSUSED */
1059 void
1060 rt_timer_timer(void *arg)
1061 {
1062 struct rttimer_queue *rtq;
1063 struct rttimer *r;
1064 int s;
1065
1066 s = splsoftnet();
1067 LIST_FOREACH(rtq, &rttimer_queue_head, rtq_link) {
1068 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL &&
1069 (r->rtt_time + rtq->rtq_timeout) < time_uptime) {
1070 LIST_REMOVE(r, rtt_link);
1071 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
1072 RTTIMER_CALLOUT(r);
1073 pool_put(&rttimer_pool, r);
1074 if (rtq->rtq_count > 0)
1075 rtq->rtq_count--;
1076 else
1077 printf("rt_timer_timer: rtq_count reached 0\n");
1078 }
1079 }
1080 splx(s);
1081
1082 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL);
1083 }
1084
1085 #ifdef RTCACHE_DEBUG
1086 #ifndef RTCACHE_DEBUG_SIZE
1087 #define RTCACHE_DEBUG_SIZE (1024 * 1024)
1088 #endif
1089 static const char *cache_caller[RTCACHE_DEBUG_SIZE];
1090 static struct route *cache_entry[RTCACHE_DEBUG_SIZE];
1091 size_t cache_cur;
1092 #endif
1093
1094 #ifdef RTCACHE_DEBUG
1095 static void
1096 _rtcache_init_debug(const char *caller, struct route *ro, int flag)
1097 #else
1098 static void
1099 _rtcache_init(struct route *ro, int flag)
1100 #endif
1101 {
1102 #ifdef RTCACHE_DEBUG
1103 size_t i;
1104 for (i = 0; i < cache_cur; ++i) {
1105 if (cache_entry[i] == ro)
1106 panic("Reinit of route %p, initialised from %s", ro, cache_caller[i]);
1107 }
1108 #endif
1109
1110 ro->ro_rt = rtalloc1(rtcache_getdst(ro), flag);
1111 if (ro->ro_rt != NULL) {
1112 #ifdef RTCACHE_DEBUG
1113 if (cache_cur == RTCACHE_DEBUG_SIZE)
1114 panic("Route cache debug overflow");
1115 cache_caller[cache_cur] = caller;
1116 cache_entry[cache_cur] = ro;
1117 ++cache_cur;
1118 #endif
1119 rtcache(ro);
1120 }
1121 }
1122
1123 #ifdef RTCACHE_DEBUG
1124 void
1125 rtcache_init_debug(const char *caller, struct route *ro)
1126 {
1127 _rtcache_init_debug(caller, ro, 1);
1128 }
1129
1130 void
1131 rtcache_init_noclone_debug(const char *caller, struct route *ro)
1132 {
1133 _rtcache_init_debug(caller, ro, 0);
1134 }
1135
1136 #else
1137 void
1138 rtcache_init(struct route *ro)
1139 {
1140 _rtcache_init(ro, 1);
1141 }
1142
1143 void
1144 rtcache_init_noclone(struct route *ro)
1145 {
1146 _rtcache_init(ro, 0);
1147 }
1148 #endif
1149
1150 #ifdef RTCACHE_DEBUG
1151 void
1152 rtcache_copy_debug(const char *caller, struct route *new_ro, const struct route *old_ro, size_t new_len)
1153 #else
1154 void
1155 rtcache_copy(struct route *new_ro, const struct route *old_ro, size_t new_len)
1156 #endif
1157 {
1158 #ifdef RTCACHE_DEBUG
1159 size_t i;
1160
1161 for (i = 0; i < cache_cur; ++i) {
1162 if (cache_entry[i] == new_ro)
1163 panic("Copy to initalised route %p (before %s)", new_ro, cache_caller[i]);
1164 }
1165 #endif
1166
1167 memset(new_ro, 0, new_len);
1168 #if 0
1169 if (old_ro->ro_sa != NULL)
1170 new_ro->ro_sa = sockaddr_dup(old_ro->ro_sa);
1171 #else
1172 if (old_ro->ro_dst.sa_len + offsetof(struct route, ro_dst) > new_len)
1173 panic("rtcache_copy: dst address will overflow new route");
1174 memcpy(&new_ro->ro_dst, &old_ro->ro_dst, old_ro->ro_dst.sa_len);
1175 #endif
1176 new_ro->ro_rt = old_ro->ro_rt;
1177 if (new_ro->ro_rt != NULL) {
1178 #ifdef RTCACHE_DEBUG
1179 if (cache_cur == RTCACHE_DEBUG_SIZE)
1180 panic("Route cache debug overflow");
1181 cache_caller[cache_cur] = caller;
1182 cache_entry[cache_cur] = new_ro;
1183 ++cache_cur;
1184 #endif
1185 rtcache(new_ro);
1186 ++new_ro->ro_rt->rt_refcnt;
1187 }
1188 }
1189
1190 static void
1191 rtcache_clear(struct route *ro)
1192 {
1193 #ifdef RTCACHE_DEBUG
1194 size_t j, i = cache_cur;
1195 for (i = j = 0; i < cache_cur; ++i, ++j) {
1196 if (cache_entry[i] == ro) {
1197 if (ro->ro_rt == NULL)
1198 panic("Route cache manipulated (allocated by %s)", cache_caller[i]);
1199 --j;
1200 } else {
1201 cache_caller[j] = cache_caller[i];
1202 cache_entry[j] = cache_entry[i];
1203 }
1204 }
1205 if (ro->ro_rt != NULL) {
1206 if (i != j + 1)
1207 panic("Wrong entries after rtcache_free: %zu (expected %zu)", j, i - 1);
1208 --cache_cur;
1209 }
1210 #endif
1211
1212 if (ro->ro_rt != NULL)
1213 rtflush(ro);
1214 ro->ro_rt = NULL;
1215 }
1216
1217 void
1218 rtcache_free(struct route *ro)
1219 {
1220 rtcache_clear(ro);
1221 #if 0
1222 if (ro->ro_sa != NULL) {
1223 sockaddr_free(ro->ro_sa);
1224 ro->ro_sa = NULL;
1225 }
1226 #endif
1227 }
1228
1229 void
1230 rtcache_update(struct route *ro)
1231 {
1232 rtcache_clear(ro);
1233 rtcache_init(ro);
1234 }
1235