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