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