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