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