]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/rip/rip.c
RIP: Use message authentication interface
[thirdparty/bird.git] / proto / rip / rip.c
1 /*
2 * BIRD -- Routing Information Protocol (RIP)
3 *
4 * (c) 1998--1999 Pavel Machek <pavel@ucw.cz>
5 * (c) 2004--2013 Ondrej Filip <feela@network.cz>
6 * (c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org>
7 * (c) 2009--2015 CZ.NIC z.s.p.o.
8 *
9 * Can be freely distributed and used under the terms of the GNU GPL.
10 */
11
12 /**
13 * DOC: Routing Information Protocol (RIP)
14 *
15 * The RIP protocol is implemented in two files: |rip.c| containing the protocol
16 * logic, route management and the protocol glue with BIRD core, and |packets.c|
17 * handling RIP packet processing, RX, TX and protocol sockets.
18 *
19 * Each instance of RIP is described by a structure &rip_proto, which contains
20 * an internal RIP routing table, a list of protocol interfaces and the main
21 * timer responsible for RIP routing table cleanup.
22 *
23 * RIP internal routing table contains incoming and outgoing routes. For each
24 * network (represented by structure &rip_entry) there is one outgoing route
25 * stored directly in &rip_entry and an one-way linked list of incoming routes
26 * (structures &rip_rte). The list contains incoming routes from different RIP
27 * neighbors, but only routes with the lowest metric are stored (i.e., all
28 * stored incoming routes have the same metric).
29 *
30 * Note that RIP itself does not select outgoing route, that is done by the core
31 * routing table. When a new incoming route is received, it is propagated to the
32 * RIP table by rip_update_rte() and possibly stored in the list of incoming
33 * routes. Then the change may be propagated to the core by rip_announce_rte().
34 * The core selects the best route and propagate it to RIP by rip_rt_notify(),
35 * which updates outgoing route part of &rip_entry and possibly triggers route
36 * propagation by rip_trigger_update().
37 *
38 * RIP interfaces are represented by structures &rip_iface. A RIP interface
39 * contains a per-interface socket, a list of associated neighbors, interface
40 * configuration, and state information related to scheduled interface events
41 * and running update sessions. RIP interfaces are added and removed based on
42 * core interface notifications.
43 *
44 * There are two RIP interface events - regular updates and triggered updates.
45 * Both are managed from the RIP interface timer (rip_iface_timer()). Regular
46 * updates are called at fixed interval and propagate the whole routing table,
47 * while triggered updates are scheduled by rip_trigger_update() due to some
48 * routing table change and propagate only the routes modified since the time
49 * they were scheduled. There are also unicast-destined requested updates, but
50 * these are sent directly as a reaction to received RIP request message. The
51 * update session is started by rip_send_table(). There may be at most one
52 * active update session per interface, as the associated state (including the
53 * fib iterator) is stored directly in &rip_iface structure.
54 *
55 * RIP neighbors are represented by structures &rip_neighbor. Compared to
56 * neighbor handling in other routing protocols, RIP does not have explicit
57 * neighbor discovery and adjacency maintenance, which makes the &rip_neighbor
58 * related code a bit peculiar. RIP neighbors are interlinked with core neighbor
59 * structures (&neighbor) and use core neighbor notifications to ensure that RIP
60 * neighbors are timely removed. RIP neighbors are added based on received route
61 * notifications and removed based on core neighbor and RIP interface events.
62 *
63 * RIP neighbors are linked by RIP routes and use counter to track the number of
64 * associated routes, but when these RIP routes timeout, associated RIP neighbor
65 * is still alive (with zero counter). When RIP neighbor is removed but still
66 * has some associated routes, it is not freed, just changed to detached state
67 * (core neighbors and RIP ifaces are unlinked), then during the main timer
68 * cleanup phase the associated routes are removed and the &rip_neighbor
69 * structure is finally freed.
70 *
71 * Supported standards:
72 * - RFC 1058 - RIPv1
73 * - RFC 2453 - RIPv2
74 * - RFC 2080 - RIPng
75 * - RFC 4822 - RIP cryptographic authentication
76 */
77
78 #include <stdlib.h>
79 #include "rip.h"
80
81
82 static inline void rip_lock_neighbor(struct rip_neighbor *n);
83 static inline void rip_unlock_neighbor(struct rip_neighbor *n);
84 static inline int rip_iface_link_up(struct rip_iface *ifa);
85 static inline void rip_kick_timer(struct rip_proto *p);
86 static inline void rip_iface_kick_timer(struct rip_iface *ifa);
87 static void rip_iface_timer(timer *timer);
88 static void rip_trigger_update(struct rip_proto *p);
89
90
91 /*
92 * RIP routes
93 */
94
95 static void
96 rip_init_entry(struct fib_node *fn)
97 {
98 // struct rip_entry *en = (void) *fn;
99
100 const uint offset = OFFSETOF(struct rip_entry, routes);
101 memset((byte *)fn + offset, 0, sizeof(struct rip_entry) - offset);
102 }
103
104 static struct rip_rte *
105 rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src)
106 {
107 struct rip_rte *rt = sl_alloc(p->rte_slab);
108
109 memcpy(rt, src, sizeof(struct rip_rte));
110 rt->next = *rp;
111 *rp = rt;
112
113 rip_lock_neighbor(rt->from);
114
115 return rt;
116 }
117
118 static inline void
119 rip_remove_rte(struct rip_proto *p, struct rip_rte **rp)
120 {
121 struct rip_rte *rt = *rp;
122
123 rip_unlock_neighbor(rt->from);
124
125 *rp = rt->next;
126 sl_free(p->rte_slab, rt);
127 }
128
129 static inline int rip_same_rte(struct rip_rte *a, struct rip_rte *b)
130 { return a->metric == b->metric && a->tag == b->tag && ipa_equal(a->next_hop, b->next_hop); }
131
132 static inline int rip_valid_rte(struct rip_rte *rt)
133 { return rt->from->ifa != NULL; }
134
135 /**
136 * rip_announce_rte - announce route from RIP routing table to the core
137 * @p: RIP instance
138 * @en: related network
139 *
140 * The function takes a list of incoming routes from @en, prepare appropriate
141 * &rte for the core and propagate it by rte_update().
142 */
143 static void
144 rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
145 {
146 struct rip_rte *rt = en->routes;
147
148 /* Find first valid rte */
149 while (rt && !rip_valid_rte(rt))
150 rt = rt->next;
151
152 if (rt)
153 {
154 /* Update */
155 net *n = net_get(p->p.table, en->n.prefix, en->n.pxlen);
156
157 rta a0 = {
158 .src = p->p.main_source,
159 .source = RTS_RIP,
160 .scope = SCOPE_UNIVERSE,
161 .cast = RTC_UNICAST
162 };
163
164 u8 rt_metric = rt->metric;
165 u16 rt_tag = rt->tag;
166 struct rip_rte *rt2 = rt->next;
167
168 /* Find second valid rte */
169 while (rt2 && !rip_valid_rte(rt2))
170 rt2 = rt2->next;
171
172 if (p->ecmp && rt2)
173 {
174 /* ECMP route */
175 struct mpnh *nhs = NULL;
176 int num = 0;
177
178 for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
179 {
180 if (!rip_valid_rte(rt))
181 continue;
182
183 struct mpnh *nh = alloca(sizeof(struct mpnh));
184 nh->gw = rt->next_hop;
185 nh->iface = rt->from->nbr->iface;
186 nh->weight = rt->from->ifa->cf->ecmp_weight;
187 mpnh_insert(&nhs, nh);
188 num++;
189
190 if (rt->tag != rt_tag)
191 rt_tag = 0;
192 }
193
194 a0.dest = RTD_MULTIPATH;
195 a0.nexthops = nhs;
196 }
197 else
198 {
199 /* Unipath route */
200 a0.dest = RTD_ROUTER;
201 a0.gw = rt->next_hop;
202 a0.iface = rt->from->nbr->iface;
203 a0.from = rt->from->nbr->addr;
204 }
205
206 rta *a = rta_lookup(&a0);
207 rte *e = rte_get_temp(a);
208
209 e->u.rip.from = a0.iface;
210 e->u.rip.metric = rt_metric;
211 e->u.rip.tag = rt_tag;
212
213 e->net = n;
214 e->pflags = 0;
215
216 rte_update(&p->p, n, e);
217 }
218 else
219 {
220 /* Withdraw */
221 net *n = net_find(p->p.table, en->n.prefix, en->n.pxlen);
222 rte_update(&p->p, n, NULL);
223 }
224 }
225
226 /**
227 * rip_update_rte - enter a route update to RIP routing table
228 * @p: RIP instance
229 * @prefix: network prefix
230 * @pxlen: network prefix length
231 * @new: a &rip_rte representing the new route
232 *
233 * The function is called by the RIP packet processing code whenever it receives
234 * a reachable route. The appropriate routing table entry is found and the list
235 * of incoming routes is updated. Eventually, the change is also propagated to
236 * the core by rip_announce_rte(). Note that for unreachable routes,
237 * rip_withdraw_rte() should be called instead of rip_update_rte().
238 */
239 void
240 rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new)
241 {
242 struct rip_entry *en = fib_get(&p->rtable, prefix, pxlen);
243 struct rip_rte *rt, **rp;
244 int changed = 0;
245
246 /* If the new route is better, remove all current routes */
247 if (en->routes && new->metric < en->routes->metric)
248 while (en->routes)
249 rip_remove_rte(p, &en->routes);
250
251 /* Find the old route (also set rp for later) */
252 for (rp = &en->routes; rt = *rp; rp = &rt->next)
253 if (rt->from == new->from)
254 {
255 if (rip_same_rte(rt, new))
256 {
257 rt->expires = new->expires;
258 return;
259 }
260
261 /* Remove the old route */
262 rip_remove_rte(p, rp);
263 changed = 1;
264 break;
265 }
266
267 /* If the new route is optimal, add it to the list */
268 if (!en->routes || new->metric == en->routes->metric)
269 {
270 rt = rip_add_rte(p, rp, new);
271 changed = 1;
272 }
273
274 /* Announce change if on relevant position (the first or any for ECMP) */
275 if (changed && (rp == &en->routes || p->ecmp))
276 rip_announce_rte(p, en);
277 }
278
279 /**
280 * rip_withdraw_rte - enter a route withdraw to RIP routing table
281 * @p: RIP instance
282 * @prefix: network prefix
283 * @pxlen: network prefix length
284 * @from: a &rip_neighbor propagating the withdraw
285 *
286 * The function is called by the RIP packet processing code whenever it receives
287 * an unreachable route. The incoming route for given network from nbr @from is
288 * removed. Eventually, the change is also propagated by rip_announce_rte().
289 */
290 void
291 rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from)
292 {
293 struct rip_entry *en = fib_find(&p->rtable, prefix, pxlen);
294 struct rip_rte *rt, **rp;
295
296 if (!en)
297 return;
298
299 /* Find the old route */
300 for (rp = &en->routes; rt = *rp; rp = &rt->next)
301 if (rt->from == from)
302 break;
303
304 if (!rt)
305 return;
306
307 /* Remove the old route */
308 rip_remove_rte(p, rp);
309
310 /* Announce change if on relevant position */
311 if (rp == &en->routes || p->ecmp)
312 rip_announce_rte(p, en);
313 }
314
315 /*
316 * rip_rt_notify - core tells us about new route, so store
317 * it into our data structures.
318 */
319 static void
320 rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net, struct rte *new,
321 struct rte *old UNUSED, struct ea_list *attrs)
322 {
323 struct rip_proto *p = (struct rip_proto *) P;
324 struct rip_entry *en;
325 int old_metric;
326
327 if (new)
328 {
329 /* Update */
330 u32 rt_metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
331 u32 rt_tag = ea_get_int(attrs, EA_RIP_TAG, 0);
332
333 if (rt_metric > p->infinity)
334 {
335 log(L_WARN "%s: Invalid rip_metric value %u for route %I/%d",
336 p->p.name, rt_metric, net->n.prefix, net->n.pxlen);
337 rt_metric = p->infinity;
338 }
339
340 if (rt_tag > 0xffff)
341 {
342 log(L_WARN "%s: Invalid rip_tag value %u for route %I/%d",
343 p->p.name, rt_tag, net->n.prefix, net->n.pxlen);
344 rt_metric = p->infinity;
345 rt_tag = 0;
346 }
347
348 /*
349 * Note that we accept exported routes with infinity metric (this could
350 * happen if rip_metric is modified in filters). Such entry has infinity
351 * metric but is RIP_ENTRY_VALID and therefore is not subject to garbage
352 * collection.
353 */
354
355 en = fib_get(&p->rtable, &net->n.prefix, net->n.pxlen);
356
357 old_metric = en->valid ? en->metric : -1;
358
359 en->valid = RIP_ENTRY_VALID;
360 en->metric = rt_metric;
361 en->tag = rt_tag;
362 en->from = (new->attrs->src->proto == P) ? new->u.rip.from : NULL;
363 en->iface = new->attrs->iface;
364 en->next_hop = new->attrs->gw;
365 }
366 else
367 {
368 /* Withdraw */
369 en = fib_find(&p->rtable, &net->n.prefix, net->n.pxlen);
370
371 if (!en || en->valid != RIP_ENTRY_VALID)
372 return;
373
374 old_metric = en->metric;
375
376 en->valid = RIP_ENTRY_STALE;
377 en->metric = p->infinity;
378 en->tag = 0;
379 en->from = NULL;
380 en->iface = NULL;
381 en->next_hop = IPA_NONE;
382 }
383
384 /* Activate triggered updates */
385 if (en->metric != old_metric)
386 {
387 en->changed = now;
388 rip_trigger_update(p);
389 }
390 }
391
392
393 /*
394 * RIP neighbors
395 */
396
397 struct rip_neighbor *
398 rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa)
399 {
400 neighbor *nbr = neigh_find2(&p->p, a, ifa->iface, 0);
401
402 if (!nbr || (nbr->scope == SCOPE_HOST) || !rip_iface_link_up(ifa))
403 return NULL;
404
405 if (nbr->data)
406 return nbr->data;
407
408 TRACE(D_EVENTS, "New neighbor %I on %s", *a, ifa->iface->name);
409
410 struct rip_neighbor *n = mb_allocz(p->p.pool, sizeof(struct rip_neighbor));
411 n->ifa = ifa;
412 n->nbr = nbr;
413 nbr->data = n;
414 n->csn = nbr->aux;
415
416 add_tail(&ifa->neigh_list, NODE n);
417
418 return n;
419 }
420
421 static void
422 rip_remove_neighbor(struct rip_proto *p, struct rip_neighbor *n)
423 {
424 neighbor *nbr = n->nbr;
425
426 TRACE(D_EVENTS, "Removing neighbor %I on %s", nbr->addr, nbr->iface->name);
427
428 rem_node(NODE n);
429 n->ifa = NULL;
430 n->nbr = NULL;
431 nbr->data = NULL;
432 nbr->aux = n->csn;
433
434 rfree(n->bfd_req);
435 n->bfd_req = NULL;
436 n->last_seen = 0;
437
438 if (!n->uc)
439 mb_free(n);
440
441 /* Related routes are removed in rip_timer() */
442 rip_kick_timer(p);
443 }
444
445 static inline void
446 rip_lock_neighbor(struct rip_neighbor *n)
447 {
448 n->uc++;
449 }
450
451 static inline void
452 rip_unlock_neighbor(struct rip_neighbor *n)
453 {
454 n->uc--;
455
456 if (!n->nbr && !n->uc)
457 mb_free(n);
458 }
459
460 static void
461 rip_neigh_notify(struct neighbor *nbr)
462 {
463 struct rip_proto *p = (struct rip_proto *) nbr->proto;
464 struct rip_neighbor *n = nbr->data;
465
466 if (!n)
467 return;
468
469 /*
470 * We assume that rip_neigh_notify() is called before rip_if_notify() for
471 * IF_CHANGE_DOWN and therefore n->ifa is still valid. We have no such
472 * ordering assumption for IF_CHANGE_LINK, so we test link state of the
473 * underlying iface instead of just rip_iface state.
474 */
475 if ((nbr->scope <= 0) || !rip_iface_link_up(n->ifa))
476 rip_remove_neighbor(p, n);
477 }
478
479 static void
480 rip_bfd_notify(struct bfd_request *req)
481 {
482 struct rip_neighbor *n = req->data;
483 struct rip_proto *p = n->ifa->rip;
484
485 if (req->down)
486 {
487 TRACE(D_EVENTS, "BFD session down for nbr %I on %s",
488 n->nbr->addr, n->ifa->iface->name);
489 rip_remove_neighbor(p, n);
490 }
491 }
492
493 void
494 rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n)
495 {
496 int use_bfd = n->ifa->cf->bfd && n->last_seen;
497
498 if (use_bfd && !n->bfd_req)
499 {
500 /*
501 * For RIPv2, use the same address as rip_open_socket(). For RIPng, neighbor
502 * should contain an address from the same prefix, thus also link-local. It
503 * may cause problems if two link-local addresses are assigned to one iface.
504 */
505 ip_addr saddr = rip_is_v2(p) ? n->ifa->sk->saddr : n->nbr->ifa->ip;
506 n->bfd_req = bfd_request_session(p->p.pool, n->nbr->addr, saddr,
507 n->nbr->iface, rip_bfd_notify, n);
508 }
509
510 if (!use_bfd && n->bfd_req)
511 {
512 rfree(n->bfd_req);
513 n->bfd_req = NULL;
514 }
515 }
516
517
518 /*
519 * RIP interfaces
520 */
521
522 static void
523 rip_iface_start(struct rip_iface *ifa)
524 {
525 struct rip_proto *p = ifa->rip;
526
527 TRACE(D_EVENTS, "Starting interface %s", ifa->iface->name);
528
529 ifa->next_regular = now + (random() % ifa->cf->update_time) + 1;
530 ifa->next_triggered = now; /* Available immediately */
531 ifa->want_triggered = 1; /* All routes in triggered update */
532 tm_start(ifa->timer, 1); /* Or 100 ms */
533 ifa->up = 1;
534
535 if (!ifa->cf->passive)
536 rip_send_request(ifa->rip, ifa);
537 }
538
539 static void
540 rip_iface_stop(struct rip_iface *ifa)
541 {
542 struct rip_proto *p = ifa->rip;
543 struct rip_neighbor *n;
544
545 TRACE(D_EVENTS, "Stopping interface %s", ifa->iface->name);
546
547 rip_reset_tx_session(p, ifa);
548
549 WALK_LIST_FIRST(n, ifa->neigh_list)
550 rip_remove_neighbor(p, n);
551
552 tm_stop(ifa->timer);
553 ifa->up = 0;
554 }
555
556 static inline int
557 rip_iface_link_up(struct rip_iface *ifa)
558 {
559 return !ifa->cf->check_link || (ifa->iface->flags & IF_LINK_UP);
560 }
561
562 static void
563 rip_iface_update_state(struct rip_iface *ifa)
564 {
565 int up = ifa->sk && rip_iface_link_up(ifa);
566
567 if (up == ifa->up)
568 return;
569
570 if (up)
571 rip_iface_start(ifa);
572 else
573 rip_iface_stop(ifa);
574 }
575
576 static void
577 rip_iface_update_buffers(struct rip_iface *ifa)
578 {
579 if (!ifa->sk)
580 return;
581
582 uint rbsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
583 uint tbsize = ifa->cf->tx_length ?: ifa->iface->mtu;
584 rbsize = MAX(rbsize, tbsize);
585
586 sk_set_rbsize(ifa->sk, rbsize);
587 sk_set_tbsize(ifa->sk, tbsize);
588
589 uint headers = (rip_is_v2(ifa->rip) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH) + UDP_HEADER_LENGTH;
590 ifa->tx_plen = tbsize - headers;
591
592 if (ifa->cf->auth_type == RIP_AUTH_CRYPTO)
593 ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH + max_mac_length(ifa->cf->passwords);
594 }
595
596 static inline void
597 rip_iface_update_bfd(struct rip_iface *ifa)
598 {
599 struct rip_proto *p = ifa->rip;
600 struct rip_neighbor *n;
601
602 WALK_LIST(n, ifa->neigh_list)
603 rip_update_bfd(p, n);
604 }
605
606
607 static void
608 rip_iface_locked(struct object_lock *lock)
609 {
610 struct rip_iface *ifa = lock->data;
611 struct rip_proto *p = ifa->rip;
612
613 if (!rip_open_socket(ifa))
614 {
615 log(L_ERR "%s: Cannot open socket for %s", p->p.name, ifa->iface->name);
616 return;
617 }
618
619 rip_iface_update_buffers(ifa);
620 rip_iface_update_state(ifa);
621 }
622
623
624 static struct rip_iface *
625 rip_find_iface(struct rip_proto *p, struct iface *what)
626 {
627 struct rip_iface *ifa;
628
629 WALK_LIST(ifa, p->iface_list)
630 if (ifa->iface == what)
631 return ifa;
632
633 return NULL;
634 }
635
636 static void
637 rip_add_iface(struct rip_proto *p, struct iface *iface, struct rip_iface_config *ic)
638 {
639 struct rip_iface *ifa;
640
641 TRACE(D_EVENTS, "Adding interface %s", iface->name);
642
643 ifa = mb_allocz(p->p.pool, sizeof(struct rip_iface));
644 ifa->rip = p;
645 ifa->iface = iface;
646 ifa->cf = ic;
647
648 if (ipa_nonzero(ic->address))
649 ifa->addr = ic->address;
650 else if (ic->mode == RIP_IM_MULTICAST)
651 ifa->addr = rip_is_v2(p) ? IP4_RIP_ROUTERS : IP6_RIP_ROUTERS;
652 else /* Broadcast */
653 ifa->addr = iface->addr->brd;
654
655 init_list(&ifa->neigh_list);
656
657 add_tail(&p->iface_list, NODE ifa);
658
659 ifa->timer = tm_new_set(p->p.pool, rip_iface_timer, ifa, 0, 0);
660
661 struct object_lock *lock = olock_new(p->p.pool);
662 lock->type = OBJLOCK_UDP;
663 lock->port = ic->port;
664 lock->iface = iface;
665 lock->data = ifa;
666 lock->hook = rip_iface_locked;
667 ifa->lock = lock;
668
669 olock_acquire(lock);
670 }
671
672 static void
673 rip_remove_iface(struct rip_proto *p, struct rip_iface *ifa)
674 {
675 rip_iface_stop(ifa);
676
677 TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
678
679 rem_node(NODE ifa);
680
681 rfree(ifa->sk);
682 rfree(ifa->lock);
683 rfree(ifa->timer);
684
685 mb_free(ifa);
686 }
687
688 static int
689 rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_iface_config *new)
690 {
691 struct rip_iface_config *old = ifa->cf;
692
693 /* Change of these options would require to reset the iface socket */
694 if ((new->mode != old->mode) ||
695 (new->port != old->port) ||
696 (new->tx_tos != old->tx_tos) ||
697 (new->tx_priority != old->tx_priority) ||
698 (new->ttl_security != old->ttl_security))
699 return 0;
700
701 TRACE(D_EVENTS, "Reconfiguring interface %s", ifa->iface->name);
702
703 ifa->cf = new;
704
705 rip_iface_update_buffers(ifa);
706
707 if (ifa->next_regular > (now + new->update_time))
708 ifa->next_regular = now + (random() % new->update_time) + 1;
709
710 if (new->check_link != old->check_link)
711 rip_iface_update_state(ifa);
712
713 if (new->bfd != old->bfd)
714 rip_iface_update_bfd(ifa);
715
716 if (ifa->up)
717 rip_iface_kick_timer(ifa);
718
719 return 1;
720 }
721
722 static void
723 rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
724 {
725 struct iface *iface;
726
727 WALK_LIST(iface, iface_list)
728 {
729 if (! (iface->flags & IF_UP))
730 continue;
731
732 struct rip_iface *ifa = rip_find_iface(p, iface);
733 struct rip_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
734
735 if (ifa && ic)
736 {
737 if (rip_reconfigure_iface(p, ifa, ic))
738 continue;
739
740 /* Hard restart */
741 log(L_INFO "%s: Restarting interface %s", p->p.name, ifa->iface->name);
742 rip_remove_iface(p, ifa);
743 rip_add_iface(p, iface, ic);
744 }
745
746 if (ifa && !ic)
747 rip_remove_iface(p, ifa);
748
749 if (!ifa && ic)
750 rip_add_iface(p, iface, ic);
751 }
752 }
753
754 static void
755 rip_if_notify(struct proto *P, unsigned flags, struct iface *iface)
756 {
757 struct rip_proto *p = (void *) P;
758 struct rip_config *cf = (void *) P->cf;
759
760 if (iface->flags & IF_IGNORE)
761 return;
762
763 if (flags & IF_CHANGE_UP)
764 {
765 struct rip_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
766
767 if (ic)
768 rip_add_iface(p, iface, ic);
769
770 return;
771 }
772
773 struct rip_iface *ifa = rip_find_iface(p, iface);
774
775 if (!ifa)
776 return;
777
778 if (flags & IF_CHANGE_DOWN)
779 {
780 rip_remove_iface(p, ifa);
781 return;
782 }
783
784 if (flags & IF_CHANGE_MTU)
785 rip_iface_update_buffers(ifa);
786
787 if (flags & IF_CHANGE_LINK)
788 rip_iface_update_state(ifa);
789 }
790
791
792 /*
793 * RIP timer events
794 */
795
796 /**
797 * rip_timer - RIP main timer hook
798 * @t: timer
799 *
800 * The RIP main timer is responsible for routing table maintenance. Invalid or
801 * expired routes (&rip_rte) are removed and garbage collection of stale routing
802 * table entries (&rip_entry) is done. Changes are propagated to core tables,
803 * route reload is also done here. Note that garbage collection uses a maximal
804 * GC time, while interfaces maintain an illusion of per-interface GC times in
805 * rip_send_response().
806 *
807 * Keeping incoming routes and the selected outgoing route are two independent
808 * functions, therefore after garbage collection some entries now considered
809 * invalid (RIP_ENTRY_DUMMY) still may have non-empty list of incoming routes,
810 * while some valid entries (representing an outgoing route) may have that list
811 * empty.
812 *
813 * The main timer is not scheduled periodically but it uses the time of the
814 * current next event and the minimal interval of any possible event to compute
815 * the time of the next run.
816 */
817 static void
818 rip_timer(timer *t)
819 {
820 struct rip_proto *p = t->data;
821 struct rip_config *cf = (void *) (p->p.cf);
822 struct rip_iface *ifa;
823 struct rip_neighbor *n, *nn;
824 struct fib_iterator fit;
825 bird_clock_t next = now + MIN(cf->min_timeout_time, cf->max_garbage_time);
826 bird_clock_t expires = 0;
827
828 TRACE(D_EVENTS, "Main timer fired");
829
830 FIB_ITERATE_INIT(&fit, &p->rtable);
831
832 loop:
833 FIB_ITERATE_START(&p->rtable, &fit, node)
834 {
835 struct rip_entry *en = (struct rip_entry *) node;
836 struct rip_rte *rt, **rp;
837 int changed = 0;
838
839 /* Checking received routes for timeout and for dead neighbors */
840 for (rp = &en->routes; rt = *rp; /* rp = &rt->next */)
841 {
842 if (!rip_valid_rte(rt) || (rt->expires <= now))
843 {
844 rip_remove_rte(p, rp);
845 changed = 1;
846 continue;
847 }
848
849 next = MIN(next, rt->expires);
850 rp = &rt->next;
851 }
852
853 /* Propagating eventual change */
854 if (changed || p->rt_reload)
855 {
856 /*
857 * We have to restart the iteration because there may be a cascade of
858 * synchronous events rip_announce_rte() -> nest table change ->
859 * rip_rt_notify() -> p->rtable change, invalidating hidden variables.
860 */
861
862 FIB_ITERATE_PUT_NEXT(&fit, &p->rtable, node);
863 rip_announce_rte(p, en);
864 goto loop;
865 }
866
867 /* Checking stale entries for garbage collection timeout */
868 if (en->valid == RIP_ENTRY_STALE)
869 {
870 expires = en->changed + cf->max_garbage_time;
871
872 if (expires <= now)
873 {
874 // TRACE(D_EVENTS, "entry is too old: %I/%d", en->n.prefix, en->n.pxlen);
875 en->valid = 0;
876 }
877 else
878 next = MIN(next, expires);
879 }
880
881 /* Remove empty nodes */
882 if (!en->valid && !en->routes)
883 {
884 FIB_ITERATE_PUT(&fit, node);
885 fib_delete(&p->rtable, node);
886 goto loop;
887 }
888 }
889 FIB_ITERATE_END(node);
890
891 p->rt_reload = 0;
892
893 /* Handling neighbor expiration */
894 WALK_LIST(ifa, p->iface_list)
895 WALK_LIST_DELSAFE(n, nn, ifa->neigh_list)
896 if (n->last_seen)
897 {
898 expires = n->last_seen + n->ifa->cf->timeout_time;
899
900 if (expires <= now)
901 rip_remove_neighbor(p, n);
902 else
903 next = MIN(next, expires);
904 }
905
906 tm_start(p->timer, MAX(next - now, 1));
907 }
908
909 static inline void
910 rip_kick_timer(struct rip_proto *p)
911 {
912 if (p->timer->expires > (now + 1))
913 tm_start(p->timer, 1); /* Or 100 ms */
914 }
915
916 /**
917 * rip_iface_timer - RIP interface timer hook
918 * @t: timer
919 *
920 * RIP interface timers are responsible for scheduling both regular and
921 * triggered updates. Fixed, delay-independent period is used for regular
922 * updates, while minimal separating interval is enforced for triggered updates.
923 * The function also ensures that a new update is not started when the old one
924 * is still running.
925 */
926 static void
927 rip_iface_timer(timer *t)
928 {
929 struct rip_iface *ifa = t->data;
930 struct rip_proto *p = ifa->rip;
931 bird_clock_t period = ifa->cf->update_time;
932
933 if (ifa->cf->passive)
934 return;
935
936 TRACE(D_EVENTS, "Interface timer fired for %s", ifa->iface->name);
937
938 if (ifa->tx_active)
939 {
940 if (now < (ifa->next_regular + period))
941 { tm_start(ifa->timer, 1); return; }
942
943 /* We are too late, reset is done by rip_send_table() */
944 log(L_WARN "%s: Too slow update on %s, resetting", p->p.name, ifa->iface->name);
945 }
946
947 if (now >= ifa->next_regular)
948 {
949 /* Send regular update, set timer for next period (or following one if necessay) */
950 TRACE(D_EVENTS, "Sending regular updates for %s", ifa->iface->name);
951 rip_send_table(p, ifa, ifa->addr, 0);
952 ifa->next_regular += period * (1 + ((now - ifa->next_regular) / period));
953 ifa->want_triggered = 0;
954 p->triggered = 0;
955 }
956 else if (ifa->want_triggered && (now >= ifa->next_triggered))
957 {
958 /* Send triggered update, enforce interval between triggered updates */
959 TRACE(D_EVENTS, "Sending triggered updates for %s", ifa->iface->name);
960 rip_send_table(p, ifa, ifa->addr, ifa->want_triggered);
961 ifa->next_triggered = now + MIN(5, period / 2 + 1);
962 ifa->want_triggered = 0;
963 p->triggered = 0;
964 }
965
966 tm_start(ifa->timer, ifa->want_triggered ? 1 : (ifa->next_regular - now));
967 }
968
969 static inline void
970 rip_iface_kick_timer(struct rip_iface *ifa)
971 {
972 if (ifa->timer->expires > (now + 1))
973 tm_start(ifa->timer, 1); /* Or 100 ms */
974 }
975
976 static void
977 rip_trigger_update(struct rip_proto *p)
978 {
979 if (p->triggered)
980 return;
981
982 struct rip_iface *ifa;
983 WALK_LIST(ifa, p->iface_list)
984 {
985 /* Interface not active */
986 if (! ifa->up)
987 continue;
988
989 /* Already scheduled */
990 if (ifa->want_triggered)
991 continue;
992
993 TRACE(D_EVENTS, "Scheduling triggered updates for %s", ifa->iface->name);
994 ifa->want_triggered = now;
995 rip_iface_kick_timer(ifa);
996 }
997
998 p->triggered = 1;
999 }
1000
1001
1002 /*
1003 * RIP protocol glue
1004 */
1005
1006 static struct ea_list *
1007 rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
1008 {
1009 struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
1010
1011 l->next = next;
1012 l->flags = EALF_SORTED;
1013 l->count = 2;
1014
1015 l->attrs[0].id = EA_RIP_METRIC;
1016 l->attrs[0].flags = 0;
1017 l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
1018 l->attrs[0].u.data = metric;
1019
1020 l->attrs[1].id = EA_RIP_TAG;
1021 l->attrs[1].flags = 0;
1022 l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
1023 l->attrs[1].u.data = tag;
1024
1025 return l;
1026 }
1027
1028 static int
1029 rip_import_control(struct proto *P UNUSED, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
1030 {
1031 /* Prepare attributes with initial values */
1032 if ((*rt)->attrs->source != RTS_RIP)
1033 *attrs = rip_prepare_attrs(pool, *attrs, 1, 0);
1034
1035 return 0;
1036 }
1037
1038 static int
1039 rip_reload_routes(struct proto *P)
1040 {
1041 struct rip_proto *p = (struct rip_proto *) P;
1042
1043 if (p->rt_reload)
1044 return 1;
1045
1046 TRACE(D_EVENTS, "Scheduling route reload");
1047 p->rt_reload = 1;
1048 rip_kick_timer(p);
1049
1050 return 1;
1051 }
1052
1053 static struct ea_list *
1054 rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
1055 {
1056 return rip_prepare_attrs(pool, NULL, rt->u.rip.metric, rt->u.rip.tag);
1057 }
1058
1059 static void
1060 rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
1061 {
1062 rt->u.rip.metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
1063 rt->u.rip.tag = ea_get_int(attrs, EA_RIP_TAG, 0);
1064 }
1065
1066 static int
1067 rip_rte_better(struct rte *new, struct rte *old)
1068 {
1069 return new->u.rip.metric < old->u.rip.metric;
1070 }
1071
1072 static int
1073 rip_rte_same(struct rte *new, struct rte *old)
1074 {
1075 return ((new->u.rip.metric == old->u.rip.metric) &&
1076 (new->u.rip.tag == old->u.rip.tag) &&
1077 (new->u.rip.from == old->u.rip.from));
1078 }
1079
1080
1081 static struct proto *
1082 rip_init(struct proto_config *cfg)
1083 {
1084 struct proto *P = proto_new(cfg, sizeof(struct rip_proto));
1085
1086 P->accept_ra_types = RA_OPTIMAL;
1087 P->if_notify = rip_if_notify;
1088 P->rt_notify = rip_rt_notify;
1089 P->neigh_notify = rip_neigh_notify;
1090 P->import_control = rip_import_control;
1091 P->reload_routes = rip_reload_routes;
1092 P->make_tmp_attrs = rip_make_tmp_attrs;
1093 P->store_tmp_attrs = rip_store_tmp_attrs;
1094 P->rte_better = rip_rte_better;
1095 P->rte_same = rip_rte_same;
1096
1097 return P;
1098 }
1099
1100 static int
1101 rip_start(struct proto *P)
1102 {
1103 struct rip_proto *p = (void *) P;
1104 struct rip_config *cf = (void *) (P->cf);
1105
1106 init_list(&p->iface_list);
1107 fib_init(&p->rtable, P->pool, sizeof(struct rip_entry), 0, rip_init_entry);
1108 p->rte_slab = sl_new(P->pool, sizeof(struct rip_rte));
1109 p->timer = tm_new_set(P->pool, rip_timer, p, 0, 0);
1110
1111 p->ecmp = cf->ecmp;
1112 p->infinity = cf->infinity;
1113 p->triggered = 0;
1114
1115 p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
1116 p->log_rte_tbf = (struct tbf){ .rate = 4, .burst = 20 };
1117
1118 tm_start(p->timer, MIN(cf->min_timeout_time, cf->max_garbage_time));
1119
1120 return PS_UP;
1121 }
1122
1123 static int
1124 rip_reconfigure(struct proto *P, struct proto_config *c)
1125 {
1126 struct rip_proto *p = (void *) P;
1127 struct rip_config *new = (void *) c;
1128 // struct rip_config *old = (void *) (P->cf);
1129
1130 if (new->infinity != p->infinity)
1131 return 0;
1132
1133 TRACE(D_EVENTS, "Reconfiguring");
1134
1135 p->p.cf = c;
1136 p->ecmp = new->ecmp;
1137 rip_reconfigure_ifaces(p, new);
1138
1139 p->rt_reload = 1;
1140 rip_kick_timer(p);
1141
1142 return 1;
1143 }
1144
1145 static void
1146 rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
1147 {
1148 buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
1149
1150 if (rte->u.rip.tag)
1151 bsprintf(buf, " [%04x]", rte->u.rip.tag);
1152 }
1153
1154 static int
1155 rip_get_attr(eattr *a, byte *buf, int buflen UNUSED)
1156 {
1157 switch (a->id)
1158 {
1159 case EA_RIP_METRIC:
1160 bsprintf(buf, "metric: %d", a->u.data);
1161 return GA_FULL;
1162
1163 case EA_RIP_TAG:
1164 bsprintf(buf, "tag: %04x", a->u.data);
1165 return GA_FULL;
1166
1167 default:
1168 return GA_UNKNOWN;
1169 }
1170 }
1171
1172 void
1173 rip_show_interfaces(struct proto *P, char *iff)
1174 {
1175 struct rip_proto *p = (void *) P;
1176 struct rip_iface *ifa = NULL;
1177 struct rip_neighbor *n = NULL;
1178
1179 if (p->p.proto_state != PS_UP)
1180 {
1181 cli_msg(-1021, "%s: is not up", p->p.name);
1182 cli_msg(0, "");
1183 return;
1184 }
1185
1186 cli_msg(-1021, "%s:", p->p.name);
1187 cli_msg(-1021, "%-10s %-6s %6s %6s %6s",
1188 "Interface", "State", "Metric", "Nbrs", "Timer");
1189
1190 WALK_LIST(ifa, p->iface_list)
1191 {
1192 if (iff && !patmatch(iff, ifa->iface->name))
1193 continue;
1194
1195 int nbrs = 0;
1196 WALK_LIST(n, ifa->neigh_list)
1197 if (n->last_seen)
1198 nbrs++;
1199
1200 int timer = MAX(ifa->next_regular - now, 0);
1201 cli_msg(-1021, "%-10s %-6s %6u %6u %6u",
1202 ifa->iface->name, (ifa->up ? "Up" : "Down"), ifa->cf->metric, nbrs, timer);
1203 }
1204
1205 cli_msg(0, "");
1206 }
1207
1208 void
1209 rip_show_neighbors(struct proto *P, char *iff)
1210 {
1211 struct rip_proto *p = (void *) P;
1212 struct rip_iface *ifa = NULL;
1213 struct rip_neighbor *n = NULL;
1214
1215 if (p->p.proto_state != PS_UP)
1216 {
1217 cli_msg(-1022, "%s: is not up", p->p.name);
1218 cli_msg(0, "");
1219 return;
1220 }
1221
1222 cli_msg(-1022, "%s:", p->p.name);
1223 cli_msg(-1022, "%-25s %-10s %6s %6s %6s",
1224 "IP address", "Interface", "Metric", "Routes", "Seen");
1225
1226 WALK_LIST(ifa, p->iface_list)
1227 {
1228 if (iff && !patmatch(iff, ifa->iface->name))
1229 continue;
1230
1231 WALK_LIST(n, ifa->neigh_list)
1232 {
1233 if (!n->last_seen)
1234 continue;
1235
1236 int timer = now - n->last_seen;
1237 cli_msg(-1022, "%-25I %-10s %6u %6u %6u",
1238 n->nbr->addr, ifa->iface->name, ifa->cf->metric, n->uc, timer);
1239 }
1240 }
1241
1242 cli_msg(0, "");
1243 }
1244
1245 static void
1246 rip_dump(struct proto *P)
1247 {
1248 struct rip_proto *p = (struct rip_proto *) P;
1249 struct rip_iface *ifa;
1250 int i;
1251
1252 i = 0;
1253 FIB_WALK(&p->rtable, e)
1254 {
1255 struct rip_entry *en = (struct rip_entry *) e;
1256 debug("RIP: entry #%d: %I/%d via %I dev %s valid %d metric %d age %d s\n",
1257 i++, en->n.prefix, en->n.pxlen, en->next_hop, en->iface->name,
1258 en->valid, en->metric, now - en->changed);
1259 }
1260 FIB_WALK_END;
1261
1262 i = 0;
1263 WALK_LIST(ifa, p->iface_list)
1264 {
1265 debug("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
1266 i++, ifa->iface->name, ifa->sk ? ifa->sk->daddr : IPA_NONE,
1267 ifa->up, ifa->tx_active);
1268 }
1269 }
1270
1271
1272 struct protocol proto_rip = {
1273 .name = "RIP",
1274 .template = "rip%d",
1275 .attr_class = EAP_RIP,
1276 .preference = DEF_PREF_RIP,
1277 .config_size = sizeof(struct rip_config),
1278 .init = rip_init,
1279 .dump = rip_dump,
1280 .start = rip_start,
1281 .reconfigure = rip_reconfigure,
1282 .get_route_info = rip_get_route_info,
1283 .get_attr = rip_get_attr
1284 };