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