]> git.proxmox.com Git - mirror_frr.git/blame - ripd/ripd.c
ripd: ignore request for RTEs from unknown address-families
[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
2c61ae37 1342rip_create_socket (struct sockaddr_in *from)
a4e987e0 1343{
1344 int ret;
1345 int sock;
1346 struct sockaddr_in addr;
f69bd9da 1347
2c61ae37 1348 memset (&addr, 0, sizeof (struct sockaddr_in));
1349
1350 if (!from)
f69bd9da 1351 {
f69bd9da 1352 addr.sin_family = AF_INET;
1353 addr.sin_addr.s_addr = INADDR_ANY;
6f0e3f6e 1354#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
2c61ae37 1355 addr.sin_len = sizeof (struct sockaddr_in);
6f0e3f6e 1356#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
38d3c163 1357 } else {
1358 memcpy(&addr, from, sizeof(addr));
f69bd9da 1359 }
1360
2c61ae37 1361 /* sending port must always be the RIP port */
1362 addr.sin_port = htons (RIP_PORT_DEFAULT);
1363
a4e987e0 1364 /* Make datagram socket. */
1365 sock = socket (AF_INET, SOCK_DGRAM, 0);
1366 if (sock < 0)
1367 {
1368 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1369 exit (1);
1370 }
1371
1372 sockopt_broadcast (sock);
1373 sockopt_reuseaddr (sock);
1374 sockopt_reuseport (sock);
a4e987e0 1375#ifdef RIP_RECVMSG
1376 setsockopt_pktinfo (sock);
1377#endif /* RIP_RECVMSG */
78b31d5c
SH
1378#ifdef IPTOS_PREC_INTERNETCONTROL
1379 setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
1380#endif
a4e987e0 1381
1382 if (ripd_privs.change (ZPRIVS_RAISE))
1383 zlog_err ("rip_create_socket: could not raise privs");
f69bd9da 1384 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1385 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1386
a4e987e0 1387 {
1388 int save_errno = errno;
1389 if (ripd_privs.change (ZPRIVS_LOWER))
1390 zlog_err ("rip_create_socket: could not lower privs");
2c61ae37 1391
1392 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1393 sock, inet_ntoa(addr.sin_addr),
1394 (int) ntohs(addr.sin_port),
1395 safe_strerror(save_errno));
1396
f69bd9da 1397 close (sock);
a4e987e0 1398 return ret;
1399 }
f69bd9da 1400
a4e987e0 1401 if (ripd_privs.change (ZPRIVS_LOWER))
1402 zlog_err ("rip_create_socket: could not lower privs");
1403
1404 return sock;
1405}
1406
c49ad8f1 1407/* RIP packet send to destination address, on interface denoted by
1408 * by connected argument. NULL to argument denotes destination should be
1409 * should be RIP multicast group
1410 */
dc63bfd4 1411static int
c49ad8f1 1412rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1413 struct connected *ifc)
718e3744 1414{
931cd54d 1415 int ret, send_sock;
718e3744 1416 struct sockaddr_in sin;
c49ad8f1 1417
1418 assert (ifc != NULL);
1419
931cd54d 1420 if (IS_RIP_DEBUG_PACKET)
1421 {
f69bd9da 1422#define ADDRESS_SIZE 20
1423 char dst[ADDRESS_SIZE];
1424 dst[ADDRESS_SIZE - 1] = '\0';
1425
931cd54d 1426 if (to)
1427 {
f69bd9da 1428 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
931cd54d 1429 }
1430 else
1431 {
1432 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
f69bd9da 1433 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
931cd54d 1434 }
f69bd9da 1435#undef ADDRESS_SIZE
5d6c3779 1436 zlog_debug("rip_send_packet %s > %s (%s)",
c49ad8f1 1437 inet_ntoa(ifc->address->u.prefix4),
1438 dst, ifc->ifp->name);
931cd54d 1439 }
f69bd9da 1440
c49ad8f1 1441 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
931cd54d 1442 {
1443 /*
1444 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1445 * with multiple addresses on the same subnet: the first address
1446 * on the subnet is configured "primary", and all subsequent addresses
1447 * on that subnet are treated as "secondary" addresses.
1448 * In order to avoid routing-table bloat on other rip listeners,
1449 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1450 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1451 * flag is set, we would end up sending a packet for a "secondary"
1452 * source address on non-linux systems.
1453 */
1454 if (IS_RIP_DEBUG_PACKET)
5d6c3779 1455 zlog_debug("duplicate dropped");
931cd54d 1456 return 0;
1457 }
1458
718e3744 1459 /* Make destination address. */
1460 memset (&sin, 0, sizeof (struct sockaddr_in));
1461 sin.sin_family = AF_INET;
6f0e3f6e 1462#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
718e3744 1463 sin.sin_len = sizeof (struct sockaddr_in);
6f0e3f6e 1464#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
718e3744 1465
1466 /* When destination is specified, use it's port and address. */
1467 if (to)
1468 {
718e3744 1469 sin.sin_port = to->sin_port;
1470 sin.sin_addr = to->sin_addr;
931cd54d 1471 send_sock = rip->sock;
718e3744 1472 }
1473 else
1474 {
2c61ae37 1475 struct sockaddr_in from;
1476
718e3744 1477 sin.sin_port = htons (RIP_PORT_DEFAULT);
1478 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
2c61ae37 1479
1480 /* multicast send should bind to local interface address */
bb2315f2 1481 memset (&from, 0, sizeof (from));
2c61ae37 1482 from.sin_family = AF_INET;
1483 from.sin_port = htons (RIP_PORT_DEFAULT);
1484 from.sin_addr = ifc->address->u.prefix4;
6f0e3f6e 1485#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
2c61ae37 1486 from.sin_len = sizeof (struct sockaddr_in);
6f0e3f6e 1487#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
2c61ae37 1488
931cd54d 1489 /*
1490 * we have to open a new socket for each packet because this
1491 * is the most portable way to bind to a different source
1492 * ipv4 address for each packet.
1493 */
2c61ae37 1494 if ( (send_sock = rip_create_socket (&from)) < 0)
931cd54d 1495 {
f69bd9da 1496 zlog_warn("rip_send_packet could not create socket.");
931cd54d 1497 return -1;
f69bd9da 1498 }
c49ad8f1 1499 rip_interface_multicast_set (send_sock, ifc);
718e3744 1500 }
1501
931cd54d 1502 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
718e3744 1503 sizeof (struct sockaddr_in));
1504
1505 if (IS_RIP_DEBUG_EVENT)
5d6c3779 1506 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
cc1131ab 1507 ntohs (sin.sin_port));
718e3744 1508
1509 if (ret < 0)
6099b3b5 1510 zlog_warn ("can't send packet : %s", safe_strerror (errno));
718e3744 1511
931cd54d 1512 if (!to)
1513 close(send_sock);
1514
718e3744 1515 return ret;
1516}
1517
1518/* Add redistributed route to RIP table. */
1519void
1520rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
b892f1dd 1521 ifindex_t ifindex, struct in_addr *nexthop,
9471675f
CF
1522 unsigned int metric, unsigned char distance,
1523 route_tag_t tag)
718e3744 1524{
1525 int ret;
bce8e868
LF
1526 struct route_node *rp = NULL;
1527 struct rip_info *rinfo = NULL, newinfo;
1528 struct list *list = NULL;
718e3744 1529
1530 /* Redistribute route */
1531 ret = rip_destination_check (p->prefix);
1532 if (! ret)
1533 return;
1534
1535 rp = route_node_get (rip->table, (struct prefix *) p);
1536
bce8e868
LF
1537 memset (&newinfo, 0, sizeof (struct rip_info));
1538 newinfo.type = type;
1539 newinfo.sub_type = sub_type;
1540 newinfo.ifindex = ifindex;
1541 newinfo.metric = 1;
1542 newinfo.external_metric = metric;
1543 newinfo.distance = distance;
9471675f
CF
1544 if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */
1545 newinfo.tag = tag;
bce8e868
LF
1546 newinfo.rp = rp;
1547 if (nexthop)
1548 newinfo.nexthop = *nexthop;
718e3744 1549
bce8e868 1550 if ((list = rp->info) != NULL && listcount (list) != 0)
718e3744 1551 {
bce8e868
LF
1552 rinfo = listgetdata (listhead (list));
1553
718e3744 1554 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1555 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1556 && rinfo->metric != RIP_METRIC_INFINITY)
1557 {
1558 route_unlock_node (rp);
1559 return;
1560 }
1561
1562 /* Manually configured RIP route check. */
1563 if (rinfo->type == ZEBRA_ROUTE_RIP
16705130 1564 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1565 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
718e3744 1566 {
16705130 1567 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1568 (sub_type != RIP_ROUTE_DEFAULT)))
718e3744 1569 {
1570 route_unlock_node (rp);
1571 return;
1572 }
1573 }
1574
bce8e868
LF
1575 rinfo = rip_ecmp_replace (&newinfo);
1576 route_unlock_node (rp);
718e3744 1577 }
bce8e868
LF
1578 else
1579 rinfo = rip_ecmp_add (&newinfo);
718e3744 1580
16705130 1581 if (IS_RIP_DEBUG_EVENT) {
1582 if (!nexthop)
5d6c3779 1583 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
16705130 1584 inet_ntoa(p->prefix), p->prefixlen,
1585 ifindex2ifname(ifindex));
1586 else
5d6c3779 1587 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
16705130 1588 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1589 ifindex2ifname(ifindex));
1590 }
1591
718e3744 1592 rip_event (RIP_TRIGGERED_UPDATE, 0);
1593}
1594
1595/* Delete redistributed route from RIP table. */
1596void
1597rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
b892f1dd 1598 ifindex_t ifindex)
718e3744 1599{
1600 int ret;
1601 struct route_node *rp;
1602 struct rip_info *rinfo;
1603
1604 ret = rip_destination_check (p->prefix);
1605 if (! ret)
1606 return;
1607
1608 rp = route_node_lookup (rip->table, (struct prefix *) p);
1609 if (rp)
1610 {
bce8e868 1611 struct list *list = rp->info;
718e3744 1612
bce8e868
LF
1613 if (list != NULL && listcount (list) != 0)
1614 {
1615 rinfo = listgetdata (listhead (list));
1616 if (rinfo != NULL
1617 && rinfo->type == type
1618 && rinfo->sub_type == sub_type
1619 && rinfo->ifindex == ifindex)
1620 {
1621 /* Perform poisoned reverse. */
1622 rinfo->metric = RIP_METRIC_INFINITY;
1623 RIP_TIMER_ON (rinfo->t_garbage_collect,
1624 rip_garbage_collect, rip->garbage_time);
1625 RIP_TIMER_OFF (rinfo->t_timeout);
1626 rinfo->flags |= RIP_RTF_CHANGED;
718e3744 1627
bce8e868
LF
1628 if (IS_RIP_DEBUG_EVENT)
1629 zlog_debug ("Poisone %s/%d on the interface %s with an "
1630 "infinity metric [delete]",
1631 inet_ntoa(p->prefix), p->prefixlen,
1632 ifindex2ifname(ifindex));
16705130 1633
bce8e868
LF
1634 rip_event (RIP_TRIGGERED_UPDATE, 0);
1635 }
1636 }
1637 route_unlock_node (rp);
718e3744 1638 }
1639}
1640
1641/* Response to request called from rip_read ().*/
dc63bfd4 1642static void
718e3744 1643rip_request_process (struct rip_packet *packet, int size,
c49ad8f1 1644 struct sockaddr_in *from, struct connected *ifc)
718e3744 1645{
1646 caddr_t lim;
1647 struct rte *rte;
1648 struct prefix_ipv4 p;
1649 struct route_node *rp;
1650 struct rip_info *rinfo;
1651 struct rip_interface *ri;
1652
16705130 1653 /* Does not reponse to the requests on the loopback interfaces */
c49ad8f1 1654 if (if_is_loopback (ifc->ifp))
16705130 1655 return;
1656
429a0f8c 1657 /* Check RIP process is enabled on this interface. */
c49ad8f1 1658 ri = ifc->ifp->info;
16705130 1659 if (! ri->running)
1660 return;
718e3744 1661
1662 /* When passive interface is specified, suppress responses */
1663 if (ri->passive)
1664 return;
c49ad8f1 1665
718e3744 1666 /* RIP peer update. */
1667 rip_peer_update (from, packet->version);
1668
1669 lim = ((caddr_t) packet) + size;
1670 rte = packet->rte;
1671
1672 /* The Request is processed entry by entry. If there are no
1673 entries, no response is given. */
1674 if (lim == (caddr_t) rte)
1675 return;
1676
1677 /* There is one special case. If there is exactly one entry in the
1678 request, and it has an address family identifier of zero and a
1679 metric of infinity (i.e., 16), then this is a request to send the
1680 entire routing table. */
1681 if (lim == ((caddr_t) (rte + 1)) &&
1682 ntohs (rte->family) == 0 &&
1683 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1684 {
1685 /* All route with split horizon */
c49ad8f1 1686 rip_output_process (ifc, from, rip_all_route, packet->version);
718e3744 1687 }
1688 else
1689 {
4e054866
RW
1690 if (ntohs (rte->family) != AF_INET)
1691 return;
1692
718e3744 1693 /* Examine the list of RTEs in the Request one by one. For each
1694 entry, look up the destination in the router's routing
1695 database and, if there is a route, put that route's metric in
1696 the metric field of the RTE. If there is no explicit route
1697 to the specified destination, put infinity in the metric
1698 field. Once all the entries have been filled in, change the
1699 command from Request to Response and send the datagram back
1700 to the requestor. */
1701 p.family = AF_INET;
1702
1703 for (; ((caddr_t) rte) < lim; rte++)
1704 {
1705 p.prefix = rte->prefix;
1706 p.prefixlen = ip_masklen (rte->mask);
1707 apply_mask_ipv4 (&p);
1708
1709 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1710 if (rp)
1711 {
bce8e868 1712 rinfo = listgetdata (listhead ((struct list *)rp->info));
718e3744 1713 rte->metric = htonl (rinfo->metric);
1714 route_unlock_node (rp);
1715 }
1716 else
1717 rte->metric = htonl (RIP_METRIC_INFINITY);
1718 }
1719 packet->command = RIP_RESPONSE;
1720
c49ad8f1 1721 rip_send_packet ((u_char *)packet, size, from, ifc);
718e3744 1722 }
1723 rip_global_queries++;
1724}
1725
1726#if RIP_RECVMSG
1727/* Set IPv6 packet info to the socket. */
1728static int
1729setsockopt_pktinfo (int sock)
1730{
1731 int ret;
1732 int val = 1;
1733
1734 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1735 if (ret < 0)
6099b3b5 1736 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
718e3744 1737 return ret;
1738}
1739
1740/* Read RIP packet by recvmsg function. */
1741int
1742rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
b892f1dd 1743 ifindex_t *ifindex)
718e3744 1744{
1745 int ret;
1746 struct msghdr msg;
1747 struct iovec iov;
1748 struct cmsghdr *ptr;
1749 char adata[1024];
1750
1751 msg.msg_name = (void *) from;
1752 msg.msg_namelen = sizeof (struct sockaddr_in);
1753 msg.msg_iov = &iov;
1754 msg.msg_iovlen = 1;
1755 msg.msg_control = (void *) adata;
1756 msg.msg_controllen = sizeof adata;
1757 iov.iov_base = buf;
1758 iov.iov_len = size;
1759
1760 ret = recvmsg (sock, &msg, 0);
1761 if (ret < 0)
1762 return ret;
1763
b99760ab 1764 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
718e3744 1765 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1766 {
1767 struct in_pktinfo *pktinfo;
1768 int i;
1769
1770 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1771 i = pktinfo->ipi_ifindex;
1772 }
1773 return ret;
1774}
1775
1776/* RIP packet read function. */
1777int
1778rip_read_new (struct thread *t)
1779{
1780 int ret;
1781 int sock;
1782 char buf[RIP_PACKET_MAXSIZ];
1783 struct sockaddr_in from;
b892f1dd 1784 ifindex_t ifindex;
718e3744 1785
1786 /* Fetch socket then register myself. */
1787 sock = THREAD_FD (t);
1788 rip_event (RIP_READ, sock);
1789
1790 /* Read RIP packet. */
1791 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1792 if (ret < 0)
1793 {
6099b3b5 1794 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
718e3744 1795 return ret;
1796 }
1797
1798 return ret;
1799}
1800#endif /* RIP_RECVMSG */
1801
1802/* First entry point of RIP packet. */
dc63bfd4 1803static int
718e3744 1804rip_read (struct thread *t)
1805{
1806 int sock;
1807 int ret;
1808 int rtenum;
1809 union rip_buf rip_buf;
1810 struct rip_packet *packet;
1811 struct sockaddr_in from;
11dde9c2 1812 int len;
3e557ae1 1813 int vrecv;
11dde9c2 1814 socklen_t fromlen;
718e3744 1815 struct interface *ifp;
c49ad8f1 1816 struct connected *ifc;
718e3744 1817 struct rip_interface *ri;
bd40c341 1818 struct prefix p;
718e3744 1819
1820 /* Fetch socket then register myself. */
1821 sock = THREAD_FD (t);
1822 rip->t_read = NULL;
1823
1824 /* Add myself to tne next event */
1825 rip_event (RIP_READ, sock);
1826
1827 /* RIPd manages only IPv4. */
1828 memset (&from, 0, sizeof (struct sockaddr_in));
1829 fromlen = sizeof (struct sockaddr_in);
1830
1831 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1832 (struct sockaddr *) &from, &fromlen);
1833 if (len < 0)
1834 {
6099b3b5 1835 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
718e3744 1836 return len;
1837 }
1838
1839 /* Check is this packet comming from myself? */
31a476c7 1840 if (if_check_address (from.sin_addr))
718e3744 1841 {
1842 if (IS_RIP_DEBUG_PACKET)
5d6c3779 1843 zlog_debug ("ignore packet comes from myself");
718e3744 1844 return -1;
1845 }
1846
1847 /* Which interface is this packet comes from. */
0aabccc0 1848 ifp = if_lookup_address ((void *)&from.sin_addr, AF_INET);
c49ad8f1 1849
718e3744 1850 /* RIP packet received */
1851 if (IS_RIP_DEBUG_EVENT)
5d6c3779 1852 zlog_debug ("RECV packet from %s port %d on %s",
718e3744 1853 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1854 ifp ? ifp->name : "unknown");
1855
1856 /* If this packet come from unknown interface, ignore it. */
1857 if (ifp == NULL)
1858 {
766a0ca3 1859 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1860 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
c49ad8f1 1861 return -1;
1862 }
bd40c341
DS
1863
1864 p.family = AF_INET;
1865 p.u.prefix4 = from.sin_addr;
1866 p.prefixlen = IPV4_MAX_BITLEN;
1867
1868 ifc = connected_lookup_prefix (ifp, &p);
c49ad8f1 1869
1870 if (ifc == NULL)
1871 {
766a0ca3 1872 zlog_info ("rip_read: cannot find connected address for packet from %s "
1873 "port %d on interface %s",
1874 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
718e3744 1875 return -1;
1876 }
1877
1878 /* Packet length check. */
1879 if (len < RIP_PACKET_MINSIZ)
1880 {
1881 zlog_warn ("packet size %d is smaller than minimum size %d",
1882 len, RIP_PACKET_MINSIZ);
1883 rip_peer_bad_packet (&from);
1884 return len;
1885 }
1886 if (len > RIP_PACKET_MAXSIZ)
1887 {
1888 zlog_warn ("packet size %d is larger than max size %d",
1889 len, RIP_PACKET_MAXSIZ);
1890 rip_peer_bad_packet (&from);
1891 return len;
1892 }
1893
1894 /* Packet alignment check. */
1895 if ((len - RIP_PACKET_MINSIZ) % 20)
1896 {
1897 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1898 rip_peer_bad_packet (&from);
1899 return len;
1900 }
1901
1902 /* Set RTE number. */
1903 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1904
1905 /* For easy to handle. */
1906 packet = &rip_buf.rip_packet;
1907
1908 /* RIP version check. */
1909 if (packet->version == 0)
1910 {
1911 zlog_info ("version 0 with command %d received.", packet->command);
1912 rip_peer_bad_packet (&from);
1913 return -1;
1914 }
1915
1916 /* Dump RIP packet. */
1917 if (IS_RIP_DEBUG_RECV)
1918 rip_packet_dump (packet, len, "RECV");
1919
1920 /* RIP version adjust. This code should rethink now. RFC1058 says
1921 that "Version 1 implementations are to ignore this extra data and
1922 process only the fields specified in this document.". So RIPv3
1923 packet should be treated as RIPv1 ignoring must be zero field. */
1924 if (packet->version > RIPv2)
1925 packet->version = RIPv2;
1926
1927 /* Is RIP running or is this RIP neighbor ?*/
1928 ri = ifp->info;
1929 if (! ri->running && ! rip_neighbor_lookup (&from))
1930 {
1931 if (IS_RIP_DEBUG_EVENT)
5d6c3779 1932 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
718e3744 1933 rip_peer_bad_packet (&from);
1934 return -1;
1935 }
1936
15a2b089 1937 /* RIP Version check. RFC2453, 4.6 and 5.1 */
3e557ae1
PJ
1938 vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1939 rip->version_recv : ri->ri_receive);
15a2b089 1940 if ((packet->version == RIPv1) && !(vrecv & RIPv1))
718e3744 1941 {
15a2b089
PJ
1942 if (IS_RIP_DEBUG_PACKET)
1943 zlog_debug (" packet's v%d doesn't fit to if version spec",
1944 packet->version);
1945 rip_peer_bad_packet (&from);
1946 return -1;
718e3744 1947 }
15a2b089
PJ
1948 if ((packet->version == RIPv2) && !(vrecv & RIPv2))
1949 {
1950 if (IS_RIP_DEBUG_PACKET)
1951 zlog_debug (" packet's v%d doesn't fit to if version spec",
1952 packet->version);
1953 rip_peer_bad_packet (&from);
1954 return -1;
1955 }
1956
718e3744 1957 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1958 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1959 accepted; authenticated RIP-2 messages shall be discarded. */
718e3744 1960 if ((ri->auth_type == RIP_NO_AUTH)
1961 && rtenum
ca5e516c 1962 && (packet->version == RIPv2)
1963 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
718e3744 1964 {
1965 if (IS_RIP_DEBUG_EVENT)
5d6c3779 1966 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
718e3744 1967 packet->version);
1968 rip_peer_bad_packet (&from);
1969 return -1;
1970 }
15a2b089
PJ
1971
1972 /* RFC:
1973 If the router is configured to authenticate RIP-2 messages, then
718e3744 1974 RIP-1 messages and RIP-2 messages which pass authentication
1975 testing shall be accepted; unauthenticated and failed
1976 authentication RIP-2 messages shall be discarded. For maximum
1977 security, RIP-1 messages should be ignored when authentication is
1978 in use (see section 4.1); otherwise, the routing information from
1979 authenticated messages will be propagated by RIP-1 routers in an
15a2b089
PJ
1980 unauthenticated manner.
1981 */
1982 /* We make an exception for RIPv1 REQUEST packets, to which we'll
1983 * always reply regardless of authentication settings, because:
1984 *
1985 * - if there other authorised routers on-link, the REQUESTor can
1986 * passively obtain the routing updates anyway
1987 * - if there are no other authorised routers on-link, RIP can
1988 * easily be disabled for the link to prevent giving out information
1989 * on state of this routers RIP routing table..
1990 *
1991 * I.e. if RIPv1 has any place anymore these days, it's as a very
1992 * simple way to distribute routing information (e.g. to embedded
1993 * hosts / appliances) and the ability to give out RIPv1
1994 * routing-information freely, while still requiring RIPv2
1995 * authentication for any RESPONSEs might be vaguely useful.
1996 */
1997 if (ri->auth_type != RIP_NO_AUTH
1998 && packet->version == RIPv1)
718e3744 1999 {
15a2b089
PJ
2000 /* Discard RIPv1 messages other than REQUESTs */
2001 if (packet->command != RIP_REQUEST)
2002 {
2003 if (IS_RIP_DEBUG_PACKET)
2004 zlog_debug ("RIPv1" " dropped because authentication enabled");
2005 rip_peer_bad_packet (&from);
2006 return -1;
2007 }
2008 }
2009 else if (ri->auth_type != RIP_NO_AUTH)
2010 {
2011 const char *auth_desc;
2012
2013 if (rtenum == 0)
2014 {
2015 /* There definitely is no authentication in the packet. */
2016 if (IS_RIP_DEBUG_PACKET)
2017 zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
2018 rip_peer_bad_packet (&from);
2019 return -1;
2020 }
2021
2022 /* First RTE must be an Authentication Family RTE */
2023 if (packet->rte->family != htons(RIP_FAMILY_AUTH))
2024 {
2025 if (IS_RIP_DEBUG_PACKET)
2026 zlog_debug ("RIPv2" " dropped because authentication enabled");
718e3744 2027 rip_peer_bad_packet (&from);
2028 return -1;
15a2b089
PJ
2029 }
2030
718e3744 2031 /* Check RIPv2 authentication. */
15a2b089
PJ
2032 switch (ntohs(packet->rte->tag))
2033 {
2034 case RIP_AUTH_SIMPLE_PASSWORD:
2035 auth_desc = "simple";
2036 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2037 break;
2038
2039 case RIP_AUTH_MD5:
2040 auth_desc = "MD5";
2041 ret = rip_auth_md5 (packet, &from, len, ifp);
2042 /* Reset RIP packet length to trim MD5 data. */
2043 len = ret;
2044 break;
2045
2046 default:
2047 ret = 0;
2048 auth_desc = "unknown type";
2049 if (IS_RIP_DEBUG_PACKET)
2050 zlog_debug ("RIPv2 Unknown authentication type %d",
2051 ntohs (packet->rte->tag));
2052 }
2053
2054 if (ret)
2055 {
2056 if (IS_RIP_DEBUG_PACKET)
2057 zlog_debug ("RIPv2 %s authentication success", auth_desc);
2058 }
2059 else
2060 {
2061 if (IS_RIP_DEBUG_PACKET)
2062 zlog_debug ("RIPv2 %s authentication failure", auth_desc);
2063 rip_peer_bad_packet (&from);
2064 return -1;
2065 }
718e3744 2066 }
2067
2068 /* Process each command. */
2069 switch (packet->command)
2070 {
2071 case RIP_RESPONSE:
c49ad8f1 2072 rip_response_process (packet, len, &from, ifc);
718e3744 2073 break;
2074 case RIP_REQUEST:
2075 case RIP_POLL:
c49ad8f1 2076 rip_request_process (packet, len, &from, ifc);
718e3744 2077 break;
2078 case RIP_TRACEON:
2079 case RIP_TRACEOFF:
2080 zlog_info ("Obsolete command %s received, please sent it to routed",
2081 lookup (rip_msg, packet->command));
2082 rip_peer_bad_packet (&from);
2083 break;
2084 case RIP_POLL_ENTRY:
2085 zlog_info ("Obsolete command %s received",
2086 lookup (rip_msg, packet->command));
2087 rip_peer_bad_packet (&from);
2088 break;
2089 default:
2090 zlog_info ("Unknown RIP command %d received", packet->command);
2091 rip_peer_bad_packet (&from);
2092 break;
2093 }
2094
2095 return len;
2096}
2097
718e3744 2098/* Write routing table entry to the stream and return next index of
2099 the routing table entry in the stream. */
dc63bfd4 2100static int
718e3744 2101rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
b14ee00b 2102 u_char version, struct rip_info *rinfo)
718e3744 2103{
2104 struct in_addr mask;
718e3744 2105
2106 /* Write routing table entry. */
2107 if (version == RIPv1)
2108 {
2109 stream_putw (s, AF_INET);
2110 stream_putw (s, 0);
2111 stream_put_ipv4 (s, p->prefix.s_addr);
2112 stream_put_ipv4 (s, 0);
2113 stream_put_ipv4 (s, 0);
2114 stream_putl (s, rinfo->metric_out);
2115 }
2116 else
2117 {
2118 masklen2ip (p->prefixlen, &mask);
2119
2120 stream_putw (s, AF_INET);
16705130 2121 stream_putw (s, rinfo->tag_out);
718e3744 2122 stream_put_ipv4 (s, p->prefix.s_addr);
2123 stream_put_ipv4 (s, mask.s_addr);
2124 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2125 stream_putl (s, rinfo->metric_out);
2126 }
2127
2128 return ++num;
2129}
2130
2131/* Send update to the ifp or spcified neighbor. */
2132void
c49ad8f1 2133rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2134 int route_type, u_char version)
718e3744 2135{
2136 int ret;
2137 struct stream *s;
2138 struct route_node *rp;
2139 struct rip_info *rinfo;
2140 struct rip_interface *ri;
2141 struct prefix_ipv4 *p;
2142 struct prefix_ipv4 classfull;
727d104b 2143 struct prefix_ipv4 ifaddrclass;
b14ee00b 2144 struct key *key = NULL;
2145 /* this might need to made dynamic if RIP ever supported auth methods
2146 with larger key string sizes */
2147 char auth_str[RIP_AUTH_SIMPLE_SIZE];
dc63bfd4 2148 size_t doff = 0; /* offset of digest offset field */
2c61ae37 2149 int num = 0;
718e3744 2150 int rtemax;
01d0908a 2151 int subnetted = 0;
bce8e868
LF
2152 struct list *list = NULL;
2153 struct listnode *listnode = NULL;
718e3744 2154
2155 /* Logging output event. */
2156 if (IS_RIP_DEBUG_EVENT)
2157 {
2158 if (to)
5d6c3779 2159 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
718e3744 2160 else
5d6c3779 2161 zlog_debug ("update routes on interface %s ifindex %d",
c49ad8f1 2162 ifc->ifp->name, ifc->ifp->ifindex);
718e3744 2163 }
2164
2165 /* Set output stream. */
2166 s = rip->obuf;
2167
2168 /* Reset stream and RTE counter. */
2169 stream_reset (s);
6a7cff75 2170 rtemax = RIP_MAX_RTE;
718e3744 2171
2172 /* Get RIP interface. */
c49ad8f1 2173 ri = ifc->ifp->info;
718e3744 2174
2175 /* If output interface is in simple password authentication mode, we
2176 need space for authentication data. */
2177 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2178 rtemax -= 1;
2179
2180 /* If output interface is in MD5 authentication mode, we need space
2181 for authentication header and data. */
2182 if (ri->auth_type == RIP_AUTH_MD5)
2183 rtemax -= 2;
2184
2185 /* If output interface is in simple password authentication mode
2186 and string or keychain is specified we need space for auth. data */
b14ee00b 2187 if (ri->auth_type != RIP_NO_AUTH)
718e3744 2188 {
2189 if (ri->key_chain)
2190 {
2191 struct keychain *keychain;
2192
2193 keychain = keychain_lookup (ri->key_chain);
2194 if (keychain)
b14ee00b 2195 key = key_lookup_for_send (keychain);
718e3744 2196 }
b14ee00b 2197 /* to be passed to auth functions later */
2198 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
718e3744 2199 }
2200
727d104b 2201 if (version == RIPv1)
2202 {
c49ad8f1 2203 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
727d104b 2204 apply_classful_mask_ipv4 (&ifaddrclass);
2205 subnetted = 0;
c49ad8f1 2206 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
01d0908a 2207 subnetted = 1;
727d104b 2208 }
2209
718e3744 2210 for (rp = route_top (rip->table); rp; rp = route_next (rp))
bce8e868 2211 if ((list = rp->info) != NULL && listcount (list) != 0)
718e3744 2212 {
bce8e868 2213 rinfo = listgetdata (listhead (list));
727d104b 2214 /* For RIPv1, if we are subnetted, output subnets in our network */
2215 /* that have the same mask as the output "interface". For other */
2216 /* networks, only the classfull version is output. */
718e3744 2217
2218 if (version == RIPv1)
2219 {
727d104b 2220 p = (struct prefix_ipv4 *) &rp->p;
718e3744 2221
2222 if (IS_RIP_DEBUG_PACKET)
5d6c3779 2223 zlog_debug("RIPv1 mask check, %s/%d considered for output",
727d104b 2224 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
718e3744 2225
727d104b 2226 if (subnetted &&
2227 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2228 {
c49ad8f1 2229 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
727d104b 2230 (rp->p.prefixlen != 32))
2231 continue;
2232 }
2233 else
2234 {
2235 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2236 apply_classful_mask_ipv4(&classfull);
2237 if (rp->p.u.prefix4.s_addr != 0 &&
2238 classfull.prefixlen != rp->p.prefixlen)
2239 continue;
2240 }
718e3744 2241 if (IS_RIP_DEBUG_PACKET)
5d6c3779 2242 zlog_debug("RIPv1 mask check, %s/%d made it through",
727d104b 2243 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
718e3744 2244 }
2245 else
2246 p = (struct prefix_ipv4 *) &rp->p;
2247
2248 /* Apply output filters. */
7c989d74 2249 ret = rip_filter (RIP_FILTER_OUT, p, ri);
718e3744 2250 if (ret < 0)
2251 continue;
2252
2253 /* Changed route only output. */
2254 if (route_type == rip_changed_route &&
2255 (! (rinfo->flags & RIP_RTF_CHANGED)))
2256 continue;
2257
2258 /* Split horizon. */
2259 /* if (split_horizon == rip_split_horizon) */
16705130 2260 if (ri->split_horizon == RIP_SPLIT_HORIZON)
718e3744 2261 {
42d14d98 2262 /*
2263 * We perform split horizon for RIP and connected route.
2264 * For rip routes, we want to suppress the route if we would
2265 * end up sending the route back on the interface that we
2266 * learned it from, with a higher metric. For connected routes,
2267 * we suppress the route if the prefix is a subset of the
2268 * source address that we are going to use for the packet
2269 * (in order to handle the case when multiple subnets are
2270 * configured on the same interface).
2271 */
bce8e868
LF
2272 int suppress = 0;
2273 struct rip_info *tmp_rinfo = NULL;
2274
2275 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
2276 if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2277 tmp_rinfo->ifindex == ifc->ifp->ifindex)
2278 {
2279 suppress = 1;
2280 break;
2281 }
2282
2283 if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT &&
c49ad8f1 2284 prefix_match((struct prefix *)p, ifc->address))
bce8e868
LF
2285 suppress = 1;
2286
2287 if (suppress)
718e3744 2288 continue;
2289 }
2290
2291 /* Preparation for route-map. */
2292 rinfo->metric_set = 0;
2293 rinfo->nexthop_out.s_addr = 0;
2294 rinfo->metric_out = rinfo->metric;
16705130 2295 rinfo->tag_out = rinfo->tag;
c49ad8f1 2296 rinfo->ifindex_out = ifc->ifp->ifindex;
718e3744 2297
16705130 2298 /* In order to avoid some local loops,
2299 * if the RIP route has a nexthop via this interface, keep the nexthop,
2300 * otherwise set it to 0. The nexthop should not be propagated
2301 * beyond the local broadcast/multicast area in order
2302 * to avoid an IGP multi-level recursive look-up.
2303 * see (4.4)
2304 */
c49ad8f1 2305 if (rinfo->ifindex == ifc->ifp->ifindex)
718e3744 2306 rinfo->nexthop_out = rinfo->nexthop;
16705130 2307
2308 /* Interface route-map */
2309 if (ri->routemap[RIP_FILTER_OUT])
2310 {
2311 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2312 (struct prefix *) p, RMAP_RIP,
2313 rinfo);
2314
2315 if (ret == RMAP_DENYMATCH)
2316 {
2317 if (IS_RIP_DEBUG_PACKET)
5d6c3779 2318 zlog_debug ("RIP %s/%d is filtered by route-map out",
16705130 2319 inet_ntoa (p->prefix), p->prefixlen);
2320 continue;
2321 }
2322 }
718e3744 2323
16705130 2324 /* Apply redistribute route map - continue, if deny */
718e3744 2325 if (rip->route_map[rinfo->type].name
2326 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2327 {
2328 ret = route_map_apply (rip->route_map[rinfo->type].map,
2329 (struct prefix *)p, RMAP_RIP, rinfo);
2330
2331 if (ret == RMAP_DENYMATCH)
2332 {
2333 if (IS_RIP_DEBUG_PACKET)
5d6c3779 2334 zlog_debug ("%s/%d is filtered by route-map",
718e3744 2335 inet_ntoa (p->prefix), p->prefixlen);
2336 continue;
2337 }
2338 }
2339
2340 /* When route-map does not set metric. */
2341 if (! rinfo->metric_set)
2342 {
2343 /* If redistribute metric is set. */
2344 if (rip->route_map[rinfo->type].metric_config
2345 && rinfo->metric != RIP_METRIC_INFINITY)
2346 {
2347 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2348 }
2349 else
2350 {
2351 /* If the route is not connected or localy generated
2352 one, use default-metric value*/
2353 if (rinfo->type != ZEBRA_ROUTE_RIP
2354 && rinfo->type != ZEBRA_ROUTE_CONNECT
2355 && rinfo->metric != RIP_METRIC_INFINITY)
2356 rinfo->metric_out = rip->default_metric;
2357 }
2358 }
2359
2360 /* Apply offset-list */
2361 if (rinfo->metric != RIP_METRIC_INFINITY)
c49ad8f1 2362 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
718e3744 2363
2364 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2365 rinfo->metric_out = RIP_METRIC_INFINITY;
16705130 2366
2367 /* Perform split-horizon with poisoned reverse
2368 * for RIP and connected routes.
2369 **/
2370 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
42d14d98 2371 /*
2372 * We perform split horizon for RIP and connected route.
2373 * For rip routes, we want to suppress the route if we would
2374 * end up sending the route back on the interface that we
2375 * learned it from, with a higher metric. For connected routes,
2376 * we suppress the route if the prefix is a subset of the
2377 * source address that we are going to use for the packet
2378 * (in order to handle the case when multiple subnets are
2379 * configured on the same interface).
2380 */
bce8e868
LF
2381 struct rip_info *tmp_rinfo = NULL;
2382
2383 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
2384 if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2385 tmp_rinfo->ifindex == ifc->ifp->ifindex)
2386 rinfo->metric_out = RIP_METRIC_INFINITY;
2387 if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT &&
c49ad8f1 2388 prefix_match((struct prefix *)p, ifc->address))
bce8e868 2389 rinfo->metric_out = RIP_METRIC_INFINITY;
16705130 2390 }
b14ee00b 2391
2392 /* Prepare preamble, auth headers, if needs be */
2393 if (num == 0)
2394 {
2395 stream_putc (s, RIP_RESPONSE);
2396 stream_putc (s, version);
2397 stream_putw (s, 0);
2398
0cb8a01c 2399 /* auth header for !v1 && !no_auth */
2400 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
b14ee00b 2401 doff = rip_auth_header_write (s, ri, key, auth_str,
2402 RIP_AUTH_SIMPLE_SIZE);
2403 }
2404
718e3744 2405 /* Write RTE to the stream. */
b14ee00b 2406 num = rip_write_rte (num, s, p, version, rinfo);
718e3744 2407 if (num == rtemax)
2408 {
2409 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
b14ee00b 2410 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
718e3744 2411
2412 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
c49ad8f1 2413 to, ifc);
718e3744 2414
2415 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2416 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2417 stream_get_endp(s), "SEND");
2418 num = 0;
2419 stream_reset (s);
2420 }
2421 }
2422
2423 /* Flush unwritten RTE. */
2424 if (num != 0)
2425 {
2426 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
b14ee00b 2427 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
718e3744 2428
c49ad8f1 2429 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
718e3744 2430
2431 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2432 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2433 stream_get_endp (s), "SEND");
2434 num = 0;
2435 stream_reset (s);
2436 }
2437
2438 /* Statistics updates. */
2439 ri->sent_updates++;
2440}
2441
2442/* Send RIP packet to the interface. */
dc63bfd4 2443static void
c49ad8f1 2444rip_update_interface (struct connected *ifc, u_char version, int route_type)
718e3744 2445{
718e3744 2446 struct sockaddr_in to;
2447
2448 /* When RIP version is 2 and multicast enable interface. */
c49ad8f1 2449 if (version == RIPv2 && if_is_multicast (ifc->ifp))
718e3744 2450 {
2451 if (IS_RIP_DEBUG_EVENT)
5d6c3779 2452 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
718e3744 2453
c49ad8f1 2454 rip_output_process (ifc, NULL, route_type, version);
718e3744 2455 return;
2456 }
c49ad8f1 2457
718e3744 2458 /* If we can't send multicast packet, send it with unicast. */
c49ad8f1 2459 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
718e3744 2460 {
c49ad8f1 2461 if (ifc->address->family == AF_INET)
2462 {
2463 /* Destination address and port setting. */
2464 memset (&to, 0, sizeof (struct sockaddr_in));
2465 if (ifc->destination)
e4529636 2466 /* use specified broadcast or peer destination addr */
c49ad8f1 2467 to.sin_addr = ifc->destination->u.prefix4;
e4529636 2468 else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
c49ad8f1 2469 /* calculate the appropriate broadcast address */
2470 to.sin_addr.s_addr =
2471 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2472 ifc->address->prefixlen);
e4529636
AS
2473 else
2474 /* do not know where to send the packet */
2475 return;
c49ad8f1 2476 to.sin_port = htons (RIP_PORT_DEFAULT);
718e3744 2477
c49ad8f1 2478 if (IS_RIP_DEBUG_EVENT)
e4529636
AS
2479 zlog_debug("%s announce to %s on %s",
2480 CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
2481 inet_ntoa (to.sin_addr), ifc->ifp->name);
718e3744 2482
c49ad8f1 2483 rip_output_process (ifc, &to, route_type, version);
2484 }
718e3744 2485 }
2486}
2487
2488/* Update send to all interface and neighbor. */
dc63bfd4 2489static void
718e3744 2490rip_update_process (int route_type)
2491{
1eb8ef25 2492 struct listnode *node;
2493 struct listnode *ifnode, *ifnnode;
cc1131ab 2494 struct connected *connected;
718e3744 2495 struct interface *ifp;
2496 struct rip_interface *ri;
2497 struct route_node *rp;
2498 struct sockaddr_in to;
bd40c341 2499 struct prefix *p;
718e3744 2500
2501 /* Send RIP update to each interface. */
b2d7c082 2502 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
718e3744 2503 {
718e3744 2504 if (if_is_loopback (ifp))
2505 continue;
2506
2e3b2e47 2507 if (! if_is_operative (ifp))
718e3744 2508 continue;
2509
2510 /* Fetch RIP interface information. */
2511 ri = ifp->info;
2512
2513 /* When passive interface is specified, suppress announce to the
2514 interface. */
2515 if (ri->passive)
2516 continue;
2517
2518 if (ri->running)
2519 {
b9d92881
AS
2520 /*
2521 * If there is no version configuration in the interface,
2522 * use rip's version setting.
2523 */
2524 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2525 rip->version_send : ri->ri_send);
2526
718e3744 2527 if (IS_RIP_DEBUG_EVENT)
b9d92881 2528 zlog_debug("SEND UPDATE to %s ifindex %d",
85b123a4 2529 ifp->name, ifp->ifindex);
718e3744 2530
cc1131ab 2531 /* send update on each connected network */
1eb8ef25 2532 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
cc1131ab 2533 {
b9d92881
AS
2534 if (connected->address->family == AF_INET)
2535 {
2536 if (vsend & RIPv1)
2537 rip_update_interface (connected, RIPv1, route_type);
2538 if ((vsend & RIPv2) && if_is_multicast(ifp))
2539 rip_update_interface (connected, RIPv2, route_type);
2540 }
2541 }
718e3744 2542 }
2543 }
2544
2545 /* RIP send updates to each neighbor. */
2546 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2547 if (rp->info != NULL)
2548 {
bd40c341 2549 p = &rp->p;
718e3744 2550
bd40c341 2551 ifp = if_lookup_prefix (p);
718e3744 2552 if (! ifp)
2553 {
c49ad8f1 2554 zlog_warn ("Neighbor %s doesnt have connected interface!",
bd40c341 2555 inet_ntoa (p->u.prefix4));
718e3744 2556 continue;
2557 }
c49ad8f1 2558
bd40c341 2559 if ( (connected = connected_lookup_prefix (ifp, p)) == NULL)
c49ad8f1 2560 {
2561 zlog_warn ("Neighbor %s doesnt have connected network",
bd40c341 2562 inet_ntoa (p->u.prefix4));
c49ad8f1 2563 continue;
2564 }
2565
718e3744 2566 /* Set destination address and port */
2567 memset (&to, 0, sizeof (struct sockaddr_in));
bd40c341 2568 to.sin_addr = p->u.prefix4;
718e3744 2569 to.sin_port = htons (RIP_PORT_DEFAULT);
2570
2571 /* RIP version is rip's configuration. */
c49ad8f1 2572 rip_output_process (connected, &to, route_type, rip->version_send);
718e3744 2573 }
2574}
2575
2576/* RIP's periodical timer. */
dc63bfd4 2577static int
718e3744 2578rip_update (struct thread *t)
2579{
2580 /* Clear timer pointer. */
2581 rip->t_update = NULL;
2582
2583 if (IS_RIP_DEBUG_EVENT)
5d6c3779 2584 zlog_debug ("update timer fire!");
718e3744 2585
2586 /* Process update output. */
2587 rip_update_process (rip_all_route);
2588
2589 /* Triggered updates may be suppressed if a regular update is due by
2590 the time the triggered update would be sent. */
2591 if (rip->t_triggered_interval)
2592 {
2593 thread_cancel (rip->t_triggered_interval);
2594 rip->t_triggered_interval = NULL;
2595 }
2596 rip->trigger = 0;
2597
2598 /* Register myself. */
2599 rip_event (RIP_UPDATE_EVENT, 0);
2600
2601 return 0;
2602}
2603
2604/* Walk down the RIP routing table then clear changed flag. */
dc63bfd4 2605static void
216565ab 2606rip_clear_changed_flag (void)
718e3744 2607{
2608 struct route_node *rp;
bce8e868
LF
2609 struct rip_info *rinfo = NULL;
2610 struct list *list = NULL;
2611 struct listnode *listnode = NULL;
718e3744 2612
2613 for (rp = route_top (rip->table); rp; rp = route_next (rp))
bce8e868
LF
2614 if ((list = rp->info) != NULL)
2615 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
2616 {
2617 UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
2618 /* This flag can be set only on the first entry. */
2619 break;
2620 }
718e3744 2621}
2622
2623/* Triggered update interval timer. */
dc63bfd4 2624static int
718e3744 2625rip_triggered_interval (struct thread *t)
2626{
2627 int rip_triggered_update (struct thread *);
2628
2629 rip->t_triggered_interval = NULL;
2630
2631 if (rip->trigger)
2632 {
2633 rip->trigger = 0;
2634 rip_triggered_update (t);
2635 }
2636 return 0;
2637}
2638
2639/* Execute triggered update. */
dc63bfd4 2640static int
718e3744 2641rip_triggered_update (struct thread *t)
2642{
2643 int interval;
2644
2645 /* Clear thred pointer. */
2646 rip->t_triggered_update = NULL;
2647
2648 /* Cancel interval timer. */
2649 if (rip->t_triggered_interval)
2650 {
2651 thread_cancel (rip->t_triggered_interval);
2652 rip->t_triggered_interval = NULL;
2653 }
2654 rip->trigger = 0;
2655
2656 /* Logging triggered update. */
2657 if (IS_RIP_DEBUG_EVENT)
5d6c3779 2658 zlog_debug ("triggered update!");
718e3744 2659
2660 /* Split Horizon processing is done when generating triggered
2661 updates as well as normal updates (see section 2.6). */
2662 rip_update_process (rip_changed_route);
2663
2664 /* Once all of the triggered updates have been generated, the route
2665 change flags should be cleared. */
2666 rip_clear_changed_flag ();
2667
2668 /* After a triggered update is sent, a timer should be set for a
2669 random interval between 1 and 5 seconds. If other changes that
2670 would trigger updates occur before the timer expires, a single
2671 update is triggered when the timer expires. */
2672 interval = (random () % 5) + 1;
2673
2674 rip->t_triggered_interval =
2675 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2676
2677 return 0;
2678}
2679
2680/* Withdraw redistributed route. */
2681void
2682rip_redistribute_withdraw (int type)
2683{
2684 struct route_node *rp;
bce8e868
LF
2685 struct rip_info *rinfo = NULL;
2686 struct list *list = NULL;
718e3744 2687
2688 if (!rip)
2689 return;
2690
2691 for (rp = route_top (rip->table); rp; rp = route_next (rp))
bce8e868 2692 if ((list = rp->info) != NULL)
718e3744 2693 {
bce8e868 2694 rinfo = listgetdata (listhead (list));
718e3744 2695 if (rinfo->type == type
2696 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2697 {
2698 /* Perform poisoned reverse. */
2699 rinfo->metric = RIP_METRIC_INFINITY;
2700 RIP_TIMER_ON (rinfo->t_garbage_collect,
2701 rip_garbage_collect, rip->garbage_time);
2702 RIP_TIMER_OFF (rinfo->t_timeout);
2703 rinfo->flags |= RIP_RTF_CHANGED;
2704
16705130 2705 if (IS_RIP_DEBUG_EVENT) {
2706 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2707
5d6c3779 2708 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
16705130 2709 inet_ntoa(p->prefix), p->prefixlen,
2710 ifindex2ifname(rinfo->ifindex));
2711 }
2712
718e3744 2713 rip_event (RIP_TRIGGERED_UPDATE, 0);
2714 }
2715 }
2716}
2717
2718/* Create new RIP instance and set it to global variable. */
dc63bfd4 2719static int
2720rip_create (void)
718e3744 2721{
393deb9b 2722 rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
718e3744 2723
2724 /* Set initial value. */
f38a471c 2725 rip->version_send = RI_RIP_VERSION_2;
2726 rip->version_recv = RI_RIP_VERSION_1_AND_2;
718e3744 2727 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2728 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2729 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2730 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2731
2732 /* Initialize RIP routig table. */
2733 rip->table = route_table_init ();
2734 rip->route = route_table_init ();
2735 rip->neighbor = route_table_init ();
2736
2737 /* Make output stream. */
2738 rip->obuf = stream_new (1500);
2739
2740 /* Make socket. */
f69bd9da 2741 rip->sock = rip_create_socket (NULL);
718e3744 2742 if (rip->sock < 0)
2743 return rip->sock;
2744
2745 /* Create read and timer thread. */
2746 rip_event (RIP_READ, rip->sock);
2747 rip_event (RIP_UPDATE_EVENT, 1);
2748
2749 return 0;
2750}
2751
2752/* Sned RIP request to the destination. */
2753int
2754rip_request_send (struct sockaddr_in *to, struct interface *ifp,
931cd54d 2755 u_char version, struct connected *connected)
718e3744 2756{
2757 struct rte *rte;
2758 struct rip_packet rip_packet;
1eb8ef25 2759 struct listnode *node, *nnode;
718e3744 2760
2761 memset (&rip_packet, 0, sizeof (rip_packet));
2762
2763 rip_packet.command = RIP_REQUEST;
2764 rip_packet.version = version;
2765 rte = rip_packet.rte;
2766 rte->metric = htonl (RIP_METRIC_INFINITY);
2767
931cd54d 2768 if (connected)
2769 {
2770 /*
2771 * connected is only sent for ripv1 case, or when
2772 * interface does not support multicast. Caller loops
2773 * over each connected address for this case.
2774 */
11dde9c2 2775 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
c49ad8f1 2776 to, connected) != sizeof (rip_packet))
931cd54d 2777 return -1;
2778 else
2779 return sizeof (rip_packet);
2780 }
2781
cc1131ab 2782 /* send request on each connected network */
1eb8ef25 2783 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
cc1131ab 2784 {
2785 struct prefix_ipv4 *p;
2786
2787 p = (struct prefix_ipv4 *) connected->address;
2788
2789 if (p->family != AF_INET)
2790 continue;
2791
11dde9c2 2792 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
c49ad8f1 2793 to, connected) != sizeof (rip_packet))
cc1131ab 2794 return -1;
2795 }
2796 return sizeof (rip_packet);
718e3744 2797}
6b0655a2 2798
dc63bfd4 2799static int
718e3744 2800rip_update_jitter (unsigned long time)
2801{
239389ba 2802#define JITTER_BOUND 4
2803 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2804 Given that, we cannot let time be less than JITTER_BOUND seconds.
2805 The RIPv2 RFC says jitter should be small compared to
2806 update_time. We consider 1/JITTER_BOUND to be small.
2807 */
2808
2809 int jitter_input = time;
2810 int jitter;
2811
2812 if (jitter_input < JITTER_BOUND)
2813 jitter_input = JITTER_BOUND;
2814
b06fd125 2815 jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input));
239389ba 2816
2817 return jitter/JITTER_BOUND;
718e3744 2818}
2819
2820void
2821rip_event (enum rip_event event, int sock)
2822{
2823 int jitter = 0;
2824
2825 switch (event)
2826 {
2827 case RIP_READ:
2828 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2829 break;
2830 case RIP_UPDATE_EVENT:
2831 if (rip->t_update)
2832 {
2833 thread_cancel (rip->t_update);
2834 rip->t_update = NULL;
2835 }
2836 jitter = rip_update_jitter (rip->update_time);
2837 rip->t_update =
2838 thread_add_timer (master, rip_update, NULL,
2839 sock ? 2 : rip->update_time + jitter);
2840 break;
2841 case RIP_TRIGGERED_UPDATE:
2842 if (rip->t_triggered_interval)
2843 rip->trigger = 1;
2844 else if (! rip->t_triggered_update)
2845 rip->t_triggered_update =
2846 thread_add_event (master, rip_triggered_update, NULL, 0);
2847 break;
2848 default:
2849 break;
2850 }
2851}
6b0655a2 2852
718e3744 2853DEFUN (router_rip,
2854 router_rip_cmd,
2855 "router rip",
2856 "Enable a routing process\n"
2857 "Routing Information Protocol (RIP)\n")
2858{
2859 int ret;
2860
2861 /* If rip is not enabled before. */
2862 if (! rip)
2863 {
2864 ret = rip_create ();
2865 if (ret < 0)
2866 {
2867 zlog_info ("Can't create RIP");
2868 return CMD_WARNING;
2869 }
2870 }
2871 vty->node = RIP_NODE;
2872 vty->index = rip;
2873
2874 return CMD_SUCCESS;
2875}
2876
2877DEFUN (no_router_rip,
2878 no_router_rip_cmd,
2879 "no router rip",
2880 NO_STR
2881 "Enable a routing process\n"
2882 "Routing Information Protocol (RIP)\n")
2883{
2884 if (rip)
2885 rip_clean ();
2886 return CMD_SUCCESS;
2887}
2888
2889DEFUN (rip_version,
2890 rip_version_cmd,
2891 "version <1-2>",
2892 "Set routing protocol version\n"
2893 "version\n")
2894{
2895 int version;
2896
2897 version = atoi (argv[0]);
2898 if (version != RIPv1 && version != RIPv2)
2899 {
2900 vty_out (vty, "invalid rip version %d%s", version,
2901 VTY_NEWLINE);
2902 return CMD_WARNING;
2903 }
f38a471c 2904 rip->version_send = version;
2905 rip->version_recv = version;
718e3744 2906
2907 return CMD_SUCCESS;
2908}
2909
2910DEFUN (no_rip_version,
2911 no_rip_version_cmd,
2912 "no version",
2913 NO_STR
2914 "Set routing protocol version\n")
2915{
2916 /* Set RIP version to the default. */
f38a471c 2917 rip->version_send = RI_RIP_VERSION_2;
2918 rip->version_recv = RI_RIP_VERSION_1_AND_2;
718e3744 2919
2920 return CMD_SUCCESS;
2921}
2922
2923ALIAS (no_rip_version,
2924 no_rip_version_val_cmd,
2925 "no version <1-2>",
2926 NO_STR
2927 "Set routing protocol version\n"
2928 "version\n")
2929
2930DEFUN (rip_route,
2931 rip_route_cmd,
2932 "route A.B.C.D/M",
2933 "RIP static route configuration\n"
2934 "IP prefix <network>/<length>\n")
2935{
2936 int ret;
2937 struct prefix_ipv4 p;
2938 struct route_node *node;
2939
2940 ret = str2prefix_ipv4 (argv[0], &p);
2941 if (ret < 0)
2942 {
2943 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2944 return CMD_WARNING;
2945 }
2946 apply_mask_ipv4 (&p);
2947
2948 /* For router rip configuration. */
2949 node = route_node_get (rip->route, (struct prefix *) &p);
2950
2951 if (node->info)
2952 {
2953 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2954 route_unlock_node (node);
2955 return CMD_WARNING;
2956 }
2957
e5f745ca 2958 node->info = (void *)1;
718e3744 2959
9471675f 2960 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0, 0);
718e3744 2961
2962 return CMD_SUCCESS;
2963}
2964
2965DEFUN (no_rip_route,
2966 no_rip_route_cmd,
2967 "no route A.B.C.D/M",
2968 NO_STR
2969 "RIP static route configuration\n"
2970 "IP prefix <network>/<length>\n")
2971{
2972 int ret;
2973 struct prefix_ipv4 p;
2974 struct route_node *node;
2975
2976 ret = str2prefix_ipv4 (argv[0], &p);
2977 if (ret < 0)
2978 {
2979 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2980 return CMD_WARNING;
2981 }
2982 apply_mask_ipv4 (&p);
2983
2984 /* For router rip configuration. */
2985 node = route_node_lookup (rip->route, (struct prefix *) &p);
2986 if (! node)
2987 {
2988 vty_out (vty, "Can't find route %s.%s", argv[0],
2989 VTY_NEWLINE);
2990 return CMD_WARNING;
2991 }
2992
2993 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2994 route_unlock_node (node);
2995
2996 node->info = NULL;
2997 route_unlock_node (node);
2998
2999 return CMD_SUCCESS;
3000}
3001
2c239705 3002#if 0
dc63bfd4 3003static void
216565ab 3004rip_update_default_metric (void)
718e3744 3005{
3006 struct route_node *np;
bce8e868
LF
3007 struct rip_info *rinfo = NULL;
3008 struct list *list = NULL;
3009 struct listnode *listnode = NULL;
718e3744 3010
3011 for (np = route_top (rip->table); np; np = route_next (np))
bce8e868
LF
3012 if ((list = np->info) != NULL)
3013 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
3014 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3015 rinfo->metric = rip->default_metric;
718e3744 3016}
2c239705 3017#endif
718e3744 3018
3019DEFUN (rip_default_metric,
3020 rip_default_metric_cmd,
3021 "default-metric <1-16>",
3022 "Set a metric of redistribute routes\n"
3023 "Default metric\n")
3024{
3025 if (rip)
3026 {
3027 rip->default_metric = atoi (argv[0]);
3028 /* rip_update_default_metric (); */
3029 }
3030 return CMD_SUCCESS;
3031}
3032
3033DEFUN (no_rip_default_metric,
3034 no_rip_default_metric_cmd,
3035 "no default-metric",
3036 NO_STR
3037 "Set a metric of redistribute routes\n"
3038 "Default metric\n")
3039{
3040 if (rip)
3041 {
3042 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3043 /* rip_update_default_metric (); */
3044 }
3045 return CMD_SUCCESS;
3046}
3047
3048ALIAS (no_rip_default_metric,
3049 no_rip_default_metric_val_cmd,
3050 "no default-metric <1-16>",
3051 NO_STR
3052 "Set a metric of redistribute routes\n"
3053 "Default metric\n")
3054
3055DEFUN (rip_timers,
3056 rip_timers_cmd,
3057 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3058 "Adjust routing timers\n"
3059 "Basic routing protocol update timers\n"
3060 "Routing table update timer value in second. Default is 30.\n"
3061 "Routing information timeout timer. Default is 180.\n"
3062 "Garbage collection timer. Default is 120.\n")
3063{
3064 unsigned long update;
3065 unsigned long timeout;
3066 unsigned long garbage;
3067 char *endptr = NULL;
3068 unsigned long RIP_TIMER_MAX = 2147483647;
3069 unsigned long RIP_TIMER_MIN = 5;
3070
3071 update = strtoul (argv[0], &endptr, 10);
3072 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3073 {
3074 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3075 return CMD_WARNING;
3076 }
3077
3078 timeout = strtoul (argv[1], &endptr, 10);
3079 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3080 {
3081 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3082 return CMD_WARNING;
3083 }
3084
3085 garbage = strtoul (argv[2], &endptr, 10);
3086 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3087 {
3088 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3089 return CMD_WARNING;
3090 }
3091
3092 /* Set each timer value. */
3093 rip->update_time = update;
3094 rip->timeout_time = timeout;
3095 rip->garbage_time = garbage;
3096
3097 /* Reset update timer thread. */
3098 rip_event (RIP_UPDATE_EVENT, 0);
3099
3100 return CMD_SUCCESS;
3101}
3102
3103DEFUN (no_rip_timers,
3104 no_rip_timers_cmd,
3105 "no timers basic",
3106 NO_STR
3107 "Adjust routing timers\n"
3108 "Basic routing protocol update timers\n")
3109{
3110 /* Set each timer value to the default. */
3111 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3112 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3113 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3114
3115 /* Reset update timer thread. */
3116 rip_event (RIP_UPDATE_EVENT, 0);
3117
3118 return CMD_SUCCESS;
3119}
16705130 3120
3121ALIAS (no_rip_timers,
3122 no_rip_timers_val_cmd,
3123 "no timers basic <0-65535> <0-65535> <0-65535>",
3124 NO_STR
3125 "Adjust routing timers\n"
3126 "Basic routing protocol update timers\n"
3127 "Routing table update timer value in second. Default is 30.\n"
3128 "Routing information timeout timer. Default is 180.\n"
3129 "Garbage collection timer. Default is 120.\n")
3130
6b0655a2 3131
718e3744 3132struct route_table *rip_distance_table;
3133
3134struct rip_distance
3135{
3136 /* Distance value for the IP source prefix. */
3137 u_char distance;
3138
3139 /* Name of the access-list to be matched. */
3140 char *access_list;
3141};
3142
dc63bfd4 3143static struct rip_distance *
216565ab 3144rip_distance_new (void)
718e3744 3145{
393deb9b 3146 return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
718e3744 3147}
3148
dc63bfd4 3149static void
718e3744 3150rip_distance_free (struct rip_distance *rdistance)
3151{
3152 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3153}
3154
dc63bfd4 3155static int
98b718a9 3156rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3157 const char *access_list_str)
718e3744 3158{
3159 int ret;
3160 struct prefix_ipv4 p;
3161 u_char distance;
3162 struct route_node *rn;
3163 struct rip_distance *rdistance;
3164
3165 ret = str2prefix_ipv4 (ip_str, &p);
3166 if (ret == 0)
3167 {
3168 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3169 return CMD_WARNING;
3170 }
3171
3172 distance = atoi (distance_str);
3173
3174 /* Get RIP distance node. */
3175 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3176 if (rn->info)
3177 {
3178 rdistance = rn->info;
3179 route_unlock_node (rn);
3180 }
3181 else
3182 {
3183 rdistance = rip_distance_new ();
3184 rn->info = rdistance;
3185 }
3186
3187 /* Set distance value. */
3188 rdistance->distance = distance;
3189
3190 /* Reset access-list configuration. */
3191 if (rdistance->access_list)
3192 {
3193 free (rdistance->access_list);
3194 rdistance->access_list = NULL;
3195 }
3196 if (access_list_str)
3197 rdistance->access_list = strdup (access_list_str);
3198
3199 return CMD_SUCCESS;
3200}
3201
dc63bfd4 3202static int
98b718a9 3203rip_distance_unset (struct vty *vty, const char *distance_str,
3204 const char *ip_str, const char *access_list_str)
718e3744 3205{
3206 int ret;
3207 struct prefix_ipv4 p;
718e3744 3208 struct route_node *rn;
3209 struct rip_distance *rdistance;
3210
3211 ret = str2prefix_ipv4 (ip_str, &p);
3212 if (ret == 0)
3213 {
3214 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3215 return CMD_WARNING;
3216 }
3217
718e3744 3218 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3219 if (! rn)
3220 {
3221 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3222 return CMD_WARNING;
3223 }
3224
3225 rdistance = rn->info;
3226
3227 if (rdistance->access_list)
3228 free (rdistance->access_list);
3229 rip_distance_free (rdistance);
3230
3231 rn->info = NULL;
3232 route_unlock_node (rn);
3233 route_unlock_node (rn);
3234
3235 return CMD_SUCCESS;
3236}
3237
dc63bfd4 3238static void
216565ab 3239rip_distance_reset (void)
718e3744 3240{
3241 struct route_node *rn;
3242 struct rip_distance *rdistance;
3243
3244 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3245 if ((rdistance = rn->info) != NULL)
3246 {
3247 if (rdistance->access_list)
3248 free (rdistance->access_list);
3249 rip_distance_free (rdistance);
3250 rn->info = NULL;
3251 route_unlock_node (rn);
3252 }
3253}
3254
3255/* Apply RIP information to distance method. */
3256u_char
3257rip_distance_apply (struct rip_info *rinfo)
3258{
3259 struct route_node *rn;
3260 struct prefix_ipv4 p;
3261 struct rip_distance *rdistance;
3262 struct access_list *alist;
3263
3264 if (! rip)
3265 return 0;
3266
3267 memset (&p, 0, sizeof (struct prefix_ipv4));
3268 p.family = AF_INET;
3269 p.prefix = rinfo->from;
3270 p.prefixlen = IPV4_MAX_BITLEN;
3271
3272 /* Check source address. */
3273 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3274 if (rn)
3275 {
3276 rdistance = rn->info;
3277 route_unlock_node (rn);
3278
3279 if (rdistance->access_list)
3280 {
3281 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3282 if (alist == NULL)
3283 return 0;
3284 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3285 return 0;
3286
3287 return rdistance->distance;
3288 }
3289 else
3290 return rdistance->distance;
3291 }
3292
3293 if (rip->distance)
3294 return rip->distance;
3295
3296 return 0;
3297}
3298
dc63bfd4 3299static void
718e3744 3300rip_distance_show (struct vty *vty)
3301{
3302 struct route_node *rn;
3303 struct rip_distance *rdistance;
3304 int header = 1;
3305 char buf[BUFSIZ];
3306
3307 vty_out (vty, " Distance: (default is %d)%s",
3308 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3309 VTY_NEWLINE);
3310
3311 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3312 if ((rdistance = rn->info) != NULL)
3313 {
3314 if (header)
3315 {
3316 vty_out (vty, " Address Distance List%s",
3317 VTY_NEWLINE);
3318 header = 0;
3319 }
3320 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3321 vty_out (vty, " %-20s %4d %s%s",
3322 buf, rdistance->distance,
3323 rdistance->access_list ? rdistance->access_list : "",
3324 VTY_NEWLINE);
3325 }
3326}
3327
3328DEFUN (rip_distance,
3329 rip_distance_cmd,
3330 "distance <1-255>",
3331 "Administrative distance\n"
3332 "Distance value\n")
3333{
3334 rip->distance = atoi (argv[0]);
3335 return CMD_SUCCESS;
3336}
3337
3338DEFUN (no_rip_distance,
3339 no_rip_distance_cmd,
3340 "no distance <1-255>",
3341 NO_STR
3342 "Administrative distance\n"
3343 "Distance value\n")
3344{
3345 rip->distance = 0;
3346 return CMD_SUCCESS;
3347}
3348
3349DEFUN (rip_distance_source,
3350 rip_distance_source_cmd,
3351 "distance <1-255> A.B.C.D/M",
3352 "Administrative distance\n"
3353 "Distance value\n"
3354 "IP source prefix\n")
3355{
3356 rip_distance_set (vty, argv[0], argv[1], NULL);
3357 return CMD_SUCCESS;
3358}
3359
3360DEFUN (no_rip_distance_source,
3361 no_rip_distance_source_cmd,
3362 "no distance <1-255> A.B.C.D/M",
3363 NO_STR
3364 "Administrative distance\n"
3365 "Distance value\n"
3366 "IP source prefix\n")
3367{
3368 rip_distance_unset (vty, argv[0], argv[1], NULL);
3369 return CMD_SUCCESS;
3370}
3371
3372DEFUN (rip_distance_source_access_list,
3373 rip_distance_source_access_list_cmd,
3374 "distance <1-255> A.B.C.D/M WORD",
3375 "Administrative distance\n"
3376 "Distance value\n"
3377 "IP source prefix\n"
3378 "Access list name\n")
3379{
3380 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3381 return CMD_SUCCESS;
3382}
3383
3384DEFUN (no_rip_distance_source_access_list,
3385 no_rip_distance_source_access_list_cmd,
3386 "no distance <1-255> A.B.C.D/M WORD",
3387 NO_STR
3388 "Administrative distance\n"
3389 "Distance value\n"
3390 "IP source prefix\n"
3391 "Access list name\n")
3392{
3393 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3394 return CMD_SUCCESS;
3395}
6b0655a2 3396
8478ae7e
LF
3397/* Update ECMP routes to zebra when ECMP is disabled. */
3398static void
3399rip_ecmp_disable (void)
3400{
3401 struct route_node *rp;
3402 struct rip_info *rinfo, *tmp_rinfo;
3403 struct list *list;
3404 struct listnode *node, *nextnode;
3405
3406 if (!rip)
3407 return;
3408
3409 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3410 if ((list = rp->info) != NULL && listcount (list) > 1)
3411 {
3412 rinfo = listgetdata (listhead (list));
3413 if (!rip_route_rte (rinfo))
3414 continue;
3415
3416 /* Drop all other entries, except the first one. */
3417 for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
3418 if (tmp_rinfo != rinfo)
3419 {
3420 RIP_TIMER_OFF (tmp_rinfo->t_timeout);
3421 RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
3422 list_delete_node (list, node);
3423 rip_info_free (tmp_rinfo);
3424 }
3425
3426 /* Update zebra. */
3427 rip_zebra_ipv4_add (rp);
3428
3429 /* Set the route change flag. */
3430 SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
3431
3432 /* Signal the output process to trigger an update. */
3433 rip_event (RIP_TRIGGERED_UPDATE, 0);
3434 }
3435}
3436
3437DEFUN (rip_allow_ecmp,
3438 rip_allow_ecmp_cmd,
3439 "allow-ecmp",
3440 "Allow Equal Cost MultiPath\n")
3441{
3442 if (rip->ecmp)
3443 {
3444 vty_out (vty, "ECMP is already enabled.%s", VTY_NEWLINE);
3445 return CMD_WARNING;
3446 }
3447
3448 rip->ecmp = 1;
3449 zlog_info ("ECMP is enabled.");
3450 return CMD_SUCCESS;
3451}
3452
3453DEFUN (no_rip_allow_ecmp,
3454 no_rip_allow_ecmp_cmd,
3455 "no allow-ecmp",
3456 NO_STR
3457 "Allow Equal Cost MultiPath\n")
3458{
3459 if (!rip->ecmp)
3460 {
3461 vty_out (vty, "ECMP is already disabled.%s", VTY_NEWLINE);
3462 return CMD_WARNING;
3463 }
3464
3465 rip->ecmp = 0;
3466 zlog_info ("ECMP is disabled.");
3467 rip_ecmp_disable ();
3468 return CMD_SUCCESS;
3469}
3470
718e3744 3471/* Print out routes update time. */
dc63bfd4 3472static void
718e3744 3473rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3474{
718e3744 3475 time_t clock;
3476 struct tm *tm;
3477#define TIME_BUF 25
3478 char timebuf [TIME_BUF];
3479 struct thread *thread;
3480
718e3744 3481 if ((thread = rinfo->t_timeout) != NULL)
3482 {
a1fdf947 3483 clock = thread_timer_remain_second (thread);
718e3744 3484 tm = gmtime (&clock);
3485 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3486 vty_out (vty, "%5s", timebuf);
3487 }
3488 else if ((thread = rinfo->t_garbage_collect) != NULL)
3489 {
a1fdf947 3490 clock = thread_timer_remain_second (thread);
718e3744 3491 tm = gmtime (&clock);
3492 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3493 vty_out (vty, "%5s", timebuf);
3494 }
3495}
3496
dc63bfd4 3497static const char *
718e3744 3498rip_route_type_print (int sub_type)
3499{
3500 switch (sub_type)
3501 {
3502 case RIP_ROUTE_RTE:
3503 return "n";
3504 case RIP_ROUTE_STATIC:
3505 return "s";
3506 case RIP_ROUTE_DEFAULT:
3507 return "d";
3508 case RIP_ROUTE_REDISTRIBUTE:
3509 return "r";
3510 case RIP_ROUTE_INTERFACE:
3511 return "i";
3512 default:
3513 return "?";
3514 }
3515}
3516
3517DEFUN (show_ip_rip,
3518 show_ip_rip_cmd,
3519 "show ip rip",
3520 SHOW_STR
3521 IP_STR
3522 "Show RIP routes\n")
3523{
3524 struct route_node *np;
bce8e868
LF
3525 struct rip_info *rinfo = NULL;
3526 struct list *list = NULL;
3527 struct listnode *listnode = NULL;
718e3744 3528
3529 if (! rip)
3530 return CMD_SUCCESS;
3531
16705130 3532 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3533 "Sub-codes:%s"
3534 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
718e3744 3535 " (i) - interface%s%s"
a1455d86 3536 " Network Next Hop Metric From Tag Time%s",
16705130 3537 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
718e3744 3538
3539 for (np = route_top (rip->table); np; np = route_next (np))
bce8e868
LF
3540 if ((list = np->info) != NULL)
3541 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
718e3744 3542 {
3543 int len;
3544
f52d13cb 3545 len = vty_out (vty, "%c(%s) %s/%d",
718e3744 3546 /* np->lock, For debugging. */
f52d13cb 3547 zebra_route_char(rinfo->type),
718e3744 3548 rip_route_type_print (rinfo->sub_type),
3549 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3550
a1455d86 3551 len = 24 - len;
718e3744 3552
3553 if (len > 0)
3554 vty_out (vty, "%*s", len, " ");
3555
3556 if (rinfo->nexthop.s_addr)
3557 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3558 rinfo->metric);
3559 else
3560 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3561
3562 /* Route which exist in kernel routing table. */
3563 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3564 (rinfo->sub_type == RIP_ROUTE_RTE))
3565 {
3566 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
dc9ffce8 3567 vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag);
718e3744 3568 rip_vty_out_uptime (vty, rinfo);
3569 }
3570 else if (rinfo->metric == RIP_METRIC_INFINITY)
3571 {
3572 vty_out (vty, "self ");
dc9ffce8 3573 vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag);
718e3744 3574 rip_vty_out_uptime (vty, rinfo);
3575 }
3576 else
16705130 3577 {
fbf5d033 3578 if (rinfo->external_metric)
3579 {
3580 len = vty_out (vty, "self (%s:%d)",
f52d13cb 3581 zebra_route_string(rinfo->type),
fbf5d033 3582 rinfo->external_metric);
3583 len = 16 - len;
3584 if (len > 0)
3585 vty_out (vty, "%*s", len, " ");
3586 }
3587 else
3588 vty_out (vty, "self ");
dc9ffce8 3589 vty_out (vty, "%3"ROUTE_TAG_PRI, (route_tag_t)rinfo->tag);
16705130 3590 }
718e3744 3591
3592 vty_out (vty, "%s", VTY_NEWLINE);
3593 }
3594 return CMD_SUCCESS;
3595}
3596
16705130 3597/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3598DEFUN (show_ip_rip_status,
3599 show_ip_rip_status_cmd,
3600 "show ip rip status",
718e3744 3601 SHOW_STR
3602 IP_STR
16705130 3603 "Show RIP routes\n"
718e3744 3604 "IP routing protocol process parameters and statistics\n")
3605{
52dc7ee6 3606 struct listnode *node;
718e3744 3607 struct interface *ifp;
3608 struct rip_interface *ri;
1423c809 3609 extern const struct message ri_version_msg[];
8a676be3 3610 const char *send_version;
3611 const char *receive_version;
718e3744 3612
3613 if (! rip)
3614 return CMD_SUCCESS;
3615
3616 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3617 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3618 rip->update_time);
a4c64828
AS
3619 vty_out (vty, " next due in %lu seconds%s",
3620 thread_timer_remain_second(rip->t_update),
718e3744 3621 VTY_NEWLINE);
3622 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3623 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3624 VTY_NEWLINE);
3625
3626 /* Filtering status show. */
3627 config_show_distribute (vty);
3628
3629 /* Default metric information. */
3630 vty_out (vty, " Default redistribution metric is %d%s",
3631 rip->default_metric, VTY_NEWLINE);
3632
3633 /* Redistribute information. */
3634 vty_out (vty, " Redistributing:");
3635 config_write_rip_redistribute (vty, 0);
3636 vty_out (vty, "%s", VTY_NEWLINE);
3637
f38a471c 3638 vty_out (vty, " Default version control: send version %s,",
3639 lookup(ri_version_msg,rip->version_send));
3640 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3641 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3642 else
3643 vty_out (vty, " receive version %s %s",
3644 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
718e3744 3645
3646 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3647
b2d7c082 3648 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
718e3744 3649 {
718e3744 3650 ri = ifp->info;
3651
82f5ee1e
SH
3652 if (!ri->running)
3653 continue;
3654
718e3744 3655 if (ri->enable_network || ri->enable_interface)
3656 {
3657 if (ri->ri_send == RI_RIP_UNSPEC)
f38a471c 3658 send_version = lookup (ri_version_msg, rip->version_send);
718e3744 3659 else
3660 send_version = lookup (ri_version_msg, ri->ri_send);
3661
3662 if (ri->ri_receive == RI_RIP_UNSPEC)
f38a471c 3663 receive_version = lookup (ri_version_msg, rip->version_recv);
718e3744 3664 else
3665 receive_version = lookup (ri_version_msg, ri->ri_receive);
3666
3667 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3668 send_version,
3669 receive_version,
3670 ri->key_chain ? ri->key_chain : "",
3671 VTY_NEWLINE);
3672 }
3673 }
3674
3675 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3676 config_write_rip_network (vty, 0);
3677
4aaff3f8 3678 {
3679 int found_passive = 0;
b2d7c082 3680 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
4aaff3f8 3681 {
4aaff3f8 3682 ri = ifp->info;
3683
3684 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3685 {
3686 if (!found_passive)
3687 {
3688 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3689 found_passive = 1;
3690 }
3691 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3692 }
3693 }
3694 }
3695
718e3744 3696 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3697 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3698 rip_peer_display (vty);
3699
3700 rip_distance_show (vty);
3701
3702 return CMD_SUCCESS;
3703}
3704
3705/* RIP configuration write function. */
dc63bfd4 3706static int
718e3744 3707config_write_rip (struct vty *vty)
3708{
3709 int write = 0;
3710 struct route_node *rn;
3711 struct rip_distance *rdistance;
3712
3713 if (rip)
3714 {
3715 /* Router RIP statement. */
3716 vty_out (vty, "router rip%s", VTY_NEWLINE);
3717 write++;
3718
3719 /* RIP version statement. Default is RIP version 2. */
f38a471c 3720 if (rip->version_send != RI_RIP_VERSION_2
3721 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3722 vty_out (vty, " version %d%s", rip->version_send,
718e3744 3723 VTY_NEWLINE);
3724
3725 /* RIP timer configuration. */
3726 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3727 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3728 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3729 vty_out (vty, " timers basic %lu %lu %lu%s",
3730 rip->update_time,
3731 rip->timeout_time,
3732 rip->garbage_time,
3733 VTY_NEWLINE);
3734
3735 /* Default information configuration. */
3736 if (rip->default_information)
3737 {
3738 if (rip->default_information_route_map)
3739 vty_out (vty, " default-information originate route-map %s%s",
3740 rip->default_information_route_map, VTY_NEWLINE);
3741 else
3742 vty_out (vty, " default-information originate%s",
3743 VTY_NEWLINE);
3744 }
3745
3746 /* Redistribute configuration. */
3747 config_write_rip_redistribute (vty, 1);
3748
3749 /* RIP offset-list configuration. */
3750 config_write_rip_offset_list (vty);
3751
3752 /* RIP enabled network and interface configuration. */
3753 config_write_rip_network (vty, 1);
3754
3755 /* RIP default metric configuration */
3756 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3757 vty_out (vty, " default-metric %d%s",
3758 rip->default_metric, VTY_NEWLINE);
3759
3760 /* Distribute configuration. */
3761 write += config_write_distribute (vty);
3762
16705130 3763 /* Interface routemap configuration */
3764 write += config_write_if_rmap (vty);
3765
718e3744 3766 /* Distance configuration. */
3767 if (rip->distance)
3768 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3769
3770 /* RIP source IP prefix distance configuration. */
3771 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3772 if ((rdistance = rn->info) != NULL)
3773 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3774 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3775 rdistance->access_list ? rdistance->access_list : "",
3776 VTY_NEWLINE);
3777
8478ae7e
LF
3778 /* ECMP configuration. */
3779 if (rip->ecmp)
3780 vty_out (vty, " allow-ecmp%s", VTY_NEWLINE);
3781
718e3744 3782 /* RIP static route configuration. */
3783 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3784 if (rn->info)
3785 vty_out (vty, " route %s/%d%s",
3786 inet_ntoa (rn->p.u.prefix4),
3787 rn->p.prefixlen,
3788 VTY_NEWLINE);
3789
3790 }
3791 return write;
3792}
3793
3794/* RIP node structure. */
7fc626de 3795static struct cmd_node rip_node =
718e3744 3796{
3797 RIP_NODE,
3798 "%s(config-router)# ",
3799 1
3800};
6b0655a2 3801
718e3744 3802/* Distribute-list update functions. */
dc63bfd4 3803static void
718e3744 3804rip_distribute_update (struct distribute *dist)
3805{
3806 struct interface *ifp;
3807 struct rip_interface *ri;
3808 struct access_list *alist;
3809 struct prefix_list *plist;
3810
3811 if (! dist->ifname)
3812 return;
3813
3814 ifp = if_lookup_by_name (dist->ifname);
3815 if (ifp == NULL)
3816 return;
3817
3818 ri = ifp->info;
3819
fb23cf4a 3820 if (dist->list[DISTRIBUTE_V4_IN])
718e3744 3821 {
fb23cf4a 3822 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]);
718e3744 3823 if (alist)
3824 ri->list[RIP_FILTER_IN] = alist;
3825 else
3826 ri->list[RIP_FILTER_IN] = NULL;
3827 }
3828 else
3829 ri->list[RIP_FILTER_IN] = NULL;
3830
fb23cf4a 3831 if (dist->list[DISTRIBUTE_V4_OUT])
718e3744 3832 {
fb23cf4a 3833 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]);
718e3744 3834 if (alist)
3835 ri->list[RIP_FILTER_OUT] = alist;
3836 else
3837 ri->list[RIP_FILTER_OUT] = NULL;
3838 }
3839 else
3840 ri->list[RIP_FILTER_OUT] = NULL;
3841
fb23cf4a 3842 if (dist->prefix[DISTRIBUTE_V4_IN])
718e3744 3843 {
fb23cf4a 3844 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]);
718e3744 3845 if (plist)
3846 ri->prefix[RIP_FILTER_IN] = plist;
3847 else
3848 ri->prefix[RIP_FILTER_IN] = NULL;
3849 }
3850 else
3851 ri->prefix[RIP_FILTER_IN] = NULL;
3852
fb23cf4a 3853 if (dist->prefix[DISTRIBUTE_V4_OUT])
718e3744 3854 {
fb23cf4a 3855 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]);
718e3744 3856 if (plist)
3857 ri->prefix[RIP_FILTER_OUT] = plist;
3858 else
3859 ri->prefix[RIP_FILTER_OUT] = NULL;
3860 }
3861 else
3862 ri->prefix[RIP_FILTER_OUT] = NULL;
3863}
3864
3865void
3866rip_distribute_update_interface (struct interface *ifp)
3867{
3868 struct distribute *dist;
3869
3870 dist = distribute_lookup (ifp->name);
3871 if (dist)
3872 rip_distribute_update (dist);
3873}
3874
3875/* Update all interface's distribute list. */
02ff83c5 3876/* ARGSUSED */
dc63bfd4 3877static void
02ff83c5 3878rip_distribute_update_all (struct prefix_list *notused)
718e3744 3879{
3880 struct interface *ifp;
1eb8ef25 3881 struct listnode *node, *nnode;
718e3744 3882
b2d7c082 3883 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
1eb8ef25 3884 rip_distribute_update_interface (ifp);
718e3744 3885}
11dde9c2 3886/* ARGSUSED */
dc63bfd4 3887static void
11dde9c2 3888rip_distribute_update_all_wrapper(struct access_list *notused)
3889{
02ff83c5 3890 rip_distribute_update_all(NULL);
11dde9c2 3891}
6b0655a2 3892
718e3744 3893/* Delete all added rip route. */
3894void
216565ab 3895rip_clean (void)
718e3744 3896{
3897 int i;
3898 struct route_node *rp;
bce8e868
LF
3899 struct rip_info *rinfo = NULL;
3900 struct list *list = NULL;
3901 struct listnode *listnode = NULL;
718e3744 3902
3903 if (rip)
3904 {
3905 /* Clear RIP routes */
3906 for (rp = route_top (rip->table); rp; rp = route_next (rp))
bce8e868
LF
3907 if ((list = rp->info) != NULL)
3908 {
3909 rinfo = listgetdata (listhead (list));
3910 if (rip_route_rte (rinfo))
3911 rip_zebra_ipv4_delete (rp);
3912
3913 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
3914 {
3915 RIP_TIMER_OFF (rinfo->t_timeout);
3916 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3917 rip_info_free (rinfo);
3918 }
3919 list_delete (list);
3920 rp->info = NULL;
3921 route_unlock_node (rp);
3922 }
718e3744 3923
3924 /* Cancel RIP related timers. */
3925 RIP_TIMER_OFF (rip->t_update);
3926 RIP_TIMER_OFF (rip->t_triggered_update);
3927 RIP_TIMER_OFF (rip->t_triggered_interval);
3928
3929 /* Cancel read thread. */
3930 if (rip->t_read)
3931 {
3932 thread_cancel (rip->t_read);
3933 rip->t_read = NULL;
3934 }
3935
3936 /* Close RIP socket. */
3937 if (rip->sock >= 0)
3938 {
3939 close (rip->sock);
3940 rip->sock = -1;
3941 }
3942
3943 /* Static RIP route configuration. */
3944 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3945 if (rp->info)
3946 {
3947 rp->info = NULL;
3948 route_unlock_node (rp);
3949 }
3950
3951 /* RIP neighbor configuration. */
3952 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3953 if (rp->info)
3954 {
3955 rp->info = NULL;
3956 route_unlock_node (rp);
3957 }
3958
3959 /* Redistribute related clear. */
3960 if (rip->default_information_route_map)
3961 free (rip->default_information_route_map);
3962
3963 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3964 if (rip->route_map[i].name)
3965 free (rip->route_map[i].name);
3966
3967 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3968 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3969 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3970
3971 XFREE (MTYPE_RIP, rip);
3972 rip = NULL;
3973 }
3974
3975 rip_clean_network ();
4aaff3f8 3976 rip_passive_nondefault_clean ();
718e3744 3977 rip_offset_clean ();
1dec2166 3978 rip_interfaces_clean ();
718e3744 3979 rip_distance_reset ();
3980 rip_redistribute_clean ();
3981}
3982
3983/* Reset all values to the default settings. */
3984void
216565ab 3985rip_reset (void)
718e3744 3986{
3987 /* Reset global counters. */
3988 rip_global_route_changes = 0;
3989 rip_global_queries = 0;
3990
3991 /* Call ripd related reset functions. */
3992 rip_debug_reset ();
3993 rip_route_map_reset ();
3994
3995 /* Call library reset functions. */
3996 vty_reset ();
3997 access_list_reset ();
3998 prefix_list_reset ();
3999
4000 distribute_list_reset ();
4001
1dec2166 4002 rip_interfaces_reset ();
718e3744 4003 rip_distance_reset ();
4004
4005 rip_zclient_reset ();
4006}
4007
dc63bfd4 4008static void
16705130 4009rip_if_rmap_update (struct if_rmap *if_rmap)
4010{
4011 struct interface *ifp;
4012 struct rip_interface *ri;
4013 struct route_map *rmap;
4014
4015 ifp = if_lookup_by_name (if_rmap->ifname);
4016 if (ifp == NULL)
4017 return;
4018
4019 ri = ifp->info;
4020
4021 if (if_rmap->routemap[IF_RMAP_IN])
4022 {
4023 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
4024 if (rmap)
4025 ri->routemap[IF_RMAP_IN] = rmap;
4026 else
4027 ri->routemap[IF_RMAP_IN] = NULL;
4028 }
4029 else
4030 ri->routemap[RIP_FILTER_IN] = NULL;
4031
4032 if (if_rmap->routemap[IF_RMAP_OUT])
4033 {
4034 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
4035 if (rmap)
4036 ri->routemap[IF_RMAP_OUT] = rmap;
4037 else
4038 ri->routemap[IF_RMAP_OUT] = NULL;
4039 }
4040 else
4041 ri->routemap[RIP_FILTER_OUT] = NULL;
4042}
4043
4044void
4045rip_if_rmap_update_interface (struct interface *ifp)
4046{
4047 struct if_rmap *if_rmap;
4048
4049 if_rmap = if_rmap_lookup (ifp->name);
4050 if (if_rmap)
4051 rip_if_rmap_update (if_rmap);
4052}
4053
dc63bfd4 4054static void
16705130 4055rip_routemap_update_redistribute (void)
4056{
4057 int i;
4058
4059 if (rip)
4060 {
4061 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
4062 {
4063 if (rip->route_map[i].name)
4064 rip->route_map[i].map =
4065 route_map_lookup_by_name (rip->route_map[i].name);
4066 }
4067 }
4068}
4069
11dde9c2 4070/* ARGSUSED */
dc63bfd4 4071static void
98b718a9 4072rip_routemap_update (const char *notused)
16705130 4073{
4074 struct interface *ifp;
1eb8ef25 4075 struct listnode *node, *nnode;
16705130 4076
b2d7c082 4077 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
1eb8ef25 4078 rip_if_rmap_update_interface (ifp);
16705130 4079
4080 rip_routemap_update_redistribute ();
4081}
4082
718e3744 4083/* Allocate new rip structure and set default value. */
4084void
dc63bfd4 4085rip_init (void)
718e3744 4086{
4087 /* Randomize for triggered update random(). */
b06fd125 4088 srandom (time (NULL));
718e3744 4089
4090 /* Install top nodes. */
4091 install_node (&rip_node, config_write_rip);
4092
4093 /* Install rip commands. */
4094 install_element (VIEW_NODE, &show_ip_rip_cmd);
16705130 4095 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
718e3744 4096 install_element (CONFIG_NODE, &router_rip_cmd);
4097 install_element (CONFIG_NODE, &no_router_rip_cmd);
4098
4099 install_default (RIP_NODE);
4100 install_element (RIP_NODE, &rip_version_cmd);
4101 install_element (RIP_NODE, &no_rip_version_cmd);
4102 install_element (RIP_NODE, &no_rip_version_val_cmd);
4103 install_element (RIP_NODE, &rip_default_metric_cmd);
4104 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4105 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4106 install_element (RIP_NODE, &rip_timers_cmd);
4107 install_element (RIP_NODE, &no_rip_timers_cmd);
16705130 4108 install_element (RIP_NODE, &no_rip_timers_val_cmd);
718e3744 4109 install_element (RIP_NODE, &rip_route_cmd);
4110 install_element (RIP_NODE, &no_rip_route_cmd);
4111 install_element (RIP_NODE, &rip_distance_cmd);
4112 install_element (RIP_NODE, &no_rip_distance_cmd);
4113 install_element (RIP_NODE, &rip_distance_source_cmd);
4114 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4115 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4116 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
8478ae7e
LF
4117 install_element (RIP_NODE, &rip_allow_ecmp_cmd);
4118 install_element (RIP_NODE, &no_rip_allow_ecmp_cmd);
718e3744 4119
4120 /* Debug related init. */
4121 rip_debug_init ();
4122
718e3744 4123 /* SNMP init. */
4124#ifdef HAVE_SNMP
4125 rip_snmp_init ();
4126#endif /* HAVE_SNMP */
4127
4128 /* Access list install. */
4129 access_list_init ();
11dde9c2 4130 access_list_add_hook (rip_distribute_update_all_wrapper);
4131 access_list_delete_hook (rip_distribute_update_all_wrapper);
718e3744 4132
4133 /* Prefix list initialize.*/
4134 prefix_list_init ();
4135 prefix_list_add_hook (rip_distribute_update_all);
4136 prefix_list_delete_hook (rip_distribute_update_all);
4137
4138 /* Distribute list install. */
4139 distribute_list_init (RIP_NODE);
4140 distribute_list_add_hook (rip_distribute_update);
4141 distribute_list_delete_hook (rip_distribute_update);
4142
16705130 4143 /* Route-map */
4144 rip_route_map_init ();
4145 rip_offset_init ();
4146
4147 route_map_add_hook (rip_routemap_update);
4148 route_map_delete_hook (rip_routemap_update);
4149
4150 if_rmap_init (RIP_NODE);
4151 if_rmap_hook_add (rip_if_rmap_update);
4152 if_rmap_hook_delete (rip_if_rmap_update);
4153
718e3744 4154 /* Distance control. */
4155 rip_distance_table = route_table_init ();
4156}