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