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