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