1 /* $OpenBSD: table.c,v 1.18 2005/04/12 15:26:47 cloder Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #if !defined(lint)
33 static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
34 #endif
35
36 #include "defs.h"
37
38 static struct rt_spare *rts_better(struct rt_entry *);
39
40 struct radix_node_head *rhead; /* root of the radix tree */
41
42 int need_flash = 1; /* flash update needed
43 * start =1 to suppress the 1st
44 */
45
46 struct timeval age_timer; /* next check of old routes */
47 struct timeval need_kern = { /* need to update kernel table */
48 EPOCH+MIN_WAITTIME-1
49 };
50
51 int stopint;
52
53 int total_routes;
54
55 naddr age_bad_gate;
56
57
58 /* It is desirable to "aggregate" routes, to combine differing routes of
59 * the same metric and next hop into a common route with a smaller netmask
60 * or to suppress redundant routes, routes that add no information to
61 * routes with smaller netmasks.
62 *
63 * A route is redundant if and only if any and all routes with smaller
64 * but matching netmasks and nets are the same. Since routes are
65 * kept sorted in the radix tree, redundant routes always come second.
66 *
67 * There are two kinds of aggregations. First, two routes of the same bit
68 * mask and differing only in the least significant bit of the network
69 * number can be combined into a single route with a coarser mask.
70 *
71 * Second, a route can be suppressed in favor of another route with a more
72 * coarse mask provided no incompatible routes with intermediate masks
73 * are present. The second kind of aggregation involves suppressing routes.
74 * A route must not be suppressed if an incompatible route exists with
75 * an intermediate mask, since the suppressed route would be covered
76 * by the intermediate.
77 *
78 * This code relies on the radix tree walk encountering routes
79 * sorted first by address, with the smallest address first.
80 */
81
82 struct ag_info ag_slots[NUM_AG_SLOTS], *ag_avail, *ag_corsest, *ag_finest;
83
84 /* #define DEBUG_AG */
85 #ifdef DEBUG_AG
86 #define CHECK_AG() {int acnt = 0; struct ag_info *cag; \
87 for (cag = ag_avail; cag != 0; cag = cag->ag_fine) \
88 acnt++; \
89 for (cag = ag_corsest; cag != 0; cag = cag->ag_fine) \
90 acnt++; \
91 if (acnt != NUM_AG_SLOTS) { \
92 (void)fflush(stderr); \
93 abort(); \
94 } \
95 }
96 #else
97 #define CHECK_AG()
98 #endif
99
100
101 /* Output the contents of an aggregation table slot.
102 * This function must always be immediately followed with the deletion
103 * of the target slot.
104 */
105 static void
ag_out(struct ag_info * ag,void (* out)(struct ag_info *))106 ag_out(struct ag_info *ag,
107 void (*out)(struct ag_info *))
108 {
109 struct ag_info *ag_cors;
110 naddr bit;
111
112
113 /* If we output both the even and odd twins, then the immediate parent,
114 * if it is present, is redundant, unless the parent manages to
115 * aggregate into something coarser.
116 * On successive calls, this code detects the even and odd twins,
117 * and marks the parent.
118 *
119 * Note that the order in which the radix tree code emits routes
120 * ensures that the twins are seen before the parent is emitted.
121 */
122 ag_cors = ag->ag_cors;
123 if (ag_cors != 0
124 && ag_cors->ag_mask == ag->ag_mask<<1
125 && ag_cors->ag_dst_h == (ag->ag_dst_h & ag_cors->ag_mask)) {
126 ag_cors->ag_state |= ((ag_cors->ag_dst_h == ag->ag_dst_h)
127 ? AGS_REDUN0
128 : AGS_REDUN1);
129 }
130
131 /* Skip it if this route is itself redundant.
132 *
133 * It is ok to change the contents of the slot here, since it is
134 * always deleted next.
135 */
136 if (ag->ag_state & AGS_REDUN0) {
137 if (ag->ag_state & AGS_REDUN1)
138 return;
139 bit = (-ag->ag_mask) >> 1;
140 ag->ag_dst_h |= bit;
141 ag->ag_mask |= bit;
142
143 } else if (ag->ag_state & AGS_REDUN1) {
144 bit = (-ag->ag_mask) >> 1;
145 ag->ag_mask |= bit;
146 }
147 out(ag);
148 }
149
150
151 static void
ag_del(struct ag_info * ag)152 ag_del(struct ag_info *ag)
153 {
154 CHECK_AG();
155
156 if (ag->ag_cors == 0)
157 ag_corsest = ag->ag_fine;
158 else
159 ag->ag_cors->ag_fine = ag->ag_fine;
160
161 if (ag->ag_fine == 0)
162 ag_finest = ag->ag_cors;
163 else
164 ag->ag_fine->ag_cors = ag->ag_cors;
165
166 ag->ag_fine = ag_avail;
167 ag_avail = ag;
168
169 CHECK_AG();
170 }
171
172
173 /* Flush routes waiting for aggretation.
174 * This must not suppress a route unless it is known that among all
175 * routes with coarser masks that match it, the one with the longest
176 * mask is appropriate. This is ensured by scanning the routes
177 * in lexical order, and with the most restritive mask first
178 * among routes to the same destination.
179 */
180 void
ag_flush(naddr lim_dst_h,naddr lim_mask,void (* out)(struct ag_info *))181 ag_flush(naddr lim_dst_h, /* flush routes to here */
182 naddr lim_mask, /* matching this mask */
183 void (*out)(struct ag_info *))
184 {
185 struct ag_info *ag, *ag_cors;
186 naddr dst_h;
187
188
189 for (ag = ag_finest;
190 ag != 0 && ag->ag_mask >= lim_mask;
191 ag = ag_cors) {
192 ag_cors = ag->ag_cors;
193
194 /* work on only the specified routes */
195 dst_h = ag->ag_dst_h;
196 if ((dst_h & lim_mask) != lim_dst_h)
197 continue;
198
199 if (!(ag->ag_state & AGS_SUPPRESS))
200 ag_out(ag, out);
201
202 else for ( ; ; ag_cors = ag_cors->ag_cors) {
203 /* Look for a route that can suppress the
204 * current route */
205 if (ag_cors == 0) {
206 /* failed, so output it and look for
207 * another route to work on
208 */
209 ag_out(ag, out);
210 break;
211 }
212
213 if ((dst_h & ag_cors->ag_mask) == ag_cors->ag_dst_h) {
214 /* We found a route with a coarser mask that
215 * aggregates the current target.
216 *
217 * If it has a different next hop, it
218 * cannot replace the target, so output
219 * the target.
220 */
221 if (ag->ag_gate != ag_cors->ag_gate
222 && !(ag->ag_state & AGS_FINE_GATE)
223 && !(ag_cors->ag_state & AGS_CORS_GATE)) {
224 ag_out(ag, out);
225 break;
226 }
227
228 /* If the coarse route has a good enough
229 * metric, it suppresses the target.
230 */
231 if (ag_cors->ag_pref <= ag->ag_pref) {
232 if (ag_cors->ag_seqno > ag->ag_seqno)
233 ag_cors->ag_seqno = ag->ag_seqno;
234 if (AG_IS_REDUN(ag->ag_state)
235 && ag_cors->ag_mask==ag->ag_mask<<1) {
236 if (ag_cors->ag_dst_h == dst_h)
237 ag_cors->ag_state |= AGS_REDUN0;
238 else
239 ag_cors->ag_state |= AGS_REDUN1;
240 }
241 if (ag->ag_tag != ag_cors->ag_tag)
242 ag_cors->ag_tag = 0;
243 if (ag->ag_nhop != ag_cors->ag_nhop)
244 ag_cors->ag_nhop = 0;
245 break;
246 }
247 }
248 }
249
250 /* That route has either been output or suppressed */
251 ag_cors = ag->ag_cors;
252 ag_del(ag);
253 }
254
255 CHECK_AG();
256 }
257
258
259 /* Try to aggregate a route with previous routes.
260 */
261 void
ag_check(naddr dst,naddr mask,naddr gate,naddr nhop,char metric,char pref,u_int seqno,u_short tag,u_short state,void (* out)(struct ag_info *))262 ag_check(naddr dst,
263 naddr mask,
264 naddr gate,
265 naddr nhop,
266 char metric,
267 char pref,
268 u_int seqno,
269 u_short tag,
270 u_short state,
271 void (*out)(struct ag_info *)) /* output using this */
272 {
273 struct ag_info *ag, *nag, *ag_cors;
274 naddr xaddr;
275 int x;
276
277 NTOHL(dst);
278
279 /* Punt non-contiguous subnet masks.
280 *
281 * (X & -X) contains a single bit if and only if X is a power of 2.
282 * (X + (X & -X)) == 0 if and only if X is a power of 2.
283 */
284 if ((mask & -mask) + mask != 0) {
285 struct ag_info nc_ag;
286
287 nc_ag.ag_dst_h = dst;
288 nc_ag.ag_mask = mask;
289 nc_ag.ag_gate = gate;
290 nc_ag.ag_nhop = nhop;
291 nc_ag.ag_metric = metric;
292 nc_ag.ag_pref = pref;
293 nc_ag.ag_tag = tag;
294 nc_ag.ag_state = state;
295 nc_ag.ag_seqno = seqno;
296 out(&nc_ag);
297 return;
298 }
299
300 /* Search for the right slot in the aggregation table.
301 */
302 ag_cors = 0;
303 ag = ag_corsest;
304 while (ag != 0) {
305 if (ag->ag_mask >= mask)
306 break;
307
308 /* Suppress old routes (i.e. combine with compatible routes
309 * with coarser masks) as we look for the right slot in the
310 * aggregation table for the new route.
311 * A route to an address less than the current destination
312 * will not be affected by the current route or any route
313 * seen hereafter. That means it is safe to suppress it.
314 * This check keeps poor routes (eg. with large hop counts)
315 * from preventing suppresion of finer routes.
316 */
317 if (ag_cors != 0
318 && ag->ag_dst_h < dst
319 && (ag->ag_state & AGS_SUPPRESS)
320 && ag_cors->ag_pref <= ag->ag_pref
321 && (ag->ag_dst_h & ag_cors->ag_mask) == ag_cors->ag_dst_h
322 && (ag_cors->ag_gate == ag->ag_gate
323 || (ag->ag_state & AGS_FINE_GATE)
324 || (ag_cors->ag_state & AGS_CORS_GATE))) {
325 if (ag_cors->ag_seqno > ag->ag_seqno)
326 ag_cors->ag_seqno = ag->ag_seqno;
327 if (AG_IS_REDUN(ag->ag_state)
328 && ag_cors->ag_mask==ag->ag_mask<<1) {
329 if (ag_cors->ag_dst_h == dst)
330 ag_cors->ag_state |= AGS_REDUN0;
331 else
332 ag_cors->ag_state |= AGS_REDUN1;
333 }
334 if (ag->ag_tag != ag_cors->ag_tag)
335 ag_cors->ag_tag = 0;
336 if (ag->ag_nhop != ag_cors->ag_nhop)
337 ag_cors->ag_nhop = 0;
338 ag_del(ag);
339 CHECK_AG();
340 } else {
341 ag_cors = ag;
342 }
343 ag = ag_cors->ag_fine;
344 }
345
346 /* If we find the even/odd twin of the new route, and if the
347 * masks and so forth are equal, we can aggregate them.
348 * We can probably promote one of the pair.
349 *
350 * Since the routes are encountered in lexical order,
351 * the new route must be odd. However, the second or later
352 * times around this loop, it could be the even twin promoted
353 * from the even/odd pair of twins of the finer route.
354 */
355 while (ag != 0
356 && ag->ag_mask == mask
357 && ((ag->ag_dst_h ^ dst) & (mask<<1)) == 0) {
358
359 /* Here we know the target route and the route in the current
360 * slot have the same netmasks and differ by at most the
361 * last bit. They are either for the same destination, or
362 * for an even/odd pair of destinations.
363 */
364 if (ag->ag_dst_h == dst) {
365 /* We have two routes to the same destination.
366 * Routes are encountered in lexical order, so a
367 * route is never promoted until the parent route is
368 * already present. So we know that the new route is
369 * a promoted pair and the route already in the slot
370 * is the explicit route.
371 *
372 * Prefer the best route if their metrics differ,
373 * or the promoted one if not, following a sort
374 * of longest-match rule.
375 */
376 if (pref <= ag->ag_pref) {
377 ag->ag_gate = gate;
378 ag->ag_nhop = nhop;
379 ag->ag_tag = tag;
380 ag->ag_metric = metric;
381 ag->ag_pref = pref;
382 x = ag->ag_state;
383 ag->ag_state = state;
384 state = x;
385 }
386
387 /* The sequence number controls flash updating,
388 * and should be the smaller of the two.
389 */
390 if (ag->ag_seqno > seqno)
391 ag->ag_seqno = seqno;
392
393 /* some bits are set if they are set on either route */
394 ag->ag_state |= (state & (AGS_PROMOTE_EITHER
395 | AGS_REDUN0 | AGS_REDUN1));
396 return;
397 }
398
399 /* If one of the routes can be promoted and the other can
400 * be suppressed, it may be possible to combine them or
401 * worthwhile to promote one.
402 *
403 * Note that any route that can be promoted is always
404 * marked to be eligible to be suppressed.
405 */
406 if (!((state & AGS_PROMOTE)
407 && (ag->ag_state & AGS_SUPPRESS))
408 && !((ag->ag_state & AGS_PROMOTE)
409 && (state & AGS_SUPPRESS)))
410 break;
411
412 /* A pair of even/odd twin routes can be combined
413 * if either is redundant, or if they are via the
414 * same gateway and have the same metric.
415 */
416 if (AG_IS_REDUN(ag->ag_state)
417 || AG_IS_REDUN(state)
418 || (ag->ag_gate == gate
419 && ag->ag_pref == pref
420 && (state & ag->ag_state & AGS_PROMOTE) != 0)) {
421
422 /* We have both the even and odd pairs.
423 * Since the routes are encountered in order,
424 * the route in the slot must be the even twin.
425 *
426 * Combine and promote the pair of routes.
427 */
428 if (seqno > ag->ag_seqno)
429 seqno = ag->ag_seqno;
430 if (!AG_IS_REDUN(state))
431 state &= ~AGS_REDUN1;
432 if (AG_IS_REDUN(ag->ag_state))
433 state |= AGS_REDUN0;
434 else
435 state &= ~AGS_REDUN0;
436 state |= (ag->ag_state & AGS_PROMOTE_EITHER);
437 if (ag->ag_tag != tag)
438 tag = 0;
439 if (ag->ag_nhop != nhop)
440 nhop = 0;
441
442 /* Get rid of the even twin that was already
443 * in the slot.
444 */
445 ag_del(ag);
446
447 } else if (ag->ag_pref >= pref
448 && (ag->ag_state & AGS_PROMOTE)) {
449 /* If we cannot combine the pair, maybe the route
450 * with the worse metric can be promoted.
451 *
452 * Promote the old, even twin, by giving its slot
453 * in the table to the new, odd twin.
454 */
455 ag->ag_dst_h = dst;
456
457 xaddr = ag->ag_gate;
458 ag->ag_gate = gate;
459 gate = xaddr;
460
461 xaddr = ag->ag_nhop;
462 ag->ag_nhop = nhop;
463 nhop = xaddr;
464
465 x = ag->ag_tag;
466 ag->ag_tag = tag;
467 tag = x;
468
469 x = ag->ag_state;
470 ag->ag_state = state;
471 state = x;
472 if (!AG_IS_REDUN(state))
473 state &= ~AGS_REDUN0;
474
475 x = ag->ag_metric;
476 ag->ag_metric = metric;
477 metric = x;
478
479 x = ag->ag_pref;
480 ag->ag_pref = pref;
481 pref = x;
482
483 if (seqno >= ag->ag_seqno)
484 seqno = ag->ag_seqno;
485 else
486 ag->ag_seqno = seqno;
487
488 } else {
489 if (!(state & AGS_PROMOTE))
490 break; /* cannot promote either twin */
491
492 /* promote the new, odd twin by shaving its
493 * mask and address.
494 */
495 if (seqno > ag->ag_seqno)
496 seqno = ag->ag_seqno;
497 else
498 ag->ag_seqno = seqno;
499 if (!AG_IS_REDUN(state))
500 state &= ~AGS_REDUN1;
501 }
502
503 mask <<= 1;
504 dst &= mask;
505
506 if (ag_cors == 0) {
507 ag = ag_corsest;
508 break;
509 }
510 ag = ag_cors;
511 ag_cors = ag->ag_cors;
512 }
513
514 /* When we can no longer promote and combine routes,
515 * flush the old route in the target slot. Also flush
516 * any finer routes that we know will never be aggregated by
517 * the new route.
518 *
519 * In case we moved toward coarser masks,
520 * get back where we belong
521 */
522 if (ag != 0
523 && ag->ag_mask < mask) {
524 ag_cors = ag;
525 ag = ag->ag_fine;
526 }
527
528 /* Empty the target slot
529 */
530 if (ag != 0 && ag->ag_mask == mask) {
531 ag_flush(ag->ag_dst_h, ag->ag_mask, out);
532 ag = (ag_cors == 0) ? ag_corsest : ag_cors->ag_fine;
533 }
534
535 #ifdef DEBUG_AG
536 (void)fflush(stderr);
537 if (ag == 0 && ag_cors != ag_finest)
538 abort();
539 if (ag_cors == 0 && ag != ag_corsest)
540 abort();
541 if (ag != 0 && ag->ag_cors != ag_cors)
542 abort();
543 if (ag_cors != 0 && ag_cors->ag_fine != ag)
544 abort();
545 CHECK_AG();
546 #endif
547
548 /* Save the new route on the end of the table.
549 */
550 nag = ag_avail;
551 ag_avail = nag->ag_fine;
552
553 nag->ag_dst_h = dst;
554 nag->ag_mask = mask;
555 nag->ag_gate = gate;
556 nag->ag_nhop = nhop;
557 nag->ag_metric = metric;
558 nag->ag_pref = pref;
559 nag->ag_tag = tag;
560 nag->ag_state = state;
561 nag->ag_seqno = seqno;
562
563 nag->ag_fine = ag;
564 if (ag != 0)
565 ag->ag_cors = nag;
566 else
567 ag_finest = nag;
568 nag->ag_cors = ag_cors;
569 if (ag_cors == 0)
570 ag_corsest = nag;
571 else
572 ag_cors->ag_fine = nag;
573 CHECK_AG();
574 }
575
576
577 static char *
rtm_type_name(u_char type)578 rtm_type_name(u_char type)
579 {
580 static char *rtm_types[] = {
581 "RTM_ADD",
582 "RTM_DELETE",
583 "RTM_CHANGE",
584 "RTM_GET",
585 "RTM_LOSING",
586 "RTM_REDIRECT",
587 "RTM_MISS",
588 "RTM_LOCK",
589 "RTM_OLDADD",
590 "RTM_OLDDEL",
591 "RTM_RESOLVE",
592 "RTM_NEWADDR",
593 "RTM_DELADDR",
594 "RTM_IFINFO"
595 };
596 static char name0[10];
597
598
599 if (type > sizeof(rtm_types)/sizeof(rtm_types[0])
600 || type == 0) {
601 snprintf(name0, sizeof name0, "RTM type %#x", type);
602 return name0;
603 } else {
604 return rtm_types[type-1];
605 }
606 }
607
608
609 /* Trim a mask in a sockaddr
610 * Produce a length of 0 for an address of 0.
611 * Otherwise produce the index of the first zero byte.
612 */
613 void
614 #ifdef _HAVE_SIN_LEN
masktrim(struct sockaddr_in * ap)615 masktrim(struct sockaddr_in *ap)
616 #else
617 masktrim(struct sockaddr_in_new *ap)
618 #endif
619 {
620 char *cp;
621
622 if (ap->sin_addr.s_addr == 0) {
623 ap->sin_len = 0;
624 return;
625 }
626 cp = (char *)(&ap->sin_addr.s_addr+1);
627 while (*--cp == 0)
628 continue;
629 ap->sin_len = cp - (char*)ap + 1;
630 }
631
632
633 /* Tell the kernel to add, delete or change a route
634 */
635 static void
rtioctl(int action,naddr dst,naddr gate,naddr mask,int metric,int flags)636 rtioctl(int action, /* RTM_DELETE, etc */
637 naddr dst,
638 naddr gate,
639 naddr mask,
640 int metric,
641 int flags)
642 {
643 struct {
644 struct rt_msghdr w_rtm;
645 struct sockaddr_in w_dst;
646 struct sockaddr_in w_gate;
647 #ifdef _HAVE_SA_LEN
648 struct sockaddr_in w_mask;
649 #else
650 struct sockaddr_in_new w_mask;
651 #endif
652 } w;
653 long cc;
654
655 again:
656 bzero(&w, sizeof(w));
657 w.w_rtm.rtm_msglen = sizeof(w);
658 w.w_rtm.rtm_version = RTM_VERSION;
659 w.w_rtm.rtm_type = action;
660 w.w_rtm.rtm_flags = flags;
661 w.w_rtm.rtm_seq = ++rt_sock_seqno;
662 w.w_rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
663 if (metric != 0) {
664 w.w_rtm.rtm_rmx.rmx_hopcount = metric;
665 w.w_rtm.rtm_inits |= RTV_HOPCOUNT;
666 }
667 w.w_dst.sin_family = AF_INET;
668 w.w_dst.sin_addr.s_addr = dst;
669 w.w_gate.sin_family = AF_INET;
670 w.w_gate.sin_addr.s_addr = gate;
671 #ifdef _HAVE_SA_LEN
672 w.w_dst.sin_len = sizeof(w.w_dst);
673 w.w_gate.sin_len = sizeof(w.w_gate);
674 #endif
675 if (mask == HOST_MASK) {
676 w.w_rtm.rtm_flags |= RTF_HOST;
677 w.w_rtm.rtm_msglen -= sizeof(w.w_mask);
678 } else {
679 w.w_rtm.rtm_addrs |= RTA_NETMASK;
680 w.w_mask.sin_addr.s_addr = htonl(mask);
681 #ifdef _HAVE_SA_LEN
682 masktrim(&w.w_mask);
683 if (w.w_mask.sin_len == 0)
684 w.w_mask.sin_len = sizeof(long);
685 w.w_rtm.rtm_msglen -= (sizeof(w.w_mask) - w.w_mask.sin_len);
686 #endif
687 }
688
689 if (TRACEKERNEL)
690 trace_kernel("write kernel %s %s->%s metric=%d flags=%#x\n",
691 rtm_type_name(action),
692 addrname(dst, mask, 0), naddr_ntoa(gate),
693 metric, flags);
694
695 #ifndef NO_INSTALL
696 cc = write(rt_sock, &w, w.w_rtm.rtm_msglen);
697 if (cc == w.w_rtm.rtm_msglen)
698 return;
699 if (cc < 0) {
700 if (errno == ESRCH
701 && (action == RTM_CHANGE || action == RTM_DELETE)) {
702 trace_act("route to %s disappeared before %s\n",
703 addrname(dst, mask, 0),
704 rtm_type_name(action));
705 if (action == RTM_CHANGE) {
706 action = RTM_ADD;
707 goto again;
708 }
709 return;
710 }
711 msglog("write(rt_sock) %s %s --> %s: %s",
712 rtm_type_name(action),
713 addrname(dst, mask, 0), naddr_ntoa(gate),
714 strerror(errno));
715 } else {
716 msglog("write(rt_sock) wrote %ld instead of %d",
717 cc, w.w_rtm.rtm_msglen);
718 }
719 #endif
720 }
721
722
723 #define KHASH_SIZE 71 /* should be prime */
724 #define KHASH(a,m) khash_bins[((a) ^ (m)) % KHASH_SIZE]
725 static struct khash {
726 struct khash *k_next;
727 naddr k_dst;
728 naddr k_mask;
729 naddr k_gate;
730 short k_metric;
731 u_short k_state;
732 #define KS_NEW 0x001
733 #define KS_DELETE 0x002
734 #define KS_ADD 0x004 /* add to the kernel */
735 #define KS_CHANGE 0x008 /* tell kernel to change the route */
736 #define KS_DEL_ADD 0x010 /* delete & add to change the kernel */
737 #define KS_STATIC 0x020 /* Static flag in kernel */
738 #define KS_GATEWAY 0x040 /* G flag in kernel */
739 #define KS_DYNAMIC 0x080 /* result of redirect */
740 #define KS_DELETED 0x100 /* already deleted */
741 time_t k_keep;
742 #define K_KEEP_LIM 30
743 time_t k_redirect_time;
744 } *khash_bins[KHASH_SIZE];
745
746
747 static struct khash*
kern_find(naddr dst,naddr mask,struct khash *** ppk)748 kern_find(naddr dst, naddr mask, struct khash ***ppk)
749 {
750 struct khash *k, **pk;
751
752 for (pk = &KHASH(dst,mask); (k = *pk) != 0; pk = &k->k_next) {
753 if (k->k_dst == dst && k->k_mask == mask)
754 break;
755 }
756 if (ppk != 0)
757 *ppk = pk;
758 return k;
759 }
760
761
762 static struct khash*
kern_add(naddr dst,naddr mask)763 kern_add(naddr dst, naddr mask)
764 {
765 struct khash *k, **pk;
766
767 k = kern_find(dst, mask, &pk);
768 if (k != 0)
769 return k;
770
771 k = (struct khash *)malloc(sizeof(*k));
772
773 bzero(k, sizeof(*k));
774 k->k_dst = dst;
775 k->k_mask = mask;
776 k->k_state = KS_NEW;
777 k->k_keep = now.tv_sec;
778 *pk = k;
779
780 return k;
781 }
782
783
784 /* If a kernel route has a non-zero metric, check that it is still in the
785 * daemon table, and not deleted by interfaces coming and going.
786 */
787 static void
kern_check_static(struct khash * k,struct interface * ifp)788 kern_check_static(struct khash *k,
789 struct interface *ifp)
790 {
791 struct rt_entry *rt;
792 naddr int_addr;
793
794 if (k->k_metric == 0)
795 return;
796
797 int_addr = (ifp != 0) ? ifp->int_addr : loopaddr;
798
799 rt = rtget(k->k_dst, k->k_mask);
800 if (rt != 0) {
801 if (!(rt->rt_state & RS_STATIC))
802 rtchange(rt, rt->rt_state | RS_STATIC,
803 k->k_gate, int_addr,
804 k->k_metric, 0, ifp, now.tv_sec, 0);
805 } else {
806 rtadd(k->k_dst, k->k_mask, k->k_gate, int_addr,
807 k->k_metric, 0, RS_STATIC, ifp);
808 }
809 }
810
811
812 /* add a route the kernel told us
813 */
814 static void
rtm_add(struct rt_msghdr * rtm,struct rt_addrinfo * info,time_t keep)815 rtm_add(struct rt_msghdr *rtm,
816 struct rt_addrinfo *info,
817 time_t keep)
818 {
819 struct khash *k;
820 struct interface *ifp;
821 naddr mask;
822
823
824 if (rtm->rtm_flags & RTF_HOST) {
825 mask = HOST_MASK;
826 } else if (INFO_MASK(info) != 0) {
827 mask = ntohl(S_ADDR(INFO_MASK(info)));
828 } else {
829 msglog("punt %s without mask",
830 rtm_type_name(rtm->rtm_type));
831 return;
832 }
833
834 if (INFO_GATE(info) == 0
835 || INFO_GATE(info)->sa_family != AF_INET) {
836 msglog("punt %s without gateway",
837 rtm_type_name(rtm->rtm_type));
838 return;
839 }
840
841 k = kern_add(S_ADDR(INFO_DST(info)), mask);
842 if (k->k_state & KS_NEW)
843 k->k_keep = now.tv_sec+keep;
844 k->k_gate = S_ADDR(INFO_GATE(info));
845 k->k_metric = rtm->rtm_rmx.rmx_hopcount;
846 if (k->k_metric < 0)
847 k->k_metric = 0;
848 else if (k->k_metric > HOPCNT_INFINITY)
849 k->k_metric = HOPCNT_INFINITY;
850 k->k_state &= ~(KS_DELETED | KS_GATEWAY | KS_STATIC | KS_NEW);
851 if (rtm->rtm_flags & RTF_GATEWAY)
852 k->k_state |= KS_GATEWAY;
853 if (rtm->rtm_flags & RTF_STATIC)
854 k->k_state |= KS_STATIC;
855
856 if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
857 if (supplier) {
858 /* Routers are not supposed to listen to redirects,
859 * so delete it.
860 */
861 k->k_state &= ~KS_DYNAMIC;
862 k->k_state |= KS_DELETE;
863 LIM_SEC(need_kern, 0);
864 trace_act("mark redirected %s --> %s for deletion"
865 " since this is a router\n",
866 addrname(k->k_dst, k->k_mask, 0),
867 naddr_ntoa(k->k_gate));
868 } else {
869 k->k_state |= KS_DYNAMIC;
870 k->k_redirect_time = now.tv_sec;
871 }
872 return;
873 }
874
875 /* If it is not a static route, quit until the next comparison
876 * between the kernel and daemon tables, when it will be deleted.
877 */
878 if (!(k->k_state & KS_STATIC)) {
879 k->k_state |= KS_DELETE;
880 LIM_SEC(need_kern, k->k_keep);
881 return;
882 }
883
884 /* Put static routes with real metrics into the daemon table so
885 * they can be advertised.
886 *
887 * Find the interface concerned
888 */
889 ifp = iflookup(k->k_gate);
890 if (ifp == 0) {
891 /* if there is no known interface,
892 * maybe there is a new interface
893 */
894 ifinit();
895 ifp = iflookup(k->k_gate);
896 if (ifp == 0)
897 msglog("static route %s --> %s impossibly lacks ifp",
898 addrname(S_ADDR(INFO_DST(info)), mask, 0),
899 naddr_ntoa(k->k_gate));
900 }
901
902 kern_check_static(k, ifp);
903 }
904
905
906 /* deal with packet loss
907 */
908 static void
rtm_lose(struct rt_msghdr * rtm,struct rt_addrinfo * info)909 rtm_lose(struct rt_msghdr *rtm,
910 struct rt_addrinfo *info)
911 {
912 if (INFO_GATE(info) == 0
913 || INFO_GATE(info)->sa_family != AF_INET) {
914 msglog("punt %s without gateway",
915 rtm_type_name(rtm->rtm_type));
916 return;
917 }
918
919 if (!supplier)
920 rdisc_age(S_ADDR(INFO_GATE(info)));
921
922 age(S_ADDR(INFO_GATE(info)));
923 }
924
925
926 /* Clean the kernel table by copying it to the daemon image.
927 * Eventually the daemon will delete any extra routes.
928 */
929 void
flush_kern(void)930 flush_kern(void)
931 {
932 size_t needed;
933 int mib[6];
934 char *buf, *next, *lim;
935 struct rt_msghdr *rtm;
936 struct interface *ifp;
937 static struct sockaddr_in gate_sa;
938 struct rt_addrinfo info;
939
940
941 mib[0] = CTL_NET;
942 mib[1] = PF_ROUTE;
943 mib[2] = 0; /* protocol */
944 mib[3] = 0; /* wildcard address family */
945 mib[4] = NET_RT_DUMP;
946 mib[5] = 0; /* no flags */
947 if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) {
948 DBGERR(1,"RT_DUMP-sysctl-estimate");
949 return;
950 }
951 buf = malloc(needed);
952 if (sysctl(mib, 6, buf, &needed, 0, 0) < 0)
953 BADERR(1,"RT_DUMP");
954 lim = buf + needed;
955 for (next = buf; next < lim; next += rtm->rtm_msglen) {
956 rtm = (struct rt_msghdr *)next;
957
958 rt_xaddrs(&info,
959 (struct sockaddr *)(rtm+1),
960 (struct sockaddr *)(next + rtm->rtm_msglen),
961 rtm->rtm_addrs);
962
963 if (INFO_DST(&info) == 0
964 || INFO_DST(&info)->sa_family != AF_INET)
965 continue;
966
967 /* ignore ARP table entries on systems with a merged route
968 * and ARP table.
969 */
970 if (rtm->rtm_flags & RTF_LLINFO)
971 continue;
972
973 if (INFO_GATE(&info) == 0)
974 continue;
975 if (INFO_GATE(&info)->sa_family != AF_INET) {
976 if (INFO_GATE(&info)->sa_family != AF_LINK)
977 continue;
978 ifp = ifwithindex(((struct sockaddr_dl *)
979 INFO_GATE(&info))->sdl_index);
980 if (ifp == 0)
981 continue;
982 if ((ifp->int_if_flags & IFF_POINTOPOINT)
983 || S_ADDR(INFO_DST(&info)) == ifp->int_addr)
984 gate_sa.sin_addr.s_addr = ifp->int_addr;
985 else
986 gate_sa.sin_addr.s_addr = htonl(ifp->int_net);
987 #ifdef _HAVE_SA_LEN
988 gate_sa.sin_len = sizeof(gate_sa);
989 #endif
990 gate_sa.sin_family = AF_INET;
991 INFO_GATE(&info) = (struct sockaddr *)&gate_sa;
992 }
993
994 /* ignore multicast addresses
995 */
996 if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info)))))
997 continue;
998
999 /* Note static routes and interface routes, and also
1000 * preload the image of the kernel table so that
1001 * we can later clean it, as well as avoid making
1002 * unneeded changes. Keep the old kernel routes for a
1003 * few seconds to allow a RIP or router-discovery
1004 * response to be heard.
1005 */
1006 rtm_add(rtm,&info,MIN_WAITTIME);
1007 }
1008 free(buf);
1009 }
1010
1011
1012 /* Listen to announcements from the kernel
1013 */
1014 void
read_rt(void)1015 read_rt(void)
1016 {
1017 long cc;
1018 struct interface *ifp;
1019 naddr mask;
1020 union {
1021 struct {
1022 struct rt_msghdr rtm;
1023 struct sockaddr addrs[RTAX_MAX];
1024 } r;
1025 struct if_msghdr ifm;
1026 } m;
1027 char str[100], *strp;
1028 struct rt_addrinfo info;
1029
1030
1031 for (;;) {
1032 cc = read(rt_sock, &m, sizeof(m));
1033 if (cc <= 0) {
1034 if (cc < 0 && errno != EWOULDBLOCK)
1035 LOGERR("read(rt_sock)");
1036 return;
1037 }
1038
1039 if (m.r.rtm.rtm_version != RTM_VERSION) {
1040 msglog("bogus routing message version %d",
1041 m.r.rtm.rtm_version);
1042 continue;
1043 }
1044
1045 /* Ignore our own results.
1046 */
1047 if (m.r.rtm.rtm_type <= RTM_CHANGE
1048 && m.r.rtm.rtm_pid == mypid) {
1049 static int complained = 0;
1050 if (!complained) {
1051 msglog("receiving our own change messages");
1052 complained = 1;
1053 }
1054 continue;
1055 }
1056
1057 /* ignore routes from bgpd and ospfd */
1058 if (m.r.rtm.rtm_flags & (RTF_PROTO1|RTF_PROTO2))
1059 continue;
1060
1061 if (m.r.rtm.rtm_type == RTM_IFINFO
1062 || m.r.rtm.rtm_type == RTM_NEWADDR
1063 || m.r.rtm.rtm_type == RTM_DELADDR) {
1064 ifp = ifwithindex(m.ifm.ifm_index);
1065 if (ifp == 0)
1066 trace_act("note %s with flags %#x"
1067 " for index #%d\n",
1068 rtm_type_name(m.r.rtm.rtm_type),
1069 m.ifm.ifm_flags,
1070 m.ifm.ifm_index);
1071 else
1072 trace_act("note %s with flags %#x for %s\n",
1073 rtm_type_name(m.r.rtm.rtm_type),
1074 m.ifm.ifm_flags,
1075 ifp->int_name);
1076
1077 /* After being informed of a change to an interface,
1078 * check them all now if the check would otherwise
1079 * be a long time from now, if the interface is
1080 * not known, or if the interface has been turned
1081 * off or on.
1082 */
1083 if (ifinit_timer.tv_sec-now.tv_sec>=CHECK_BAD_INTERVAL
1084 || ifp == 0
1085 || ((ifp->int_if_flags ^ m.ifm.ifm_flags)
1086 & IFF_UP_RUNNING) != 0)
1087 ifinit_timer.tv_sec = now.tv_sec;
1088 continue;
1089 }
1090
1091 strlcpy(str, rtm_type_name(m.r.rtm.rtm_type),
1092 sizeof str);
1093 strp = &str[strlen(str)];
1094 if (m.r.rtm.rtm_type <= RTM_CHANGE) {
1095 snprintf(strp, str + sizeof str - strp,
1096 " from pid %ld", (long)m.r.rtm.rtm_pid);
1097 strp+= strlen(strp);
1098 }
1099
1100 rt_xaddrs(&info, m.r.addrs, &m.r.addrs[RTAX_MAX],
1101 m.r.rtm.rtm_addrs);
1102
1103 if (INFO_DST(&info) == 0) {
1104 trace_act("ignore %s without dst\n", str);
1105 continue;
1106 }
1107
1108 if (INFO_DST(&info)->sa_family != AF_INET) {
1109 trace_act("ignore %s for AF %d\n", str,
1110 INFO_DST(&info)->sa_family);
1111 continue;
1112 }
1113
1114 mask = ((INFO_MASK(&info) != 0)
1115 ? ntohl(S_ADDR(INFO_MASK(&info)))
1116 : (m.r.rtm.rtm_flags & RTF_HOST)
1117 ? HOST_MASK
1118 : std_mask(S_ADDR(INFO_DST(&info))));
1119
1120 snprintf(strp, str + sizeof str - strp, ": %s",
1121 addrname(S_ADDR(INFO_DST(&info)), mask, 0));
1122 strp+= strlen(strp);
1123
1124 if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info))))) {
1125 trace_act("ignore multicast %s\n", str);
1126 continue;
1127 }
1128
1129 if (INFO_GATE(&info) != 0
1130 && INFO_GATE(&info)->sa_family == AF_INET) {
1131 snprintf(strp, str + sizeof str - strp,
1132 " --> %s", saddr_ntoa(INFO_GATE(&info)));
1133 strp+= strlen(strp);
1134 }
1135
1136 if (INFO_AUTHOR(&info) != 0) {
1137 snprintf(strp, str + sizeof str - strp,
1138 " by authority of %s",
1139 saddr_ntoa(INFO_AUTHOR(&info)));
1140 strp+= strlen(strp);
1141 }
1142
1143 switch (m.r.rtm.rtm_type) {
1144 case RTM_ADD:
1145 case RTM_CHANGE:
1146 case RTM_REDIRECT:
1147 if (m.r.rtm.rtm_errno != 0) {
1148 trace_act("ignore %s with \"%s\" error\n",
1149 str, strerror(m.r.rtm.rtm_errno));
1150 } else {
1151 trace_act("%s\n", str);
1152 rtm_add(&m.r.rtm,&info,0);
1153 }
1154 break;
1155
1156 case RTM_DELETE:
1157 if (m.r.rtm.rtm_errno != 0) {
1158 trace_act("ignore %s with \"%s\" error\n",
1159 str, strerror(m.r.rtm.rtm_errno));
1160 } else {
1161 trace_act("%s\n", str);
1162 del_static(S_ADDR(INFO_DST(&info)), mask, 1);
1163 }
1164 break;
1165
1166 case RTM_LOSING:
1167 trace_act("%s\n", str);
1168 rtm_lose(&m.r.rtm,&info);
1169 break;
1170
1171 default:
1172 trace_act("ignore %s\n", str);
1173 break;
1174 }
1175 }
1176 }
1177
1178
1179 /* after aggregating, note routes that belong in the kernel
1180 */
1181 static void
kern_out(struct ag_info * ag)1182 kern_out(struct ag_info *ag)
1183 {
1184 struct khash *k;
1185
1186
1187 /* Do not install bad routes if they are not already present.
1188 * This includes routes that had RS_NET_SYN for interfaces that
1189 * recently died.
1190 */
1191 if (ag->ag_metric == HOPCNT_INFINITY) {
1192 k = kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0);
1193 if (k == 0)
1194 return;
1195 } else {
1196 k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask);
1197 }
1198
1199 if (k->k_state & KS_NEW) {
1200 /* will need to add new entry to the kernel table */
1201 k->k_state = KS_ADD;
1202 if (ag->ag_state & AGS_GATEWAY)
1203 k->k_state |= KS_GATEWAY;
1204 k->k_gate = ag->ag_gate;
1205 k->k_metric = ag->ag_metric;
1206 return;
1207 }
1208
1209 if (k->k_state & KS_STATIC)
1210 return;
1211
1212 /* modify existing kernel entry if necessary */
1213 if (k->k_gate != ag->ag_gate
1214 || k->k_metric != ag->ag_metric) {
1215 k->k_gate = ag->ag_gate;
1216 k->k_metric = ag->ag_metric;
1217 k->k_state |= KS_CHANGE;
1218 }
1219
1220 if (k->k_state & KS_DYNAMIC) {
1221 k->k_state &= ~KS_DYNAMIC;
1222 k->k_state |= (KS_ADD | KS_DEL_ADD);
1223 }
1224
1225 if ((k->k_state & KS_GATEWAY)
1226 && !(ag->ag_state & AGS_GATEWAY)) {
1227 k->k_state &= ~KS_GATEWAY;
1228 k->k_state |= (KS_ADD | KS_DEL_ADD);
1229 } else if (!(k->k_state & KS_GATEWAY)
1230 && (ag->ag_state & AGS_GATEWAY)) {
1231 k->k_state |= KS_GATEWAY;
1232 k->k_state |= (KS_ADD | KS_DEL_ADD);
1233 }
1234
1235 /* Deleting-and-adding is necessary to change aspects of a route.
1236 * Just delete instead of deleting and then adding a bad route.
1237 * Otherwise, we want to keep the route in the kernel.
1238 */
1239 if (k->k_metric == HOPCNT_INFINITY
1240 && (k->k_state & KS_DEL_ADD))
1241 k->k_state |= KS_DELETE;
1242 else
1243 k->k_state &= ~KS_DELETE;
1244 #undef RT
1245 }
1246
1247
1248 /* ARGSUSED */
1249 static int
walk_kern(struct radix_node * rn,void * w)1250 walk_kern(struct radix_node *rn,
1251 void *w)
1252 {
1253 #define RT ((struct rt_entry *)rn)
1254 char metric, pref;
1255 u_int ags = 0;
1256
1257
1258 /* Do not install synthetic routes */
1259 if (RT->rt_state & RS_NET_SYN)
1260 return 0;
1261
1262 if (!(RT->rt_state & RS_IF)) {
1263 ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
1264
1265 } else {
1266 /* Do not install routes for "external" remote interfaces.
1267 */
1268 if (RT->rt_ifp != 0 && (RT->rt_ifp->int_state & IS_EXTERNAL))
1269 return 0;
1270
1271 ags |= AGS_IF;
1272
1273 /* If it is not an interface, or an alias for an interface,
1274 * it must be a "gateway."
1275 *
1276 * If it is a "remote" interface, it is also a "gateway" to
1277 * the kernel if is not a alias.
1278 */
1279 if (RT->rt_ifp == 0
1280 || ((RT->rt_ifp->int_state & IS_REMOTE)
1281 && RT->rt_ifp->int_metric == 0))
1282 ags |= (AGS_GATEWAY | AGS_SUPPRESS | AGS_PROMOTE);
1283 }
1284
1285 if (RT->rt_state & RS_RDISC)
1286 ags |= AGS_CORS_GATE;
1287
1288 /* aggregate good routes without regard to their metric */
1289 pref = 1;
1290 metric = RT->rt_metric;
1291 if (metric == HOPCNT_INFINITY) {
1292 /* if the route is dead, so try hard to aggregate. */
1293 pref = HOPCNT_INFINITY;
1294 ags |= (AGS_FINE_GATE | AGS_SUPPRESS);
1295 }
1296
1297 ag_check(RT->rt_dst, RT->rt_mask, RT->rt_gate, 0,
1298 metric,pref, 0, 0, ags, kern_out);
1299 return 0;
1300 #undef RT
1301 }
1302
1303
1304 /* Update the kernel table to match the daemon table.
1305 */
1306 static void
fix_kern(void)1307 fix_kern(void)
1308 {
1309 int i, flags;
1310 struct khash *k, **pk;
1311
1312
1313 need_kern = age_timer;
1314
1315 /* Walk daemon table, updating the copy of the kernel table.
1316 */
1317 (void)rn_walktree(rhead, walk_kern, 0);
1318 ag_flush(0,0,kern_out);
1319
1320 for (i = 0; i < KHASH_SIZE; i++) {
1321 for (pk = &khash_bins[i]; (k = *pk) != 0; ) {
1322 /* Do not touch static routes */
1323 if (k->k_state & KS_STATIC) {
1324 kern_check_static(k,0);
1325 pk = &k->k_next;
1326 continue;
1327 }
1328
1329 /* check hold on routes deleted by the operator */
1330 if (k->k_keep > now.tv_sec) {
1331 LIM_SEC(need_kern, k->k_keep);
1332 k->k_state |= KS_DELETE;
1333 pk = &k->k_next;
1334 continue;
1335 }
1336
1337 if ((k->k_state & (KS_DELETE | KS_DYNAMIC))
1338 == KS_DELETE) {
1339 if (!(k->k_state & KS_DELETED))
1340 rtioctl(RTM_DELETE,
1341 k->k_dst, k->k_gate, k->k_mask,
1342 0, 0);
1343 *pk = k->k_next;
1344 free(k);
1345 continue;
1346 }
1347
1348 if (0 != (k->k_state&(KS_ADD|KS_CHANGE|KS_DEL_ADD))) {
1349 if (k->k_state & KS_DEL_ADD) {
1350 rtioctl(RTM_DELETE,
1351 k->k_dst,k->k_gate,k->k_mask,
1352 0, 0);
1353 k->k_state &= ~KS_DYNAMIC;
1354 }
1355
1356 flags = 0;
1357 if (0 != (k->k_state&(KS_GATEWAY|KS_DYNAMIC)))
1358 flags |= RTF_GATEWAY;
1359
1360 if (k->k_state & KS_ADD) {
1361 rtioctl(RTM_ADD,
1362 k->k_dst, k->k_gate, k->k_mask,
1363 k->k_metric, flags);
1364 } else if (k->k_state & KS_CHANGE) {
1365 rtioctl(RTM_CHANGE,
1366 k->k_dst,k->k_gate,k->k_mask,
1367 k->k_metric, flags);
1368 }
1369 k->k_state &= ~(KS_ADD|KS_CHANGE|KS_DEL_ADD);
1370 }
1371
1372 /* Mark this route to be deleted in the next cycle.
1373 * This deletes routes that disappear from the
1374 * daemon table, since the normal aging code
1375 * will clear the bit for routes that have not
1376 * disappeared from the daemon table.
1377 */
1378 k->k_state |= KS_DELETE;
1379 pk = &k->k_next;
1380 }
1381 }
1382 }
1383
1384
1385 /* Delete a static route in the image of the kernel table.
1386 */
1387 void
del_static(naddr dst,naddr mask,int gone)1388 del_static(naddr dst,
1389 naddr mask,
1390 int gone)
1391 {
1392 struct khash *k;
1393 struct rt_entry *rt;
1394
1395 /* Just mark it in the table to be deleted next time the kernel
1396 * table is updated.
1397 * If it has already been deleted, mark it as such, and set its
1398 * keep-timer so that it will not be deleted again for a while.
1399 * This lets the operator delete a route added by the daemon
1400 * and add a replacement.
1401 */
1402 k = kern_find(dst, mask, 0);
1403 if (k != 0) {
1404 k->k_state &= ~(KS_STATIC | KS_DYNAMIC);
1405 k->k_state |= KS_DELETE;
1406 if (gone) {
1407 k->k_state |= KS_DELETED;
1408 k->k_keep = now.tv_sec + K_KEEP_LIM;
1409 }
1410 }
1411
1412 rt = rtget(dst, mask);
1413 if (rt != 0 && (rt->rt_state & RS_STATIC))
1414 rtbad(rt);
1415 }
1416
1417
1418 /* Delete all routes generated from ICMP Redirects that use a given gateway,
1419 * as well as old redirected routes.
1420 */
1421 void
del_redirects(naddr bad_gate,time_t old)1422 del_redirects(naddr bad_gate,
1423 time_t old)
1424 {
1425 int i;
1426 struct khash *k;
1427
1428
1429 for (i = 0; i < KHASH_SIZE; i++) {
1430 for (k = khash_bins[i]; k != 0; k = k->k_next) {
1431 if (!(k->k_state & KS_DYNAMIC)
1432 || (k->k_state & KS_STATIC))
1433 continue;
1434
1435 if (k->k_gate != bad_gate
1436 && k->k_redirect_time > old
1437 && !supplier)
1438 continue;
1439
1440 k->k_state |= KS_DELETE;
1441 k->k_state &= ~KS_DYNAMIC;
1442 need_kern.tv_sec = now.tv_sec;
1443 trace_act("mark redirected %s --> %s for deletion\n",
1444 addrname(k->k_dst, k->k_mask, 0),
1445 naddr_ntoa(k->k_gate));
1446 }
1447 }
1448 }
1449
1450
1451 /* Start the daemon tables.
1452 */
1453 void
rtinit(void)1454 rtinit(void)
1455 {
1456 extern int max_keylen;
1457 int i;
1458 struct ag_info *ag;
1459
1460 /* Initialize the radix trees */
1461 max_keylen = sizeof(struct sockaddr_in);
1462 rn_init();
1463 rn_inithead((void**)&rhead, 32);
1464
1465 /* mark all of the slots in the table free */
1466 ag_avail = ag_slots;
1467 for (ag = ag_slots, i = 1; i < NUM_AG_SLOTS; i++) {
1468 ag->ag_fine = ag+1;
1469 ag++;
1470 }
1471 }
1472
1473
1474 #ifdef _HAVE_SIN_LEN
1475 static struct sockaddr_in dst_sock = {sizeof(dst_sock), AF_INET};
1476 static struct sockaddr_in mask_sock = {sizeof(mask_sock), AF_INET};
1477 #else
1478 static struct sockaddr_in_new dst_sock = {_SIN_ADDR_SIZE, AF_INET};
1479 static struct sockaddr_in_new mask_sock = {_SIN_ADDR_SIZE, AF_INET};
1480 #endif
1481
1482
1483 void
set_need_flash(void)1484 set_need_flash(void)
1485 {
1486 if (!need_flash) {
1487 need_flash = 1;
1488 /* Do not send the flash update immediately. Wait a little
1489 * while to hear from other routers.
1490 */
1491 no_flash.tv_sec = now.tv_sec + MIN_WAITTIME;
1492 }
1493 }
1494
1495
1496 /* Get a particular routing table entry
1497 */
1498 struct rt_entry *
rtget(naddr dst,naddr mask)1499 rtget(naddr dst, naddr mask)
1500 {
1501 struct rt_entry *rt;
1502
1503 dst_sock.sin_addr.s_addr = dst;
1504 mask_sock.sin_addr.s_addr = mask;
1505 masktrim(&mask_sock);
1506 rt = (struct rt_entry *)rhead->rnh_lookup(&dst_sock,&mask_sock,rhead);
1507 if (!rt
1508 || rt->rt_dst != dst
1509 || rt->rt_mask != mask)
1510 return 0;
1511
1512 return rt;
1513 }
1514
1515
1516 /* Find a route to dst as the kernel would.
1517 */
1518 struct rt_entry *
rtfind(naddr dst)1519 rtfind(naddr dst)
1520 {
1521 dst_sock.sin_addr.s_addr = dst;
1522 return (struct rt_entry *)rhead->rnh_matchaddr(&dst_sock, rhead);
1523 }
1524
1525
1526 /* add a route to the table
1527 */
1528 void
rtadd(naddr dst,naddr mask,naddr gate,naddr router,int metric,u_short tag,u_int state,struct interface * ifp)1529 rtadd(naddr dst,
1530 naddr mask,
1531 naddr gate, /* forward packets here */
1532 naddr router, /* on the authority of this router */
1533 int metric,
1534 u_short tag,
1535 u_int state, /* rs_state for the entry */
1536 struct interface *ifp)
1537 {
1538 struct rt_entry *rt;
1539 naddr smask;
1540 int i;
1541 struct rt_spare *rts;
1542
1543 rt = (struct rt_entry *)rtmalloc(sizeof (*rt), "rtadd");
1544 bzero(rt, sizeof(*rt));
1545 for (rts = rt->rt_spares, i = NUM_SPARES; i != 0; i--, rts++)
1546 rts->rts_metric = HOPCNT_INFINITY;
1547
1548 rt->rt_nodes->rn_key = (caddr_t)&rt->rt_dst_sock;
1549 rt->rt_dst = dst;
1550 rt->rt_dst_sock.sin_family = AF_INET;
1551 #ifdef _HAVE_SIN_LEN
1552 rt->rt_dst_sock.sin_len = dst_sock.sin_len;
1553 #endif
1554 if (mask != HOST_MASK) {
1555 smask = std_mask(dst);
1556 if ((smask & ~mask) == 0 && mask > smask)
1557 state |= RS_SUBNET;
1558 }
1559 mask_sock.sin_addr.s_addr = mask;
1560 masktrim(&mask_sock);
1561 rt->rt_mask = mask;
1562 rt->rt_state = state;
1563 rt->rt_gate = gate;
1564 rt->rt_router = router;
1565 rt->rt_time = now.tv_sec;
1566 rt->rt_metric = metric;
1567 rt->rt_poison_metric = HOPCNT_INFINITY;
1568 rt->rt_tag = tag;
1569 rt->rt_ifp = ifp;
1570 rt->rt_seqno = update_seqno;
1571
1572 if (++total_routes == MAX_ROUTES)
1573 msglog("have maximum (%d) routes", total_routes);
1574 if (TRACEACTIONS)
1575 trace_add_del("Add", rt);
1576
1577 need_kern.tv_sec = now.tv_sec;
1578 set_need_flash();
1579
1580 if (0 == rhead->rnh_addaddr(&rt->rt_dst_sock, &mask_sock,
1581 rhead, rt->rt_nodes)) {
1582 msglog("rnh_addaddr() failed for %s mask=%#x",
1583 naddr_ntoa(dst), mask);
1584 }
1585 }
1586
1587
1588 /* notice a changed route
1589 */
1590 void
rtchange(struct rt_entry * rt,u_int state,naddr gate,naddr router,int metric,u_short tag,struct interface * ifp,time_t new_time,char * label)1591 rtchange(struct rt_entry *rt,
1592 u_int state, /* new state bits */
1593 naddr gate, /* now forward packets here */
1594 naddr router, /* on the authority of this router */
1595 int metric, /* new metric */
1596 u_short tag,
1597 struct interface *ifp,
1598 time_t new_time,
1599 char *label)
1600 {
1601 if (rt->rt_metric != metric) {
1602 /* Fix the kernel immediately if it seems the route
1603 * has gone bad, since there may be a working route that
1604 * aggregates this route.
1605 */
1606 if (metric == HOPCNT_INFINITY) {
1607 need_kern.tv_sec = now.tv_sec;
1608 if (new_time >= now.tv_sec - EXPIRE_TIME)
1609 new_time = now.tv_sec - EXPIRE_TIME;
1610 }
1611 rt->rt_seqno = update_seqno;
1612 set_need_flash();
1613 }
1614
1615 if (rt->rt_gate != gate) {
1616 need_kern.tv_sec = now.tv_sec;
1617 rt->rt_seqno = update_seqno;
1618 set_need_flash();
1619 }
1620
1621 state |= (rt->rt_state & RS_SUBNET);
1622
1623 /* Keep various things from deciding ageless routes are stale.
1624 */
1625 if (!AGE_RT(state, ifp))
1626 new_time = now.tv_sec;
1627
1628 if (TRACEACTIONS)
1629 trace_change(rt, state, gate, router, metric, tag, ifp,
1630 new_time,
1631 label ? label : "Chg ");
1632
1633 rt->rt_state = state;
1634 rt->rt_gate = gate;
1635 rt->rt_router = router;
1636 rt->rt_metric = metric;
1637 rt->rt_tag = tag;
1638 rt->rt_ifp = ifp;
1639 rt->rt_time = new_time;
1640 }
1641
1642
1643 /* check for a better route among the spares
1644 */
1645 static struct rt_spare *
rts_better(struct rt_entry * rt)1646 rts_better(struct rt_entry *rt)
1647 {
1648 struct rt_spare *rts, *rts1;
1649 int i;
1650
1651 /* find the best alternative among the spares */
1652 rts = rt->rt_spares+1;
1653 for (i = NUM_SPARES, rts1 = rts+1; i > 2; i--, rts1++) {
1654 if (BETTER_LINK(rt,rts1,rts))
1655 rts = rts1;
1656 }
1657
1658 return rts;
1659 }
1660
1661
1662 /* switch to a backup route
1663 */
1664 void
rtswitch(struct rt_entry * rt,struct rt_spare * rts)1665 rtswitch(struct rt_entry *rt,
1666 struct rt_spare *rts)
1667 {
1668 struct rt_spare swap;
1669 char *label;
1670
1671
1672 /* Do not change permanent routes */
1673 if (0 != (rt->rt_state & (RS_MHOME | RS_STATIC | RS_RDISC
1674 | RS_NET_SYN | RS_IF)))
1675 return;
1676
1677 /* find the best alternative among the spares */
1678 if (rts == 0)
1679 rts = rts_better(rt);
1680
1681 /* Do not bother if it is not worthwhile.
1682 */
1683 if (!BETTER_LINK(rt, rts, rt->rt_spares))
1684 return;
1685
1686 swap = rt->rt_spares[0];
1687 if (asprintf(&label, "Use #%d", (int)(rts - rt->rt_spares)) == -1)
1688 msglog("asprintf: cannot allocate memory");
1689 else {
1690 rtchange(rt, rt->rt_state & ~(RS_NET_SYN | RS_RDISC),
1691 rts->rts_gate, rts->rts_router, rts->rts_metric,
1692 rts->rts_tag, rts->rts_ifp, rts->rts_time, label);
1693 free(label);
1694 }
1695 *rts = swap;
1696 }
1697
1698
1699 void
rtdelete(struct rt_entry * rt)1700 rtdelete(struct rt_entry *rt)
1701 {
1702 struct khash *k;
1703
1704
1705 if (TRACEACTIONS)
1706 trace_add_del("Del", rt);
1707
1708 k = kern_find(rt->rt_dst, rt->rt_mask, 0);
1709 if (k != 0) {
1710 k->k_state |= KS_DELETE;
1711 need_kern.tv_sec = now.tv_sec;
1712 }
1713
1714 dst_sock.sin_addr.s_addr = rt->rt_dst;
1715 mask_sock.sin_addr.s_addr = rt->rt_mask;
1716 masktrim(&mask_sock);
1717 if (rt != (struct rt_entry *)rhead->rnh_deladdr(&dst_sock, &mask_sock,
1718 rhead, NULL)) {
1719 msglog("rnh_deladdr() failed");
1720 } else {
1721 free(rt);
1722 total_routes--;
1723 }
1724 }
1725
1726
1727 /* Get rid of a bad route, and try to switch to a replacement.
1728 */
1729 void
rtbad(struct rt_entry * rt)1730 rtbad(struct rt_entry *rt)
1731 {
1732 /* Poison the route */
1733 rtchange(rt, rt->rt_state & ~(RS_IF | RS_LOCAL | RS_STATIC),
1734 rt->rt_gate, rt->rt_router, HOPCNT_INFINITY, rt->rt_tag,
1735 0, rt->rt_time, 0);
1736
1737 rtswitch(rt, 0);
1738 }
1739
1740
1741 /* Junk a RS_NET_SYN or RS_LOCAL route,
1742 * unless it is needed by another interface.
1743 */
1744 void
rtbad_sub(struct rt_entry * rt)1745 rtbad_sub(struct rt_entry *rt)
1746 {
1747 struct interface *ifp, *ifp1;
1748 struct intnet *intnetp;
1749 u_int state;
1750
1751
1752 ifp1 = 0;
1753 state = 0;
1754
1755 if (rt->rt_state & RS_LOCAL) {
1756 /* Is this the route through loopback for the interface?
1757 * If so, see if it is used by any other interfaces, such
1758 * as a point-to-point interface with the same local address.
1759 */
1760 for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
1761 /* Retain it if another interface needs it.
1762 */
1763 if (ifp->int_addr == rt->rt_ifp->int_addr) {
1764 state |= RS_LOCAL;
1765 ifp1 = ifp;
1766 break;
1767 }
1768 }
1769
1770 }
1771
1772 if (!(state & RS_LOCAL)) {
1773 /* Retain RIPv1 logical network route if there is another
1774 * interface that justifies it.
1775 */
1776 if (rt->rt_state & RS_NET_SYN) {
1777 for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
1778 if ((ifp->int_state & IS_NEED_NET_SYN)
1779 && rt->rt_mask == ifp->int_std_mask
1780 && rt->rt_dst == ifp->int_std_addr) {
1781 state |= RS_NET_SYN;
1782 ifp1 = ifp;
1783 break;
1784 }
1785 }
1786 }
1787
1788 /* or if there is an authority route that needs it. */
1789 for (intnetp = intnets;
1790 intnetp != 0;
1791 intnetp = intnetp->intnet_next) {
1792 if (intnetp->intnet_addr == rt->rt_dst
1793 && intnetp->intnet_mask == rt->rt_mask) {
1794 state |= (RS_NET_SYN | RS_NET_INT);
1795 break;
1796 }
1797 }
1798 }
1799
1800 if (ifp1 != 0 || (state & RS_NET_SYN)) {
1801 rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN | RS_LOCAL))
1802 | state),
1803 rt->rt_gate, rt->rt_router, rt->rt_metric,
1804 rt->rt_tag, ifp1, rt->rt_time, 0);
1805 } else {
1806 rtbad(rt);
1807 }
1808 }
1809
1810
1811 /* Called while walking the table looking for sick interfaces
1812 * or after a time change.
1813 */
1814 /* ARGSUSED */
1815 int
walk_bad(struct radix_node * rn,void * w)1816 walk_bad(struct radix_node *rn,
1817 void *w)
1818 {
1819 #define RT ((struct rt_entry *)rn)
1820 struct rt_spare *rts;
1821 int i;
1822 time_t new_time;
1823
1824
1825 /* fix any spare routes through the interface
1826 */
1827 rts = RT->rt_spares;
1828 for (i = NUM_SPARES; i != 1; i--) {
1829 rts++;
1830
1831 if (rts->rts_ifp != 0
1832 && (rts->rts_ifp->int_state & IS_BROKE)) {
1833 /* mark the spare route to be deleted immediately */
1834 new_time = rts->rts_time;
1835 if (new_time >= now_garbage)
1836 new_time = now_garbage-1;
1837 trace_upslot(RT, rts, rts->rts_gate,
1838 rts->rts_router, 0,
1839 HOPCNT_INFINITY, rts->rts_tag,
1840 new_time);
1841 rts->rts_ifp = 0;
1842 rts->rts_metric = HOPCNT_INFINITY;
1843 rts->rts_time = new_time;
1844 }
1845 }
1846
1847 /* Deal with the main route
1848 */
1849 /* finished if it has been handled before or if its interface is ok
1850 */
1851 if (RT->rt_ifp == 0 || !(RT->rt_ifp->int_state & IS_BROKE))
1852 return 0;
1853
1854 /* Bad routes for other than interfaces are easy.
1855 */
1856 if (0 == (RT->rt_state & (RS_IF | RS_NET_SYN | RS_LOCAL))) {
1857 rtbad(RT);
1858 return 0;
1859 }
1860
1861 rtbad_sub(RT);
1862 return 0;
1863 #undef RT
1864 }
1865
1866
1867 /* Check the age of an individual route.
1868 */
1869 /* ARGSUSED */
1870 static int
walk_age(struct radix_node * rn,void * w)1871 walk_age(struct radix_node *rn,
1872 void *w)
1873 {
1874 #define RT ((struct rt_entry *)rn)
1875 struct interface *ifp;
1876 struct rt_spare *rts;
1877 int i;
1878
1879
1880 /* age all of the spare routes, including the primary route
1881 * currently in use
1882 */
1883 rts = RT->rt_spares;
1884 for (i = NUM_SPARES; i != 0; i--, rts++) {
1885
1886 ifp = rts->rts_ifp;
1887 if (i == NUM_SPARES) {
1888 if (!AGE_RT(RT->rt_state, ifp)) {
1889 /* Keep various things from deciding ageless
1890 * routes are stale
1891 */
1892 rts->rts_time = now.tv_sec;
1893 continue;
1894 }
1895
1896 /* forget RIP routes after RIP has been turned off.
1897 */
1898 if (rip_sock < 0) {
1899 rtdelete(RT);
1900 return 0;
1901 }
1902 }
1903
1904 /* age failing routes
1905 */
1906 if (age_bad_gate == rts->rts_gate
1907 && rts->rts_time >= now_stale) {
1908 rts->rts_time -= SUPPLY_INTERVAL;
1909 }
1910
1911 /* trash the spare routes when they go bad */
1912 if (rts->rts_metric < HOPCNT_INFINITY
1913 && now_garbage > rts->rts_time) {
1914 trace_upslot(RT, rts, rts->rts_gate,
1915 rts->rts_router, rts->rts_ifp,
1916 HOPCNT_INFINITY, rts->rts_tag,
1917 rts->rts_time);
1918 rts->rts_metric = HOPCNT_INFINITY;
1919 }
1920 }
1921
1922
1923 /* finished if the active route is still fresh */
1924 if (now_stale <= RT->rt_time)
1925 return 0;
1926
1927 /* try to switch to an alternative */
1928 rtswitch(RT, 0);
1929
1930 /* Delete a dead route after it has been publically mourned. */
1931 if (now_garbage > RT->rt_time) {
1932 rtdelete(RT);
1933 return 0;
1934 }
1935
1936 /* Start poisoning a bad route before deleting it. */
1937 if (now.tv_sec - RT->rt_time > EXPIRE_TIME)
1938 rtchange(RT, RT->rt_state, RT->rt_gate, RT->rt_router,
1939 HOPCNT_INFINITY, RT->rt_tag, RT->rt_ifp,
1940 RT->rt_time, 0);
1941 return 0;
1942 }
1943
1944
1945 /* Watch for dead routes and interfaces.
1946 */
1947 void
age(naddr bad_gate)1948 age(naddr bad_gate)
1949 {
1950 struct interface *ifp;
1951
1952
1953 age_timer.tv_sec = now.tv_sec + (rip_sock < 0
1954 ? NEVER
1955 : SUPPLY_INTERVAL);
1956
1957 for (ifp = ifnet; ifp; ifp = ifp->int_next) {
1958 /* Check for dead IS_REMOTE interfaces by timing their
1959 * transmissions.
1960 */
1961 if ((ifp->int_state & IS_REMOTE)
1962 && !(ifp->int_state & IS_PASSIVE)
1963 && (ifp->int_state & IS_ACTIVE)) {
1964 LIM_SEC(age_timer, now.tv_sec+SUPPLY_INTERVAL);
1965
1966 if (now.tv_sec - ifp->int_act_time > EXPIRE_TIME
1967 && !(ifp->int_state & IS_BROKE)) {
1968 msglog("remote interface %s to %s timed out"
1969 "--turned off",
1970 ifp->int_name,
1971 naddr_ntoa(ifp->int_addr));
1972 if_bad(ifp);
1973 }
1974 }
1975 }
1976
1977 /* Age routes. */
1978 age_bad_gate = bad_gate;
1979 (void)rn_walktree(rhead, walk_age, 0);
1980
1981 /* Update the kernel routing table. */
1982 fix_kern();
1983 }
1984