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