Line data Source code
1 : /* RIP version 1 and 2.
2 : * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
3 : * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
4 : *
5 : * This file is part of GNU Zebra.
6 : *
7 : * GNU Zebra is free software; you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the
9 : * Free Software Foundation; either version 2, or (at your option) any
10 : * later version.
11 : *
12 : * GNU Zebra is distributed in the hope that it will be useful, but
13 : * WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : * General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License along
18 : * with this program; see the file COPYING; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 : */
21 :
22 : #include <zebra.h>
23 :
24 : #include "vrf.h"
25 : #include "if.h"
26 : #include "command.h"
27 : #include "prefix.h"
28 : #include "table.h"
29 : #include "thread.h"
30 : #include "memory.h"
31 : #include "log.h"
32 : #include "stream.h"
33 : #include "filter.h"
34 : #include "sockunion.h"
35 : #include "sockopt.h"
36 : #include "routemap.h"
37 : #include "if_rmap.h"
38 : #include "plist.h"
39 : #include "distribute.h"
40 : #ifdef CRYPTO_INTERNAL
41 : #include "md5.h"
42 : #endif
43 : #include "keychain.h"
44 : #include "privs.h"
45 : #include "lib_errors.h"
46 : #include "northbound_cli.h"
47 : #include "network.h"
48 : #include "lib/printfrr.h"
49 :
50 : #include "ripd/ripd.h"
51 : #include "ripd/rip_nb.h"
52 : #include "ripd/rip_debug.h"
53 : #include "ripd/rip_errors.h"
54 : #include "ripd/rip_interface.h"
55 :
56 : /* UDP receive buffer size */
57 : #define RIP_UDP_RCV_BUF 41600
58 :
59 15 : DEFINE_MGROUP(RIPD, "ripd");
60 15 : DEFINE_MTYPE_STATIC(RIPD, RIP, "RIP structure");
61 15 : DEFINE_MTYPE_STATIC(RIPD, RIP_VRF_NAME, "RIP VRF name");
62 15 : DEFINE_MTYPE_STATIC(RIPD, RIP_INFO, "RIP route info");
63 15 : DEFINE_MTYPE_STATIC(RIPD, RIP_DISTANCE, "RIP distance");
64 :
65 : /* Prototypes. */
66 : static void rip_output_process(struct connected *, struct sockaddr_in *, int,
67 : uint8_t);
68 : static void rip_triggered_update(struct thread *);
69 : static int rip_update_jitter(unsigned long);
70 : static void rip_distance_table_node_cleanup(struct route_table *table,
71 : struct route_node *node);
72 : static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock);
73 : static void rip_instance_disable(struct rip *rip);
74 :
75 : static void rip_distribute_update(struct distribute_ctx *ctx,
76 : struct distribute *dist);
77 :
78 : static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
79 : struct if_rmap *if_rmap);
80 :
81 : /* RIP output routes type. */
82 : enum { rip_all_route, rip_changed_route };
83 :
84 : /* RIP command strings. */
85 : static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"},
86 : {RIP_RESPONSE, "RESPONSE"},
87 : {RIP_TRACEON, "TRACEON"},
88 : {RIP_TRACEOFF, "TRACEOFF"},
89 : {RIP_POLL, "POLL"},
90 : {RIP_POLL_ENTRY, "POLL ENTRY"},
91 : {0}};
92 :
93 : /* Generate rb-tree of RIP instances. */
94 54 : static inline int rip_instance_compare(const struct rip *a, const struct rip *b)
95 : {
96 54 : return strcmp(a->vrf_name, b->vrf_name);
97 : }
98 54 : RB_GENERATE(rip_instance_head, rip, entry, rip_instance_compare)
99 :
100 : struct rip_instance_head rip_instances = RB_INITIALIZER(&rip_instances);
101 :
102 : /* Utility function to set broadcast option to the socket. */
103 5 : static int sockopt_broadcast(int sock)
104 : {
105 5 : int ret;
106 5 : int on = 1;
107 :
108 5 : ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,
109 : sizeof(on));
110 5 : if (ret < 0) {
111 0 : zlog_warn("can't set sockopt SO_BROADCAST to socket %d", sock);
112 0 : return -1;
113 : }
114 : return 0;
115 : }
116 :
117 69 : int rip_route_rte(struct rip_info *rinfo)
118 : {
119 69 : return (rinfo->type == ZEBRA_ROUTE_RIP
120 69 : && rinfo->sub_type == RIP_ROUTE_RTE);
121 : }
122 :
123 19 : static struct rip_info *rip_info_new(void)
124 : {
125 19 : return XCALLOC(MTYPE_RIP_INFO, sizeof(struct rip_info));
126 : }
127 :
128 19 : void rip_info_free(struct rip_info *rinfo)
129 : {
130 0 : XFREE(MTYPE_RIP_INFO, rinfo);
131 0 : }
132 :
133 0 : struct rip *rip_info_get_instance(const struct rip_info *rinfo)
134 : {
135 0 : return route_table_get_info(rinfo->rp->table);
136 : }
137 :
138 : /* RIP route garbage collect timer. */
139 0 : static void rip_garbage_collect(struct thread *t)
140 : {
141 0 : struct rip_info *rinfo;
142 0 : struct route_node *rp;
143 :
144 0 : rinfo = THREAD_ARG(t);
145 :
146 : /* Off timeout timer. */
147 0 : THREAD_OFF(rinfo->t_timeout);
148 :
149 : /* Get route_node pointer. */
150 0 : rp = rinfo->rp;
151 :
152 : /* Unlock route_node. */
153 0 : listnode_delete(rp->info, rinfo);
154 0 : if (list_isempty((struct list *)rp->info)) {
155 0 : list_delete((struct list **)&rp->info);
156 0 : route_unlock_node(rp);
157 : }
158 :
159 : /* Free RIP routing information. */
160 0 : rip_info_free(rinfo);
161 0 : }
162 :
163 : static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo);
164 :
165 : /* Add new route to the ECMP list.
166 : * RETURN: the new entry added in the list, or NULL if it is not the first
167 : * entry and ECMP is not allowed.
168 : */
169 19 : struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new)
170 : {
171 19 : struct route_node *rp = rinfo_new->rp;
172 19 : struct rip_info *rinfo = NULL;
173 19 : struct list *list = NULL;
174 :
175 19 : if (rp->info == NULL)
176 19 : rp->info = list_new();
177 19 : list = (struct list *)rp->info;
178 :
179 : /* If ECMP is not allowed and some entry already exists in the list,
180 : * do nothing. */
181 19 : if (listcount(list) && !rip->ecmp)
182 : return NULL;
183 :
184 19 : rinfo = rip_info_new();
185 19 : memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
186 19 : listnode_add(list, rinfo);
187 :
188 19 : if (rip_route_rte(rinfo)) {
189 10 : rip_timeout_update(rip, rinfo);
190 10 : rip_zebra_ipv4_add(rip, rp);
191 : }
192 :
193 : /* Set the route change flag on the first entry. */
194 19 : rinfo = listgetdata(listhead(list));
195 19 : SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
196 :
197 : /* Signal the output process to trigger an update (see section 2.5). */
198 19 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
199 :
200 19 : return rinfo;
201 : }
202 :
203 : /* Replace the ECMP list with the new route.
204 : * RETURN: the new entry added in the list
205 : */
206 8 : struct rip_info *rip_ecmp_replace(struct rip *rip, struct rip_info *rinfo_new)
207 : {
208 8 : struct route_node *rp = rinfo_new->rp;
209 8 : struct list *list = (struct list *)rp->info;
210 8 : struct rip_info *rinfo = NULL, *tmp_rinfo = NULL;
211 8 : struct listnode *node = NULL, *nextnode = NULL;
212 :
213 8 : if (list == NULL || listcount(list) == 0)
214 0 : return rip_ecmp_add(rip, rinfo_new);
215 :
216 : /* Get the first entry */
217 8 : rinfo = listgetdata(listhead(list));
218 :
219 : /* Learnt route replaced by a local one. Delete it from zebra. */
220 8 : if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new))
221 0 : if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
222 0 : rip_zebra_ipv4_delete(rip, rp);
223 :
224 : /* Re-use the first entry, and delete the others. */
225 16 : for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) {
226 8 : if (tmp_rinfo == rinfo)
227 8 : continue;
228 :
229 0 : THREAD_OFF(tmp_rinfo->t_timeout);
230 0 : THREAD_OFF(tmp_rinfo->t_garbage_collect);
231 0 : list_delete_node(list, node);
232 16 : rip_info_free(tmp_rinfo);
233 : }
234 :
235 8 : THREAD_OFF(rinfo->t_timeout);
236 8 : THREAD_OFF(rinfo->t_garbage_collect);
237 8 : memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
238 :
239 8 : if (rip_route_rte(rinfo)) {
240 0 : rip_timeout_update(rip, rinfo);
241 : /* The ADD message implies an update. */
242 0 : rip_zebra_ipv4_add(rip, rp);
243 : }
244 :
245 : /* Set the route change flag. */
246 8 : SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
247 :
248 : /* Signal the output process to trigger an update (see section 2.5). */
249 8 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
250 :
251 8 : return rinfo;
252 : }
253 :
254 : /* Delete one route from the ECMP list.
255 : * RETURN:
256 : * null - the entry is freed, and other entries exist in the list
257 : * the entry - the entry is the last one in the list; its metric is set
258 : * to INFINITY, and the garbage collector is started for it
259 : */
260 8 : struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo)
261 : {
262 8 : struct route_node *rp = rinfo->rp;
263 8 : struct list *list = (struct list *)rp->info;
264 :
265 8 : THREAD_OFF(rinfo->t_timeout);
266 :
267 8 : if (listcount(list) > 1) {
268 : /* Some other ECMP entries still exist. Just delete this entry.
269 : */
270 0 : THREAD_OFF(rinfo->t_garbage_collect);
271 0 : listnode_delete(list, rinfo);
272 0 : if (rip_route_rte(rinfo)
273 0 : && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
274 : /* The ADD message implies the update. */
275 0 : rip_zebra_ipv4_add(rip, rp);
276 0 : rip_info_free(rinfo);
277 0 : rinfo = NULL;
278 : } else {
279 8 : assert(rinfo == listgetdata(listhead(list)));
280 :
281 : /* This is the only entry left in the list. We must keep it in
282 : * the list for garbage collection time, with INFINITY metric.
283 : */
284 :
285 8 : rinfo->metric = RIP_METRIC_INFINITY;
286 8 : RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect,
287 : rip->garbage_time);
288 :
289 8 : if (rip_route_rte(rinfo)
290 0 : && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
291 0 : rip_zebra_ipv4_delete(rip, rp);
292 : }
293 :
294 : /* Set the route change flag on the first entry. */
295 8 : rinfo = listgetdata(listhead(list));
296 8 : SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
297 :
298 : /* Signal the output process to trigger an update (see section 2.5). */
299 8 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
300 :
301 8 : return rinfo;
302 : }
303 :
304 : /* Timeout RIP routes. */
305 0 : static void rip_timeout(struct thread *t)
306 : {
307 0 : struct rip_info *rinfo = THREAD_ARG(t);
308 0 : struct rip *rip = rip_info_get_instance(rinfo);
309 :
310 0 : rip_ecmp_delete(rip, rinfo);
311 0 : }
312 :
313 17 : static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo)
314 : {
315 17 : if (rinfo->metric != RIP_METRIC_INFINITY) {
316 17 : THREAD_OFF(rinfo->t_timeout);
317 17 : thread_add_timer(master, rip_timeout, rinfo, rip->timeout_time,
318 : &rinfo->t_timeout);
319 : }
320 17 : }
321 :
322 50 : static int rip_filter(int rip_distribute, struct prefix_ipv4 *p,
323 : struct rip_interface *ri)
324 : {
325 50 : struct distribute *dist;
326 50 : struct access_list *alist;
327 50 : struct prefix_list *plist;
328 117 : int distribute = rip_distribute == RIP_FILTER_OUT ? DISTRIBUTE_V4_OUT
329 50 : : DISTRIBUTE_V4_IN;
330 17 : const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in";
331 :
332 : /* Input distribute-list filtering. */
333 50 : if (ri->list[rip_distribute] &&
334 0 : access_list_apply(ri->list[rip_distribute], (struct prefix *)p) ==
335 : FILTER_DENY) {
336 0 : if (IS_RIP_DEBUG_PACKET)
337 0 : zlog_debug("%pFX filtered by distribute %s", p, inout);
338 0 : return -1;
339 : }
340 :
341 50 : if (ri->prefix[rip_distribute] &&
342 0 : prefix_list_apply(ri->prefix[rip_distribute], (struct prefix *)p) ==
343 : PREFIX_DENY) {
344 0 : if (IS_RIP_DEBUG_PACKET)
345 0 : zlog_debug("%pFX filtered by prefix-list %s", p, inout);
346 0 : return -1;
347 : }
348 :
349 : /* All interface filter check. */
350 50 : dist = distribute_lookup(ri->rip->distribute_ctx, NULL);
351 50 : if (!dist)
352 : return 0;
353 :
354 0 : if (dist->list[distribute]) {
355 0 : alist = access_list_lookup(AFI_IP, dist->list[distribute]);
356 :
357 0 : if (alist) {
358 0 : if (access_list_apply(alist, (struct prefix *)p) ==
359 : FILTER_DENY) {
360 0 : if (IS_RIP_DEBUG_PACKET)
361 0 : zlog_debug(
362 : "%pFX filtered by distribute %s",
363 : p, inout);
364 0 : return -1;
365 : }
366 : }
367 : }
368 0 : if (dist->prefix[distribute]) {
369 0 : plist = prefix_list_lookup(AFI_IP, dist->prefix[distribute]);
370 :
371 0 : if (plist) {
372 0 : if (prefix_list_apply(plist, (struct prefix *)p) ==
373 : PREFIX_DENY) {
374 0 : if (IS_RIP_DEBUG_PACKET)
375 0 : zlog_debug(
376 : "%pFX filtered by prefix-list %s",
377 : p, inout);
378 0 : return -1;
379 : }
380 : }
381 : }
382 :
383 : return 0;
384 : }
385 :
386 : /* Check nexthop address validity. */
387 17 : static int rip_nexthop_check(struct rip *rip, struct in_addr *addr)
388 : {
389 17 : struct interface *ifp;
390 17 : struct listnode *cnode;
391 17 : struct connected *ifc;
392 17 : struct prefix *p;
393 :
394 : /* If nexthop address matches local configured address then it is
395 : invalid nexthop. */
396 :
397 93 : FOR_ALL_INTERFACES (rip->vrf, ifp) {
398 202 : for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
399 84 : p = ifc->address;
400 :
401 84 : if (p->family == AF_INET
402 42 : && IPV4_ADDR_SAME(&p->u.prefix4, addr))
403 : return -1;
404 : }
405 : }
406 : return 0;
407 : }
408 :
409 : /* RIP add route to routing table. */
410 17 : static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
411 : struct interface *ifp)
412 : {
413 17 : struct rip *rip;
414 17 : int ret;
415 17 : struct prefix_ipv4 p;
416 17 : struct route_node *rp;
417 17 : struct rip_info *rinfo = NULL, newinfo;
418 17 : struct rip_interface *ri;
419 17 : struct in_addr *nexthop;
420 17 : int same = 0;
421 17 : unsigned char old_dist, new_dist;
422 17 : struct list *list = NULL;
423 17 : struct listnode *node = NULL;
424 :
425 : /* Make prefix structure. */
426 17 : memset(&p, 0, sizeof(struct prefix_ipv4));
427 17 : p.family = AF_INET;
428 17 : p.prefix = rte->prefix;
429 17 : p.prefixlen = ip_masklen(rte->mask);
430 :
431 : /* Make sure mask is applied. */
432 17 : apply_mask_ipv4(&p);
433 :
434 17 : ri = ifp->info;
435 17 : rip = ri->rip;
436 :
437 : /* Apply input filters. */
438 17 : ret = rip_filter(RIP_FILTER_IN, &p, ri);
439 17 : if (ret < 0)
440 0 : return;
441 :
442 17 : memset(&newinfo, 0, sizeof(newinfo));
443 17 : newinfo.type = ZEBRA_ROUTE_RIP;
444 17 : newinfo.sub_type = RIP_ROUTE_RTE;
445 17 : newinfo.nh.gate.ipv4 = rte->nexthop;
446 17 : newinfo.from = from->sin_addr;
447 17 : newinfo.nh.ifindex = ifp->ifindex;
448 17 : newinfo.nh.type = NEXTHOP_TYPE_IPV4_IFINDEX;
449 17 : newinfo.metric = rte->metric;
450 17 : newinfo.metric_out = rte->metric; /* XXX */
451 17 : newinfo.tag = ntohs(rte->tag); /* XXX */
452 :
453 : /* Modify entry according to the interface routemap. */
454 17 : if (ri->routemap[RIP_FILTER_IN]) {
455 : /* The object should be of the type of rip_info */
456 0 : ret = route_map_apply(ri->routemap[RIP_FILTER_IN],
457 : (struct prefix *)&p, &newinfo);
458 :
459 0 : if (ret == RMAP_DENYMATCH) {
460 0 : if (IS_RIP_DEBUG_PACKET)
461 0 : zlog_debug(
462 : "RIP %pFX is filtered by route-map in",
463 : &p);
464 0 : return;
465 : }
466 :
467 : /* Get back the object */
468 0 : rte->nexthop = newinfo.nexthop_out;
469 0 : rte->tag = htons(newinfo.tag_out); /* XXX */
470 0 : rte->metric = newinfo.metric_out; /* XXX: the routemap uses the
471 : metric_out field */
472 : }
473 :
474 : /* Once the entry has been validated, update the metric by
475 : adding the cost of the network on which the message
476 : arrived. If the result is greater than infinity, use infinity
477 : (RFC2453 Sec. 3.9.2) */
478 : /* Zebra ripd can handle offset-list in. */
479 17 : ret = rip_offset_list_apply_in(&p, ifp, &rte->metric);
480 :
481 : /* If offset-list does not modify the metric use interface's
482 : metric. */
483 17 : if (!ret)
484 17 : rte->metric += ifp->metric ? ifp->metric : 1;
485 :
486 17 : if (rte->metric > RIP_METRIC_INFINITY)
487 0 : rte->metric = RIP_METRIC_INFINITY;
488 :
489 : /* Set nexthop pointer. */
490 17 : if (rte->nexthop.s_addr == INADDR_ANY)
491 17 : nexthop = &from->sin_addr;
492 : else
493 0 : nexthop = &rte->nexthop;
494 :
495 : /* Check if nexthop address is myself, then do nothing. */
496 17 : if (rip_nexthop_check(rip, nexthop) < 0) {
497 0 : if (IS_RIP_DEBUG_PACKET)
498 0 : zlog_debug("Nexthop address %pI4 is myself",
499 : nexthop);
500 0 : return;
501 : }
502 :
503 : /* Get index for the prefix. */
504 17 : rp = route_node_get(rip->table, (struct prefix *)&p);
505 :
506 17 : newinfo.rp = rp;
507 17 : newinfo.nh.gate.ipv4 = *nexthop;
508 17 : newinfo.nh.type = NEXTHOP_TYPE_IPV4;
509 17 : newinfo.metric = rte->metric;
510 17 : newinfo.tag = ntohs(rte->tag);
511 17 : newinfo.distance = rip_distance_apply(rip, &newinfo);
512 :
513 17 : new_dist = newinfo.distance ? newinfo.distance
514 : : ZEBRA_RIP_DISTANCE_DEFAULT;
515 :
516 : /* Check to see whether there is already RIP route on the table. */
517 17 : if ((list = rp->info) != NULL)
518 7 : for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) {
519 : /* Need to compare with redistributed entry or local
520 : * entry */
521 7 : if (!rip_route_rte(rinfo))
522 : break;
523 :
524 7 : if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
525 7 : && IPV4_ADDR_SAME(&rinfo->nh.gate.ipv4, nexthop))
526 : break;
527 :
528 0 : if (listnextnode(node))
529 0 : continue;
530 :
531 : /* Not found in the list */
532 :
533 0 : if (rte->metric > rinfo->metric) {
534 : /* New route has a greater metric.
535 : * Discard it. */
536 0 : route_unlock_node(rp);
537 0 : return;
538 : }
539 :
540 0 : if (rte->metric < rinfo->metric)
541 : /* New route has a smaller metric.
542 : * Replace the ECMP list
543 : * with the new one in below. */
544 : break;
545 :
546 : /* Metrics are same. We compare the distances.
547 : */
548 0 : old_dist = rinfo->distance ? rinfo->distance
549 : : ZEBRA_RIP_DISTANCE_DEFAULT;
550 :
551 0 : if (new_dist > old_dist) {
552 : /* New route has a greater distance.
553 : * Discard it. */
554 0 : route_unlock_node(rp);
555 0 : return;
556 : }
557 :
558 0 : if (new_dist < old_dist)
559 : /* New route has a smaller distance.
560 : * Replace the ECMP list
561 : * with the new one in below. */
562 : break;
563 :
564 : /* Metrics and distances are both same. Keep
565 : * "rinfo" null and
566 : * the new route is added in the ECMP list in
567 : * below. */
568 : }
569 :
570 7 : if (rinfo) {
571 : /* Local static route. */
572 7 : if (rinfo->type == ZEBRA_ROUTE_RIP
573 7 : && ((rinfo->sub_type == RIP_ROUTE_STATIC)
574 7 : || (rinfo->sub_type == RIP_ROUTE_DEFAULT))
575 0 : && rinfo->metric != RIP_METRIC_INFINITY) {
576 0 : route_unlock_node(rp);
577 0 : return;
578 : }
579 :
580 : /* Redistributed route check. */
581 7 : if (rinfo->type != ZEBRA_ROUTE_RIP
582 0 : && rinfo->metric != RIP_METRIC_INFINITY) {
583 0 : old_dist = rinfo->distance;
584 : /* Only routes directly connected to an interface
585 : * (nexthop == 0)
586 : * may have a valid NULL distance */
587 0 : if (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY)
588 0 : old_dist = old_dist
589 : ? old_dist
590 : : ZEBRA_RIP_DISTANCE_DEFAULT;
591 : /* If imported route does not have STRICT precedence,
592 : mark it as a ghost */
593 0 : if (new_dist <= old_dist
594 0 : && rte->metric != RIP_METRIC_INFINITY)
595 0 : rip_ecmp_replace(rip, &newinfo);
596 :
597 0 : route_unlock_node(rp);
598 0 : return;
599 : }
600 : }
601 :
602 10 : if (!rinfo) {
603 10 : if (rp->info)
604 0 : route_unlock_node(rp);
605 :
606 : /* Now, check to see whether there is already an explicit route
607 : for the destination prefix. If there is no such route, add
608 : this route to the routing table, unless the metric is
609 : infinity (there is no point in adding a route which
610 : unusable). */
611 10 : if (rte->metric != RIP_METRIC_INFINITY)
612 10 : rip_ecmp_add(rip, &newinfo);
613 : } else {
614 : /* Route is there but we are not sure the route is RIP or not.
615 : */
616 :
617 : /* If there is an existing route, compare the next hop address
618 : to the address of the router from which the datagram came.
619 : If this datagram is from the same router as the existing
620 : route, reinitialize the timeout. */
621 7 : same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
622 7 : && (rinfo->nh.ifindex == ifp->ifindex));
623 :
624 7 : old_dist = rinfo->distance ? rinfo->distance
625 : : ZEBRA_RIP_DISTANCE_DEFAULT;
626 :
627 : /* Next, compare the metrics. If the datagram is from the same
628 : router as the existing route, and the new metric is different
629 : than the old one; or, if the new metric is lower than the old
630 : one, or if the tag has been changed; or if there is a route
631 : with a lower administrave distance; or an update of the
632 : distance on the actual route; do the following actions: */
633 7 : if ((same && rinfo->metric != rte->metric)
634 7 : || (rte->metric < rinfo->metric)
635 7 : || ((same) && (rinfo->metric == rte->metric)
636 7 : && (newinfo.tag != rinfo->tag))
637 7 : || (old_dist > new_dist)
638 7 : || ((old_dist != new_dist) && same)) {
639 0 : if (listcount(list) == 1) {
640 0 : if (newinfo.metric != RIP_METRIC_INFINITY)
641 0 : rip_ecmp_replace(rip, &newinfo);
642 : else
643 0 : rip_ecmp_delete(rip, rinfo);
644 : } else {
645 0 : if (newinfo.metric < rinfo->metric)
646 0 : rip_ecmp_replace(rip, &newinfo);
647 0 : else if (newinfo.metric > rinfo->metric)
648 0 : rip_ecmp_delete(rip, rinfo);
649 0 : else if (new_dist < old_dist)
650 0 : rip_ecmp_replace(rip, &newinfo);
651 0 : else if (new_dist > old_dist)
652 0 : rip_ecmp_delete(rip, rinfo);
653 : else {
654 0 : int update = CHECK_FLAG(rinfo->flags,
655 : RIP_RTF_FIB)
656 : ? 1
657 : : 0;
658 :
659 0 : assert(newinfo.metric
660 : != RIP_METRIC_INFINITY);
661 :
662 0 : THREAD_OFF(rinfo->t_timeout);
663 0 : THREAD_OFF(rinfo->t_garbage_collect);
664 0 : memcpy(rinfo, &newinfo,
665 : sizeof(struct rip_info));
666 0 : rip_timeout_update(rip, rinfo);
667 :
668 0 : if (update)
669 0 : rip_zebra_ipv4_add(rip, rp);
670 :
671 : /* - Set the route change flag on the
672 : * first entry. */
673 0 : rinfo = listgetdata(listhead(list));
674 0 : SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
675 0 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
676 : }
677 : }
678 : } else /* same & no change */
679 7 : rip_timeout_update(rip, rinfo);
680 :
681 : /* Unlock tempolary lock of the route. */
682 7 : route_unlock_node(rp);
683 : }
684 : }
685 :
686 : /* Dump RIP packet */
687 0 : static void rip_packet_dump(struct rip_packet *packet, int size,
688 : const char *sndrcv)
689 : {
690 0 : caddr_t lim;
691 0 : struct rte *rte;
692 0 : const char *command_str;
693 0 : uint8_t netmask = 0;
694 0 : uint8_t *p;
695 :
696 : /* Set command string. */
697 0 : if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
698 0 : command_str = lookup_msg(rip_msg, packet->command, NULL);
699 : else
700 : command_str = "unknown";
701 :
702 : /* Dump packet header. */
703 0 : zlog_debug("%s %s version %d packet size %d", sndrcv, command_str,
704 : packet->version, size);
705 :
706 : /* Dump each routing table entry. */
707 0 : rte = packet->rte;
708 :
709 0 : for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) {
710 0 : if (packet->version == RIPv2) {
711 0 : netmask = ip_masklen(rte->mask);
712 :
713 0 : if (rte->family == htons(RIP_FAMILY_AUTH)) {
714 0 : if (rte->tag
715 0 : == htons(RIP_AUTH_SIMPLE_PASSWORD)) {
716 0 : p = (uint8_t *)&rte->prefix;
717 :
718 0 : zlog_debug(
719 : " family 0x%X type %d auth string: %s",
720 : ntohs(rte->family),
721 : ntohs(rte->tag), p);
722 0 : } else if (rte->tag == htons(RIP_AUTH_MD5)) {
723 0 : struct rip_md5_info *md5;
724 :
725 0 : md5 = (struct rip_md5_info *)&packet
726 : ->rte;
727 :
728 0 : zlog_debug(
729 : " family 0x%X type %d (MD5 authentication)",
730 : ntohs(md5->family),
731 : ntohs(md5->type));
732 0 : zlog_debug(
733 : " RIP-2 packet len %d Key ID %d Auth Data len %d",
734 : ntohs(md5->packet_len),
735 : md5->keyid, md5->auth_len);
736 0 : zlog_debug(" Sequence Number %ld",
737 : (unsigned long)ntohl(
738 : md5->sequence));
739 0 : } else if (rte->tag == htons(RIP_AUTH_DATA)) {
740 0 : p = (uint8_t *)&rte->prefix;
741 :
742 0 : zlog_debug(
743 : " family 0x%X type %d (MD5 data)",
744 : ntohs(rte->family),
745 : ntohs(rte->tag));
746 0 : zlog_debug(
747 : " MD5: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
748 : p[0], p[1], p[2], p[3], p[4],
749 : p[5], p[6], p[7], p[8], p[9],
750 : p[10], p[11], p[12], p[13],
751 : p[14], p[15]);
752 : } else {
753 0 : zlog_debug(
754 : " family 0x%X type %d (Unknown auth type)",
755 : ntohs(rte->family),
756 : ntohs(rte->tag));
757 : }
758 : } else
759 0 : zlog_debug(
760 : " %pI4/%d -> %pI4 family %d tag %" ROUTE_TAG_PRI
761 : " metric %ld",
762 : &rte->prefix, netmask, &rte->nexthop,
763 : ntohs(rte->family),
764 : (route_tag_t)ntohs(rte->tag),
765 : (unsigned long)ntohl(rte->metric));
766 : } else {
767 0 : zlog_debug(" %pI4 family %d tag %" ROUTE_TAG_PRI
768 : " metric %ld",
769 : &rte->prefix, ntohs(rte->family),
770 : (route_tag_t)ntohs(rte->tag),
771 : (unsigned long)ntohl(rte->metric));
772 : }
773 : }
774 0 : }
775 :
776 : /* Check if the destination address is valid (unicast; not net 0
777 : or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
778 : check net 0 because we accept default route. */
779 87 : static int rip_destination_check(struct in_addr addr)
780 : {
781 87 : uint32_t destination;
782 :
783 : /* Convert to host byte order. */
784 87 : destination = ntohl(addr.s_addr);
785 :
786 87 : if (IPV4_NET127(destination))
787 : return 0;
788 :
789 : /* Net 0 may match to the default route. */
790 87 : if (IPV4_NET0(destination) && destination != 0)
791 : return 0;
792 :
793 : /* Unicast address must belong to class A, B, C. */
794 87 : if (IN_CLASSA(destination))
795 : return 1;
796 41 : if (IN_CLASSB(destination))
797 : return 1;
798 41 : if (IN_CLASSC(destination))
799 41 : return 1;
800 :
801 : return 0;
802 : }
803 :
804 : /* RIP version 2 authentication. */
805 0 : static int rip_auth_simple_password(struct rte *rte, struct sockaddr_in *from,
806 : struct interface *ifp)
807 : {
808 0 : struct rip_interface *ri;
809 0 : char *auth_str = (char *)rte + offsetof(struct rte, prefix);
810 0 : int i;
811 :
812 : /* reject passwords with zeros in the middle of the string */
813 0 : for (i = strnlen(auth_str, 16); i < 16; i++) {
814 0 : if (auth_str[i] != '\0')
815 : return 0;
816 : }
817 :
818 0 : if (IS_RIP_DEBUG_EVENT)
819 0 : zlog_debug("RIPv2 simple password authentication from %pI4",
820 : &from->sin_addr);
821 :
822 0 : ri = ifp->info;
823 :
824 0 : if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
825 0 : || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
826 : return 0;
827 :
828 : /* Simple password authentication. */
829 0 : if (ri->auth_str) {
830 0 : if (strncmp(auth_str, ri->auth_str, 16) == 0)
831 : return 1;
832 : }
833 0 : if (ri->key_chain) {
834 0 : struct keychain *keychain;
835 0 : struct key *key;
836 :
837 0 : keychain = keychain_lookup(ri->key_chain);
838 0 : if (keychain == NULL || keychain->key == NULL)
839 : return 0;
840 :
841 0 : key = key_match_for_accept(keychain, auth_str);
842 0 : if (key)
843 : return 1;
844 : }
845 : return 0;
846 : }
847 :
848 : /* RIP version 2 authentication with MD5. */
849 0 : static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
850 : int length, struct interface *ifp)
851 : {
852 0 : struct rip_interface *ri;
853 0 : struct rip_md5_info *md5;
854 0 : struct rip_md5_data *md5data;
855 0 : struct keychain *keychain;
856 0 : struct key *key;
857 : #ifdef CRYPTO_OPENSSL
858 : EVP_MD_CTX *ctx;
859 : #elif CRYPTO_INTERNAL
860 0 : MD5_CTX ctx;
861 : #endif
862 0 : uint8_t digest[RIP_AUTH_MD5_SIZE];
863 0 : uint16_t packet_len;
864 0 : char auth_str[RIP_AUTH_MD5_SIZE] = {};
865 :
866 0 : if (IS_RIP_DEBUG_EVENT)
867 0 : zlog_debug("RIPv2 MD5 authentication from %pI4",
868 : &from->sin_addr);
869 :
870 0 : ri = ifp->info;
871 0 : md5 = (struct rip_md5_info *)&packet->rte;
872 :
873 : /* Check auth type. */
874 0 : if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
875 : return 0;
876 :
877 : /* If the authentication length is less than 16, then it must be wrong
878 : * for
879 : * any interpretation of rfc2082. Some implementations also interpret
880 : * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka
881 : * RIP_AUTH_MD5_COMPAT_SIZE.
882 : */
883 0 : if (!((md5->auth_len == RIP_AUTH_MD5_SIZE)
884 : || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) {
885 0 : if (IS_RIP_DEBUG_EVENT)
886 0 : zlog_debug(
887 : "RIPv2 MD5 authentication, strange authentication length field %d",
888 : md5->auth_len);
889 0 : return 0;
890 : }
891 :
892 : /* grab and verify check packet length */
893 0 : packet_len = ntohs(md5->packet_len);
894 :
895 0 : if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) {
896 0 : if (IS_RIP_DEBUG_EVENT)
897 0 : zlog_debug(
898 : "RIPv2 MD5 authentication, packet length field %d greater than received length %d!",
899 : md5->packet_len, length);
900 0 : return 0;
901 : }
902 :
903 : /* retrieve authentication data */
904 0 : md5data = (struct rip_md5_data *)(((uint8_t *)packet) + packet_len);
905 :
906 0 : if (ri->key_chain) {
907 0 : keychain = keychain_lookup(ri->key_chain);
908 0 : if (keychain == NULL)
909 : return 0;
910 :
911 0 : key = key_lookup_for_accept(keychain, md5->keyid);
912 0 : if (key == NULL || key->string == NULL)
913 : return 0;
914 :
915 0 : memcpy(auth_str, key->string,
916 0 : MIN(sizeof(auth_str), strlen(key->string)));
917 0 : } else if (ri->auth_str)
918 0 : memcpy(auth_str, ri->auth_str,
919 0 : MIN(sizeof(auth_str), strlen(ri->auth_str)));
920 :
921 0 : if (auth_str[0] == 0)
922 : return 0;
923 :
924 : /* MD5 digest authentication. */
925 : #ifdef CRYPTO_OPENSSL
926 : unsigned int md5_size = RIP_AUTH_MD5_SIZE;
927 : ctx = EVP_MD_CTX_new();
928 : EVP_DigestInit(ctx, EVP_md5());
929 : EVP_DigestUpdate(ctx, packet, packet_len + RIP_HEADER_SIZE);
930 : EVP_DigestUpdate(ctx, auth_str, RIP_AUTH_MD5_SIZE);
931 : EVP_DigestFinal(ctx, digest, &md5_size);
932 : EVP_MD_CTX_free(ctx);
933 : #elif CRYPTO_INTERNAL
934 0 : memset(&ctx, 0, sizeof(ctx));
935 0 : MD5Init(&ctx);
936 0 : MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
937 0 : MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
938 0 : MD5Final(digest, &ctx);
939 : #endif
940 :
941 0 : if (memcmp(md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
942 : return packet_len;
943 : else
944 : return 0;
945 : }
946 :
947 : /* Pick correct auth string for sends, prepare auth_str buffer for use.
948 : * (left justified and padded).
949 : *
950 : * presumes one of ri or key is valid, and that the auth strings they point
951 : * to are nul terminated. If neither are present, auth_str will be fully
952 : * zero padded.
953 : *
954 : */
955 0 : static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key,
956 : char *auth_str, int len)
957 : {
958 0 : assert(ri || key);
959 :
960 0 : memset(auth_str, 0, len);
961 0 : if (key && key->string)
962 0 : memcpy(auth_str, key->string,
963 0 : MIN((size_t)len, strlen(key->string)));
964 0 : else if (ri->auth_str)
965 0 : memcpy(auth_str, ri->auth_str,
966 0 : MIN((size_t)len, strlen(ri->auth_str)));
967 :
968 0 : return;
969 : }
970 :
971 : /* Write RIPv2 simple password authentication information
972 : *
973 : * auth_str is presumed to be 2 bytes and correctly prepared
974 : * (left justified and zero padded).
975 : */
976 0 : static void rip_auth_simple_write(struct stream *s, char *auth_str, int len)
977 : {
978 0 : assert(s && len == RIP_AUTH_SIMPLE_SIZE);
979 :
980 0 : stream_putw(s, RIP_FAMILY_AUTH);
981 0 : stream_putw(s, RIP_AUTH_SIMPLE_PASSWORD);
982 0 : stream_put(s, auth_str, RIP_AUTH_SIMPLE_SIZE);
983 :
984 0 : return;
985 : }
986 :
987 : /* write RIPv2 MD5 "authentication header"
988 : * (uses the auth key data field)
989 : *
990 : * Digest offset field is set to 0.
991 : *
992 : * returns: offset of the digest offset field, which must be set when
993 : * length to the auth-data MD5 digest is known.
994 : */
995 0 : static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri,
996 : struct key *key)
997 : {
998 0 : size_t doff = 0;
999 0 : static uint32_t seq = 0;
1000 :
1001 0 : assert(s && ri && ri->auth_type == RIP_AUTH_MD5);
1002 :
1003 : /* MD5 authentication. */
1004 0 : stream_putw(s, RIP_FAMILY_AUTH);
1005 0 : stream_putw(s, RIP_AUTH_MD5);
1006 :
1007 : /* MD5 AH digest offset field.
1008 : *
1009 : * Set to placeholder value here, to true value when RIP-2 Packet length
1010 : * is known. Actual value is set in .....().
1011 : */
1012 0 : doff = stream_get_endp(s);
1013 0 : stream_putw(s, 0);
1014 :
1015 : /* Key ID. */
1016 0 : if (key)
1017 0 : stream_putc(s, key->index % 256);
1018 : else
1019 0 : stream_putc(s, 1);
1020 :
1021 : /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1022 : * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for
1023 : * this
1024 : * to be configurable.
1025 : */
1026 0 : stream_putc(s, ri->md5_auth_len);
1027 :
1028 : /* Sequence Number (non-decreasing). */
1029 : /* RFC2080: The value used in the sequence number is
1030 : arbitrary, but two suggestions are the time of the
1031 : message's creation or a simple message counter. */
1032 0 : stream_putl(s, ++seq);
1033 :
1034 : /* Reserved field must be zero. */
1035 0 : stream_putl(s, 0);
1036 0 : stream_putl(s, 0);
1037 :
1038 0 : return doff;
1039 : }
1040 :
1041 : /* If authentication is in used, write the appropriate header
1042 : * returns stream offset to which length must later be written
1043 : * or 0 if this is not required
1044 : */
1045 0 : static size_t rip_auth_header_write(struct stream *s, struct rip_interface *ri,
1046 : struct key *key, char *auth_str, int len)
1047 : {
1048 0 : assert(ri->auth_type != RIP_NO_AUTH);
1049 :
1050 0 : switch (ri->auth_type) {
1051 0 : case RIP_AUTH_SIMPLE_PASSWORD:
1052 0 : rip_auth_prepare_str_send(ri, key, auth_str, len);
1053 0 : rip_auth_simple_write(s, auth_str, len);
1054 0 : return 0;
1055 0 : case RIP_AUTH_MD5:
1056 0 : return rip_auth_md5_ah_write(s, ri, key);
1057 : }
1058 : assert(1);
1059 : return 0;
1060 : }
1061 :
1062 : /* Write RIPv2 MD5 authentication data trailer */
1063 0 : static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri,
1064 : size_t doff, char *auth_str, int authlen)
1065 : {
1066 0 : unsigned long len;
1067 : #ifdef CRYPTO_OPENSSL
1068 : EVP_MD_CTX *ctx;
1069 : #elif CRYPTO_INTERNAL
1070 0 : MD5_CTX ctx;
1071 : #endif
1072 0 : unsigned char digest[RIP_AUTH_MD5_SIZE];
1073 :
1074 : /* Make it sure this interface is configured as MD5
1075 : authentication. */
1076 0 : assert((ri->auth_type == RIP_AUTH_MD5)
1077 : && (authlen == RIP_AUTH_MD5_SIZE));
1078 0 : assert(doff > 0);
1079 :
1080 : /* Get packet length. */
1081 0 : len = stream_get_endp(s);
1082 :
1083 : /* Check packet length. */
1084 0 : if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) {
1085 0 : flog_err(EC_RIP_PACKET,
1086 : "%s: packet length %ld is less than minimum length.",
1087 : __func__, len);
1088 0 : return;
1089 : }
1090 :
1091 : /* Set the digest offset length in the header */
1092 0 : stream_putw_at(s, doff, len);
1093 :
1094 : /* Set authentication data. */
1095 0 : stream_putw(s, RIP_FAMILY_AUTH);
1096 0 : stream_putw(s, RIP_AUTH_DATA);
1097 :
1098 : /* Generate a digest for the RIP packet. */
1099 : #ifdef CRYPTO_OPENSSL
1100 : unsigned int md5_size = RIP_AUTH_MD5_SIZE;
1101 : ctx = EVP_MD_CTX_new();
1102 : EVP_DigestInit(ctx, EVP_md5());
1103 : EVP_DigestUpdate(ctx, STREAM_DATA(s), stream_get_endp(s));
1104 : EVP_DigestUpdate(ctx, auth_str, RIP_AUTH_MD5_SIZE);
1105 : EVP_DigestFinal(ctx, digest, &md5_size);
1106 : EVP_MD_CTX_free(ctx);
1107 : #elif CRYPTO_INTERNAL
1108 0 : memset(&ctx, 0, sizeof(ctx));
1109 0 : MD5Init(&ctx);
1110 0 : MD5Update(&ctx, STREAM_DATA(s), stream_get_endp(s));
1111 0 : MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1112 0 : MD5Final(digest, &ctx);
1113 : #endif
1114 :
1115 : /* Copy the digest to the packet. */
1116 0 : stream_write(s, digest, RIP_AUTH_MD5_SIZE);
1117 : }
1118 :
1119 : /* RIP routing information. */
1120 7 : static void rip_response_process(struct rip_packet *packet, int size,
1121 : struct sockaddr_in *from,
1122 : struct connected *ifc)
1123 : {
1124 7 : struct rip_interface *ri = ifc->ifp->info;
1125 7 : struct rip *rip = ri->rip;
1126 7 : caddr_t lim;
1127 7 : struct rte *rte;
1128 7 : struct prefix_ipv4 ifaddr;
1129 7 : struct prefix_ipv4 ifaddrclass;
1130 7 : int subnetted;
1131 :
1132 7 : memset(&ifaddr, 0, sizeof(ifaddr));
1133 : /* We don't know yet. */
1134 7 : subnetted = -1;
1135 :
1136 : /* The Response must be ignored if it is not from the RIP
1137 : port. (RFC2453 - Sec. 3.9.2)*/
1138 7 : if (from->sin_port != htons(RIP_PORT_DEFAULT)) {
1139 0 : zlog_info("response doesn't come from RIP port: %d",
1140 : from->sin_port);
1141 0 : rip_peer_bad_packet(rip, from);
1142 0 : return;
1143 : }
1144 :
1145 : /* The datagram's IPv4 source address should be checked to see
1146 : whether the datagram is from a valid neighbor; the source of the
1147 : datagram must be on a directly connected network (RFC2453 - Sec.
1148 : 3.9.2) */
1149 7 : if (if_lookup_address((void *)&from->sin_addr, AF_INET,
1150 7 : rip->vrf->vrf_id)
1151 : == NULL) {
1152 0 : zlog_info(
1153 : "This datagram doesn't come from a valid neighbor: %pI4",
1154 : &from->sin_addr);
1155 0 : rip_peer_bad_packet(rip, from);
1156 0 : return;
1157 : }
1158 :
1159 : /* It is also worth checking to see whether the response is from one
1160 : of the router's own addresses. */
1161 :
1162 7 : ; /* Alredy done in rip_read () */
1163 :
1164 : /* Update RIP peer. */
1165 7 : rip_peer_update(rip, from, packet->version);
1166 :
1167 : /* Set RTE pointer. */
1168 7 : rte = packet->rte;
1169 :
1170 24 : for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) {
1171 : /* RIPv2 authentication check. */
1172 : /* If the Address Family Identifier of the first (and only the
1173 : first) entry in the message is 0xFFFF, then the remainder of
1174 : the entry contains the authentication. */
1175 : /* If the packet gets here it means authentication enabled */
1176 : /* Check is done in rip_read(). So, just skipping it */
1177 17 : if (packet->version == RIPv2 && rte == packet->rte
1178 7 : && rte->family == htons(RIP_FAMILY_AUTH))
1179 0 : continue;
1180 :
1181 17 : if (rte->family != htons(AF_INET)) {
1182 : /* Address family check. RIP only supports AF_INET. */
1183 0 : zlog_info("Unsupported family %d from %pI4",
1184 : ntohs(rte->family),
1185 : &from->sin_addr);
1186 0 : continue;
1187 : }
1188 :
1189 : /* - is the destination address valid (e.g., unicast; not net 0
1190 : or 127) */
1191 17 : if (!rip_destination_check(rte->prefix)) {
1192 0 : zlog_info(
1193 : "Network is net 0 or net 127 or it is not unicast network");
1194 0 : rip_peer_bad_route(rip, from);
1195 0 : continue;
1196 : }
1197 :
1198 : /* Convert metric value to host byte order. */
1199 17 : rte->metric = ntohl(rte->metric);
1200 :
1201 : /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1202 17 : if (!(rte->metric >= 1 && rte->metric <= 16)) {
1203 0 : zlog_info("Route's metric is not in the 1-16 range.");
1204 0 : rip_peer_bad_route(rip, from);
1205 0 : continue;
1206 : }
1207 :
1208 : /* RIPv1 does not have nexthop value. */
1209 17 : if (packet->version == RIPv1
1210 0 : && rte->nexthop.s_addr != INADDR_ANY) {
1211 0 : zlog_info("RIPv1 packet with nexthop value %pI4",
1212 : &rte->nexthop);
1213 0 : rip_peer_bad_route(rip, from);
1214 0 : continue;
1215 : }
1216 :
1217 : /* That is, if the provided information is ignored, a possibly
1218 : sub-optimal, but absolutely valid, route may be taken. If
1219 : the received Next Hop is not directly reachable, it should be
1220 : treated as 0.0.0.0. */
1221 17 : if (packet->version == RIPv2
1222 17 : && rte->nexthop.s_addr != INADDR_ANY) {
1223 0 : uint32_t addrval;
1224 :
1225 : /* Multicast address check. */
1226 0 : addrval = ntohl(rte->nexthop.s_addr);
1227 0 : if (IN_CLASSD(addrval)) {
1228 0 : zlog_info(
1229 : "Nexthop %pI4 is multicast address, skip this rte",
1230 : &rte->nexthop);
1231 0 : continue;
1232 : }
1233 :
1234 0 : if (!if_lookup_address((void *)&rte->nexthop, AF_INET,
1235 0 : rip->vrf->vrf_id)) {
1236 0 : struct route_node *rn;
1237 0 : struct rip_info *rinfo;
1238 :
1239 0 : rn = route_node_match_ipv4(rip->table,
1240 : &rte->nexthop);
1241 :
1242 0 : if (rn) {
1243 0 : rinfo = rn->info;
1244 :
1245 0 : if (rinfo->type == ZEBRA_ROUTE_RIP
1246 0 : && rinfo->sub_type
1247 : == RIP_ROUTE_RTE) {
1248 0 : if (IS_RIP_DEBUG_EVENT)
1249 0 : zlog_debug(
1250 : "Next hop %pI4 is on RIP network. Set nexthop to the packet's originator",
1251 : &rte->nexthop);
1252 0 : rte->nexthop = rinfo->from;
1253 : } else {
1254 0 : if (IS_RIP_DEBUG_EVENT)
1255 0 : zlog_debug(
1256 : "Next hop %pI4 is not directly reachable. Treat it as 0.0.0.0",
1257 : &rte->nexthop);
1258 0 : rte->nexthop.s_addr =
1259 : INADDR_ANY;
1260 : }
1261 :
1262 0 : route_unlock_node(rn);
1263 : } else {
1264 0 : if (IS_RIP_DEBUG_EVENT)
1265 0 : zlog_debug(
1266 : "Next hop %pI4 is not directly reachable. Treat it as 0.0.0.0",
1267 : &rte->nexthop);
1268 0 : rte->nexthop.s_addr = INADDR_ANY;
1269 : }
1270 : }
1271 : }
1272 :
1273 : /* For RIPv1, there won't be a valid netmask.
1274 : * This is a best guess at the masks. If everyone was using old
1275 : * Ciscos before the 'ip subnet zero' option, it would be almost
1276 : * right too :-)
1277 : *
1278 : * Cisco summarize ripv1 advertisements to the classful boundary
1279 : * (/16 for class B's) except when the RIP packet does to inside
1280 : * the classful network in question.
1281 : */
1282 17 : if ((packet->version == RIPv1
1283 0 : && rte->prefix.s_addr != INADDR_ANY)
1284 17 : || (packet->version == RIPv2
1285 17 : && (rte->prefix.s_addr != INADDR_ANY
1286 17 : && rte->mask.s_addr == INADDR_ANY))) {
1287 0 : uint32_t destination;
1288 :
1289 0 : if (subnetted == -1) {
1290 0 : memcpy(&ifaddr, ifc->address, sizeof(ifaddr));
1291 0 : memcpy(&ifaddrclass, &ifaddr,
1292 : sizeof(ifaddrclass));
1293 0 : apply_classful_mask_ipv4(&ifaddrclass);
1294 0 : subnetted = 0;
1295 0 : if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1296 0 : subnetted = 1;
1297 : }
1298 :
1299 0 : destination = ntohl(rte->prefix.s_addr);
1300 :
1301 0 : if (IN_CLASSA(destination))
1302 0 : masklen2ip(8, &rte->mask);
1303 0 : else if (IN_CLASSB(destination))
1304 0 : masklen2ip(16, &rte->mask);
1305 0 : else if (IN_CLASSC(destination))
1306 0 : masklen2ip(24, &rte->mask);
1307 :
1308 0 : if (subnetted == 1)
1309 0 : masklen2ip(ifaddrclass.prefixlen,
1310 : (struct in_addr *)&destination);
1311 0 : if ((subnetted == 1)
1312 0 : && ((rte->prefix.s_addr & destination)
1313 0 : == ifaddrclass.prefix.s_addr)) {
1314 0 : masklen2ip(ifaddr.prefixlen, &rte->mask);
1315 0 : if ((rte->prefix.s_addr & rte->mask.s_addr)
1316 : != rte->prefix.s_addr)
1317 0 : masklen2ip(32, &rte->mask);
1318 0 : if (IS_RIP_DEBUG_EVENT)
1319 0 : zlog_debug("Subnetted route %pI4",
1320 : &rte->prefix);
1321 : } else {
1322 0 : if ((rte->prefix.s_addr & rte->mask.s_addr)
1323 : != rte->prefix.s_addr)
1324 0 : continue;
1325 : }
1326 :
1327 0 : if (IS_RIP_DEBUG_EVENT) {
1328 0 : zlog_debug("Resultant route %pI4",
1329 : &rte->prefix);
1330 0 : zlog_debug("Resultant mask %pI4",
1331 : &rte->mask);
1332 : }
1333 : }
1334 :
1335 : /* In case of RIPv2, if prefix in RTE is not netmask applied one
1336 : ignore the entry. */
1337 17 : if ((packet->version == RIPv2)
1338 17 : && (rte->mask.s_addr != INADDR_ANY)
1339 17 : && ((rte->prefix.s_addr & rte->mask.s_addr)
1340 : != rte->prefix.s_addr)) {
1341 0 : zlog_warn(
1342 : "RIPv2 address %pI4 is not mask /%d applied one",
1343 : &rte->prefix, ip_masklen(rte->mask));
1344 0 : rip_peer_bad_route(rip, from);
1345 0 : continue;
1346 : }
1347 :
1348 : /* Default route's netmask is ignored. */
1349 17 : if (packet->version == RIPv2
1350 17 : && (rte->prefix.s_addr == INADDR_ANY)
1351 0 : && (rte->mask.s_addr != INADDR_ANY)) {
1352 0 : if (IS_RIP_DEBUG_EVENT)
1353 0 : zlog_debug(
1354 : "Default route with non-zero netmask. Set zero to netmask");
1355 0 : rte->mask.s_addr = INADDR_ANY;
1356 : }
1357 :
1358 : /* Routing table updates. */
1359 17 : rip_rte_process(rte, from, ifc->ifp);
1360 : }
1361 : }
1362 :
1363 : /* Make socket for RIP protocol. */
1364 5 : int rip_create_socket(struct vrf *vrf)
1365 : {
1366 5 : int ret;
1367 5 : int sock;
1368 5 : struct sockaddr_in addr;
1369 5 : const char *vrf_dev = NULL;
1370 :
1371 5 : memset(&addr, 0, sizeof(struct sockaddr_in));
1372 5 : addr.sin_family = AF_INET;
1373 5 : addr.sin_addr.s_addr = INADDR_ANY;
1374 : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1375 : addr.sin_len = sizeof(struct sockaddr_in);
1376 : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1377 : /* sending port must always be the RIP port */
1378 5 : addr.sin_port = htons(RIP_PORT_DEFAULT);
1379 :
1380 : /* Make datagram socket. */
1381 5 : if (vrf->vrf_id != VRF_DEFAULT)
1382 0 : vrf_dev = vrf->name;
1383 10 : frr_with_privs(&ripd_privs) {
1384 5 : sock = vrf_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, vrf->vrf_id,
1385 : vrf_dev);
1386 5 : if (sock < 0) {
1387 0 : flog_err_sys(EC_LIB_SOCKET,
1388 : "Cannot create UDP socket: %s",
1389 : safe_strerror(errno));
1390 0 : return -1;
1391 : }
1392 : }
1393 :
1394 5 : sockopt_broadcast(sock);
1395 5 : sockopt_reuseaddr(sock);
1396 5 : sockopt_reuseport(sock);
1397 5 : setsockopt_ipv4_multicast_loop(sock, 0);
1398 : #ifdef IPTOS_PREC_INTERNETCONTROL
1399 5 : setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
1400 : #endif
1401 5 : setsockopt_so_recvbuf(sock, RIP_UDP_RCV_BUF);
1402 :
1403 10 : frr_with_privs(&ripd_privs) {
1404 5 : if ((ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
1405 : < 0) {
1406 0 : zlog_err("%s: Can't bind socket %d to %pI4 port %d: %s",
1407 : __func__, sock, &addr.sin_addr,
1408 : (int)ntohs(addr.sin_port),
1409 : safe_strerror(errno));
1410 :
1411 0 : close(sock);
1412 0 : return ret;
1413 : }
1414 : }
1415 :
1416 5 : return sock;
1417 : }
1418 :
1419 : /* RIP packet send to destination address, on interface denoted by
1420 : * by connected argument. NULL to argument denotes destination should be
1421 : * should be RIP multicast group
1422 : */
1423 14 : static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
1424 : struct connected *ifc)
1425 : {
1426 14 : struct rip_interface *ri;
1427 14 : struct rip *rip;
1428 14 : int ret;
1429 14 : struct sockaddr_in sin;
1430 14 : struct msghdr msg;
1431 14 : struct iovec iov;
1432 : #ifdef GNU_LINUX
1433 14 : struct cmsghdr *cmsgptr;
1434 14 : char adata[256] = {};
1435 14 : struct in_pktinfo *pkt;
1436 : #endif /* GNU_LINUX */
1437 :
1438 14 : assert(ifc != NULL);
1439 14 : ri = ifc->ifp->info;
1440 14 : rip = ri->rip;
1441 :
1442 14 : if (IS_RIP_DEBUG_PACKET) {
1443 : #define ADDRESS_SIZE 20
1444 0 : char dst[ADDRESS_SIZE];
1445 :
1446 0 : if (to) {
1447 0 : inet_ntop(AF_INET, &to->sin_addr, dst, sizeof(dst));
1448 : } else {
1449 0 : sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
1450 0 : inet_ntop(AF_INET, &sin.sin_addr, dst, sizeof(dst));
1451 : }
1452 : #undef ADDRESS_SIZE
1453 0 : zlog_debug("%s %pI4 > %s (%s)", __func__,
1454 : &ifc->address->u.prefix4, dst, ifc->ifp->name);
1455 : }
1456 :
1457 14 : if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
1458 : /*
1459 : * ZEBRA_IFA_SECONDARY is set on linux when an interface is
1460 : * configured with multiple addresses on the same
1461 : * subnet: the first address on the subnet is configured
1462 : * "primary", and all subsequent addresses on that subnet
1463 : * are treated as "secondary" addresses. In order to avoid
1464 : * routing-table bloat on other rip listeners, we do not send
1465 : * out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1466 : * XXX Since Linux is the only system for which the
1467 : * ZEBRA_IFA_SECONDARY flag is set, we would end up
1468 : * sending a packet for a "secondary" source address on
1469 : * non-linux systems.
1470 : */
1471 0 : if (IS_RIP_DEBUG_PACKET)
1472 0 : zlog_debug("duplicate dropped");
1473 0 : return 0;
1474 : }
1475 :
1476 : /* Make destination address. */
1477 14 : memset(&sin, 0, sizeof(sin));
1478 14 : sin.sin_family = AF_INET;
1479 : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1480 : sin.sin_len = sizeof(struct sockaddr_in);
1481 : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1482 :
1483 : /* When destination is specified, use it's port and address. */
1484 14 : if (to) {
1485 2 : sin.sin_port = to->sin_port;
1486 2 : sin.sin_addr = to->sin_addr;
1487 : } else {
1488 12 : sin.sin_port = htons(RIP_PORT_DEFAULT);
1489 12 : sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
1490 :
1491 12 : rip_interface_multicast_set(rip->sock, ifc);
1492 : }
1493 :
1494 14 : memset(&msg, 0, sizeof(msg));
1495 14 : msg.msg_name = (void *)&sin;
1496 14 : msg.msg_namelen = sizeof(struct sockaddr_in);
1497 14 : msg.msg_iov = &iov;
1498 14 : msg.msg_iovlen = 1;
1499 14 : iov.iov_base = buf;
1500 14 : iov.iov_len = size;
1501 :
1502 : #ifdef GNU_LINUX
1503 14 : msg.msg_control = (void *)adata;
1504 14 : msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
1505 :
1506 14 : cmsgptr = (struct cmsghdr *)adata;
1507 14 : cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1508 14 : cmsgptr->cmsg_level = IPPROTO_IP;
1509 14 : cmsgptr->cmsg_type = IP_PKTINFO;
1510 14 : pkt = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
1511 14 : pkt->ipi_ifindex = ifc->ifp->ifindex;
1512 14 : pkt->ipi_spec_dst.s_addr = ifc->address->u.prefix4.s_addr;
1513 : #endif /* GNU_LINUX */
1514 :
1515 14 : ret = sendmsg(rip->sock, &msg, 0);
1516 :
1517 14 : if (IS_RIP_DEBUG_EVENT)
1518 1 : zlog_debug("SEND to %pI4%d", &sin.sin_addr,
1519 : ntohs(sin.sin_port));
1520 :
1521 14 : if (ret < 0)
1522 0 : zlog_warn("can't send packet : %s", safe_strerror(errno));
1523 :
1524 : return ret;
1525 : }
1526 :
1527 : /* Add redistributed route to RIP table. */
1528 55 : void rip_redistribute_add(struct rip *rip, int type, int sub_type,
1529 : struct prefix_ipv4 *p, struct nexthop *nh,
1530 : unsigned int metric, unsigned char distance,
1531 : route_tag_t tag)
1532 : {
1533 55 : int ret;
1534 55 : struct route_node *rp = NULL;
1535 55 : struct rip_info *rinfo = NULL, newinfo;
1536 55 : struct list *list = NULL;
1537 :
1538 : /* Redistribute route */
1539 55 : ret = rip_destination_check(p->prefix);
1540 55 : if (!ret)
1541 38 : return;
1542 :
1543 55 : rp = route_node_get(rip->table, (struct prefix *)p);
1544 :
1545 55 : memset(&newinfo, 0, sizeof(newinfo));
1546 55 : newinfo.type = type;
1547 55 : newinfo.sub_type = sub_type;
1548 55 : newinfo.metric = 1;
1549 55 : newinfo.external_metric = metric;
1550 55 : newinfo.distance = distance;
1551 55 : if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */
1552 55 : newinfo.tag = tag;
1553 55 : newinfo.rp = rp;
1554 55 : newinfo.nh = *nh;
1555 :
1556 55 : if ((list = rp->info) != NULL && listcount(list) != 0) {
1557 46 : rinfo = listgetdata(listhead(list));
1558 :
1559 46 : if (rinfo->type == ZEBRA_ROUTE_CONNECT
1560 46 : && rinfo->sub_type == RIP_ROUTE_INTERFACE
1561 44 : && rinfo->metric != RIP_METRIC_INFINITY) {
1562 38 : route_unlock_node(rp);
1563 38 : return;
1564 : }
1565 :
1566 : /* Manually configured RIP route check. */
1567 8 : if (rinfo->type == ZEBRA_ROUTE_RIP
1568 0 : && ((rinfo->sub_type == RIP_ROUTE_STATIC)
1569 0 : || (rinfo->sub_type == RIP_ROUTE_DEFAULT))) {
1570 0 : if (type != ZEBRA_ROUTE_RIP
1571 0 : || ((sub_type != RIP_ROUTE_STATIC)
1572 0 : && (sub_type != RIP_ROUTE_DEFAULT))) {
1573 0 : route_unlock_node(rp);
1574 0 : return;
1575 : }
1576 : }
1577 :
1578 8 : (void)rip_ecmp_replace(rip, &newinfo);
1579 8 : route_unlock_node(rp);
1580 : } else
1581 9 : (void)rip_ecmp_add(rip, &newinfo);
1582 :
1583 17 : if (IS_RIP_DEBUG_EVENT) {
1584 1 : zlog_debug("Redistribute new prefix %pFX", p);
1585 : }
1586 :
1587 17 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
1588 : }
1589 :
1590 : /* Delete redistributed route from RIP table. */
1591 15 : void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
1592 : struct prefix_ipv4 *p, ifindex_t ifindex)
1593 : {
1594 15 : int ret;
1595 15 : struct route_node *rp;
1596 15 : struct rip_info *rinfo;
1597 :
1598 15 : ret = rip_destination_check(p->prefix);
1599 15 : if (!ret)
1600 : return;
1601 :
1602 15 : rp = route_node_lookup(rip->table, (struct prefix *)p);
1603 15 : if (rp) {
1604 12 : struct list *list = rp->info;
1605 :
1606 12 : if (list != NULL && listcount(list) != 0) {
1607 12 : rinfo = listgetdata(listhead(list));
1608 12 : if (rinfo != NULL && rinfo->type == type
1609 12 : && rinfo->sub_type == sub_type
1610 9 : && rinfo->nh.ifindex == ifindex) {
1611 : /* Perform poisoned reverse. */
1612 9 : rinfo->metric = RIP_METRIC_INFINITY;
1613 9 : RIP_TIMER_ON(rinfo->t_garbage_collect,
1614 : rip_garbage_collect,
1615 : rip->garbage_time);
1616 9 : THREAD_OFF(rinfo->t_timeout);
1617 9 : rinfo->flags |= RIP_RTF_CHANGED;
1618 :
1619 9 : if (IS_RIP_DEBUG_EVENT)
1620 0 : zlog_debug(
1621 : "Poison %pFX on the interface %s with an infinity metric [delete]",
1622 : p,
1623 : ifindex2ifname(
1624 : ifindex,
1625 : rip->vrf->vrf_id));
1626 :
1627 9 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
1628 : }
1629 : }
1630 12 : route_unlock_node(rp);
1631 : }
1632 : }
1633 :
1634 : /* Response to request called from rip_read ().*/
1635 2 : static void rip_request_process(struct rip_packet *packet, int size,
1636 : struct sockaddr_in *from, struct connected *ifc)
1637 : {
1638 2 : struct rip *rip;
1639 2 : caddr_t lim;
1640 2 : struct rte *rte;
1641 2 : struct prefix_ipv4 p;
1642 2 : struct route_node *rp;
1643 2 : struct rip_info *rinfo;
1644 2 : struct rip_interface *ri;
1645 :
1646 : /* Does not reponse to the requests on the loopback interfaces */
1647 2 : if (if_is_loopback(ifc->ifp))
1648 0 : return;
1649 :
1650 : /* Check RIP process is enabled on this interface. */
1651 2 : ri = ifc->ifp->info;
1652 2 : if (!ri->running)
1653 : return;
1654 2 : rip = ri->rip;
1655 :
1656 : /* When passive interface is specified, suppress responses */
1657 2 : if (ri->passive)
1658 : return;
1659 :
1660 : /* RIP peer update. */
1661 2 : rip_peer_update(rip, from, packet->version);
1662 :
1663 2 : lim = ((caddr_t)packet) + size;
1664 2 : rte = packet->rte;
1665 :
1666 : /* The Request is processed entry by entry. If there are no
1667 : entries, no response is given. */
1668 2 : if (lim == (caddr_t)rte)
1669 : return;
1670 :
1671 : /* There is one special case. If there is exactly one entry in the
1672 : request, and it has an address family identifier of zero and a
1673 : metric of infinity (i.e., 16), then this is a request to send the
1674 : entire routing table. */
1675 2 : if (lim == ((caddr_t)(rte + 1)) && ntohs(rte->family) == 0
1676 2 : && ntohl(rte->metric) == RIP_METRIC_INFINITY) {
1677 : /* All route with split horizon */
1678 2 : rip_output_process(ifc, from, rip_all_route, packet->version);
1679 : } else {
1680 0 : if (ntohs(rte->family) != AF_INET)
1681 : return;
1682 :
1683 : /* Examine the list of RTEs in the Request one by one. For each
1684 : entry, look up the destination in the router's routing
1685 : database and, if there is a route, put that route's metric in
1686 : the metric field of the RTE. If there is no explicit route
1687 : to the specified destination, put infinity in the metric
1688 : field. Once all the entries have been filled in, change the
1689 : command from Request to Response and send the datagram back
1690 : to the requestor. */
1691 0 : p.family = AF_INET;
1692 :
1693 0 : for (; ((caddr_t)rte) < lim; rte++) {
1694 0 : p.prefix = rte->prefix;
1695 0 : p.prefixlen = ip_masklen(rte->mask);
1696 0 : apply_mask_ipv4(&p);
1697 :
1698 0 : rp = route_node_lookup(rip->table, (struct prefix *)&p);
1699 0 : if (rp) {
1700 0 : rinfo = listgetdata(
1701 : listhead((struct list *)rp->info));
1702 0 : rte->metric = htonl(rinfo->metric);
1703 0 : route_unlock_node(rp);
1704 : } else
1705 0 : rte->metric = htonl(RIP_METRIC_INFINITY);
1706 : }
1707 0 : packet->command = RIP_RESPONSE;
1708 :
1709 0 : (void)rip_send_packet((uint8_t *)packet, size, from, ifc);
1710 : }
1711 2 : rip->counters.queries++;
1712 : }
1713 :
1714 : /* First entry point of RIP packet. */
1715 9 : static void rip_read(struct thread *t)
1716 : {
1717 9 : struct rip *rip = THREAD_ARG(t);
1718 9 : int sock;
1719 9 : int ret;
1720 9 : int rtenum;
1721 9 : union rip_buf rip_buf;
1722 9 : struct rip_packet *packet;
1723 9 : struct sockaddr_in from;
1724 9 : int len;
1725 9 : int vrecv;
1726 9 : socklen_t fromlen;
1727 9 : struct interface *ifp = NULL;
1728 9 : struct connected *ifc;
1729 9 : struct rip_interface *ri;
1730 9 : struct prefix p;
1731 :
1732 : /* Fetch socket then register myself. */
1733 9 : sock = THREAD_FD(t);
1734 :
1735 : /* Add myself to tne next event */
1736 9 : rip_event(rip, RIP_READ, sock);
1737 :
1738 : /* RIPd manages only IPv4. */
1739 9 : memset(&from, 0, sizeof(from));
1740 9 : fromlen = sizeof(struct sockaddr_in);
1741 :
1742 9 : len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0,
1743 : (struct sockaddr *)&from, &fromlen);
1744 9 : if (len < 0) {
1745 0 : zlog_info("recvfrom failed (VRF %s): %s", rip->vrf_name,
1746 : safe_strerror(errno));
1747 0 : return;
1748 : }
1749 :
1750 : /* Check is this packet comming from myself? */
1751 9 : if (if_check_address(rip, from.sin_addr)) {
1752 0 : if (IS_RIP_DEBUG_PACKET)
1753 0 : zlog_debug("ignore packet comes from myself (VRF %s)",
1754 : rip->vrf_name);
1755 0 : return;
1756 : }
1757 :
1758 : /* Which interface is this packet comes from. */
1759 18 : ifc = if_lookup_address((void *)&from.sin_addr, AF_INET,
1760 9 : rip->vrf->vrf_id);
1761 9 : if (ifc)
1762 9 : ifp = ifc->ifp;
1763 :
1764 : /* RIP packet received */
1765 9 : if (IS_RIP_DEBUG_EVENT)
1766 0 : zlog_debug("RECV packet from %pI4 port %d on %s (VRF %s)",
1767 : &from.sin_addr, ntohs(from.sin_port),
1768 : ifp ? ifp->name : "unknown", rip->vrf_name);
1769 :
1770 : /* If this packet come from unknown interface, ignore it. */
1771 9 : if (ifp == NULL) {
1772 0 : zlog_info(
1773 : "%s: cannot find interface for packet from %pI4 port %d (VRF %s)",
1774 : __func__, &from.sin_addr, ntohs(from.sin_port),
1775 : rip->vrf_name);
1776 0 : return;
1777 : }
1778 :
1779 9 : p.family = AF_INET;
1780 9 : p.u.prefix4 = from.sin_addr;
1781 9 : p.prefixlen = IPV4_MAX_BITLEN;
1782 :
1783 9 : ifc = connected_lookup_prefix(ifp, &p);
1784 :
1785 9 : if (ifc == NULL) {
1786 0 : zlog_info(
1787 : "%s: cannot find connected address for packet from %pI4 port %d on interface %s (VRF %s)",
1788 : __func__, &from.sin_addr, ntohs(from.sin_port),
1789 : ifp->name, rip->vrf_name);
1790 0 : return;
1791 : }
1792 :
1793 : /* Packet length check. */
1794 9 : if (len < RIP_PACKET_MINSIZ) {
1795 0 : zlog_warn("packet size %d is smaller than minimum size %d", len,
1796 : RIP_PACKET_MINSIZ);
1797 0 : rip_peer_bad_packet(rip, &from);
1798 0 : return;
1799 : }
1800 9 : if (len > RIP_PACKET_MAXSIZ) {
1801 0 : zlog_warn("packet size %d is larger than max size %d", len,
1802 : RIP_PACKET_MAXSIZ);
1803 0 : rip_peer_bad_packet(rip, &from);
1804 0 : return;
1805 : }
1806 :
1807 : /* Packet alignment check. */
1808 9 : if ((len - RIP_PACKET_MINSIZ) % 20) {
1809 0 : zlog_warn("packet size %d is wrong for RIP packet alignment",
1810 : len);
1811 0 : rip_peer_bad_packet(rip, &from);
1812 0 : return;
1813 : }
1814 :
1815 : /* Set RTE number. */
1816 9 : rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1817 :
1818 : /* For easy to handle. */
1819 9 : packet = &rip_buf.rip_packet;
1820 :
1821 : /* RIP version check. */
1822 9 : if (packet->version == 0) {
1823 0 : zlog_info("version 0 with command %d received.",
1824 : packet->command);
1825 0 : rip_peer_bad_packet(rip, &from);
1826 0 : return;
1827 : }
1828 :
1829 : /* Dump RIP packet. */
1830 9 : if (IS_RIP_DEBUG_RECV)
1831 0 : rip_packet_dump(packet, len, "RECV");
1832 :
1833 : /* RIP version adjust. This code should rethink now. RFC1058 says
1834 : that "Version 1 implementations are to ignore this extra data and
1835 : process only the fields specified in this document.". So RIPv3
1836 : packet should be treated as RIPv1 ignoring must be zero field. */
1837 9 : if (packet->version > RIPv2)
1838 0 : packet->version = RIPv2;
1839 :
1840 : /* Is RIP running or is this RIP neighbor ?*/
1841 9 : ri = ifp->info;
1842 9 : if (!ri->running && !rip_neighbor_lookup(rip, &from)) {
1843 0 : if (IS_RIP_DEBUG_EVENT)
1844 0 : zlog_debug("RIP is not enabled on interface %s.",
1845 : ifp->name);
1846 0 : rip_peer_bad_packet(rip, &from);
1847 0 : return;
1848 : }
1849 :
1850 : /* RIP Version check. RFC2453, 4.6 and 5.1 */
1851 18 : vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv
1852 9 : : ri->ri_receive);
1853 9 : if (vrecv == RI_RIP_VERSION_NONE
1854 9 : || ((packet->version == RIPv1) && !(vrecv & RIPv1))
1855 9 : || ((packet->version == RIPv2) && !(vrecv & RIPv2))) {
1856 0 : if (IS_RIP_DEBUG_PACKET)
1857 0 : zlog_debug(
1858 : " packet's v%d doesn't fit to if version spec",
1859 : packet->version);
1860 0 : rip_peer_bad_packet(rip, &from);
1861 0 : return;
1862 : }
1863 :
1864 : /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1865 : messages, then RIP-1 and unauthenticated RIP-2 messages will be
1866 : accepted; authenticated RIP-2 messages shall be discarded. */
1867 9 : if ((ri->auth_type == RIP_NO_AUTH) && rtenum
1868 9 : && (packet->version == RIPv2)
1869 9 : && (packet->rte->family == htons(RIP_FAMILY_AUTH))) {
1870 0 : if (IS_RIP_DEBUG_EVENT)
1871 0 : zlog_debug(
1872 : "packet RIPv%d is dropped because authentication disabled",
1873 : packet->version);
1874 0 : ripd_notif_send_auth_type_failure(ifp->name);
1875 0 : rip_peer_bad_packet(rip, &from);
1876 0 : return;
1877 : }
1878 :
1879 : /* RFC:
1880 : If the router is configured to authenticate RIP-2 messages, then
1881 : RIP-1 messages and RIP-2 messages which pass authentication
1882 : testing shall be accepted; unauthenticated and failed
1883 : authentication RIP-2 messages shall be discarded. For maximum
1884 : security, RIP-1 messages should be ignored when authentication is
1885 : in use (see section 4.1); otherwise, the routing information from
1886 : authenticated messages will be propagated by RIP-1 routers in an
1887 : unauthenticated manner.
1888 : */
1889 : /* We make an exception for RIPv1 REQUEST packets, to which we'll
1890 : * always reply regardless of authentication settings, because:
1891 : *
1892 : * - if there other authorised routers on-link, the REQUESTor can
1893 : * passively obtain the routing updates anyway
1894 : * - if there are no other authorised routers on-link, RIP can
1895 : * easily be disabled for the link to prevent giving out information
1896 : * on state of this routers RIP routing table..
1897 : *
1898 : * I.e. if RIPv1 has any place anymore these days, it's as a very
1899 : * simple way to distribute routing information (e.g. to embedded
1900 : * hosts / appliances) and the ability to give out RIPv1
1901 : * routing-information freely, while still requiring RIPv2
1902 : * authentication for any RESPONSEs might be vaguely useful.
1903 : */
1904 9 : if (ri->auth_type != RIP_NO_AUTH && packet->version == RIPv1) {
1905 : /* Discard RIPv1 messages other than REQUESTs */
1906 0 : if (packet->command != RIP_REQUEST) {
1907 0 : if (IS_RIP_DEBUG_PACKET)
1908 0 : zlog_debug(
1909 : "RIPv1 dropped because authentication enabled");
1910 0 : ripd_notif_send_auth_type_failure(ifp->name);
1911 0 : rip_peer_bad_packet(rip, &from);
1912 0 : return;
1913 : }
1914 9 : } else if (ri->auth_type != RIP_NO_AUTH) {
1915 0 : const char *auth_desc;
1916 :
1917 0 : if (rtenum == 0) {
1918 : /* There definitely is no authentication in the packet.
1919 : */
1920 0 : if (IS_RIP_DEBUG_PACKET)
1921 0 : zlog_debug(
1922 : "RIPv2 authentication failed: no auth RTE in packet");
1923 0 : ripd_notif_send_auth_type_failure(ifp->name);
1924 0 : rip_peer_bad_packet(rip, &from);
1925 0 : return;
1926 : }
1927 :
1928 : /* First RTE must be an Authentication Family RTE */
1929 0 : if (packet->rte->family != htons(RIP_FAMILY_AUTH)) {
1930 0 : if (IS_RIP_DEBUG_PACKET)
1931 0 : zlog_debug(
1932 : "RIPv2 dropped because authentication enabled");
1933 0 : ripd_notif_send_auth_type_failure(ifp->name);
1934 0 : rip_peer_bad_packet(rip, &from);
1935 0 : return;
1936 : }
1937 :
1938 : /* Check RIPv2 authentication. */
1939 0 : switch (ntohs(packet->rte->tag)) {
1940 0 : case RIP_AUTH_SIMPLE_PASSWORD:
1941 0 : auth_desc = "simple";
1942 0 : ret = rip_auth_simple_password(packet->rte, &from, ifp);
1943 0 : break;
1944 :
1945 0 : case RIP_AUTH_MD5:
1946 0 : auth_desc = "MD5";
1947 0 : ret = rip_auth_md5(packet, &from, len, ifp);
1948 : /* Reset RIP packet length to trim MD5 data. */
1949 0 : len = ret;
1950 0 : break;
1951 :
1952 0 : default:
1953 0 : ret = 0;
1954 0 : auth_desc = "unknown type";
1955 0 : if (IS_RIP_DEBUG_PACKET)
1956 0 : zlog_debug(
1957 : "RIPv2 Unknown authentication type %d",
1958 : ntohs(packet->rte->tag));
1959 : }
1960 :
1961 0 : if (ret) {
1962 0 : if (IS_RIP_DEBUG_PACKET)
1963 0 : zlog_debug("RIPv2 %s authentication success",
1964 : auth_desc);
1965 : } else {
1966 0 : if (IS_RIP_DEBUG_PACKET)
1967 0 : zlog_debug("RIPv2 %s authentication failure",
1968 : auth_desc);
1969 0 : ripd_notif_send_auth_failure(ifp->name);
1970 0 : rip_peer_bad_packet(rip, &from);
1971 0 : return;
1972 : }
1973 : }
1974 :
1975 : /* Process each command. */
1976 9 : switch (packet->command) {
1977 7 : case RIP_RESPONSE:
1978 7 : rip_response_process(packet, len, &from, ifc);
1979 7 : break;
1980 2 : case RIP_REQUEST:
1981 : case RIP_POLL:
1982 2 : rip_request_process(packet, len, &from, ifc);
1983 2 : break;
1984 0 : case RIP_TRACEON:
1985 : case RIP_TRACEOFF:
1986 0 : zlog_info(
1987 : "Obsolete command %s received, please sent it to routed",
1988 : lookup_msg(rip_msg, packet->command, NULL));
1989 0 : rip_peer_bad_packet(rip, &from);
1990 0 : break;
1991 0 : case RIP_POLL_ENTRY:
1992 0 : zlog_info("Obsolete command %s received",
1993 : lookup_msg(rip_msg, packet->command, NULL));
1994 0 : rip_peer_bad_packet(rip, &from);
1995 0 : break;
1996 0 : default:
1997 0 : zlog_info("Unknown RIP command %d received", packet->command);
1998 0 : rip_peer_bad_packet(rip, &from);
1999 0 : break;
2000 : }
2001 : }
2002 :
2003 : /* Write routing table entry to the stream and return next index of
2004 : the routing table entry in the stream. */
2005 17 : static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p,
2006 : uint8_t version, struct rip_info *rinfo)
2007 : {
2008 17 : struct in_addr mask;
2009 :
2010 : /* Write routing table entry. */
2011 17 : if (version == RIPv1) {
2012 0 : stream_putw(s, AF_INET);
2013 0 : stream_putw(s, 0);
2014 0 : stream_put_ipv4(s, p->prefix.s_addr);
2015 0 : stream_put_ipv4(s, 0);
2016 0 : stream_put_ipv4(s, 0);
2017 0 : stream_putl(s, rinfo->metric_out);
2018 : } else {
2019 17 : masklen2ip(p->prefixlen, &mask);
2020 :
2021 17 : stream_putw(s, AF_INET);
2022 17 : stream_putw(s, rinfo->tag_out);
2023 17 : stream_put_ipv4(s, p->prefix.s_addr);
2024 17 : stream_put_ipv4(s, mask.s_addr);
2025 17 : stream_put_ipv4(s, rinfo->nexthop_out.s_addr);
2026 17 : stream_putl(s, rinfo->metric_out);
2027 : }
2028 :
2029 17 : return ++num;
2030 : }
2031 :
2032 : /* Send update to the ifp or spcified neighbor. */
2033 7 : void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
2034 : int route_type, uint8_t version)
2035 : {
2036 7 : struct rip *rip;
2037 7 : int ret;
2038 7 : struct stream *s;
2039 7 : struct route_node *rp;
2040 7 : struct rip_info *rinfo;
2041 7 : struct rip_interface *ri;
2042 7 : struct prefix_ipv4 *p;
2043 7 : struct prefix_ipv4 classfull;
2044 7 : struct prefix_ipv4 ifaddrclass;
2045 7 : struct key *key = NULL;
2046 : /* this might need to made dynamic if RIP ever supported auth methods
2047 : with larger key string sizes */
2048 7 : char auth_str[RIP_AUTH_SIMPLE_SIZE];
2049 7 : size_t doff = 0; /* offset of digest offset field */
2050 7 : int num = 0;
2051 7 : int rtemax;
2052 7 : int subnetted = 0;
2053 7 : struct list *list = NULL;
2054 7 : struct listnode *listnode = NULL;
2055 :
2056 : /* Logging output event. */
2057 7 : if (IS_RIP_DEBUG_EVENT) {
2058 0 : if (to)
2059 0 : zlog_debug("update routes to neighbor %pI4",
2060 : &to->sin_addr);
2061 : else
2062 0 : zlog_debug("update routes on interface %s ifindex %d",
2063 : ifc->ifp->name, ifc->ifp->ifindex);
2064 : }
2065 :
2066 : /* Get RIP interface. */
2067 7 : ri = ifc->ifp->info;
2068 7 : rip = ri->rip;
2069 :
2070 : /* Set output stream. */
2071 7 : s = rip->obuf;
2072 :
2073 : /* Reset stream and RTE counter. */
2074 7 : stream_reset(s);
2075 7 : rtemax = RIP_MAX_RTE;
2076 :
2077 : /* If output interface is in simple password authentication mode, we
2078 : need space for authentication data. */
2079 7 : if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2080 0 : rtemax -= 1;
2081 :
2082 : /* If output interface is in MD5 authentication mode, we need space
2083 : for authentication header and data. */
2084 7 : if (ri->auth_type == RIP_AUTH_MD5)
2085 0 : rtemax -= 2;
2086 :
2087 : /* If output interface is in simple password authentication mode
2088 : and string or keychain is specified we need space for auth. data */
2089 7 : if (ri->auth_type != RIP_NO_AUTH) {
2090 0 : if (ri->key_chain) {
2091 0 : struct keychain *keychain;
2092 :
2093 0 : keychain = keychain_lookup(ri->key_chain);
2094 0 : if (keychain)
2095 0 : key = key_lookup_for_send(keychain);
2096 : }
2097 : /* to be passed to auth functions later */
2098 0 : rip_auth_prepare_str_send(ri, key, auth_str, sizeof(auth_str));
2099 0 : if (strlen(auth_str) == 0)
2100 0 : return;
2101 : }
2102 :
2103 7 : if (version == RIPv1) {
2104 0 : memcpy(&ifaddrclass, ifc->address, sizeof(ifaddrclass));
2105 0 : apply_classful_mask_ipv4(&ifaddrclass);
2106 0 : subnetted = 0;
2107 0 : if (ifc->address->prefixlen > ifaddrclass.prefixlen)
2108 7 : subnetted = 1;
2109 : }
2110 :
2111 66 : for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
2112 59 : list = rp->info;
2113 :
2114 59 : if (list == NULL)
2115 26 : continue;
2116 :
2117 33 : if (listcount(list) == 0)
2118 0 : continue;
2119 :
2120 33 : rinfo = listgetdata(listhead(list));
2121 : /*
2122 : * For RIPv1, if we are subnetted, output subnets in our
2123 : * network that have the same mask as the output "interface".
2124 : * For other networks, only the classfull version is output.
2125 : */
2126 33 : if (version == RIPv1) {
2127 0 : p = (struct prefix_ipv4 *)&rp->p;
2128 :
2129 0 : if (IS_RIP_DEBUG_PACKET)
2130 0 : zlog_debug(
2131 : "RIPv1 mask check, %pFX considered for output",
2132 : &rp->p);
2133 :
2134 0 : if (subnetted &&
2135 0 : prefix_match((struct prefix *)&ifaddrclass,
2136 : &rp->p)) {
2137 0 : if ((ifc->address->prefixlen !=
2138 0 : rp->p.prefixlen) &&
2139 : (rp->p.prefixlen != IPV4_MAX_BITLEN))
2140 0 : continue;
2141 : } else {
2142 0 : memcpy(&classfull, &rp->p,
2143 : sizeof(struct prefix_ipv4));
2144 0 : apply_classful_mask_ipv4(&classfull);
2145 0 : if (rp->p.u.prefix4.s_addr != INADDR_ANY &&
2146 0 : classfull.prefixlen != rp->p.prefixlen)
2147 0 : continue;
2148 : }
2149 0 : if (IS_RIP_DEBUG_PACKET)
2150 0 : zlog_debug(
2151 : "RIPv1 mask check, %pFX made it through",
2152 : &rp->p);
2153 : } else
2154 33 : p = (struct prefix_ipv4 *)&rp->p;
2155 :
2156 : /* Apply output filters. */
2157 33 : ret = rip_filter(RIP_FILTER_OUT, p, ri);
2158 33 : if (ret < 0)
2159 0 : continue;
2160 :
2161 : /* Changed route only output. */
2162 33 : if (route_type == rip_changed_route &&
2163 12 : (!(rinfo->flags & RIP_RTF_CHANGED)))
2164 0 : continue;
2165 :
2166 : /* Split horizon. */
2167 33 : if (ri->split_horizon == RIP_SPLIT_HORIZON) {
2168 : /*
2169 : * We perform split horizon for RIP and connected
2170 : * route. For rip routes, we want to suppress the
2171 : * route if we would end up sending the route back on
2172 : * the interface that we learned it from, with a
2173 : * higher metric. For connected routes, we suppress
2174 : * the route if the prefix is a subset of the source
2175 : * address that we are going to use for the packet
2176 : * (in order to handle the case when multiple subnets
2177 : * are configured on the same interface).
2178 : */
2179 33 : int suppress = 0;
2180 33 : struct rip_info *tmp_rinfo = NULL;
2181 33 : struct connected *tmp_ifc = NULL;
2182 :
2183 57 : for (ALL_LIST_ELEMENTS_RO(list, listnode, tmp_rinfo))
2184 33 : if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2185 17 : tmp_rinfo->nh.ifindex ==
2186 17 : ifc->ifp->ifindex) {
2187 : suppress = 1;
2188 : break;
2189 : }
2190 :
2191 33 : if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT) {
2192 46 : for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected,
2193 : listnode, tmp_ifc))
2194 23 : if (prefix_match((struct prefix *)p,
2195 23 : tmp_ifc->address)) {
2196 : suppress = 1;
2197 : break;
2198 : }
2199 : }
2200 :
2201 24 : if (suppress)
2202 16 : continue;
2203 : }
2204 :
2205 : /* Preparation for route-map. */
2206 17 : rinfo->metric_set = 0;
2207 17 : rinfo->nexthop_out.s_addr = 0;
2208 17 : rinfo->metric_out = rinfo->metric;
2209 17 : rinfo->tag_out = rinfo->tag;
2210 17 : rinfo->ifindex_out = ifc->ifp->ifindex;
2211 :
2212 : /* In order to avoid some local loops, if the RIP route has
2213 : * a nexthop via this interface, keep the nexthop, otherwise
2214 : * set it to 0. The nexthop should not be propagated beyond
2215 : * the local broadcast/multicast area in order to avoid an
2216 : * IGP multi-level recursive look-up. see (4.4)
2217 : */
2218 17 : if (rinfo->nh.ifindex == ifc->ifp->ifindex)
2219 0 : rinfo->nexthop_out = rinfo->nh.gate.ipv4;
2220 :
2221 : /* Interface route-map */
2222 17 : if (ri->routemap[RIP_FILTER_OUT]) {
2223 0 : ret = route_map_apply(ri->routemap[RIP_FILTER_OUT],
2224 : (struct prefix *)p, rinfo);
2225 :
2226 0 : if (ret == RMAP_DENYMATCH) {
2227 0 : if (IS_RIP_DEBUG_PACKET)
2228 0 : zlog_debug(
2229 : "RIP %pFX is filtered by route-map out",
2230 : p);
2231 0 : continue;
2232 : }
2233 : }
2234 :
2235 : /* Apply redistribute route map - continue, if deny */
2236 17 : if (rip->redist[rinfo->type].route_map.name &&
2237 0 : rinfo->sub_type != RIP_ROUTE_INTERFACE) {
2238 0 : ret = route_map_apply(
2239 : rip->redist[rinfo->type].route_map.map,
2240 : (struct prefix *)p, rinfo);
2241 :
2242 0 : if (ret == RMAP_DENYMATCH) {
2243 0 : if (IS_RIP_DEBUG_PACKET)
2244 0 : zlog_debug(
2245 : "%pFX is filtered by route-map",
2246 : p);
2247 0 : continue;
2248 : }
2249 : }
2250 :
2251 : /* When route-map does not set metric. */
2252 17 : if (!rinfo->metric_set) {
2253 : /* If redistribute metric is set. */
2254 17 : if (rip->redist[rinfo->type].metric_config &&
2255 0 : rinfo->metric != RIP_METRIC_INFINITY) {
2256 0 : rinfo->metric_out =
2257 0 : rip->redist[rinfo->type].metric;
2258 : } else {
2259 : /* If the route is not connected or localy
2260 : * generated one, use default-metric value
2261 : */
2262 17 : if (rinfo->type != ZEBRA_ROUTE_RIP &&
2263 1 : rinfo->type != ZEBRA_ROUTE_CONNECT &&
2264 1 : rinfo->metric != RIP_METRIC_INFINITY)
2265 1 : rinfo->metric_out = rip->default_metric;
2266 : }
2267 : }
2268 :
2269 : /* Apply offset-list */
2270 17 : if (rinfo->metric != RIP_METRIC_INFINITY)
2271 17 : rip_offset_list_apply_out(p, ifc->ifp,
2272 : &rinfo->metric_out);
2273 :
2274 17 : if (rinfo->metric_out > RIP_METRIC_INFINITY)
2275 0 : rinfo->metric_out = RIP_METRIC_INFINITY;
2276 :
2277 : /* Perform split-horizon with poisoned reverse
2278 : * for RIP and connected routes.
2279 : **/
2280 17 : if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
2281 : /*
2282 : * We perform split horizon for RIP and connected
2283 : * route. For rip routes, we want to suppress the
2284 : * route if we would end up sending the route back
2285 : * on the interface that we learned it from, with a
2286 : * higher metric. For connected routes, we suppress
2287 : * the route if the prefix is a subset of the source
2288 : * address that we are going to use for the packet
2289 : * (in order to handle the case when multiple
2290 : * subnets are configured on the same interface).
2291 : */
2292 0 : struct rip_info *tmp_rinfo = NULL;
2293 0 : struct connected *tmp_ifc = NULL;
2294 :
2295 0 : for (ALL_LIST_ELEMENTS_RO(list, listnode, tmp_rinfo))
2296 0 : if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2297 0 : tmp_rinfo->nh.ifindex == ifc->ifp->ifindex)
2298 0 : rinfo->metric_out = RIP_METRIC_INFINITY;
2299 :
2300 0 : if (rinfo->metric_out != RIP_METRIC_INFINITY &&
2301 0 : rinfo->type == ZEBRA_ROUTE_CONNECT) {
2302 0 : for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected,
2303 : listnode, tmp_ifc))
2304 0 : if (prefix_match((struct prefix *)p,
2305 0 : tmp_ifc->address)) {
2306 0 : rinfo->metric_out =
2307 : RIP_METRIC_INFINITY;
2308 0 : break;
2309 : }
2310 : }
2311 : }
2312 :
2313 : /* Prepare preamble, auth headers, if needs be */
2314 17 : if (num == 0) {
2315 7 : stream_putc(s, RIP_RESPONSE);
2316 7 : stream_putc(s, version);
2317 7 : stream_putw(s, 0);
2318 :
2319 : /* auth header for !v1 && !no_auth */
2320 7 : if ((ri->auth_type != RIP_NO_AUTH) &&
2321 : (version != RIPv1))
2322 0 : doff = rip_auth_header_write(
2323 : s, ri, key, auth_str,
2324 : RIP_AUTH_SIMPLE_SIZE);
2325 : }
2326 :
2327 : /* Write RTE to the stream. */
2328 17 : num = rip_write_rte(num, s, p, version, rinfo);
2329 17 : if (num == rtemax) {
2330 0 : if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2331 0 : rip_auth_md5_set(s, ri, doff, auth_str,
2332 : RIP_AUTH_SIMPLE_SIZE);
2333 :
2334 0 : ret = rip_send_packet(STREAM_DATA(s),
2335 0 : stream_get_endp(s), to, ifc);
2336 :
2337 0 : if (ret >= 0 && IS_RIP_DEBUG_SEND)
2338 0 : rip_packet_dump(
2339 : (struct rip_packet *)STREAM_DATA(s),
2340 0 : stream_get_endp(s), "SEND");
2341 0 : num = 0;
2342 0 : stream_reset(s);
2343 : }
2344 : }
2345 :
2346 : /* Flush unwritten RTE. */
2347 7 : if (num != 0) {
2348 7 : if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2349 0 : rip_auth_md5_set(s, ri, doff, auth_str,
2350 : RIP_AUTH_SIMPLE_SIZE);
2351 :
2352 7 : ret = rip_send_packet(STREAM_DATA(s), stream_get_endp(s), to,
2353 : ifc);
2354 :
2355 7 : if (ret >= 0 && IS_RIP_DEBUG_SEND)
2356 0 : rip_packet_dump((struct rip_packet *)STREAM_DATA(s),
2357 0 : stream_get_endp(s), "SEND");
2358 7 : stream_reset(s);
2359 : }
2360 :
2361 : /* Statistics updates. */
2362 7 : ri->sent_updates++;
2363 : }
2364 :
2365 : /* Send RIP packet to the interface. */
2366 5 : static void rip_update_interface(struct connected *ifc, uint8_t version,
2367 : int route_type)
2368 : {
2369 5 : struct interface *ifp = ifc->ifp;
2370 5 : struct rip_interface *ri = ifp->info;
2371 5 : struct sockaddr_in to;
2372 :
2373 : /* When RIP version is 2 and multicast enable interface. */
2374 5 : if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast(ifp)) {
2375 5 : if (IS_RIP_DEBUG_EVENT)
2376 0 : zlog_debug("multicast announce on %s ", ifp->name);
2377 :
2378 5 : rip_output_process(ifc, NULL, route_type, version);
2379 10 : return;
2380 : }
2381 :
2382 : /* If we can't send multicast packet, send it with unicast. */
2383 0 : if (if_is_broadcast(ifp) || if_is_pointopoint(ifp)) {
2384 0 : if (ifc->address->family == AF_INET) {
2385 : /* Destination address and port setting. */
2386 0 : memset(&to, 0, sizeof(to));
2387 0 : if (ifc->destination)
2388 : /* use specified broadcast or peer destination
2389 : * addr */
2390 0 : to.sin_addr = ifc->destination->u.prefix4;
2391 0 : else if (ifc->address->prefixlen < IPV4_MAX_BITLEN)
2392 : /* calculate the appropriate broadcast address
2393 : */
2394 0 : to.sin_addr.s_addr = ipv4_broadcast_addr(
2395 : ifc->address->u.prefix4.s_addr,
2396 : ifc->address->prefixlen);
2397 : else
2398 : /* do not know where to send the packet */
2399 : return;
2400 0 : to.sin_port = htons(RIP_PORT_DEFAULT);
2401 :
2402 0 : if (IS_RIP_DEBUG_EVENT)
2403 0 : zlog_debug("%s announce to %pI4 on %s",
2404 : CONNECTED_PEER(ifc) ? "unicast"
2405 : : "broadcast",
2406 : &to.sin_addr, ifp->name);
2407 :
2408 0 : rip_output_process(ifc, &to, route_type, version);
2409 : }
2410 : }
2411 : }
2412 :
2413 : /* Update send to all interface and neighbor. */
2414 9 : static void rip_update_process(struct rip *rip, int route_type)
2415 : {
2416 9 : struct listnode *ifnode, *ifnnode;
2417 9 : struct connected *connected;
2418 9 : struct interface *ifp;
2419 9 : struct rip_interface *ri;
2420 9 : struct route_node *rp;
2421 9 : struct sockaddr_in to;
2422 9 : struct prefix *p;
2423 :
2424 : /* Send RIP update to each interface. */
2425 50 : FOR_ALL_INTERFACES (rip->vrf, ifp) {
2426 32 : if (if_is_loopback(ifp))
2427 9 : continue;
2428 :
2429 23 : if (!if_is_operative(ifp))
2430 3 : continue;
2431 :
2432 : /* Fetch RIP interface information. */
2433 20 : ri = ifp->info;
2434 :
2435 : /* When passive interface is specified, suppress announce to the
2436 : interface. */
2437 20 : if (ri->passive)
2438 1 : continue;
2439 :
2440 19 : if (!ri->running)
2441 14 : continue;
2442 :
2443 : /*
2444 : * If there is no version configuration in the
2445 : * interface, use rip's version setting.
2446 : */
2447 10 : int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send
2448 5 : : ri->ri_send);
2449 :
2450 5 : if (IS_RIP_DEBUG_EVENT)
2451 0 : zlog_debug("SEND UPDATE to %s ifindex %d", ifp->name,
2452 : ifp->ifindex);
2453 :
2454 : /* send update on each connected network */
2455 20 : for (ALL_LIST_ELEMENTS(ifp->connected, ifnode, ifnnode,
2456 : connected)) {
2457 10 : if (connected->address->family == AF_INET) {
2458 5 : if (vsend & RIPv1)
2459 0 : rip_update_interface(connected, RIPv1,
2460 : route_type);
2461 5 : if ((vsend & RIPv2) && if_is_multicast(ifp))
2462 5 : rip_update_interface(connected, RIPv2,
2463 : route_type);
2464 : }
2465 : }
2466 : }
2467 :
2468 : /* RIP send updates to each neighbor. */
2469 9 : for (rp = route_top(rip->neighbor); rp; rp = route_next(rp)) {
2470 0 : if (rp->info == NULL)
2471 0 : continue;
2472 :
2473 0 : p = &rp->p;
2474 :
2475 0 : connected = if_lookup_address(&p->u.prefix4, AF_INET,
2476 0 : rip->vrf->vrf_id);
2477 0 : if (!connected) {
2478 0 : zlog_warn(
2479 : "Neighbor %pI4 doesn't have connected interface!",
2480 : &p->u.prefix4);
2481 0 : continue;
2482 : }
2483 :
2484 : /* Set destination address and port */
2485 0 : memset(&to, 0, sizeof(struct sockaddr_in));
2486 0 : to.sin_addr = p->u.prefix4;
2487 0 : to.sin_port = htons(RIP_PORT_DEFAULT);
2488 :
2489 : /* RIP version is rip's configuration. */
2490 0 : rip_output_process(connected, &to, route_type,
2491 0 : rip->version_send);
2492 : }
2493 9 : }
2494 :
2495 : /* RIP's periodical timer. */
2496 2 : static void rip_update(struct thread *t)
2497 : {
2498 2 : struct rip *rip = THREAD_ARG(t);
2499 :
2500 2 : if (IS_RIP_DEBUG_EVENT)
2501 0 : zlog_debug("update timer fire!");
2502 :
2503 : /* Process update output. */
2504 2 : rip_update_process(rip, rip_all_route);
2505 :
2506 : /* Triggered updates may be suppressed if a regular update is due by
2507 : the time the triggered update would be sent. */
2508 2 : THREAD_OFF(rip->t_triggered_interval);
2509 2 : rip->trigger = 0;
2510 :
2511 : /* Register myself. */
2512 2 : rip_event(rip, RIP_UPDATE_EVENT, 0);
2513 2 : }
2514 :
2515 : /* Walk down the RIP routing table then clear changed flag. */
2516 7 : static void rip_clear_changed_flag(struct rip *rip)
2517 : {
2518 7 : struct route_node *rp;
2519 7 : struct rip_info *rinfo = NULL;
2520 7 : struct list *list = NULL;
2521 7 : struct listnode *listnode = NULL;
2522 :
2523 32 : for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
2524 25 : list = rp->info;
2525 :
2526 25 : if (list == NULL)
2527 9 : continue;
2528 :
2529 16 : for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
2530 16 : UNSET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
2531 : /* This flag can be set only on the first entry. */
2532 16 : break;
2533 : }
2534 : }
2535 7 : }
2536 :
2537 : /* Triggered update interval timer. */
2538 2 : static void rip_triggered_interval(struct thread *t)
2539 : {
2540 2 : struct rip *rip = THREAD_ARG(t);
2541 :
2542 2 : if (rip->trigger) {
2543 2 : rip->trigger = 0;
2544 2 : rip_triggered_update(t);
2545 : }
2546 2 : }
2547 :
2548 : /* Execute triggered update. */
2549 7 : static void rip_triggered_update(struct thread *t)
2550 : {
2551 7 : struct rip *rip = THREAD_ARG(t);
2552 7 : int interval;
2553 :
2554 : /* Cancel interval timer. */
2555 7 : THREAD_OFF(rip->t_triggered_interval);
2556 7 : rip->trigger = 0;
2557 :
2558 : /* Logging triggered update. */
2559 7 : if (IS_RIP_DEBUG_EVENT)
2560 1 : zlog_debug("triggered update!");
2561 :
2562 : /* Split Horizon processing is done when generating triggered
2563 : updates as well as normal updates (see section 2.6). */
2564 7 : rip_update_process(rip, rip_changed_route);
2565 :
2566 : /* Once all of the triggered updates have been generated, the route
2567 : change flags should be cleared. */
2568 7 : rip_clear_changed_flag(rip);
2569 :
2570 : /* After a triggered update is sent, a timer should be set for a
2571 : random interval between 1 and 5 seconds. If other changes that
2572 : would trigger updates occur before the timer expires, a single
2573 : update is triggered when the timer expires. */
2574 7 : interval = (frr_weak_random() % 5) + 1;
2575 :
2576 7 : thread_add_timer(master, rip_triggered_interval, rip, interval,
2577 : &rip->t_triggered_interval);
2578 7 : }
2579 :
2580 : /* Withdraw redistributed route. */
2581 0 : void rip_redistribute_withdraw(struct rip *rip, int type)
2582 : {
2583 0 : struct route_node *rp;
2584 0 : struct rip_info *rinfo = NULL;
2585 0 : struct list *list = NULL;
2586 :
2587 0 : for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
2588 0 : list = rp->info;
2589 :
2590 0 : if (list == NULL)
2591 0 : continue;
2592 :
2593 0 : rinfo = listgetdata(listhead(list));
2594 :
2595 0 : if (rinfo->type != type)
2596 0 : continue;
2597 :
2598 0 : if (rinfo->sub_type == RIP_ROUTE_INTERFACE)
2599 0 : continue;
2600 :
2601 : /* Perform poisoned reverse. */
2602 0 : rinfo->metric = RIP_METRIC_INFINITY;
2603 0 : RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect,
2604 : rip->garbage_time);
2605 0 : THREAD_OFF(rinfo->t_timeout);
2606 0 : rinfo->flags |= RIP_RTF_CHANGED;
2607 :
2608 0 : if (IS_RIP_DEBUG_EVENT) {
2609 0 : struct prefix_ipv4 *p = (struct prefix_ipv4 *)&rp->p;
2610 :
2611 0 : zlog_debug(
2612 : "Poisone %pFX on the interface %s with an infinity metric [withdraw]",
2613 : p,
2614 : ifindex2ifname(rinfo->nh.ifindex,
2615 : rip->vrf->vrf_id));
2616 : }
2617 :
2618 0 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
2619 : }
2620 0 : }
2621 :
2622 11 : struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id)
2623 : {
2624 11 : struct vrf *vrf;
2625 :
2626 11 : vrf = vrf_lookup_by_id(vrf_id);
2627 11 : if (!vrf)
2628 : return NULL;
2629 :
2630 11 : return vrf->info;
2631 : }
2632 :
2633 59 : struct rip *rip_lookup_by_vrf_name(const char *vrf_name)
2634 : {
2635 59 : struct rip rip;
2636 :
2637 59 : rip.vrf_name = (char *)vrf_name;
2638 :
2639 59 : return RB_FIND(rip_instance_head, &rip_instances, &rip);
2640 : }
2641 :
2642 : /* Create new RIP instance and set it to global variable. */
2643 5 : struct rip *rip_create(const char *vrf_name, struct vrf *vrf, int socket)
2644 : {
2645 5 : struct rip *rip;
2646 :
2647 5 : rip = XCALLOC(MTYPE_RIP, sizeof(struct rip));
2648 5 : rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf_name);
2649 :
2650 : /* Set initial value. */
2651 5 : rip->ecmp = yang_get_default_bool("%s/allow-ecmp", RIP_INSTANCE);
2652 10 : rip->default_metric =
2653 5 : yang_get_default_uint8("%s/default-metric", RIP_INSTANCE);
2654 10 : rip->distance =
2655 5 : yang_get_default_uint8("%s/distance/default", RIP_INSTANCE);
2656 10 : rip->passive_default =
2657 5 : yang_get_default_bool("%s/passive-default", RIP_INSTANCE);
2658 5 : rip->garbage_time = yang_get_default_uint32("%s/timers/flush-interval",
2659 : RIP_INSTANCE);
2660 5 : rip->timeout_time = yang_get_default_uint32(
2661 : "%s/timers/holddown-interval", RIP_INSTANCE);
2662 5 : rip->update_time = yang_get_default_uint32("%s/timers/update-interval",
2663 : RIP_INSTANCE);
2664 10 : rip->version_send =
2665 5 : yang_get_default_enum("%s/version/send", RIP_INSTANCE);
2666 10 : rip->version_recv =
2667 5 : yang_get_default_enum("%s/version/receive", RIP_INSTANCE);
2668 :
2669 : /* Initialize RIP data structures. */
2670 5 : rip->table = route_table_init();
2671 5 : route_table_set_info(rip->table, rip);
2672 5 : rip->neighbor = route_table_init();
2673 5 : rip->peer_list = list_new();
2674 5 : rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
2675 5 : rip->peer_list->del = rip_peer_list_del;
2676 5 : rip->distance_table = route_table_init();
2677 5 : rip->distance_table->cleanup = rip_distance_table_node_cleanup;
2678 5 : rip->enable_interface = vector_init(1);
2679 5 : rip->enable_network = route_table_init();
2680 5 : rip->passive_nondefault = vector_init(1);
2681 5 : rip->offset_list_master = list_new();
2682 5 : rip->offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
2683 5 : rip->offset_list_master->del = (void (*)(void *))offset_list_free;
2684 :
2685 : /* Distribute list install. */
2686 5 : rip->distribute_ctx = distribute_list_ctx_create(vrf);
2687 5 : distribute_list_add_hook(rip->distribute_ctx, rip_distribute_update);
2688 5 : distribute_list_delete_hook(rip->distribute_ctx, rip_distribute_update);
2689 :
2690 : /* if rmap install. */
2691 5 : rip->if_rmap_ctx = if_rmap_ctx_create(vrf_name);
2692 5 : if_rmap_hook_add(rip->if_rmap_ctx, rip_if_rmap_update);
2693 5 : if_rmap_hook_delete(rip->if_rmap_ctx, rip_if_rmap_update);
2694 :
2695 : /* Make output stream. */
2696 5 : rip->obuf = stream_new(1500);
2697 :
2698 : /* Enable the routing instance if possible. */
2699 5 : if (vrf && vrf_is_enabled(vrf))
2700 5 : rip_instance_enable(rip, vrf, socket);
2701 : else {
2702 0 : rip->vrf = NULL;
2703 0 : rip->sock = -1;
2704 : }
2705 :
2706 5 : RB_INSERT(rip_instance_head, &rip_instances, rip);
2707 :
2708 5 : return rip;
2709 : }
2710 :
2711 : /* Sned RIP request to the destination. */
2712 7 : int rip_request_send(struct sockaddr_in *to, struct interface *ifp,
2713 : uint8_t version, struct connected *connected)
2714 : {
2715 7 : struct rte *rte;
2716 7 : struct rip_packet rip_packet;
2717 7 : struct listnode *node, *nnode;
2718 :
2719 7 : memset(&rip_packet, 0, sizeof(rip_packet));
2720 :
2721 7 : rip_packet.command = RIP_REQUEST;
2722 7 : rip_packet.version = version;
2723 7 : rte = rip_packet.rte;
2724 7 : rte->metric = htonl(RIP_METRIC_INFINITY);
2725 :
2726 7 : if (connected) {
2727 : /*
2728 : * connected is only sent for ripv1 case, or when
2729 : * interface does not support multicast. Caller loops
2730 : * over each connected address for this case.
2731 : */
2732 0 : if (rip_send_packet((uint8_t *)&rip_packet, sizeof(rip_packet),
2733 : to, connected)
2734 : != sizeof(rip_packet))
2735 : return -1;
2736 : else
2737 : return sizeof(rip_packet);
2738 : }
2739 :
2740 : /* send request on each connected network */
2741 27 : for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
2742 13 : struct prefix_ipv4 *p;
2743 :
2744 13 : p = (struct prefix_ipv4 *)connected->address;
2745 :
2746 13 : if (p->family != AF_INET)
2747 6 : continue;
2748 :
2749 7 : if (rip_send_packet((uint8_t *)&rip_packet, sizeof(rip_packet),
2750 : to, connected)
2751 : != sizeof(rip_packet))
2752 : return -1;
2753 : }
2754 : return sizeof(rip_packet);
2755 : }
2756 :
2757 11 : static int rip_update_jitter(unsigned long time)
2758 : {
2759 : #define JITTER_BOUND 4
2760 : /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2761 : Given that, we cannot let time be less than JITTER_BOUND seconds.
2762 : The RIPv2 RFC says jitter should be small compared to
2763 : update_time. We consider 1/JITTER_BOUND to be small.
2764 : */
2765 :
2766 11 : int jitter_input = time;
2767 11 : int jitter;
2768 :
2769 11 : if (jitter_input < JITTER_BOUND)
2770 : jitter_input = JITTER_BOUND;
2771 :
2772 11 : jitter = (((frr_weak_random() % ((jitter_input * 2) + 1))
2773 11 : - jitter_input));
2774 :
2775 11 : return jitter / JITTER_BOUND;
2776 : }
2777 :
2778 86 : void rip_event(struct rip *rip, enum rip_event event, int sock)
2779 : {
2780 86 : int jitter = 0;
2781 :
2782 86 : switch (event) {
2783 14 : case RIP_READ:
2784 14 : thread_add_read(master, rip_read, rip, sock, &rip->t_read);
2785 14 : break;
2786 11 : case RIP_UPDATE_EVENT:
2787 11 : THREAD_OFF(rip->t_update);
2788 11 : jitter = rip_update_jitter(rip->update_time);
2789 11 : thread_add_timer(master, rip_update, rip,
2790 : sock ? 2 : rip->update_time + jitter,
2791 : &rip->t_update);
2792 11 : break;
2793 61 : case RIP_TRIGGERED_UPDATE:
2794 61 : if (rip->t_triggered_interval)
2795 51 : rip->trigger = 1;
2796 : else
2797 10 : thread_add_event(master, rip_triggered_update, rip, 0,
2798 : &rip->t_triggered_update);
2799 : break;
2800 : default:
2801 : break;
2802 : }
2803 86 : }
2804 :
2805 0 : struct rip_distance *rip_distance_new(void)
2806 : {
2807 0 : return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance));
2808 : }
2809 :
2810 0 : void rip_distance_free(struct rip_distance *rdistance)
2811 : {
2812 0 : if (rdistance->access_list)
2813 0 : free(rdistance->access_list);
2814 0 : XFREE(MTYPE_RIP_DISTANCE, rdistance);
2815 0 : }
2816 :
2817 0 : static void rip_distance_table_node_cleanup(struct route_table *table,
2818 : struct route_node *node)
2819 : {
2820 0 : struct rip_distance *rdistance;
2821 :
2822 0 : rdistance = node->info;
2823 0 : if (rdistance)
2824 0 : rip_distance_free(rdistance);
2825 0 : }
2826 :
2827 : /* Apply RIP information to distance method. */
2828 17 : uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo)
2829 : {
2830 17 : struct route_node *rn;
2831 17 : struct prefix_ipv4 p;
2832 17 : struct rip_distance *rdistance;
2833 17 : struct access_list *alist;
2834 :
2835 17 : memset(&p, 0, sizeof(p));
2836 17 : p.family = AF_INET;
2837 17 : p.prefix = rinfo->from;
2838 17 : p.prefixlen = IPV4_MAX_BITLEN;
2839 :
2840 : /* Check source address. */
2841 17 : rn = route_node_match(rip->distance_table, (struct prefix *)&p);
2842 17 : if (rn) {
2843 0 : rdistance = rn->info;
2844 0 : route_unlock_node(rn);
2845 :
2846 0 : if (rdistance->access_list) {
2847 0 : alist = access_list_lookup(AFI_IP,
2848 : rdistance->access_list);
2849 0 : if (alist == NULL)
2850 : return 0;
2851 0 : if (access_list_apply(alist, &rinfo->rp->p)
2852 : == FILTER_DENY)
2853 : return 0;
2854 :
2855 0 : return rdistance->distance;
2856 : } else
2857 0 : return rdistance->distance;
2858 : }
2859 :
2860 17 : if (rip->distance)
2861 : return rip->distance;
2862 :
2863 : return 0;
2864 : }
2865 :
2866 9 : static void rip_distance_show(struct vty *vty, struct rip *rip)
2867 : {
2868 9 : struct route_node *rn;
2869 9 : struct rip_distance *rdistance;
2870 9 : int header = 1;
2871 9 : char buf[BUFSIZ];
2872 :
2873 9 : vty_out(vty, " Distance: (default is %u)\n",
2874 9 : rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT);
2875 :
2876 9 : for (rn = route_top(rip->distance_table); rn; rn = route_next(rn)) {
2877 0 : rdistance = rn->info;
2878 :
2879 0 : if (rdistance == NULL)
2880 0 : continue;
2881 :
2882 0 : if (header) {
2883 0 : vty_out(vty, " Address Distance List\n");
2884 0 : header = 0;
2885 : }
2886 0 : snprintfrr(buf, sizeof(buf), "%pFX", &rn->p);
2887 0 : vty_out(vty, " %-20s %4d %s\n", buf, rdistance->distance,
2888 0 : rdistance->access_list ? rdistance->access_list : "");
2889 : }
2890 9 : }
2891 :
2892 : /* Update ECMP routes to zebra when ECMP is disabled. */
2893 0 : void rip_ecmp_disable(struct rip *rip)
2894 : {
2895 0 : struct route_node *rp;
2896 0 : struct rip_info *rinfo, *tmp_rinfo;
2897 0 : struct list *list;
2898 0 : struct listnode *node, *nextnode;
2899 :
2900 0 : for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
2901 0 : list = rp->info;
2902 :
2903 0 : if (!list)
2904 0 : continue;
2905 0 : if (listcount(list) == 0)
2906 0 : continue;
2907 :
2908 0 : rinfo = listgetdata(listhead(list));
2909 0 : if (!rip_route_rte(rinfo))
2910 0 : continue;
2911 :
2912 : /* Drop all other entries, except the first one. */
2913 0 : for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) {
2914 0 : if (tmp_rinfo == rinfo)
2915 0 : continue;
2916 :
2917 0 : THREAD_OFF(tmp_rinfo->t_timeout);
2918 0 : THREAD_OFF(tmp_rinfo->t_garbage_collect);
2919 0 : list_delete_node(list, node);
2920 0 : rip_info_free(tmp_rinfo);
2921 : }
2922 :
2923 : /* Update zebra. */
2924 0 : rip_zebra_ipv4_add(rip, rp);
2925 :
2926 : /* Set the route change flag. */
2927 0 : SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
2928 :
2929 : /* Signal the output process to trigger an update. */
2930 0 : rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
2931 : }
2932 0 : }
2933 :
2934 : /* Print out routes update time. */
2935 13 : static void rip_vty_out_uptime(struct vty *vty, struct rip_info *rinfo)
2936 : {
2937 13 : time_t clock;
2938 13 : struct tm tm;
2939 : #define TIME_BUF 25
2940 13 : char timebuf[TIME_BUF];
2941 13 : struct thread *thread;
2942 :
2943 13 : if ((thread = rinfo->t_timeout) != NULL) {
2944 13 : clock = thread_timer_remain_second(thread);
2945 13 : gmtime_r(&clock, &tm);
2946 13 : strftime(timebuf, TIME_BUF, "%M:%S", &tm);
2947 13 : vty_out(vty, "%5s", timebuf);
2948 0 : } else if ((thread = rinfo->t_garbage_collect) != NULL) {
2949 0 : clock = thread_timer_remain_second(thread);
2950 0 : gmtime_r(&clock, &tm);
2951 0 : strftime(timebuf, TIME_BUF, "%M:%S", &tm);
2952 0 : vty_out(vty, "%5s", timebuf);
2953 : }
2954 13 : }
2955 :
2956 117 : static const char *rip_route_type_print(int sub_type)
2957 : {
2958 117 : switch (sub_type) {
2959 : case RIP_ROUTE_RTE:
2960 : return "n";
2961 0 : case RIP_ROUTE_STATIC:
2962 0 : return "s";
2963 0 : case RIP_ROUTE_DEFAULT:
2964 0 : return "d";
2965 2 : case RIP_ROUTE_REDISTRIBUTE:
2966 2 : return "r";
2967 102 : case RIP_ROUTE_INTERFACE:
2968 102 : return "i";
2969 0 : default:
2970 0 : return "?";
2971 : }
2972 : }
2973 :
2974 35 : DEFUN (show_ip_rip,
2975 : show_ip_rip_cmd,
2976 : "show ip rip [vrf NAME]",
2977 : SHOW_STR
2978 : IP_STR
2979 : "Show RIP routes\n"
2980 : VRF_CMD_HELP_STR)
2981 : {
2982 35 : struct rip *rip;
2983 35 : struct route_node *np;
2984 35 : struct rip_info *rinfo = NULL;
2985 35 : struct list *list = NULL;
2986 35 : struct listnode *listnode = NULL;
2987 35 : const char *vrf_name;
2988 35 : int idx = 0;
2989 :
2990 35 : if (argv_find(argv, argc, "vrf", &idx))
2991 0 : vrf_name = argv[idx + 1]->arg;
2992 : else
2993 35 : vrf_name = VRF_DEFAULT_NAME;
2994 :
2995 35 : rip = rip_lookup_by_vrf_name(vrf_name);
2996 35 : if (!rip) {
2997 0 : vty_out(vty, "%% RIP instance not found\n");
2998 0 : return CMD_SUCCESS;
2999 : }
3000 35 : if (!rip->enabled) {
3001 0 : vty_out(vty, "%% RIP instance is disabled\n");
3002 0 : return CMD_SUCCESS;
3003 : }
3004 :
3005 35 : vty_out(vty,
3006 : "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n"
3007 : "Sub-codes:\n"
3008 : " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n"
3009 : " (i) - interface\n\n"
3010 : " Network Next Hop Metric From Tag Time\n");
3011 :
3012 234 : for (np = route_top(rip->table); np; np = route_next(np)) {
3013 199 : list = np->info;
3014 :
3015 199 : if (!list)
3016 82 : continue;
3017 :
3018 234 : for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
3019 117 : int len;
3020 :
3021 117 : len = vty_out(vty, "%c(%s) %pFX",
3022 : /* np->lock, For debugging. */
3023 117 : zebra_route_char(rinfo->type),
3024 : rip_route_type_print(rinfo->sub_type),
3025 : &np->p);
3026 :
3027 117 : len = 24 - len;
3028 :
3029 117 : if (len > 0)
3030 117 : vty_out(vty, "%*s", len, " ");
3031 :
3032 117 : switch (rinfo->nh.type) {
3033 14 : case NEXTHOP_TYPE_IPV4:
3034 : case NEXTHOP_TYPE_IPV4_IFINDEX:
3035 14 : vty_out(vty, "%-20pI4 %2d ",
3036 : &rinfo->nh.gate.ipv4, rinfo->metric);
3037 14 : break;
3038 103 : case NEXTHOP_TYPE_IFINDEX:
3039 103 : vty_out(vty, "0.0.0.0 %2d ",
3040 : rinfo->metric);
3041 103 : break;
3042 0 : case NEXTHOP_TYPE_BLACKHOLE:
3043 0 : vty_out(vty, "blackhole %2d ",
3044 : rinfo->metric);
3045 0 : break;
3046 0 : case NEXTHOP_TYPE_IPV6:
3047 : case NEXTHOP_TYPE_IPV6_IFINDEX:
3048 0 : vty_out(vty, "V6 Address Hidden %2d ",
3049 : rinfo->metric);
3050 0 : break;
3051 : }
3052 :
3053 : /* Route which exist in kernel routing table. */
3054 117 : if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3055 : (rinfo->sub_type == RIP_ROUTE_RTE)) {
3056 13 : vty_out(vty, "%-15pI4 ", &rinfo->from);
3057 13 : vty_out(vty, "%3" ROUTE_TAG_PRI " ",
3058 13 : (route_tag_t)rinfo->tag);
3059 13 : rip_vty_out_uptime(vty, rinfo);
3060 104 : } else if (rinfo->metric == RIP_METRIC_INFINITY) {
3061 0 : vty_out(vty, "self ");
3062 0 : vty_out(vty, "%3" ROUTE_TAG_PRI " ",
3063 0 : (route_tag_t)rinfo->tag);
3064 0 : rip_vty_out_uptime(vty, rinfo);
3065 : } else {
3066 104 : if (rinfo->external_metric) {
3067 0 : len = vty_out(
3068 : vty, "self (%s:%d)",
3069 0 : zebra_route_string(rinfo->type),
3070 : rinfo->external_metric);
3071 0 : len = 16 - len;
3072 0 : if (len > 0)
3073 0 : vty_out(vty, "%*s", len, " ");
3074 : } else
3075 104 : vty_out(vty, "self ");
3076 104 : vty_out(vty, "%3" ROUTE_TAG_PRI,
3077 104 : (route_tag_t)rinfo->tag);
3078 : }
3079 :
3080 117 : vty_out(vty, "\n");
3081 : }
3082 : }
3083 : return CMD_SUCCESS;
3084 : }
3085 :
3086 : /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3087 9 : DEFUN (show_ip_rip_status,
3088 : show_ip_rip_status_cmd,
3089 : "show ip rip [vrf NAME] status",
3090 : SHOW_STR
3091 : IP_STR
3092 : "Show RIP routes\n"
3093 : VRF_CMD_HELP_STR
3094 : "IP routing protocol process parameters and statistics\n")
3095 : {
3096 9 : struct rip *rip;
3097 9 : struct interface *ifp;
3098 9 : struct rip_interface *ri;
3099 9 : extern const struct message ri_version_msg[];
3100 9 : const char *send_version;
3101 9 : const char *receive_version;
3102 9 : const char *vrf_name;
3103 9 : int idx = 0;
3104 :
3105 9 : if (argv_find(argv, argc, "vrf", &idx))
3106 0 : vrf_name = argv[idx + 1]->arg;
3107 : else
3108 9 : vrf_name = VRF_DEFAULT_NAME;
3109 :
3110 9 : rip = rip_lookup_by_vrf_name(vrf_name);
3111 9 : if (!rip) {
3112 0 : vty_out(vty, "%% RIP instance not found\n");
3113 0 : return CMD_SUCCESS;
3114 : }
3115 9 : if (!rip->enabled) {
3116 0 : vty_out(vty, "%% RIP instance is disabled\n");
3117 0 : return CMD_SUCCESS;
3118 : }
3119 :
3120 9 : vty_out(vty, "Routing Protocol is \"rip\"\n");
3121 9 : vty_out(vty, " Sending updates every %u seconds with +/-50%%,",
3122 : rip->update_time);
3123 9 : vty_out(vty, " next due in %lu seconds\n",
3124 : thread_timer_remain_second(rip->t_update));
3125 9 : vty_out(vty, " Timeout after %u seconds,", rip->timeout_time);
3126 9 : vty_out(vty, " garbage collect after %u seconds\n", rip->garbage_time);
3127 :
3128 : /* Filtering status show. */
3129 9 : config_show_distribute(vty, rip->distribute_ctx);
3130 :
3131 : /* Default metric information. */
3132 9 : vty_out(vty, " Default redistribution metric is %u\n",
3133 9 : rip->default_metric);
3134 :
3135 : /* Redistribute information. */
3136 9 : vty_out(vty, " Redistributing:");
3137 9 : rip_show_redistribute_config(vty, rip);
3138 9 : vty_out(vty, "\n");
3139 :
3140 9 : vty_out(vty, " Default version control: send version %s,",
3141 : lookup_msg(ri_version_msg, rip->version_send, NULL));
3142 9 : if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3143 0 : vty_out(vty, " receive any version \n");
3144 : else
3145 9 : vty_out(vty, " receive version %s \n",
3146 : lookup_msg(ri_version_msg, rip->version_recv, NULL));
3147 :
3148 9 : vty_out(vty, " Interface Send Recv Key-chain\n");
3149 :
3150 56 : FOR_ALL_INTERFACES (rip->vrf, ifp) {
3151 38 : ri = ifp->info;
3152 :
3153 38 : if (!ri->running)
3154 25 : continue;
3155 :
3156 13 : if (ri->enable_network || ri->enable_interface) {
3157 13 : if (ri->ri_send == RI_RIP_UNSPEC)
3158 13 : send_version =
3159 13 : lookup_msg(ri_version_msg,
3160 : rip->version_send, NULL);
3161 : else
3162 0 : send_version = lookup_msg(ri_version_msg,
3163 : ri->ri_send, NULL);
3164 :
3165 13 : if (ri->ri_receive == RI_RIP_UNSPEC)
3166 13 : receive_version =
3167 13 : lookup_msg(ri_version_msg,
3168 : rip->version_recv, NULL);
3169 : else
3170 0 : receive_version = lookup_msg(
3171 : ri_version_msg, ri->ri_receive, NULL);
3172 :
3173 13 : vty_out(vty, " %-17s%-3s %-3s %s\n", ifp->name,
3174 : send_version, receive_version,
3175 13 : ri->key_chain ? ri->key_chain : "");
3176 : }
3177 : }
3178 :
3179 9 : vty_out(vty, " Routing for Networks:\n");
3180 9 : rip_show_network_config(vty, rip);
3181 :
3182 9 : int found_passive = 0;
3183 56 : FOR_ALL_INTERFACES (rip->vrf, ifp) {
3184 38 : ri = ifp->info;
3185 :
3186 38 : if ((ri->enable_network || ri->enable_interface) &&
3187 19 : ri->passive) {
3188 3 : if (!found_passive) {
3189 3 : vty_out(vty, " Passive Interface(s):\n");
3190 3 : found_passive = 1;
3191 : }
3192 3 : vty_out(vty, " %s\n", ifp->name);
3193 : }
3194 : }
3195 :
3196 9 : vty_out(vty, " Routing Information Sources:\n");
3197 9 : vty_out(vty,
3198 : " Gateway BadPackets BadRoutes Distance Last Update\n");
3199 9 : rip_peer_display(vty, rip);
3200 :
3201 9 : rip_distance_show(vty, rip);
3202 :
3203 9 : return CMD_SUCCESS;
3204 : }
3205 :
3206 : /* RIP configuration write function. */
3207 0 : static int config_write_rip(struct vty *vty)
3208 : {
3209 0 : struct rip *rip;
3210 0 : int write = 0;
3211 :
3212 0 : RB_FOREACH(rip, rip_instance_head, &rip_instances) {
3213 0 : char xpath[XPATH_MAXLEN];
3214 0 : struct lyd_node *dnode;
3215 :
3216 0 : snprintf(xpath, sizeof(xpath),
3217 : "/frr-ripd:ripd/instance[vrf='%s']", rip->vrf_name);
3218 :
3219 0 : dnode = yang_dnode_get(running_config->dnode, xpath);
3220 0 : assert(dnode);
3221 :
3222 0 : nb_cli_show_dnode_cmds(vty, dnode, false);
3223 :
3224 : /* Distribute configuration. */
3225 0 : config_write_distribute(vty, rip->distribute_ctx);
3226 :
3227 : /* Interface routemap configuration */
3228 0 : config_write_if_rmap(vty, rip->if_rmap_ctx);
3229 :
3230 0 : vty_out(vty, "exit\n");
3231 :
3232 0 : write = 1;
3233 : }
3234 :
3235 0 : return write;
3236 : }
3237 :
3238 : static int config_write_rip(struct vty *vty);
3239 : /* RIP node structure. */
3240 : static struct cmd_node rip_node = {
3241 : .name = "rip",
3242 : .node = RIP_NODE,
3243 : .parent_node = CONFIG_NODE,
3244 : .prompt = "%s(config-router)# ",
3245 : .config_write = config_write_rip,
3246 : };
3247 :
3248 : /* Distribute-list update functions. */
3249 0 : static void rip_distribute_update(struct distribute_ctx *ctx,
3250 : struct distribute *dist)
3251 : {
3252 0 : struct interface *ifp;
3253 0 : struct rip_interface *ri;
3254 0 : struct access_list *alist;
3255 0 : struct prefix_list *plist;
3256 :
3257 0 : if (!ctx->vrf || !dist->ifname)
3258 : return;
3259 :
3260 0 : ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id);
3261 0 : if (ifp == NULL)
3262 : return;
3263 :
3264 0 : ri = ifp->info;
3265 :
3266 0 : if (dist->list[DISTRIBUTE_V4_IN]) {
3267 0 : alist = access_list_lookup(AFI_IP,
3268 : dist->list[DISTRIBUTE_V4_IN]);
3269 0 : if (alist)
3270 0 : ri->list[RIP_FILTER_IN] = alist;
3271 : else
3272 0 : ri->list[RIP_FILTER_IN] = NULL;
3273 : } else
3274 0 : ri->list[RIP_FILTER_IN] = NULL;
3275 :
3276 0 : if (dist->list[DISTRIBUTE_V4_OUT]) {
3277 0 : alist = access_list_lookup(AFI_IP,
3278 : dist->list[DISTRIBUTE_V4_OUT]);
3279 0 : if (alist)
3280 0 : ri->list[RIP_FILTER_OUT] = alist;
3281 : else
3282 0 : ri->list[RIP_FILTER_OUT] = NULL;
3283 : } else
3284 0 : ri->list[RIP_FILTER_OUT] = NULL;
3285 :
3286 0 : if (dist->prefix[DISTRIBUTE_V4_IN]) {
3287 0 : plist = prefix_list_lookup(AFI_IP,
3288 : dist->prefix[DISTRIBUTE_V4_IN]);
3289 0 : if (plist)
3290 0 : ri->prefix[RIP_FILTER_IN] = plist;
3291 : else
3292 0 : ri->prefix[RIP_FILTER_IN] = NULL;
3293 : } else
3294 0 : ri->prefix[RIP_FILTER_IN] = NULL;
3295 :
3296 0 : if (dist->prefix[DISTRIBUTE_V4_OUT]) {
3297 0 : plist = prefix_list_lookup(AFI_IP,
3298 : dist->prefix[DISTRIBUTE_V4_OUT]);
3299 0 : if (plist)
3300 0 : ri->prefix[RIP_FILTER_OUT] = plist;
3301 : else
3302 0 : ri->prefix[RIP_FILTER_OUT] = NULL;
3303 : } else
3304 0 : ri->prefix[RIP_FILTER_OUT] = NULL;
3305 : }
3306 :
3307 68 : void rip_distribute_update_interface(struct interface *ifp)
3308 : {
3309 68 : struct rip_interface *ri = ifp->info;
3310 68 : struct rip *rip = ri->rip;
3311 68 : struct distribute *dist;
3312 :
3313 68 : if (!rip)
3314 : return;
3315 68 : dist = distribute_lookup(rip->distribute_ctx, ifp->name);
3316 68 : if (dist)
3317 0 : rip_distribute_update(rip->distribute_ctx, dist);
3318 : }
3319 :
3320 : /* Update all interface's distribute list. */
3321 : /* ARGSUSED */
3322 0 : static void rip_distribute_update_all(struct prefix_list *notused)
3323 : {
3324 0 : struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
3325 0 : struct interface *ifp;
3326 :
3327 0 : FOR_ALL_INTERFACES (vrf, ifp)
3328 0 : rip_distribute_update_interface(ifp);
3329 0 : }
3330 : /* ARGSUSED */
3331 0 : static void rip_distribute_update_all_wrapper(struct access_list *notused)
3332 : {
3333 0 : rip_distribute_update_all(NULL);
3334 0 : }
3335 :
3336 : /* Delete all added rip route. */
3337 5 : void rip_clean(struct rip *rip)
3338 : {
3339 5 : rip_interfaces_clean(rip);
3340 :
3341 5 : if (rip->enabled)
3342 0 : rip_instance_disable(rip);
3343 :
3344 5 : stream_free(rip->obuf);
3345 :
3346 160 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
3347 155 : if (rip->redist[i].route_map.name)
3348 0 : free(rip->redist[i].route_map.name);
3349 :
3350 5 : route_table_finish(rip->table);
3351 5 : route_table_finish(rip->neighbor);
3352 5 : list_delete(&rip->peer_list);
3353 5 : distribute_list_delete(&rip->distribute_ctx);
3354 5 : if_rmap_ctx_delete(rip->if_rmap_ctx);
3355 :
3356 5 : rip_clean_network(rip);
3357 5 : rip_passive_nondefault_clean(rip);
3358 5 : vector_free(rip->enable_interface);
3359 5 : route_table_finish(rip->enable_network);
3360 5 : vector_free(rip->passive_nondefault);
3361 5 : list_delete(&rip->offset_list_master);
3362 5 : route_table_finish(rip->distance_table);
3363 :
3364 5 : RB_REMOVE(rip_instance_head, &rip_instances, rip);
3365 5 : XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name);
3366 5 : XFREE(MTYPE_RIP, rip);
3367 5 : }
3368 :
3369 0 : static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
3370 : struct if_rmap *if_rmap)
3371 : {
3372 0 : struct interface *ifp = NULL;
3373 0 : struct rip_interface *ri;
3374 0 : struct route_map *rmap;
3375 0 : struct vrf *vrf = NULL;
3376 :
3377 0 : if (ctx->name)
3378 0 : vrf = vrf_lookup_by_name(ctx->name);
3379 0 : if (vrf)
3380 0 : ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
3381 0 : if (ifp == NULL)
3382 0 : return;
3383 :
3384 0 : ri = ifp->info;
3385 0 : if (if_rmap->routemap[IF_RMAP_IN]) {
3386 0 : rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
3387 0 : if (rmap)
3388 0 : ri->routemap[IF_RMAP_IN] = rmap;
3389 : else
3390 0 : ri->routemap[IF_RMAP_IN] = NULL;
3391 : } else
3392 0 : ri->routemap[RIP_FILTER_IN] = NULL;
3393 :
3394 0 : if (if_rmap->routemap[IF_RMAP_OUT]) {
3395 0 : rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]);
3396 0 : if (rmap)
3397 0 : ri->routemap[IF_RMAP_OUT] = rmap;
3398 : else
3399 0 : ri->routemap[IF_RMAP_OUT] = NULL;
3400 : } else
3401 0 : ri->routemap[RIP_FILTER_OUT] = NULL;
3402 : }
3403 :
3404 44 : void rip_if_rmap_update_interface(struct interface *ifp)
3405 : {
3406 44 : struct rip_interface *ri = ifp->info;
3407 44 : struct rip *rip = ri->rip;
3408 44 : struct if_rmap *if_rmap;
3409 44 : struct if_rmap_ctx *ctx;
3410 :
3411 44 : if (!rip)
3412 : return;
3413 44 : ctx = rip->if_rmap_ctx;
3414 44 : if (!ctx)
3415 : return;
3416 44 : if_rmap = if_rmap_lookup(ctx, ifp->name);
3417 44 : if (if_rmap)
3418 0 : rip_if_rmap_update(ctx, if_rmap);
3419 : }
3420 :
3421 0 : static void rip_routemap_update_redistribute(struct rip *rip)
3422 : {
3423 0 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3424 0 : if (rip->redist[i].route_map.name) {
3425 0 : rip->redist[i].route_map.map = route_map_lookup_by_name(
3426 : rip->redist[i].route_map.name);
3427 0 : route_map_counter_increment(
3428 : rip->redist[i].route_map.map);
3429 : }
3430 : }
3431 0 : }
3432 :
3433 : /* ARGSUSED */
3434 0 : static void rip_routemap_update(const char *notused)
3435 : {
3436 0 : struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
3437 0 : struct rip *rip;
3438 0 : struct interface *ifp;
3439 :
3440 0 : FOR_ALL_INTERFACES (vrf, ifp)
3441 0 : rip_if_rmap_update_interface(ifp);
3442 :
3443 0 : rip = vrf->info;
3444 0 : if (rip)
3445 0 : rip_routemap_update_redistribute(rip);
3446 0 : }
3447 :
3448 : /* Link RIP instance to VRF. */
3449 5 : static void rip_vrf_link(struct rip *rip, struct vrf *vrf)
3450 : {
3451 5 : struct interface *ifp;
3452 :
3453 5 : rip->vrf = vrf;
3454 5 : rip->distribute_ctx->vrf = vrf;
3455 5 : vrf->info = rip;
3456 :
3457 10 : FOR_ALL_INTERFACES (vrf, ifp)
3458 0 : rip_interface_sync(ifp);
3459 5 : }
3460 :
3461 : /* Unlink RIP instance from VRF. */
3462 5 : static void rip_vrf_unlink(struct rip *rip, struct vrf *vrf)
3463 : {
3464 5 : struct interface *ifp;
3465 :
3466 5 : rip->vrf = NULL;
3467 5 : rip->distribute_ctx->vrf = NULL;
3468 5 : vrf->info = NULL;
3469 :
3470 32 : FOR_ALL_INTERFACES (vrf, ifp)
3471 22 : rip_interface_sync(ifp);
3472 5 : }
3473 :
3474 5 : static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock)
3475 : {
3476 5 : rip->sock = sock;
3477 :
3478 5 : rip_vrf_link(rip, vrf);
3479 5 : rip->enabled = true;
3480 :
3481 : /* Resend all redistribute requests. */
3482 5 : rip_redistribute_enable(rip);
3483 :
3484 : /* Create read and timer thread. */
3485 5 : rip_event(rip, RIP_READ, rip->sock);
3486 5 : rip_event(rip, RIP_UPDATE_EVENT, 1);
3487 :
3488 5 : rip_zebra_vrf_register(vrf);
3489 5 : }
3490 :
3491 5 : static void rip_instance_disable(struct rip *rip)
3492 : {
3493 5 : struct vrf *vrf = rip->vrf;
3494 5 : struct route_node *rp;
3495 :
3496 : /* Clear RIP routes */
3497 39 : for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
3498 34 : struct rip_info *rinfo;
3499 34 : struct list *list;
3500 34 : struct listnode *listnode;
3501 :
3502 34 : if ((list = rp->info) == NULL)
3503 15 : continue;
3504 :
3505 19 : rinfo = listgetdata(listhead(list));
3506 19 : if (rip_route_rte(rinfo))
3507 10 : rip_zebra_ipv4_delete(rip, rp);
3508 :
3509 57 : for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
3510 19 : THREAD_OFF(rinfo->t_timeout);
3511 19 : THREAD_OFF(rinfo->t_garbage_collect);
3512 19 : rip_info_free(rinfo);
3513 : }
3514 19 : list_delete(&list);
3515 19 : rp->info = NULL;
3516 19 : route_unlock_node(rp);
3517 : }
3518 :
3519 : /* Flush all redistribute requests. */
3520 5 : rip_redistribute_disable(rip);
3521 :
3522 : /* Cancel RIP related timers. */
3523 5 : THREAD_OFF(rip->t_update);
3524 5 : THREAD_OFF(rip->t_triggered_update);
3525 5 : THREAD_OFF(rip->t_triggered_interval);
3526 :
3527 : /* Cancel read thread. */
3528 5 : THREAD_OFF(rip->t_read);
3529 :
3530 : /* Close RIP socket. */
3531 5 : close(rip->sock);
3532 5 : rip->sock = -1;
3533 :
3534 : /* Clear existing peers. */
3535 5 : list_delete_all_node(rip->peer_list);
3536 :
3537 5 : rip_zebra_vrf_deregister(vrf);
3538 :
3539 5 : rip_vrf_unlink(rip, vrf);
3540 5 : rip->enabled = false;
3541 5 : }
3542 :
3543 5 : static int rip_vrf_new(struct vrf *vrf)
3544 : {
3545 5 : if (IS_RIP_DEBUG_EVENT)
3546 0 : zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name,
3547 : vrf->vrf_id);
3548 :
3549 5 : return 0;
3550 : }
3551 :
3552 5 : static int rip_vrf_delete(struct vrf *vrf)
3553 : {
3554 5 : struct rip *rip;
3555 :
3556 5 : if (IS_RIP_DEBUG_EVENT)
3557 1 : zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name,
3558 : vrf->vrf_id);
3559 :
3560 5 : rip = rip_lookup_by_vrf_name(vrf->name);
3561 5 : if (!rip)
3562 : return 0;
3563 :
3564 5 : rip_clean(rip);
3565 :
3566 5 : return 0;
3567 : }
3568 :
3569 5 : static int rip_vrf_enable(struct vrf *vrf)
3570 : {
3571 5 : struct rip *rip;
3572 5 : int socket;
3573 :
3574 5 : rip = rip_lookup_by_vrf_name(vrf->name);
3575 5 : if (!rip || rip->enabled)
3576 : return 0;
3577 :
3578 0 : if (IS_RIP_DEBUG_EVENT)
3579 0 : zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name,
3580 : vrf->vrf_id);
3581 :
3582 : /* Activate the VRF RIP instance. */
3583 0 : if (!rip->enabled) {
3584 0 : socket = rip_create_socket(vrf);
3585 0 : if (socket < 0)
3586 : return -1;
3587 :
3588 0 : rip_instance_enable(rip, vrf, socket);
3589 : }
3590 :
3591 : return 0;
3592 : }
3593 :
3594 5 : static int rip_vrf_disable(struct vrf *vrf)
3595 : {
3596 5 : struct rip *rip;
3597 :
3598 5 : rip = rip_lookup_by_vrf_name(vrf->name);
3599 5 : if (!rip || !rip->enabled)
3600 : return 0;
3601 :
3602 5 : if (IS_RIP_DEBUG_EVENT)
3603 1 : zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name,
3604 : vrf->vrf_id);
3605 :
3606 : /* Deactivate the VRF RIP instance. */
3607 5 : if (rip->enabled)
3608 5 : rip_instance_disable(rip);
3609 :
3610 : return 0;
3611 : }
3612 :
3613 5 : void rip_vrf_init(void)
3614 : {
3615 5 : vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete);
3616 :
3617 5 : vrf_cmd_init(NULL);
3618 5 : }
3619 :
3620 5 : void rip_vrf_terminate(void)
3621 : {
3622 5 : vrf_terminate();
3623 5 : }
3624 :
3625 : /* Allocate new rip structure and set default value. */
3626 5 : void rip_init(void)
3627 : {
3628 : /* Install top nodes. */
3629 5 : install_node(&rip_node);
3630 :
3631 : /* Install rip commands. */
3632 5 : install_element(VIEW_NODE, &show_ip_rip_cmd);
3633 5 : install_element(VIEW_NODE, &show_ip_rip_status_cmd);
3634 :
3635 5 : install_default(RIP_NODE);
3636 :
3637 : /* Debug related init. */
3638 5 : rip_debug_init();
3639 :
3640 : /* Access list install. */
3641 5 : access_list_init();
3642 5 : access_list_add_hook(rip_distribute_update_all_wrapper);
3643 5 : access_list_delete_hook(rip_distribute_update_all_wrapper);
3644 :
3645 : /* Prefix list initialize.*/
3646 5 : prefix_list_init();
3647 5 : prefix_list_add_hook(rip_distribute_update_all);
3648 5 : prefix_list_delete_hook(rip_distribute_update_all);
3649 :
3650 : /* Route-map */
3651 5 : rip_route_map_init();
3652 :
3653 5 : route_map_add_hook(rip_routemap_update);
3654 5 : route_map_delete_hook(rip_routemap_update);
3655 :
3656 5 : if_rmap_init(RIP_NODE);
3657 5 : }
|