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