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