blob: 22777e504eeed43bfc40a0f0e28f40438d78c7e1 [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;
390 struct rip_info *rinfo;
391 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
563 /* Next, compare the metrics. If the datagram is from the same
564 router as the existing route, and the new metric is different
565 than the old one; or, if the new metric is lower than the old
hasso16705132003-05-25 14:49:19 +0000566 one, or if the tag has been changed; do the following actions: */
paul718e3742002-12-13 20:15:29 +0000567 if ((same && rinfo->metric != rte->metric) ||
hasso16705132003-05-25 14:49:19 +0000568 (rte->metric < rinfo->metric) ||
569 (same && (rinfo->metric == rte->metric) && ntohs(rte->tag) != rinfo->tag))
paul718e3742002-12-13 20:15:29 +0000570 {
571 /* - Adopt the route from the datagram. That is, put the
572 new metric in, and adjust the next hop address (if
573 necessary). */
574 oldmetric = rinfo->metric;
575 rinfo->metric = rte->metric;
576 rinfo->tag = ntohs (rte->tag);
577 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
578 rinfo->ifindex = ifp->ifindex;
579 rinfo->distance = rip_distance_apply (rinfo);
580
581 /* Should a new route to this network be established
582 while the garbage-collection timer is running, the
583 new route will replace the one that is about to be
584 deleted. In this case the garbage-collection timer
585 must be cleared. */
586
587 if (oldmetric == RIP_METRIC_INFINITY &&
588 rinfo->metric < RIP_METRIC_INFINITY)
589 {
590 rinfo->type = ZEBRA_ROUTE_RIP;
591 rinfo->sub_type = RIP_ROUTE_RTE;
592
593 RIP_TIMER_OFF (rinfo->t_garbage_collect);
594
595 if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
596 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
597
598 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
599 rinfo->distance);
600 rinfo->flags |= RIP_RTF_FIB;
601 }
602
603 /* Update nexthop and/or metric value. */
604 if (oldmetric != RIP_METRIC_INFINITY)
605 {
606 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
607 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
608 rinfo->distance);
609 rinfo->flags |= RIP_RTF_FIB;
610
611 if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
612 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
613 }
614
615 /* - Set the route change flag and signal the output process
616 to trigger an update. */
617 rinfo->flags |= RIP_RTF_CHANGED;
618 rip_event (RIP_TRIGGERED_UPDATE, 0);
619
620 /* - If the new metric is infinity, start the deletion
621 process (described above); */
622 if (rinfo->metric == RIP_METRIC_INFINITY)
623 {
624 /* If the new metric is infinity, the deletion process
625 begins for the route, which is no longer used for
626 routing packets. Note that the deletion process is
627 started only when the metric is first set to
628 infinity. If the metric was already infinity, then a
629 new deletion process is not started. */
630 if (oldmetric != RIP_METRIC_INFINITY)
631 {
632 /* - The garbage-collection timer is set for 120 seconds. */
633 RIP_TIMER_ON (rinfo->t_garbage_collect,
634 rip_garbage_collect, rip->garbage_time);
635 RIP_TIMER_OFF (rinfo->t_timeout);
636
637 /* - The metric for the route is set to 16
638 (infinity). This causes the route to be removed
639 from service.*/
640 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
641 rinfo->flags &= ~RIP_RTF_FIB;
642
643 /* - The route change flag is to indicate that this
644 entry has been changed. */
645 /* - The output process is signalled to trigger a
646 response. */
647 ; /* Above processes are already done previously. */
648 }
649 }
650 else
651 {
652 /* otherwise, re-initialize the timeout. */
653 rip_timeout_update (rinfo);
654 }
655 }
656 /* Unlock tempolary lock of the route. */
657 route_unlock_node (rp);
658 }
659}
660
661/* Dump RIP packet */
662void
663rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)
664{
665 caddr_t lim;
666 struct rte *rte;
667 char *command_str;
668 char pbuf[BUFSIZ], nbuf[BUFSIZ];
669 u_char netmask = 0;
670 u_char *p;
671
672 /* Set command string. */
673 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
674 command_str = lookup (rip_msg, packet->command);
675 else
676 command_str = "unknown";
677
678 /* Dump packet header. */
679 zlog_info ("%s %s version %d packet size %d",
680 sndrcv, command_str, packet->version, size);
681
682 /* Dump each routing table entry. */
683 rte = packet->rte;
684
685 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
686 {
687 if (packet->version == RIPv2)
688 {
689 netmask = ip_masklen (rte->mask);
690
691 if (ntohs (rte->family) == 0xffff)
692 {
693 if (ntohs (rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)
694 {
695 p = (u_char *)&rte->prefix;
696
697 zlog_info (" family 0x%X type %d auth string: %s",
698 ntohs (rte->family), ntohs (rte->tag), p);
699 }
700 else if (ntohs (rte->tag) == RIP_AUTH_MD5)
701 {
702 struct rip_md5_info *md5;
703
704 md5 = (struct rip_md5_info *) &packet->rte;
705
706 zlog_info (" family 0x%X type %d (MD5 authentication)",
707 ntohs (md5->family), ntohs (md5->type));
708 zlog_info (" RIP-2 packet len %d Key ID %d"
709 " Auth Data len %d", ntohs (md5->packet_len),
710 md5->keyid, md5->auth_len);
711 zlog_info (" Sequence Number %ld", (u_long)ntohl (md5->sequence));
712 }
713 else if (ntohs (rte->tag) == RIP_AUTH_DATA)
714 {
715 p = (u_char *)&rte->prefix;
716
717 zlog_info (" family 0x%X type %d (MD5 data)",
718 ntohs (rte->family), ntohs (rte->tag));
719 zlog_info (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
720 "%02X%02X%02X%02X%02X%02X%02X",
721 p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
722 p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
723 }
724 else
725 {
726 zlog_info (" family 0x%X type %d (Unknown auth type)",
727 ntohs (rte->family), ntohs (rte->tag));
728 }
729 }
730 else
731 zlog_info (" %s/%d -> %s family %d tag %d metric %ld",
732 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),netmask,
733 inet_ntop (AF_INET, &rte->nexthop, nbuf, BUFSIZ),
734 ntohs (rte->family), ntohs (rte->tag),
735 (u_long)ntohl (rte->metric));
736 }
737 else
738 {
739 zlog_info (" %s family %d tag %d metric %ld",
740 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
741 ntohs (rte->family), ntohs (rte->tag),
742 (u_long)ntohl (rte->metric));
743 }
744 }
745}
746
747/* Check if the destination address is valid (unicast; not net 0
748 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
749 check net 0 because we accept default route. */
750int
751rip_destination_check (struct in_addr addr)
752{
753 u_int32_t destination;
754
755 /* Convert to host byte order. */
756 destination = ntohl (addr.s_addr);
757
758 if (IPV4_NET127 (destination))
759 return 0;
760
761 /* Net 0 may match to the default route. */
762 if (IPV4_NET0 (destination) && destination != 0)
763 return 0;
764
765 /* Unicast address must belong to class A, B, C. */
766 if (IN_CLASSA (destination))
767 return 1;
768 if (IN_CLASSB (destination))
769 return 1;
770 if (IN_CLASSC (destination))
771 return 1;
772
773 return 0;
774}
775
776/* RIP version 2 authentication. */
777int
778rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
779 struct interface *ifp)
780{
781 struct rip_interface *ri;
782 char *auth_str;
783
784 if (IS_RIP_DEBUG_EVENT)
785 zlog_info ("RIPv2 simple password authentication from %s",
786 inet_ntoa (from->sin_addr));
787
788 ri = ifp->info;
789
790 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
791 || ntohs (rte->tag) != RIP_AUTH_SIMPLE_PASSWORD)
792 return 0;
793
794 /* Simple password authentication. */
795 if (ri->auth_str)
796 {
797 auth_str = (char *) &rte->prefix;
798
799 if (strncmp (auth_str, ri->auth_str, 16) == 0)
800 return 1;
801 }
802 if (ri->key_chain)
803 {
804 struct keychain *keychain;
805 struct key *key;
806
807 keychain = keychain_lookup (ri->key_chain);
808 if (keychain == NULL)
809 return 0;
810
811 key = key_match_for_accept (keychain, (char *) &rte->prefix);
812 if (key)
813 return 1;
814 }
815 return 0;
816}
817
818/* RIP version 2 authentication with MD5. */
819int
820rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
821 struct interface *ifp)
822{
823 struct rip_interface *ri;
824 struct rip_md5_info *md5;
825 struct rip_md5_data *md5data;
826 struct keychain *keychain;
827 struct key *key;
828 struct md5_ctx ctx;
829 u_char pdigest[RIP_AUTH_MD5_SIZE];
830 u_char digest[RIP_AUTH_MD5_SIZE];
831 u_int16_t packet_len;
832 char *auth_str = NULL;
833
834 if (IS_RIP_DEBUG_EVENT)
835 zlog_info ("RIPv2 MD5 authentication from %s", inet_ntoa (from->sin_addr));
836
837 ri = ifp->info;
838 md5 = (struct rip_md5_info *) &packet->rte;
839
840 /* Check auth type. */
841 if (ri->auth_type != RIP_AUTH_MD5 || ntohs (md5->type) != RIP_AUTH_MD5)
842 return 0;
843
844 if (md5->auth_len != RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE)
845 return 0;
846
847 if (ri->key_chain)
848 {
849 keychain = keychain_lookup (ri->key_chain);
850 if (keychain == NULL)
851 return 0;
852
853 key = key_lookup_for_accept (keychain, md5->keyid);
854 if (key == NULL)
855 return 0;
856
857 auth_str = key->string;
858 }
859
860 if (ri->auth_str)
861 auth_str = ri->auth_str;
862
863 if (! auth_str)
864 return 0;
865
866 /* MD5 digest authentication. */
867 packet_len = ntohs (md5->packet_len);
868 md5data = (struct rip_md5_data *)(((u_char *) packet) + packet_len);
869
870 /* Save digest to pdigest. */
871 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
872
873 /* Overwrite digest by my secret. */
874 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
875 strncpy (md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
876
877 md5_init_ctx (&ctx);
878 md5_process_bytes (packet, packet_len + md5->auth_len, &ctx);
879 md5_finish_ctx (&ctx, digest);
880
881 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
882 return packet_len;
883 else
884 return 0;
885}
886
887void
888rip_auth_md5_set (struct stream *s, struct interface *ifp)
889{
890 struct rip_interface *ri;
891 struct keychain *keychain = NULL;
892 struct key *key = NULL;
893 unsigned long len;
894 struct md5_ctx ctx;
895 unsigned char secret[RIP_AUTH_MD5_SIZE];
896 unsigned char digest[RIP_AUTH_MD5_SIZE];
897 char *auth_str = NULL;
898
899 ri = ifp->info;
900
901 /* Make it sure this interface is configured as MD5
902 authentication. */
903 if (ri->auth_type != RIP_AUTH_MD5)
904 return;
905
906 /* Lookup key chain. */
907 if (ri->key_chain)
908 {
909 keychain = keychain_lookup (ri->key_chain);
910 if (keychain == NULL)
911 return;
912
913 /* Lookup key. */
914 key = key_lookup_for_send (keychain);
915 if (key == NULL)
916 return;
917
918 auth_str = key->string;
919 }
920
921 if (ri->auth_str)
922 auth_str = ri->auth_str;
923
924 if (! auth_str)
925 return;
926
927 /* Get packet length. */
928 len = s->putp;
929
930 /* Check packet length. */
931 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
932 {
933 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
934 return;
935 }
936
937 /* Move RTE. */
938 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
939 s->data + RIP_HEADER_SIZE,
940 len - RIP_HEADER_SIZE);
941
942 /* Set pointer to authentication header. */
943 stream_set_putp (s, RIP_HEADER_SIZE);
944 len += RIP_RTE_SIZE;
945
946 /* MD5 authentication. */
947 stream_putw (s, 0xffff);
948 stream_putw (s, RIP_AUTH_MD5);
949
950 /* RIP-2 Packet length. Actual value is filled in
951 rip_auth_md5_set(). */
952 stream_putw (s, len);
953
954 /* Key ID. */
955 if (key)
956 stream_putc (s, key->index % 256);
957 else
958 stream_putc (s, 1);
959
960 /* Auth Data Len. Set 16 for MD5 authentication
961 data. */
962 stream_putc (s, RIP_AUTH_MD5_SIZE + RIP_HEADER_SIZE);
963
964 /* Sequence Number (non-decreasing). */
965 /* RFC2080: The value used in the sequence number is
966 arbitrary, but two suggestions are the time of the
967 message's creation or a simple message counter. */
968 stream_putl (s, time (NULL));
969
970 /* Reserved field must be zero. */
971 stream_putl (s, 0);
972 stream_putl (s, 0);
973
974 /* Set pointer to authentication data. */
975 stream_set_putp (s, len);
976
977 /* Set authentication data. */
978 stream_putw (s, 0xffff);
979 stream_putw (s, 0x01);
980
981 /* Generate a digest for the RIP packet. */
982 memset (secret, 0, RIP_AUTH_MD5_SIZE);
983 strncpy (secret, auth_str, RIP_AUTH_MD5_SIZE);
984 md5_init_ctx (&ctx);
985 md5_process_bytes (s->data, s->endp, &ctx);
986 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
987 md5_finish_ctx (&ctx, digest);
988
989 /* Copy the digest to the packet. */
990 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
991}
992
993/* RIP routing information. */
994void
995rip_response_process (struct rip_packet *packet, int size,
996 struct sockaddr_in *from, struct interface *ifp)
997{
998 caddr_t lim;
999 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001000 struct prefix_ipv4 ifaddr;
1001 struct prefix_ipv4 ifaddrclass;
1002 struct connected *c;
1003 int subnetted;
paul718e3742002-12-13 20:15:29 +00001004
paul727d1042002-12-13 20:50:29 +00001005 /* We don't know yet. */
1006 subnetted = -1;
1007
paul718e3742002-12-13 20:15:29 +00001008 /* The Response must be ignored if it is not from the RIP
1009 port. (RFC2453 - Sec. 3.9.2)*/
1010 if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)
1011 {
1012 zlog_info ("response doesn't come from RIP port: %d",
1013 from->sin_port);
1014 rip_peer_bad_packet (from);
1015 return;
1016 }
1017
1018 /* The datagram's IPv4 source address should be checked to see
1019 whether the datagram is from a valid neighbor; the source of the
1020 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001021 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001022 {
1023 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1024 inet_ntoa (from->sin_addr));
1025 rip_peer_bad_packet (from);
1026 return;
1027 }
1028
1029 /* It is also worth checking to see whether the response is from one
1030 of the router's own addresses. */
1031
1032 ; /* Alredy done in rip_read () */
1033
1034 /* Update RIP peer. */
1035 rip_peer_update (from, packet->version);
1036
1037 /* Set RTE pointer. */
1038 rte = packet->rte;
1039
1040 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1041 {
1042 /* RIPv2 authentication check. */
1043 /* If the Address Family Identifier of the first (and only the
1044 first) entry in the message is 0xFFFF, then the remainder of
1045 the entry contains the authentication. */
1046 /* If the packet gets here it means authentication enabled */
1047 /* Check is done in rip_read(). So, just skipping it */
1048 if (packet->version == RIPv2 &&
1049 rte == packet->rte &&
1050 rte->family == 0xffff)
1051 continue;
1052
1053 if (ntohs (rte->family) != AF_INET)
1054 {
1055 /* Address family check. RIP only supports AF_INET. */
1056 zlog_info ("Unsupported family %d from %s.",
1057 ntohs (rte->family), inet_ntoa (from->sin_addr));
1058 continue;
1059 }
1060
1061 /* - is the destination address valid (e.g., unicast; not net 0
1062 or 127) */
1063 if (! rip_destination_check (rte->prefix))
1064 {
1065 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1066 rip_peer_bad_route (from);
1067 continue;
1068 }
1069
1070 /* Convert metric value to host byte order. */
1071 rte->metric = ntohl (rte->metric);
1072
1073 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1074 if (! (rte->metric >= 1 && rte->metric <= 16))
1075 {
1076 zlog_info ("Route's metric is not in the 1-16 range.");
1077 rip_peer_bad_route (from);
1078 continue;
1079 }
1080
1081 /* RIPv1 does not have nexthop value. */
1082 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1083 {
1084 zlog_info ("RIPv1 packet with nexthop value %s",
1085 inet_ntoa (rte->nexthop));
1086 rip_peer_bad_route (from);
1087 continue;
1088 }
1089
1090 /* That is, if the provided information is ignored, a possibly
1091 sub-optimal, but absolutely valid, route may be taken. If
1092 the received Next Hop is not directly reachable, it should be
1093 treated as 0.0.0.0. */
1094 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1095 {
1096 u_int32_t addrval;
1097
1098 /* Multicast address check. */
1099 addrval = ntohl (rte->nexthop.s_addr);
1100 if (IN_CLASSD (addrval))
1101 {
1102 zlog_info ("Nexthop %s is multicast address, skip this rte",
1103 inet_ntoa (rte->nexthop));
1104 continue;
1105 }
1106
1107 if (! if_lookup_address (rte->nexthop))
1108 {
1109 struct route_node *rn;
1110 struct rip_info *rinfo;
1111
1112 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1113
1114 if (rn)
1115 {
1116 rinfo = rn->info;
1117
1118 if (rinfo->type == ZEBRA_ROUTE_RIP
1119 && rinfo->sub_type == RIP_ROUTE_RTE)
1120 {
1121 if (IS_RIP_DEBUG_EVENT)
1122 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1123 rte->nexthop = rinfo->from;
1124 }
1125 else
1126 {
1127 if (IS_RIP_DEBUG_EVENT)
1128 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1129 rte->nexthop.s_addr = 0;
1130 }
1131
1132 route_unlock_node (rn);
1133 }
1134 else
1135 {
1136 if (IS_RIP_DEBUG_EVENT)
1137 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1138 rte->nexthop.s_addr = 0;
1139 }
1140
1141 }
1142 }
1143
1144 /* For RIPv1, there won't be a valid netmask.
1145
1146 This is a best guess at the masks. If everyone was using old
1147 Ciscos before the 'ip subnet zero' option, it would be almost
1148 right too :-)
1149
1150 Cisco summarize ripv1 advertisments to the classful boundary
1151 (/16 for class B's) except when the RIP packet does to inside
1152 the classful network in question. */
1153
1154 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1155 || (packet->version == RIPv2
1156 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1157 {
1158 u_int32_t destination;
1159
paul727d1042002-12-13 20:50:29 +00001160 if (subnetted == -1)
1161 {
1162 c = connected_lookup_address (ifp, from->sin_addr);
1163 if (c != NULL)
1164 {
1165 memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
1166 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1167 apply_classful_mask_ipv4 (&ifaddrclass);
1168 subnetted = 0;
1169 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1170 subnetted = 1;
1171 }
1172 }
1173
paul718e3742002-12-13 20:15:29 +00001174 destination = ntohl (rte->prefix.s_addr);
1175
paul727d1042002-12-13 20:50:29 +00001176 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001177 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001178 else if (IN_CLASSB (destination))
1179 masklen2ip (16, &rte->mask);
1180 else if (IN_CLASSC (destination))
1181 masklen2ip (24, &rte->mask);
1182
1183 if (subnetted == 1)
1184 masklen2ip (ifaddrclass.prefixlen,
1185 (struct in_addr *) &destination);
1186 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1187 ifaddrclass.prefix.s_addr))
1188 {
1189 masklen2ip (ifaddr.prefixlen, &rte->mask);
1190 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1191 masklen2ip (32, &rte->mask);
1192 if (IS_RIP_DEBUG_EVENT)
1193 zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
1194 }
1195 else
1196 {
1197 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1198 continue;
1199 }
1200
1201 if (IS_RIP_DEBUG_EVENT)
1202 {
1203 zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
1204 zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001205 }
1206 }
1207
1208 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1209 ignore the entry. */
1210 if ((packet->version == RIPv2)
1211 && (rte->mask.s_addr != 0)
1212 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1213 {
1214 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1215 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1216 rip_peer_bad_route (from);
1217 continue;
1218 }
1219
1220 /* Default route's netmask is ignored. */
1221 if (packet->version == RIPv2
1222 && (rte->prefix.s_addr == 0)
1223 && (rte->mask.s_addr != 0))
1224 {
1225 if (IS_RIP_DEBUG_EVENT)
1226 zlog_info ("Default route with non-zero netmask. Set zero to netmask");
1227 rte->mask.s_addr = 0;
1228 }
1229
1230 /* Routing table updates. */
1231 rip_rte_process (rte, from, ifp);
1232 }
1233}
1234
1235/* RIP packet send to destination address. */
1236int
1237rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to,
paul931cd542004-01-23 15:31:42 +00001238 struct interface *ifp, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00001239{
paul931cd542004-01-23 15:31:42 +00001240 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001241 struct sockaddr_in sin;
paul718e3742002-12-13 20:15:29 +00001242
paul931cd542004-01-23 15:31:42 +00001243 if (IS_RIP_DEBUG_PACKET)
1244 {
1245 char dst[20];
1246 if (to)
1247 {
1248 strcpy(dst, inet_ntoa(to->sin_addr));
1249 }
1250 else
1251 {
1252 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1253 strcpy(dst, inet_ntoa(sin.sin_addr));
1254 }
1255 zlog_info("rip_send_packet %s > %s (%s)",
hassoda9c9a22004-03-18 02:40:55 +00001256 (connected ? inet_ntoa(connected->address->u.prefix4) : ""),
1257 dst, ifp->name);
paul931cd542004-01-23 15:31:42 +00001258 }
hassoda9c9a22004-03-18 02:40:55 +00001259 if (connected && connected->flags & ZEBRA_IFA_SECONDARY)
paul931cd542004-01-23 15:31:42 +00001260 {
1261 /*
1262 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1263 * with multiple addresses on the same subnet: the first address
1264 * on the subnet is configured "primary", and all subsequent addresses
1265 * on that subnet are treated as "secondary" addresses.
1266 * In order to avoid routing-table bloat on other rip listeners,
1267 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1268 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1269 * flag is set, we would end up sending a packet for a "secondary"
1270 * source address on non-linux systems.
1271 */
1272 if (IS_RIP_DEBUG_PACKET)
1273 zlog_info("duplicate dropped");
1274 return 0;
1275 }
1276
paul718e3742002-12-13 20:15:29 +00001277 /* Make destination address. */
1278 memset (&sin, 0, sizeof (struct sockaddr_in));
1279 sin.sin_family = AF_INET;
1280#ifdef HAVE_SIN_LEN
1281 sin.sin_len = sizeof (struct sockaddr_in);
1282#endif /* HAVE_SIN_LEN */
1283
1284 /* When destination is specified, use it's port and address. */
1285 if (to)
1286 {
paul718e3742002-12-13 20:15:29 +00001287 sin.sin_port = to->sin_port;
1288 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001289 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001290 }
1291 else
1292 {
paul718e3742002-12-13 20:15:29 +00001293
1294 sin.sin_port = htons (RIP_PORT_DEFAULT);
1295 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1296
paul931cd542004-01-23 15:31:42 +00001297 /*
1298 * we have to open a new socket for each packet because this
1299 * is the most portable way to bind to a different source
1300 * ipv4 address for each packet.
1301 */
1302 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1303 if (send_sock < 0)
1304 {
1305 zlog_warn("rip_send_packet could not create socket %s",
1306 strerror(errno));
1307 return -1;
1308 }
1309 sockopt_broadcast (send_sock);
1310 sockopt_reuseaddr (send_sock);
1311 sockopt_reuseport (send_sock);
1312#ifdef RIP_RECVMSG
1313 setsockopt_pktinfo (send_sock);
1314#endif /* RIP_RECVMSG */
1315 rip_interface_multicast_set(send_sock, connected, if_is_pointopoint(ifp));
paul718e3742002-12-13 20:15:29 +00001316 }
1317
paul931cd542004-01-23 15:31:42 +00001318 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001319 sizeof (struct sockaddr_in));
1320
1321 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001322 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1323 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001324
1325 if (ret < 0)
1326 zlog_warn ("can't send packet : %s", strerror (errno));
1327
paul931cd542004-01-23 15:31:42 +00001328 if (!to)
1329 close(send_sock);
1330
paul718e3742002-12-13 20:15:29 +00001331 return ret;
1332}
1333
1334/* Add redistributed route to RIP table. */
1335void
1336rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1337 unsigned int ifindex, struct in_addr *nexthop)
1338{
1339 int ret;
1340 struct route_node *rp;
1341 struct rip_info *rinfo;
1342
1343 /* Redistribute route */
1344 ret = rip_destination_check (p->prefix);
1345 if (! ret)
1346 return;
1347
1348 rp = route_node_get (rip->table, (struct prefix *) p);
1349
1350 rinfo = rp->info;
1351
1352 if (rinfo)
1353 {
1354 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1355 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1356 && rinfo->metric != RIP_METRIC_INFINITY)
1357 {
1358 route_unlock_node (rp);
1359 return;
1360 }
1361
1362 /* Manually configured RIP route check. */
1363 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001364 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1365 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001366 {
hasso16705132003-05-25 14:49:19 +00001367 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1368 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001369 {
1370 route_unlock_node (rp);
1371 return;
1372 }
1373 }
1374
1375 RIP_TIMER_OFF (rinfo->t_timeout);
1376 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1377
1378 if (rip_route_rte (rinfo))
1379 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1380 rinfo->metric);
1381 rp->info = NULL;
1382 rip_info_free (rinfo);
1383
1384 route_unlock_node (rp);
1385 }
1386
1387 rinfo = rip_info_new ();
1388
1389 rinfo->type = type;
1390 rinfo->sub_type = sub_type;
1391 rinfo->ifindex = ifindex;
1392 rinfo->metric = 1;
1393 rinfo->rp = rp;
1394
1395 if (nexthop)
1396 rinfo->nexthop = *nexthop;
1397
1398 rinfo->flags |= RIP_RTF_FIB;
1399 rp->info = rinfo;
1400
1401 rinfo->flags |= RIP_RTF_CHANGED;
1402
hasso16705132003-05-25 14:49:19 +00001403 if (IS_RIP_DEBUG_EVENT) {
1404 if (!nexthop)
1405 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1406 inet_ntoa(p->prefix), p->prefixlen,
1407 ifindex2ifname(ifindex));
1408 else
1409 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1410 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1411 ifindex2ifname(ifindex));
1412 }
1413
1414
paul718e3742002-12-13 20:15:29 +00001415 rip_event (RIP_TRIGGERED_UPDATE, 0);
1416}
1417
1418/* Delete redistributed route from RIP table. */
1419void
1420rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1421 unsigned int ifindex)
1422{
1423 int ret;
1424 struct route_node *rp;
1425 struct rip_info *rinfo;
1426
1427 ret = rip_destination_check (p->prefix);
1428 if (! ret)
1429 return;
1430
1431 rp = route_node_lookup (rip->table, (struct prefix *) p);
1432 if (rp)
1433 {
1434 rinfo = rp->info;
1435
1436 if (rinfo != NULL
1437 && rinfo->type == type
1438 && rinfo->sub_type == sub_type
1439 && rinfo->ifindex == ifindex)
1440 {
1441 /* Perform poisoned reverse. */
1442 rinfo->metric = RIP_METRIC_INFINITY;
1443 RIP_TIMER_ON (rinfo->t_garbage_collect,
1444 rip_garbage_collect, rip->garbage_time);
1445 RIP_TIMER_OFF (rinfo->t_timeout);
1446 rinfo->flags |= RIP_RTF_CHANGED;
1447
hasso16705132003-05-25 14:49:19 +00001448 if (IS_RIP_DEBUG_EVENT)
1449 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1450 inet_ntoa(p->prefix), p->prefixlen,
1451 ifindex2ifname(ifindex));
1452
paul718e3742002-12-13 20:15:29 +00001453 rip_event (RIP_TRIGGERED_UPDATE, 0);
1454 }
1455 }
1456}
1457
1458/* Response to request called from rip_read ().*/
1459void
1460rip_request_process (struct rip_packet *packet, int size,
1461 struct sockaddr_in *from, struct interface *ifp)
1462{
1463 caddr_t lim;
1464 struct rte *rte;
1465 struct prefix_ipv4 p;
1466 struct route_node *rp;
1467 struct rip_info *rinfo;
1468 struct rip_interface *ri;
1469
hasso16705132003-05-25 14:49:19 +00001470 /* Does not reponse to the requests on the loopback interfaces */
1471 if (if_is_loopback (ifp))
1472 return;
1473
hasso429a0f82004-02-22 23:42:22 +00001474 /* Check RIP process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001475 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001476 if (! ri->running)
1477 return;
paul718e3742002-12-13 20:15:29 +00001478
1479 /* When passive interface is specified, suppress responses */
1480 if (ri->passive)
1481 return;
1482
1483 /* RIP peer update. */
1484 rip_peer_update (from, packet->version);
1485
1486 lim = ((caddr_t) packet) + size;
1487 rte = packet->rte;
1488
1489 /* The Request is processed entry by entry. If there are no
1490 entries, no response is given. */
1491 if (lim == (caddr_t) rte)
1492 return;
1493
1494 /* There is one special case. If there is exactly one entry in the
1495 request, and it has an address family identifier of zero and a
1496 metric of infinity (i.e., 16), then this is a request to send the
1497 entire routing table. */
1498 if (lim == ((caddr_t) (rte + 1)) &&
1499 ntohs (rte->family) == 0 &&
1500 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1501 {
paulcc1131a2003-10-15 23:20:17 +00001502 struct prefix_ipv4 saddr;
1503
1504 /* saddr will be used for determining which routes to split-horizon.
1505 Since the source address we'll pick will be on the same subnet as the
1506 destination, for the purpose of split-horizoning, we'll
1507 pretend that "from" is our source address. */
1508 saddr.family = AF_INET;
1509 saddr.prefixlen = IPV4_MAX_BITLEN;
1510 saddr.prefix = from->sin_addr;
1511
paul718e3742002-12-13 20:15:29 +00001512 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001513 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001514 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001515 }
1516 else
1517 {
1518 /* Examine the list of RTEs in the Request one by one. For each
1519 entry, look up the destination in the router's routing
1520 database and, if there is a route, put that route's metric in
1521 the metric field of the RTE. If there is no explicit route
1522 to the specified destination, put infinity in the metric
1523 field. Once all the entries have been filled in, change the
1524 command from Request to Response and send the datagram back
1525 to the requestor. */
1526 p.family = AF_INET;
1527
1528 for (; ((caddr_t) rte) < lim; rte++)
1529 {
1530 p.prefix = rte->prefix;
1531 p.prefixlen = ip_masklen (rte->mask);
1532 apply_mask_ipv4 (&p);
1533
1534 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1535 if (rp)
1536 {
1537 rinfo = rp->info;
1538 rte->metric = htonl (rinfo->metric);
1539 route_unlock_node (rp);
1540 }
1541 else
1542 rte->metric = htonl (RIP_METRIC_INFINITY);
1543 }
1544 packet->command = RIP_RESPONSE;
1545
paul931cd542004-01-23 15:31:42 +00001546 rip_send_packet ((caddr_t) packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001547 }
1548 rip_global_queries++;
1549}
1550
1551#if RIP_RECVMSG
1552/* Set IPv6 packet info to the socket. */
1553static int
1554setsockopt_pktinfo (int sock)
1555{
1556 int ret;
1557 int val = 1;
1558
1559 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1560 if (ret < 0)
1561 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1562 return ret;
1563}
1564
1565/* Read RIP packet by recvmsg function. */
1566int
1567rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1568 int *ifindex)
1569{
1570 int ret;
1571 struct msghdr msg;
1572 struct iovec iov;
1573 struct cmsghdr *ptr;
1574 char adata[1024];
1575
1576 msg.msg_name = (void *) from;
1577 msg.msg_namelen = sizeof (struct sockaddr_in);
1578 msg.msg_iov = &iov;
1579 msg.msg_iovlen = 1;
1580 msg.msg_control = (void *) adata;
1581 msg.msg_controllen = sizeof adata;
1582 iov.iov_base = buf;
1583 iov.iov_len = size;
1584
1585 ret = recvmsg (sock, &msg, 0);
1586 if (ret < 0)
1587 return ret;
1588
1589 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1590 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1591 {
1592 struct in_pktinfo *pktinfo;
1593 int i;
1594
1595 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1596 i = pktinfo->ipi_ifindex;
1597 }
1598 return ret;
1599}
1600
1601/* RIP packet read function. */
1602int
1603rip_read_new (struct thread *t)
1604{
1605 int ret;
1606 int sock;
1607 char buf[RIP_PACKET_MAXSIZ];
1608 struct sockaddr_in from;
1609 unsigned int ifindex;
1610
1611 /* Fetch socket then register myself. */
1612 sock = THREAD_FD (t);
1613 rip_event (RIP_READ, sock);
1614
1615 /* Read RIP packet. */
1616 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1617 if (ret < 0)
1618 {
1619 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1620 return ret;
1621 }
1622
1623 return ret;
1624}
1625#endif /* RIP_RECVMSG */
1626
1627/* First entry point of RIP packet. */
1628int
1629rip_read (struct thread *t)
1630{
1631 int sock;
1632 int ret;
1633 int rtenum;
1634 union rip_buf rip_buf;
1635 struct rip_packet *packet;
1636 struct sockaddr_in from;
1637 int fromlen, len;
1638 struct interface *ifp;
1639 struct rip_interface *ri;
1640
1641 /* Fetch socket then register myself. */
1642 sock = THREAD_FD (t);
1643 rip->t_read = NULL;
1644
1645 /* Add myself to tne next event */
1646 rip_event (RIP_READ, sock);
1647
1648 /* RIPd manages only IPv4. */
1649 memset (&from, 0, sizeof (struct sockaddr_in));
1650 fromlen = sizeof (struct sockaddr_in);
1651
1652 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1653 (struct sockaddr *) &from, &fromlen);
1654 if (len < 0)
1655 {
1656 zlog_info ("recvfrom failed: %s", strerror (errno));
1657 return len;
1658 }
1659
1660 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001661 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001662 {
1663 if (IS_RIP_DEBUG_PACKET)
1664 zlog_warn ("ignore packet comes from myself");
1665 return -1;
1666 }
1667
1668 /* Which interface is this packet comes from. */
1669 ifp = if_lookup_address (from.sin_addr);
1670
1671 /* RIP packet received */
1672 if (IS_RIP_DEBUG_EVENT)
1673 zlog_info ("RECV packet from %s port %d on %s",
1674 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1675 ifp ? ifp->name : "unknown");
1676
1677 /* If this packet come from unknown interface, ignore it. */
1678 if (ifp == NULL)
1679 {
1680 zlog_info ("packet comes from unknown interface");
1681 return -1;
1682 }
1683
1684 /* Packet length check. */
1685 if (len < RIP_PACKET_MINSIZ)
1686 {
1687 zlog_warn ("packet size %d is smaller than minimum size %d",
1688 len, RIP_PACKET_MINSIZ);
1689 rip_peer_bad_packet (&from);
1690 return len;
1691 }
1692 if (len > RIP_PACKET_MAXSIZ)
1693 {
1694 zlog_warn ("packet size %d is larger than max size %d",
1695 len, RIP_PACKET_MAXSIZ);
1696 rip_peer_bad_packet (&from);
1697 return len;
1698 }
1699
1700 /* Packet alignment check. */
1701 if ((len - RIP_PACKET_MINSIZ) % 20)
1702 {
1703 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1704 rip_peer_bad_packet (&from);
1705 return len;
1706 }
1707
1708 /* Set RTE number. */
1709 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1710
1711 /* For easy to handle. */
1712 packet = &rip_buf.rip_packet;
1713
1714 /* RIP version check. */
1715 if (packet->version == 0)
1716 {
1717 zlog_info ("version 0 with command %d received.", packet->command);
1718 rip_peer_bad_packet (&from);
1719 return -1;
1720 }
1721
1722 /* Dump RIP packet. */
1723 if (IS_RIP_DEBUG_RECV)
1724 rip_packet_dump (packet, len, "RECV");
1725
1726 /* RIP version adjust. This code should rethink now. RFC1058 says
1727 that "Version 1 implementations are to ignore this extra data and
1728 process only the fields specified in this document.". So RIPv3
1729 packet should be treated as RIPv1 ignoring must be zero field. */
1730 if (packet->version > RIPv2)
1731 packet->version = RIPv2;
1732
1733 /* Is RIP running or is this RIP neighbor ?*/
1734 ri = ifp->info;
1735 if (! ri->running && ! rip_neighbor_lookup (&from))
1736 {
1737 if (IS_RIP_DEBUG_EVENT)
1738 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1739 rip_peer_bad_packet (&from);
1740 return -1;
1741 }
1742
1743 /* RIP Version check. */
1744 if (packet->command == RIP_RESPONSE)
1745 {
paulf38a4712003-06-07 01:10:00 +00001746 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1747 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001748 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001749 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001750 {
1751 if (IS_RIP_DEBUG_PACKET)
1752 zlog_warn (" packet's v%d doesn't fit to if version spec",
1753 packet->version);
1754 rip_peer_bad_packet (&from);
1755 return -1;
1756 }
1757 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001758 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001759 {
1760 if (IS_RIP_DEBUG_PACKET)
1761 zlog_warn (" packet's v%d doesn't fit to if version spec",
1762 packet->version);
1763 rip_peer_bad_packet (&from);
1764 return -1;
1765 }
paul718e3742002-12-13 20:15:29 +00001766 }
1767
1768 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1769 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1770 accepted; authenticated RIP-2 messages shall be discarded. */
1771
1772 if ((ri->auth_type == RIP_NO_AUTH)
1773 && rtenum
1774 && (packet->version == RIPv2) && (packet->rte->family == 0xffff))
1775 {
1776 if (IS_RIP_DEBUG_EVENT)
1777 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1778 packet->version);
1779 rip_peer_bad_packet (&from);
1780 return -1;
1781 }
1782
1783 /* If the router is configured to authenticate RIP-2 messages, then
1784 RIP-1 messages and RIP-2 messages which pass authentication
1785 testing shall be accepted; unauthenticated and failed
1786 authentication RIP-2 messages shall be discarded. For maximum
1787 security, RIP-1 messages should be ignored when authentication is
1788 in use (see section 4.1); otherwise, the routing information from
1789 authenticated messages will be propagated by RIP-1 routers in an
1790 unauthenticated manner. */
1791
1792 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
1793 || ri->auth_type == RIP_AUTH_MD5)
1794 && rtenum)
1795 {
1796 /* We follow maximum security. */
1797 if (packet->version == RIPv1 && packet->rte->family == 0xffff)
1798 {
1799 if (IS_RIP_DEBUG_PACKET)
1800 zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version);
1801 rip_peer_bad_packet (&from);
1802 return -1;
1803 }
1804
1805 /* Check RIPv2 authentication. */
1806 if (packet->version == RIPv2)
1807 {
1808 if (packet->rte->family == 0xffff)
1809 {
1810 if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)
1811 {
1812 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1813 if (! ret)
1814 {
1815 if (IS_RIP_DEBUG_EVENT)
1816 zlog_warn ("RIPv2 simple password authentication failed");
1817 rip_peer_bad_packet (&from);
1818 return -1;
1819 }
1820 else
1821 {
1822 if (IS_RIP_DEBUG_EVENT)
1823 zlog_info ("RIPv2 simple password authentication success");
1824 }
1825 }
1826 else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5)
1827 {
1828 ret = rip_auth_md5 (packet, &from, ifp);
1829 if (! ret)
1830 {
1831 if (IS_RIP_DEBUG_EVENT)
1832 zlog_warn ("RIPv2 MD5 authentication failed");
1833 rip_peer_bad_packet (&from);
1834 return -1;
1835 }
1836 else
1837 {
1838 if (IS_RIP_DEBUG_EVENT)
1839 zlog_info ("RIPv2 MD5 authentication success");
1840 }
1841 /* Reset RIP packet length to trim MD5 data. */
1842 len = ret;
1843 }
1844 else
1845 {
1846 if (IS_RIP_DEBUG_EVENT)
1847 zlog_warn ("Unknown authentication type %d",
1848 ntohs (packet->rte->tag));
1849 rip_peer_bad_packet (&from);
1850 return -1;
1851 }
1852 }
1853 else
1854 {
1855 /* There is no authentication in the packet. */
1856 if (ri->auth_str || ri->key_chain)
1857 {
1858 if (IS_RIP_DEBUG_EVENT)
1859 zlog_warn ("RIPv2 authentication failed: no authentication in packet");
1860 rip_peer_bad_packet (&from);
1861 return -1;
1862 }
1863 }
1864 }
1865 }
1866
1867 /* Process each command. */
1868 switch (packet->command)
1869 {
1870 case RIP_RESPONSE:
1871 rip_response_process (packet, len, &from, ifp);
1872 break;
1873 case RIP_REQUEST:
1874 case RIP_POLL:
1875 rip_request_process (packet, len, &from, ifp);
1876 break;
1877 case RIP_TRACEON:
1878 case RIP_TRACEOFF:
1879 zlog_info ("Obsolete command %s received, please sent it to routed",
1880 lookup (rip_msg, packet->command));
1881 rip_peer_bad_packet (&from);
1882 break;
1883 case RIP_POLL_ENTRY:
1884 zlog_info ("Obsolete command %s received",
1885 lookup (rip_msg, packet->command));
1886 rip_peer_bad_packet (&from);
1887 break;
1888 default:
1889 zlog_info ("Unknown RIP command %d received", packet->command);
1890 rip_peer_bad_packet (&from);
1891 break;
1892 }
1893
1894 return len;
1895}
1896
1897/* Make socket for RIP protocol. */
1898int
1899rip_create_socket ()
1900{
1901 int ret;
1902 int sock;
1903 struct sockaddr_in addr;
1904 struct servent *sp;
1905
1906 memset (&addr, 0, sizeof (struct sockaddr_in));
1907
1908 /* Set RIP port. */
1909 sp = getservbyname ("router", "udp");
1910 if (sp)
1911 addr.sin_port = sp->s_port;
1912 else
1913 addr.sin_port = htons (RIP_PORT_DEFAULT);
1914
1915 /* Address shoud be any address. */
1916 addr.sin_family = AF_INET;
1917 addr.sin_addr.s_addr = INADDR_ANY;
1918
1919 /* Make datagram socket. */
1920 sock = socket (AF_INET, SOCK_DGRAM, 0);
1921 if (sock < 0)
1922 {
1923 perror ("socket");
1924 exit (1);
1925 }
1926
1927 sockopt_broadcast (sock);
1928 sockopt_reuseaddr (sock);
1929 sockopt_reuseport (sock);
1930#ifdef RIP_RECVMSG
1931 setsockopt_pktinfo (sock);
1932#endif /* RIP_RECVMSG */
1933
pauledd7c242003-06-04 13:59:38 +00001934 if (ripd_privs.change (ZPRIVS_RAISE))
1935 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001936 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1937 if (ret < 0)
1938 {
1939 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001940 if (ripd_privs.change (ZPRIVS_LOWER))
1941 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001942 return ret;
1943 }
pauledd7c242003-06-04 13:59:38 +00001944 if (ripd_privs.change (ZPRIVS_LOWER))
1945 zlog_err ("rip_create_socket: could not lower privs");
1946
paul718e3742002-12-13 20:15:29 +00001947 return sock;
1948}
1949
1950/* Write routing table entry to the stream and return next index of
1951 the routing table entry in the stream. */
1952int
1953rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
1954 u_char version, struct rip_info *rinfo, struct interface *ifp)
1955{
1956 struct in_addr mask;
1957 struct rip_interface *ri;
1958
1959 /* RIP packet header. */
1960 if (num == 0)
1961 {
1962 stream_putc (s, RIP_RESPONSE);
1963 stream_putc (s, version);
1964 stream_putw (s, 0);
1965
1966 /* In case of we need RIPv2 authentication. */
1967 if (version == RIPv2 && ifp)
1968 {
1969 ri = ifp->info;
1970
1971 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
1972 {
1973 if (ri->auth_str)
1974 {
1975 stream_putw (s, 0xffff);
1976 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1977
1978 memset ((s->data + s->putp), 0, 16);
1979 strncpy ((s->data + s->putp), ri->auth_str, 16);
1980 stream_set_putp (s, s->putp + 16);
1981
1982 num++;
1983 }
1984 if (ri->key_chain)
1985 {
1986 struct keychain *keychain;
1987 struct key *key;
1988
1989 keychain = keychain_lookup (ri->key_chain);
1990
1991 if (keychain)
1992 {
1993 key = key_lookup_for_send (keychain);
1994
1995 if (key)
1996 {
1997 stream_putw (s, 0xffff);
1998 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1999
2000 memset ((s->data + s->putp), 0, 16);
2001 strncpy ((s->data + s->putp), key->string, 16);
2002 stream_set_putp (s, s->putp + 16);
2003
2004 num++;
2005 }
2006 }
2007 }
2008 }
2009 }
2010 }
2011
2012 /* Write routing table entry. */
2013 if (version == RIPv1)
2014 {
2015 stream_putw (s, AF_INET);
2016 stream_putw (s, 0);
2017 stream_put_ipv4 (s, p->prefix.s_addr);
2018 stream_put_ipv4 (s, 0);
2019 stream_put_ipv4 (s, 0);
2020 stream_putl (s, rinfo->metric_out);
2021 }
2022 else
2023 {
2024 masklen2ip (p->prefixlen, &mask);
2025
2026 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002027 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002028 stream_put_ipv4 (s, p->prefix.s_addr);
2029 stream_put_ipv4 (s, mask.s_addr);
2030 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2031 stream_putl (s, rinfo->metric_out);
2032 }
2033
2034 return ++num;
2035}
2036
2037/* Send update to the ifp or spcified neighbor. */
2038void
paul727d1042002-12-13 20:50:29 +00002039rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002040 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002041 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002042{
2043 int ret;
2044 struct stream *s;
2045 struct route_node *rp;
2046 struct rip_info *rinfo;
2047 struct rip_interface *ri;
2048 struct prefix_ipv4 *p;
2049 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002050 struct prefix_ipv4 ifaddrclass;
2051 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002052 int num;
2053 int rtemax;
paul01d09082003-06-08 21:22:18 +00002054 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002055
2056 /* Logging output event. */
2057 if (IS_RIP_DEBUG_EVENT)
2058 {
2059 if (to)
2060 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2061 else
2062 zlog_info ("update routes on interface %s ifindex %d",
2063 ifp->name, ifp->ifindex);
2064 }
2065
2066 /* Set output stream. */
2067 s = rip->obuf;
2068
2069 /* Reset stream and RTE counter. */
2070 stream_reset (s);
2071 num = 0;
2072 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2073
2074 /* Get RIP interface. */
2075 ri = ifp->info;
2076
2077 /* If output interface is in simple password authentication mode, we
2078 need space for authentication data. */
2079 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2080 rtemax -= 1;
2081
2082 /* If output interface is in MD5 authentication mode, we need space
2083 for authentication header and data. */
2084 if (ri->auth_type == RIP_AUTH_MD5)
2085 rtemax -= 2;
2086
2087 /* If output interface is in simple password authentication mode
2088 and string or keychain is specified we need space for auth. data */
2089 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2090 {
2091 if (ri->key_chain)
2092 {
2093 struct keychain *keychain;
2094
2095 keychain = keychain_lookup (ri->key_chain);
2096 if (keychain)
2097 if (key_lookup_for_send (keychain))
2098 rtemax -=1;
2099 }
2100 else
2101 if (ri->auth_str)
2102 rtemax -=1;
2103 }
2104
paul727d1042002-12-13 20:50:29 +00002105 if (version == RIPv1)
2106 {
2107 if (ifaddr == NULL)
2108 {
2109 c = connected_lookup_address (ifp, to->sin_addr);
2110 if (c != NULL)
2111 ifaddr = c->address;
2112 }
2113 if (ifaddr == NULL)
2114 {
2115 zlog_warn ("cannot find source address for packets to neighbor %s",
2116 inet_ntoa (to->sin_addr));
2117 return;
2118 }
2119 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2120 apply_classful_mask_ipv4 (&ifaddrclass);
2121 subnetted = 0;
2122 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002123 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002124 }
2125
paul718e3742002-12-13 20:15:29 +00002126 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2127 if ((rinfo = rp->info) != NULL)
2128 {
paul727d1042002-12-13 20:50:29 +00002129 /* For RIPv1, if we are subnetted, output subnets in our network */
2130 /* that have the same mask as the output "interface". For other */
2131 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002132
2133 if (version == RIPv1)
2134 {
paul727d1042002-12-13 20:50:29 +00002135 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002136
2137 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002138 zlog_info("RIPv1 mask check, %s/%d considered for output",
2139 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002140
paul727d1042002-12-13 20:50:29 +00002141 if (subnetted &&
2142 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2143 {
2144 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2145 (rp->p.prefixlen != 32))
2146 continue;
2147 }
2148 else
2149 {
2150 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2151 apply_classful_mask_ipv4(&classfull);
2152 if (rp->p.u.prefix4.s_addr != 0 &&
2153 classfull.prefixlen != rp->p.prefixlen)
2154 continue;
2155 }
paul718e3742002-12-13 20:15:29 +00002156 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002157 zlog_info("RIPv1 mask check, %s/%d made it through",
2158 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002159 }
2160 else
2161 p = (struct prefix_ipv4 *) &rp->p;
2162
2163 /* Apply output filters. */
2164 ret = rip_outgoing_filter (p, ri);
2165 if (ret < 0)
2166 continue;
2167
2168 /* Changed route only output. */
2169 if (route_type == rip_changed_route &&
2170 (! (rinfo->flags & RIP_RTF_CHANGED)))
2171 continue;
2172
2173 /* Split horizon. */
2174 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002175 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002176 {
paul42d14d92003-11-17 09:15:18 +00002177 /*
2178 * We perform split horizon for RIP and connected route.
2179 * For rip routes, we want to suppress the route if we would
2180 * end up sending the route back on the interface that we
2181 * learned it from, with a higher metric. For connected routes,
2182 * we suppress the route if the prefix is a subset of the
2183 * source address that we are going to use for the packet
2184 * (in order to handle the case when multiple subnets are
2185 * configured on the same interface).
2186 */
2187 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2188 rinfo->ifindex == ifp->ifindex)
2189 continue;
2190 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002191 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002192 continue;
2193 }
2194
2195 /* Preparation for route-map. */
2196 rinfo->metric_set = 0;
2197 rinfo->nexthop_out.s_addr = 0;
2198 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002199 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002200 rinfo->ifindex_out = ifp->ifindex;
2201
hasso16705132003-05-25 14:49:19 +00002202 /* In order to avoid some local loops,
2203 * if the RIP route has a nexthop via this interface, keep the nexthop,
2204 * otherwise set it to 0. The nexthop should not be propagated
2205 * beyond the local broadcast/multicast area in order
2206 * to avoid an IGP multi-level recursive look-up.
2207 * see (4.4)
2208 */
2209 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002210 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002211
2212 /* Interface route-map */
2213 if (ri->routemap[RIP_FILTER_OUT])
2214 {
2215 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2216 (struct prefix *) p, RMAP_RIP,
2217 rinfo);
2218
2219 if (ret == RMAP_DENYMATCH)
2220 {
2221 if (IS_RIP_DEBUG_PACKET)
2222 zlog_info ("RIP %s/%d is filtered by route-map out",
2223 inet_ntoa (p->prefix), p->prefixlen);
2224 continue;
2225 }
2226 }
paul718e3742002-12-13 20:15:29 +00002227
hasso16705132003-05-25 14:49:19 +00002228 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002229 if (rip->route_map[rinfo->type].name
2230 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2231 {
2232 ret = route_map_apply (rip->route_map[rinfo->type].map,
2233 (struct prefix *)p, RMAP_RIP, rinfo);
2234
2235 if (ret == RMAP_DENYMATCH)
2236 {
2237 if (IS_RIP_DEBUG_PACKET)
2238 zlog_info ("%s/%d is filtered by route-map",
2239 inet_ntoa (p->prefix), p->prefixlen);
2240 continue;
2241 }
2242 }
2243
2244 /* When route-map does not set metric. */
2245 if (! rinfo->metric_set)
2246 {
2247 /* If redistribute metric is set. */
2248 if (rip->route_map[rinfo->type].metric_config
2249 && rinfo->metric != RIP_METRIC_INFINITY)
2250 {
2251 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2252 }
2253 else
2254 {
2255 /* If the route is not connected or localy generated
2256 one, use default-metric value*/
2257 if (rinfo->type != ZEBRA_ROUTE_RIP
2258 && rinfo->type != ZEBRA_ROUTE_CONNECT
2259 && rinfo->metric != RIP_METRIC_INFINITY)
2260 rinfo->metric_out = rip->default_metric;
2261 }
2262 }
2263
2264 /* Apply offset-list */
2265 if (rinfo->metric != RIP_METRIC_INFINITY)
2266 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2267
2268 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2269 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002270
2271 /* Perform split-horizon with poisoned reverse
2272 * for RIP and connected routes.
2273 **/
2274 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002275 /*
2276 * We perform split horizon for RIP and connected route.
2277 * For rip routes, we want to suppress the route if we would
2278 * end up sending the route back on the interface that we
2279 * learned it from, with a higher metric. For connected routes,
2280 * we suppress the route if the prefix is a subset of the
2281 * source address that we are going to use for the packet
2282 * (in order to handle the case when multiple subnets are
2283 * configured on the same interface).
2284 */
2285 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002286 rinfo->ifindex == ifp->ifindex)
2287 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002288 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2289 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2290 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002291 }
2292
paul718e3742002-12-13 20:15:29 +00002293 /* Write RTE to the stream. */
2294 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2295 if (num == rtemax)
2296 {
2297 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2298 rip_auth_md5_set (s, ifp);
2299
2300 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002301 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002302
2303 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2304 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2305 stream_get_endp(s), "SEND");
2306 num = 0;
2307 stream_reset (s);
2308 }
2309 }
2310
2311 /* Flush unwritten RTE. */
2312 if (num != 0)
2313 {
2314 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2315 rip_auth_md5_set (s, ifp);
2316
paul931cd542004-01-23 15:31:42 +00002317 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2318 connected);
paul718e3742002-12-13 20:15:29 +00002319
2320 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2321 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2322 stream_get_endp (s), "SEND");
2323 num = 0;
2324 stream_reset (s);
2325 }
2326
2327 /* Statistics updates. */
2328 ri->sent_updates++;
2329}
2330
2331/* Send RIP packet to the interface. */
2332void
paulcc1131a2003-10-15 23:20:17 +00002333rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002334 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002335{
2336 struct prefix_ipv4 *p;
2337 struct connected *connected;
2338 listnode node;
2339 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002340 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002341
2342 /* When RIP version is 2 and multicast enable interface. */
2343 if (version == RIPv2 && if_is_multicast (ifp))
2344 {
2345 if (IS_RIP_DEBUG_EVENT)
2346 zlog_info ("multicast announce on %s ", ifp->name);
2347
hassocaa6f8a2004-03-03 19:48:48 +00002348 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002349 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002350 return;
2351 }
2352
2353 /* If we can't send multicast packet, send it with unicast. */
2354 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2355 {
2356 for (node = listhead (ifp->connected); node; nextnode (node))
2357 {
2358 connected = getdata (node);
2359
2360 /* Fetch broadcast address or poin-to-point destination
2361 address . */
2362 p = (struct prefix_ipv4 *) connected->destination;
2363
2364 if (p->family == AF_INET)
2365 {
2366 /* Destination address and port setting. */
2367 memset (&to, 0, sizeof (struct sockaddr_in));
2368 to.sin_addr = p->prefix;
2369 to.sin_port = htons (RIP_PORT_DEFAULT);
2370
2371 if (IS_RIP_DEBUG_EVENT)
2372 zlog_info ("%s announce to %s on %s",
2373 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2374 inet_ntoa (to.sin_addr), ifp->name);
2375
paul727d1042002-12-13 20:50:29 +00002376 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002377 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002378 }
2379 }
2380 }
2381}
2382
2383/* Update send to all interface and neighbor. */
2384void
2385rip_update_process (int route_type)
2386{
paulcc1131a2003-10-15 23:20:17 +00002387 listnode node, ifnode;
2388 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002389 struct interface *ifp;
2390 struct rip_interface *ri;
2391 struct route_node *rp;
2392 struct sockaddr_in to;
2393 struct prefix_ipv4 *p;
2394
2395 /* Send RIP update to each interface. */
2396 for (node = listhead (iflist); node; nextnode (node))
2397 {
2398 ifp = getdata (node);
2399
2400 if (if_is_loopback (ifp))
2401 continue;
2402
paul2e3b2e42002-12-13 21:03:13 +00002403 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002404 continue;
2405
2406 /* Fetch RIP interface information. */
2407 ri = ifp->info;
2408
2409 /* When passive interface is specified, suppress announce to the
2410 interface. */
2411 if (ri->passive)
2412 continue;
2413
2414 if (ri->running)
2415 {
2416 if (IS_RIP_DEBUG_EVENT)
2417 {
2418 if (ifp->name)
2419 zlog_info ("SEND UPDATE to %s ifindex %d",
2420 ifp->name, ifp->ifindex);
2421 else
2422 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2423 ifp->ifindex);
2424 }
2425
paulcc1131a2003-10-15 23:20:17 +00002426 /* send update on each connected network */
2427
2428 LIST_LOOP(ifp->connected, connected, ifnode)
2429 {
2430 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002431 int done = 0;
2432 /*
2433 * If there is no version configuration in the interface,
2434 * use rip's version setting.
2435 */
paulf38a4712003-06-07 01:10:00 +00002436 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2437 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002438
2439 ifaddr = (struct prefix_ipv4 *) connected->address;
2440
2441 if (ifaddr->family != AF_INET)
2442 continue;
2443
paul931cd542004-01-23 15:31:42 +00002444 if ((vsend & RIPv1) && !done)
2445 rip_update_interface (ifp, RIPv1, route_type, connected);
2446 if ((vsend & RIPv2) && if_is_multicast(ifp))
2447 rip_update_interface (ifp, RIPv2, route_type, connected);
2448 done = 1;
2449 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2450 break;
2451
paulf38a4712003-06-07 01:10:00 +00002452 }
paul718e3742002-12-13 20:15:29 +00002453 }
2454 }
2455
2456 /* RIP send updates to each neighbor. */
2457 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2458 if (rp->info != NULL)
2459 {
2460 p = (struct prefix_ipv4 *) &rp->p;
2461
2462 ifp = if_lookup_address (p->prefix);
2463 if (! ifp)
2464 {
2465 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2466 inet_ntoa (p->prefix));
2467 continue;
2468 }
2469
2470 /* Set destination address and port */
2471 memset (&to, 0, sizeof (struct sockaddr_in));
2472 to.sin_addr = p->prefix;
2473 to.sin_port = htons (RIP_PORT_DEFAULT);
2474
2475 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002476 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2477 NULL, p);
paul718e3742002-12-13 20:15:29 +00002478 }
2479}
2480
2481/* RIP's periodical timer. */
2482int
2483rip_update (struct thread *t)
2484{
2485 /* Clear timer pointer. */
2486 rip->t_update = NULL;
2487
2488 if (IS_RIP_DEBUG_EVENT)
2489 zlog_info ("update timer fire!");
2490
2491 /* Process update output. */
2492 rip_update_process (rip_all_route);
2493
2494 /* Triggered updates may be suppressed if a regular update is due by
2495 the time the triggered update would be sent. */
2496 if (rip->t_triggered_interval)
2497 {
2498 thread_cancel (rip->t_triggered_interval);
2499 rip->t_triggered_interval = NULL;
2500 }
2501 rip->trigger = 0;
2502
2503 /* Register myself. */
2504 rip_event (RIP_UPDATE_EVENT, 0);
2505
2506 return 0;
2507}
2508
2509/* Walk down the RIP routing table then clear changed flag. */
2510void
2511rip_clear_changed_flag ()
2512{
2513 struct route_node *rp;
2514 struct rip_info *rinfo;
2515
2516 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2517 if ((rinfo = rp->info) != NULL)
2518 if (rinfo->flags & RIP_RTF_CHANGED)
2519 rinfo->flags &= ~RIP_RTF_CHANGED;
2520}
2521
2522/* Triggered update interval timer. */
2523int
2524rip_triggered_interval (struct thread *t)
2525{
2526 int rip_triggered_update (struct thread *);
2527
2528 rip->t_triggered_interval = NULL;
2529
2530 if (rip->trigger)
2531 {
2532 rip->trigger = 0;
2533 rip_triggered_update (t);
2534 }
2535 return 0;
2536}
2537
2538/* Execute triggered update. */
2539int
2540rip_triggered_update (struct thread *t)
2541{
2542 int interval;
2543
2544 /* Clear thred pointer. */
2545 rip->t_triggered_update = NULL;
2546
2547 /* Cancel interval timer. */
2548 if (rip->t_triggered_interval)
2549 {
2550 thread_cancel (rip->t_triggered_interval);
2551 rip->t_triggered_interval = NULL;
2552 }
2553 rip->trigger = 0;
2554
2555 /* Logging triggered update. */
2556 if (IS_RIP_DEBUG_EVENT)
2557 zlog_info ("triggered update!");
2558
2559 /* Split Horizon processing is done when generating triggered
2560 updates as well as normal updates (see section 2.6). */
2561 rip_update_process (rip_changed_route);
2562
2563 /* Once all of the triggered updates have been generated, the route
2564 change flags should be cleared. */
2565 rip_clear_changed_flag ();
2566
2567 /* After a triggered update is sent, a timer should be set for a
2568 random interval between 1 and 5 seconds. If other changes that
2569 would trigger updates occur before the timer expires, a single
2570 update is triggered when the timer expires. */
2571 interval = (random () % 5) + 1;
2572
2573 rip->t_triggered_interval =
2574 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2575
2576 return 0;
2577}
2578
2579/* Withdraw redistributed route. */
2580void
2581rip_redistribute_withdraw (int type)
2582{
2583 struct route_node *rp;
2584 struct rip_info *rinfo;
2585
2586 if (!rip)
2587 return;
2588
2589 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2590 if ((rinfo = rp->info) != NULL)
2591 {
2592 if (rinfo->type == type
2593 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2594 {
2595 /* Perform poisoned reverse. */
2596 rinfo->metric = RIP_METRIC_INFINITY;
2597 RIP_TIMER_ON (rinfo->t_garbage_collect,
2598 rip_garbage_collect, rip->garbage_time);
2599 RIP_TIMER_OFF (rinfo->t_timeout);
2600 rinfo->flags |= RIP_RTF_CHANGED;
2601
hasso16705132003-05-25 14:49:19 +00002602 if (IS_RIP_DEBUG_EVENT) {
2603 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2604
2605 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2606 inet_ntoa(p->prefix), p->prefixlen,
2607 ifindex2ifname(rinfo->ifindex));
2608 }
2609
paul718e3742002-12-13 20:15:29 +00002610 rip_event (RIP_TRIGGERED_UPDATE, 0);
2611 }
2612 }
2613}
2614
2615/* Create new RIP instance and set it to global variable. */
2616int
2617rip_create ()
2618{
2619 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2620 memset (rip, 0, sizeof (struct rip));
2621
2622 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002623 rip->version_send = RI_RIP_VERSION_2;
2624 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002625 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2626 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2627 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2628 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2629
2630 /* Initialize RIP routig table. */
2631 rip->table = route_table_init ();
2632 rip->route = route_table_init ();
2633 rip->neighbor = route_table_init ();
2634
2635 /* Make output stream. */
2636 rip->obuf = stream_new (1500);
2637
2638 /* Make socket. */
2639 rip->sock = rip_create_socket ();
2640 if (rip->sock < 0)
2641 return rip->sock;
2642
2643 /* Create read and timer thread. */
2644 rip_event (RIP_READ, rip->sock);
2645 rip_event (RIP_UPDATE_EVENT, 1);
2646
2647 return 0;
2648}
2649
2650/* Sned RIP request to the destination. */
2651int
2652rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002653 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002654{
2655 struct rte *rte;
2656 struct rip_packet rip_packet;
paulcc1131a2003-10-15 23:20:17 +00002657 listnode node;
paul718e3742002-12-13 20:15:29 +00002658
2659 memset (&rip_packet, 0, sizeof (rip_packet));
2660
2661 rip_packet.command = RIP_REQUEST;
2662 rip_packet.version = version;
2663 rte = rip_packet.rte;
2664 rte->metric = htonl (RIP_METRIC_INFINITY);
2665
paul931cd542004-01-23 15:31:42 +00002666 if (connected)
2667 {
2668 /*
2669 * connected is only sent for ripv1 case, or when
2670 * interface does not support multicast. Caller loops
2671 * over each connected address for this case.
2672 */
2673 if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet),
2674 to, ifp, connected) != sizeof (rip_packet))
2675 return -1;
2676 else
2677 return sizeof (rip_packet);
2678 }
2679
paulcc1131a2003-10-15 23:20:17 +00002680 /* send request on each connected network */
2681 LIST_LOOP(ifp->connected, connected, node)
2682 {
2683 struct prefix_ipv4 *p;
2684
2685 p = (struct prefix_ipv4 *) connected->address;
2686
2687 if (p->family != AF_INET)
2688 continue;
2689
paulcc1131a2003-10-15 23:20:17 +00002690 if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002691 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002692 return -1;
2693 }
2694 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002695}
2696
2697int
2698rip_update_jitter (unsigned long time)
2699{
2700 return ((rand () % (time + 1)) - (time / 2));
2701}
2702
2703void
2704rip_event (enum rip_event event, int sock)
2705{
2706 int jitter = 0;
2707
2708 switch (event)
2709 {
2710 case RIP_READ:
2711 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2712 break;
2713 case RIP_UPDATE_EVENT:
2714 if (rip->t_update)
2715 {
2716 thread_cancel (rip->t_update);
2717 rip->t_update = NULL;
2718 }
2719 jitter = rip_update_jitter (rip->update_time);
2720 rip->t_update =
2721 thread_add_timer (master, rip_update, NULL,
2722 sock ? 2 : rip->update_time + jitter);
2723 break;
2724 case RIP_TRIGGERED_UPDATE:
2725 if (rip->t_triggered_interval)
2726 rip->trigger = 1;
2727 else if (! rip->t_triggered_update)
2728 rip->t_triggered_update =
2729 thread_add_event (master, rip_triggered_update, NULL, 0);
2730 break;
2731 default:
2732 break;
2733 }
2734}
2735
2736DEFUN (router_rip,
2737 router_rip_cmd,
2738 "router rip",
2739 "Enable a routing process\n"
2740 "Routing Information Protocol (RIP)\n")
2741{
2742 int ret;
2743
2744 /* If rip is not enabled before. */
2745 if (! rip)
2746 {
2747 ret = rip_create ();
2748 if (ret < 0)
2749 {
2750 zlog_info ("Can't create RIP");
2751 return CMD_WARNING;
2752 }
2753 }
2754 vty->node = RIP_NODE;
2755 vty->index = rip;
2756
2757 return CMD_SUCCESS;
2758}
2759
2760DEFUN (no_router_rip,
2761 no_router_rip_cmd,
2762 "no router rip",
2763 NO_STR
2764 "Enable a routing process\n"
2765 "Routing Information Protocol (RIP)\n")
2766{
2767 if (rip)
2768 rip_clean ();
2769 return CMD_SUCCESS;
2770}
2771
2772DEFUN (rip_version,
2773 rip_version_cmd,
2774 "version <1-2>",
2775 "Set routing protocol version\n"
2776 "version\n")
2777{
2778 int version;
2779
2780 version = atoi (argv[0]);
2781 if (version != RIPv1 && version != RIPv2)
2782 {
2783 vty_out (vty, "invalid rip version %d%s", version,
2784 VTY_NEWLINE);
2785 return CMD_WARNING;
2786 }
paulf38a4712003-06-07 01:10:00 +00002787 rip->version_send = version;
2788 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002789
2790 return CMD_SUCCESS;
2791}
2792
2793DEFUN (no_rip_version,
2794 no_rip_version_cmd,
2795 "no version",
2796 NO_STR
2797 "Set routing protocol version\n")
2798{
2799 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002800 rip->version_send = RI_RIP_VERSION_2;
2801 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002802
2803 return CMD_SUCCESS;
2804}
2805
2806ALIAS (no_rip_version,
2807 no_rip_version_val_cmd,
2808 "no version <1-2>",
2809 NO_STR
2810 "Set routing protocol version\n"
2811 "version\n")
2812
2813DEFUN (rip_route,
2814 rip_route_cmd,
2815 "route A.B.C.D/M",
2816 "RIP static route configuration\n"
2817 "IP prefix <network>/<length>\n")
2818{
2819 int ret;
2820 struct prefix_ipv4 p;
2821 struct route_node *node;
2822
2823 ret = str2prefix_ipv4 (argv[0], &p);
2824 if (ret < 0)
2825 {
2826 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2827 return CMD_WARNING;
2828 }
2829 apply_mask_ipv4 (&p);
2830
2831 /* For router rip configuration. */
2832 node = route_node_get (rip->route, (struct prefix *) &p);
2833
2834 if (node->info)
2835 {
2836 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2837 route_unlock_node (node);
2838 return CMD_WARNING;
2839 }
2840
2841 node->info = "static";
2842
2843 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2844
2845 return CMD_SUCCESS;
2846}
2847
2848DEFUN (no_rip_route,
2849 no_rip_route_cmd,
2850 "no route A.B.C.D/M",
2851 NO_STR
2852 "RIP static route configuration\n"
2853 "IP prefix <network>/<length>\n")
2854{
2855 int ret;
2856 struct prefix_ipv4 p;
2857 struct route_node *node;
2858
2859 ret = str2prefix_ipv4 (argv[0], &p);
2860 if (ret < 0)
2861 {
2862 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2863 return CMD_WARNING;
2864 }
2865 apply_mask_ipv4 (&p);
2866
2867 /* For router rip configuration. */
2868 node = route_node_lookup (rip->route, (struct prefix *) &p);
2869 if (! node)
2870 {
2871 vty_out (vty, "Can't find route %s.%s", argv[0],
2872 VTY_NEWLINE);
2873 return CMD_WARNING;
2874 }
2875
2876 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2877 route_unlock_node (node);
2878
2879 node->info = NULL;
2880 route_unlock_node (node);
2881
2882 return CMD_SUCCESS;
2883}
2884
2885void
2886rip_update_default_metric ()
2887{
2888 struct route_node *np;
2889 struct rip_info *rinfo;
2890
2891 for (np = route_top (rip->table); np; np = route_next (np))
2892 if ((rinfo = np->info) != NULL)
2893 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2894 rinfo->metric = rip->default_metric;
2895}
2896
2897DEFUN (rip_default_metric,
2898 rip_default_metric_cmd,
2899 "default-metric <1-16>",
2900 "Set a metric of redistribute routes\n"
2901 "Default metric\n")
2902{
2903 if (rip)
2904 {
2905 rip->default_metric = atoi (argv[0]);
2906 /* rip_update_default_metric (); */
2907 }
2908 return CMD_SUCCESS;
2909}
2910
2911DEFUN (no_rip_default_metric,
2912 no_rip_default_metric_cmd,
2913 "no default-metric",
2914 NO_STR
2915 "Set a metric of redistribute routes\n"
2916 "Default metric\n")
2917{
2918 if (rip)
2919 {
2920 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2921 /* rip_update_default_metric (); */
2922 }
2923 return CMD_SUCCESS;
2924}
2925
2926ALIAS (no_rip_default_metric,
2927 no_rip_default_metric_val_cmd,
2928 "no default-metric <1-16>",
2929 NO_STR
2930 "Set a metric of redistribute routes\n"
2931 "Default metric\n")
2932
2933DEFUN (rip_timers,
2934 rip_timers_cmd,
2935 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
2936 "Adjust routing timers\n"
2937 "Basic routing protocol update timers\n"
2938 "Routing table update timer value in second. Default is 30.\n"
2939 "Routing information timeout timer. Default is 180.\n"
2940 "Garbage collection timer. Default is 120.\n")
2941{
2942 unsigned long update;
2943 unsigned long timeout;
2944 unsigned long garbage;
2945 char *endptr = NULL;
2946 unsigned long RIP_TIMER_MAX = 2147483647;
2947 unsigned long RIP_TIMER_MIN = 5;
2948
2949 update = strtoul (argv[0], &endptr, 10);
2950 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
2951 {
2952 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2953 return CMD_WARNING;
2954 }
2955
2956 timeout = strtoul (argv[1], &endptr, 10);
2957 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
2958 {
2959 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2960 return CMD_WARNING;
2961 }
2962
2963 garbage = strtoul (argv[2], &endptr, 10);
2964 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
2965 {
2966 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2967 return CMD_WARNING;
2968 }
2969
2970 /* Set each timer value. */
2971 rip->update_time = update;
2972 rip->timeout_time = timeout;
2973 rip->garbage_time = garbage;
2974
2975 /* Reset update timer thread. */
2976 rip_event (RIP_UPDATE_EVENT, 0);
2977
2978 return CMD_SUCCESS;
2979}
2980
2981DEFUN (no_rip_timers,
2982 no_rip_timers_cmd,
2983 "no timers basic",
2984 NO_STR
2985 "Adjust routing timers\n"
2986 "Basic routing protocol update timers\n")
2987{
2988 /* Set each timer value to the default. */
2989 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2990 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2991 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2992
2993 /* Reset update timer thread. */
2994 rip_event (RIP_UPDATE_EVENT, 0);
2995
2996 return CMD_SUCCESS;
2997}
hasso16705132003-05-25 14:49:19 +00002998
2999ALIAS (no_rip_timers,
3000 no_rip_timers_val_cmd,
3001 "no timers basic <0-65535> <0-65535> <0-65535>",
3002 NO_STR
3003 "Adjust routing timers\n"
3004 "Basic routing protocol update timers\n"
3005 "Routing table update timer value in second. Default is 30.\n"
3006 "Routing information timeout timer. Default is 180.\n"
3007 "Garbage collection timer. Default is 120.\n")
3008
paul718e3742002-12-13 20:15:29 +00003009
3010struct route_table *rip_distance_table;
3011
3012struct rip_distance
3013{
3014 /* Distance value for the IP source prefix. */
3015 u_char distance;
3016
3017 /* Name of the access-list to be matched. */
3018 char *access_list;
3019};
3020
3021struct rip_distance *
3022rip_distance_new ()
3023{
3024 struct rip_distance *new;
3025 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3026 memset (new, 0, sizeof (struct rip_distance));
3027 return new;
3028}
3029
3030void
3031rip_distance_free (struct rip_distance *rdistance)
3032{
3033 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3034}
3035
3036int
3037rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3038 char *access_list_str)
3039{
3040 int ret;
3041 struct prefix_ipv4 p;
3042 u_char distance;
3043 struct route_node *rn;
3044 struct rip_distance *rdistance;
3045
3046 ret = str2prefix_ipv4 (ip_str, &p);
3047 if (ret == 0)
3048 {
3049 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3050 return CMD_WARNING;
3051 }
3052
3053 distance = atoi (distance_str);
3054
3055 /* Get RIP distance node. */
3056 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3057 if (rn->info)
3058 {
3059 rdistance = rn->info;
3060 route_unlock_node (rn);
3061 }
3062 else
3063 {
3064 rdistance = rip_distance_new ();
3065 rn->info = rdistance;
3066 }
3067
3068 /* Set distance value. */
3069 rdistance->distance = distance;
3070
3071 /* Reset access-list configuration. */
3072 if (rdistance->access_list)
3073 {
3074 free (rdistance->access_list);
3075 rdistance->access_list = NULL;
3076 }
3077 if (access_list_str)
3078 rdistance->access_list = strdup (access_list_str);
3079
3080 return CMD_SUCCESS;
3081}
3082
3083int
3084rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3085 char *access_list_str)
3086{
3087 int ret;
3088 struct prefix_ipv4 p;
3089 u_char distance;
3090 struct route_node *rn;
3091 struct rip_distance *rdistance;
3092
3093 ret = str2prefix_ipv4 (ip_str, &p);
3094 if (ret == 0)
3095 {
3096 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3097 return CMD_WARNING;
3098 }
3099
3100 distance = atoi (distance_str);
3101
3102 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3103 if (! rn)
3104 {
3105 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3106 return CMD_WARNING;
3107 }
3108
3109 rdistance = rn->info;
3110
3111 if (rdistance->access_list)
3112 free (rdistance->access_list);
3113 rip_distance_free (rdistance);
3114
3115 rn->info = NULL;
3116 route_unlock_node (rn);
3117 route_unlock_node (rn);
3118
3119 return CMD_SUCCESS;
3120}
3121
3122void
3123rip_distance_reset ()
3124{
3125 struct route_node *rn;
3126 struct rip_distance *rdistance;
3127
3128 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3129 if ((rdistance = rn->info) != NULL)
3130 {
3131 if (rdistance->access_list)
3132 free (rdistance->access_list);
3133 rip_distance_free (rdistance);
3134 rn->info = NULL;
3135 route_unlock_node (rn);
3136 }
3137}
3138
3139/* Apply RIP information to distance method. */
3140u_char
3141rip_distance_apply (struct rip_info *rinfo)
3142{
3143 struct route_node *rn;
3144 struct prefix_ipv4 p;
3145 struct rip_distance *rdistance;
3146 struct access_list *alist;
3147
3148 if (! rip)
3149 return 0;
3150
3151 memset (&p, 0, sizeof (struct prefix_ipv4));
3152 p.family = AF_INET;
3153 p.prefix = rinfo->from;
3154 p.prefixlen = IPV4_MAX_BITLEN;
3155
3156 /* Check source address. */
3157 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3158 if (rn)
3159 {
3160 rdistance = rn->info;
3161 route_unlock_node (rn);
3162
3163 if (rdistance->access_list)
3164 {
3165 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3166 if (alist == NULL)
3167 return 0;
3168 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3169 return 0;
3170
3171 return rdistance->distance;
3172 }
3173 else
3174 return rdistance->distance;
3175 }
3176
3177 if (rip->distance)
3178 return rip->distance;
3179
3180 return 0;
3181}
3182
3183void
3184rip_distance_show (struct vty *vty)
3185{
3186 struct route_node *rn;
3187 struct rip_distance *rdistance;
3188 int header = 1;
3189 char buf[BUFSIZ];
3190
3191 vty_out (vty, " Distance: (default is %d)%s",
3192 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3193 VTY_NEWLINE);
3194
3195 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3196 if ((rdistance = rn->info) != NULL)
3197 {
3198 if (header)
3199 {
3200 vty_out (vty, " Address Distance List%s",
3201 VTY_NEWLINE);
3202 header = 0;
3203 }
3204 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3205 vty_out (vty, " %-20s %4d %s%s",
3206 buf, rdistance->distance,
3207 rdistance->access_list ? rdistance->access_list : "",
3208 VTY_NEWLINE);
3209 }
3210}
3211
3212DEFUN (rip_distance,
3213 rip_distance_cmd,
3214 "distance <1-255>",
3215 "Administrative distance\n"
3216 "Distance value\n")
3217{
3218 rip->distance = atoi (argv[0]);
3219 return CMD_SUCCESS;
3220}
3221
3222DEFUN (no_rip_distance,
3223 no_rip_distance_cmd,
3224 "no distance <1-255>",
3225 NO_STR
3226 "Administrative distance\n"
3227 "Distance value\n")
3228{
3229 rip->distance = 0;
3230 return CMD_SUCCESS;
3231}
3232
3233DEFUN (rip_distance_source,
3234 rip_distance_source_cmd,
3235 "distance <1-255> A.B.C.D/M",
3236 "Administrative distance\n"
3237 "Distance value\n"
3238 "IP source prefix\n")
3239{
3240 rip_distance_set (vty, argv[0], argv[1], NULL);
3241 return CMD_SUCCESS;
3242}
3243
3244DEFUN (no_rip_distance_source,
3245 no_rip_distance_source_cmd,
3246 "no distance <1-255> A.B.C.D/M",
3247 NO_STR
3248 "Administrative distance\n"
3249 "Distance value\n"
3250 "IP source prefix\n")
3251{
3252 rip_distance_unset (vty, argv[0], argv[1], NULL);
3253 return CMD_SUCCESS;
3254}
3255
3256DEFUN (rip_distance_source_access_list,
3257 rip_distance_source_access_list_cmd,
3258 "distance <1-255> A.B.C.D/M WORD",
3259 "Administrative distance\n"
3260 "Distance value\n"
3261 "IP source prefix\n"
3262 "Access list name\n")
3263{
3264 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3265 return CMD_SUCCESS;
3266}
3267
3268DEFUN (no_rip_distance_source_access_list,
3269 no_rip_distance_source_access_list_cmd,
3270 "no distance <1-255> A.B.C.D/M WORD",
3271 NO_STR
3272 "Administrative distance\n"
3273 "Distance value\n"
3274 "IP source prefix\n"
3275 "Access list name\n")
3276{
3277 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3278 return CMD_SUCCESS;
3279}
3280
3281/* Print out routes update time. */
3282void
3283rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3284{
3285 struct timeval timer_now;
3286 time_t clock;
3287 struct tm *tm;
3288#define TIME_BUF 25
3289 char timebuf [TIME_BUF];
3290 struct thread *thread;
3291
3292 gettimeofday (&timer_now, NULL);
3293
3294 if ((thread = rinfo->t_timeout) != NULL)
3295 {
3296 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3297 tm = gmtime (&clock);
3298 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3299 vty_out (vty, "%5s", timebuf);
3300 }
3301 else if ((thread = rinfo->t_garbage_collect) != NULL)
3302 {
3303 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3304 tm = gmtime (&clock);
3305 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3306 vty_out (vty, "%5s", timebuf);
3307 }
3308}
3309
3310char *
3311rip_route_type_print (int sub_type)
3312{
3313 switch (sub_type)
3314 {
3315 case RIP_ROUTE_RTE:
3316 return "n";
3317 case RIP_ROUTE_STATIC:
3318 return "s";
3319 case RIP_ROUTE_DEFAULT:
3320 return "d";
3321 case RIP_ROUTE_REDISTRIBUTE:
3322 return "r";
3323 case RIP_ROUTE_INTERFACE:
3324 return "i";
3325 default:
3326 return "?";
3327 }
3328}
3329
3330DEFUN (show_ip_rip,
3331 show_ip_rip_cmd,
3332 "show ip rip",
3333 SHOW_STR
3334 IP_STR
3335 "Show RIP routes\n")
3336{
3337 struct route_node *np;
3338 struct rip_info *rinfo;
3339
3340 if (! rip)
3341 return CMD_SUCCESS;
3342
hasso16705132003-05-25 14:49:19 +00003343 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3344 "Sub-codes:%s"
3345 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003346 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003347 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003348 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003349
3350 for (np = route_top (rip->table); np; np = route_next (np))
3351 if ((rinfo = np->info) != NULL)
3352 {
3353 int len;
3354
3355 len = vty_out (vty, "%s(%s) %s/%d",
3356 /* np->lock, For debugging. */
3357 route_info[rinfo->type].str,
3358 rip_route_type_print (rinfo->sub_type),
3359 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3360
hassoa1455d82004-03-03 19:36:24 +00003361 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003362
3363 if (len > 0)
3364 vty_out (vty, "%*s", len, " ");
3365
3366 if (rinfo->nexthop.s_addr)
3367 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3368 rinfo->metric);
3369 else
3370 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3371
3372 /* Route which exist in kernel routing table. */
3373 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3374 (rinfo->sub_type == RIP_ROUTE_RTE))
3375 {
3376 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003377 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003378 rip_vty_out_uptime (vty, rinfo);
3379 }
3380 else if (rinfo->metric == RIP_METRIC_INFINITY)
3381 {
3382 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003383 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003384 rip_vty_out_uptime (vty, rinfo);
3385 }
3386 else
hasso16705132003-05-25 14:49:19 +00003387 {
3388 vty_out (vty, "self ");
3389 vty_out (vty, "%3d", rinfo->tag);
3390 }
paul718e3742002-12-13 20:15:29 +00003391
3392 vty_out (vty, "%s", VTY_NEWLINE);
3393 }
3394 return CMD_SUCCESS;
3395}
3396
3397/* Return next event time. */
3398int
3399rip_next_thread_timer (struct thread *thread)
3400{
3401 struct timeval timer_now;
3402
3403 gettimeofday (&timer_now, NULL);
3404
3405 return thread->u.sands.tv_sec - timer_now.tv_sec;
3406}
3407
hasso16705132003-05-25 14:49:19 +00003408/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3409DEFUN (show_ip_rip_status,
3410 show_ip_rip_status_cmd,
3411 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003412 SHOW_STR
3413 IP_STR
hasso16705132003-05-25 14:49:19 +00003414 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003415 "IP routing protocol process parameters and statistics\n")
3416{
3417 listnode node;
3418 struct interface *ifp;
3419 struct rip_interface *ri;
3420 extern struct message ri_version_msg[];
3421 char *send_version;
3422 char *receive_version;
3423
3424 if (! rip)
3425 return CMD_SUCCESS;
3426
3427 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3428 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3429 rip->update_time);
3430 vty_out (vty, " next due in %d seconds%s",
3431 rip_next_thread_timer (rip->t_update),
3432 VTY_NEWLINE);
3433 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3434 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3435 VTY_NEWLINE);
3436
3437 /* Filtering status show. */
3438 config_show_distribute (vty);
3439
3440 /* Default metric information. */
3441 vty_out (vty, " Default redistribution metric is %d%s",
3442 rip->default_metric, VTY_NEWLINE);
3443
3444 /* Redistribute information. */
3445 vty_out (vty, " Redistributing:");
3446 config_write_rip_redistribute (vty, 0);
3447 vty_out (vty, "%s", VTY_NEWLINE);
3448
paulf38a4712003-06-07 01:10:00 +00003449 vty_out (vty, " Default version control: send version %s,",
3450 lookup(ri_version_msg,rip->version_send));
3451 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3452 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3453 else
3454 vty_out (vty, " receive version %s %s",
3455 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003456
3457 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3458
3459 for (node = listhead (iflist); node; node = nextnode (node))
3460 {
3461 ifp = getdata (node);
3462 ri = ifp->info;
3463
3464 if (ri->enable_network || ri->enable_interface)
3465 {
3466 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003467 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003468 else
3469 send_version = lookup (ri_version_msg, ri->ri_send);
3470
3471 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003472 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003473 else
3474 receive_version = lookup (ri_version_msg, ri->ri_receive);
3475
3476 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3477 send_version,
3478 receive_version,
3479 ri->key_chain ? ri->key_chain : "",
3480 VTY_NEWLINE);
3481 }
3482 }
3483
3484 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3485 config_write_rip_network (vty, 0);
3486
paul4aaff3f2003-06-07 01:04:45 +00003487 {
3488 int found_passive = 0;
3489 for (node = listhead (iflist); node; node = nextnode (node))
3490 {
3491 ifp = getdata (node);
3492 ri = ifp->info;
3493
3494 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3495 {
3496 if (!found_passive)
3497 {
3498 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3499 found_passive = 1;
3500 }
3501 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3502 }
3503 }
3504 }
3505
paul718e3742002-12-13 20:15:29 +00003506 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3507 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3508 rip_peer_display (vty);
3509
3510 rip_distance_show (vty);
3511
3512 return CMD_SUCCESS;
3513}
3514
3515/* RIP configuration write function. */
3516int
3517config_write_rip (struct vty *vty)
3518{
3519 int write = 0;
3520 struct route_node *rn;
3521 struct rip_distance *rdistance;
3522
3523 if (rip)
3524 {
3525 /* Router RIP statement. */
3526 vty_out (vty, "router rip%s", VTY_NEWLINE);
3527 write++;
3528
3529 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003530 if (rip->version_send != RI_RIP_VERSION_2
3531 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3532 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003533 VTY_NEWLINE);
3534
3535 /* RIP timer configuration. */
3536 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3537 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3538 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3539 vty_out (vty, " timers basic %lu %lu %lu%s",
3540 rip->update_time,
3541 rip->timeout_time,
3542 rip->garbage_time,
3543 VTY_NEWLINE);
3544
3545 /* Default information configuration. */
3546 if (rip->default_information)
3547 {
3548 if (rip->default_information_route_map)
3549 vty_out (vty, " default-information originate route-map %s%s",
3550 rip->default_information_route_map, VTY_NEWLINE);
3551 else
3552 vty_out (vty, " default-information originate%s",
3553 VTY_NEWLINE);
3554 }
3555
3556 /* Redistribute configuration. */
3557 config_write_rip_redistribute (vty, 1);
3558
3559 /* RIP offset-list configuration. */
3560 config_write_rip_offset_list (vty);
3561
3562 /* RIP enabled network and interface configuration. */
3563 config_write_rip_network (vty, 1);
3564
3565 /* RIP default metric configuration */
3566 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3567 vty_out (vty, " default-metric %d%s",
3568 rip->default_metric, VTY_NEWLINE);
3569
3570 /* Distribute configuration. */
3571 write += config_write_distribute (vty);
3572
hasso16705132003-05-25 14:49:19 +00003573 /* Interface routemap configuration */
3574 write += config_write_if_rmap (vty);
3575
paul718e3742002-12-13 20:15:29 +00003576 /* Distance configuration. */
3577 if (rip->distance)
3578 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3579
3580 /* RIP source IP prefix distance configuration. */
3581 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3582 if ((rdistance = rn->info) != NULL)
3583 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3584 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3585 rdistance->access_list ? rdistance->access_list : "",
3586 VTY_NEWLINE);
3587
3588 /* RIP static route configuration. */
3589 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3590 if (rn->info)
3591 vty_out (vty, " route %s/%d%s",
3592 inet_ntoa (rn->p.u.prefix4),
3593 rn->p.prefixlen,
3594 VTY_NEWLINE);
3595
3596 }
3597 return write;
3598}
3599
3600/* RIP node structure. */
3601struct cmd_node rip_node =
3602{
3603 RIP_NODE,
3604 "%s(config-router)# ",
3605 1
3606};
3607
3608/* Distribute-list update functions. */
3609void
3610rip_distribute_update (struct distribute *dist)
3611{
3612 struct interface *ifp;
3613 struct rip_interface *ri;
3614 struct access_list *alist;
3615 struct prefix_list *plist;
3616
3617 if (! dist->ifname)
3618 return;
3619
3620 ifp = if_lookup_by_name (dist->ifname);
3621 if (ifp == NULL)
3622 return;
3623
3624 ri = ifp->info;
3625
3626 if (dist->list[DISTRIBUTE_IN])
3627 {
3628 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3629 if (alist)
3630 ri->list[RIP_FILTER_IN] = alist;
3631 else
3632 ri->list[RIP_FILTER_IN] = NULL;
3633 }
3634 else
3635 ri->list[RIP_FILTER_IN] = NULL;
3636
3637 if (dist->list[DISTRIBUTE_OUT])
3638 {
3639 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3640 if (alist)
3641 ri->list[RIP_FILTER_OUT] = alist;
3642 else
3643 ri->list[RIP_FILTER_OUT] = NULL;
3644 }
3645 else
3646 ri->list[RIP_FILTER_OUT] = NULL;
3647
3648 if (dist->prefix[DISTRIBUTE_IN])
3649 {
3650 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3651 if (plist)
3652 ri->prefix[RIP_FILTER_IN] = plist;
3653 else
3654 ri->prefix[RIP_FILTER_IN] = NULL;
3655 }
3656 else
3657 ri->prefix[RIP_FILTER_IN] = NULL;
3658
3659 if (dist->prefix[DISTRIBUTE_OUT])
3660 {
3661 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3662 if (plist)
3663 ri->prefix[RIP_FILTER_OUT] = plist;
3664 else
3665 ri->prefix[RIP_FILTER_OUT] = NULL;
3666 }
3667 else
3668 ri->prefix[RIP_FILTER_OUT] = NULL;
3669}
3670
3671void
3672rip_distribute_update_interface (struct interface *ifp)
3673{
3674 struct distribute *dist;
3675
3676 dist = distribute_lookup (ifp->name);
3677 if (dist)
3678 rip_distribute_update (dist);
3679}
3680
3681/* Update all interface's distribute list. */
3682void
3683rip_distribute_update_all ()
3684{
3685 struct interface *ifp;
3686 listnode node;
3687
3688 for (node = listhead (iflist); node; nextnode (node))
3689 {
3690 ifp = getdata (node);
3691 rip_distribute_update_interface (ifp);
3692 }
3693}
3694
3695/* Delete all added rip route. */
3696void
3697rip_clean ()
3698{
3699 int i;
3700 struct route_node *rp;
3701 struct rip_info *rinfo;
3702
3703 if (rip)
3704 {
3705 /* Clear RIP routes */
3706 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3707 if ((rinfo = rp->info) != NULL)
3708 {
3709 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3710 rinfo->sub_type == RIP_ROUTE_RTE)
3711 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3712 &rinfo->nexthop, rinfo->metric);
3713
3714 RIP_TIMER_OFF (rinfo->t_timeout);
3715 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3716
3717 rp->info = NULL;
3718 route_unlock_node (rp);
3719
3720 rip_info_free (rinfo);
3721 }
3722
3723 /* Cancel RIP related timers. */
3724 RIP_TIMER_OFF (rip->t_update);
3725 RIP_TIMER_OFF (rip->t_triggered_update);
3726 RIP_TIMER_OFF (rip->t_triggered_interval);
3727
3728 /* Cancel read thread. */
3729 if (rip->t_read)
3730 {
3731 thread_cancel (rip->t_read);
3732 rip->t_read = NULL;
3733 }
3734
3735 /* Close RIP socket. */
3736 if (rip->sock >= 0)
3737 {
3738 close (rip->sock);
3739 rip->sock = -1;
3740 }
3741
3742 /* Static RIP route configuration. */
3743 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3744 if (rp->info)
3745 {
3746 rp->info = NULL;
3747 route_unlock_node (rp);
3748 }
3749
3750 /* RIP neighbor configuration. */
3751 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3752 if (rp->info)
3753 {
3754 rp->info = NULL;
3755 route_unlock_node (rp);
3756 }
3757
3758 /* Redistribute related clear. */
3759 if (rip->default_information_route_map)
3760 free (rip->default_information_route_map);
3761
3762 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3763 if (rip->route_map[i].name)
3764 free (rip->route_map[i].name);
3765
3766 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3767 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3768 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3769
3770 XFREE (MTYPE_RIP, rip);
3771 rip = NULL;
3772 }
3773
3774 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003775 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003776 rip_offset_clean ();
3777 rip_interface_clean ();
3778 rip_distance_reset ();
3779 rip_redistribute_clean ();
3780}
3781
3782/* Reset all values to the default settings. */
3783void
3784rip_reset ()
3785{
3786 /* Reset global counters. */
3787 rip_global_route_changes = 0;
3788 rip_global_queries = 0;
3789
3790 /* Call ripd related reset functions. */
3791 rip_debug_reset ();
3792 rip_route_map_reset ();
3793
3794 /* Call library reset functions. */
3795 vty_reset ();
3796 access_list_reset ();
3797 prefix_list_reset ();
3798
3799 distribute_list_reset ();
3800
3801 rip_interface_reset ();
3802 rip_distance_reset ();
3803
3804 rip_zclient_reset ();
3805}
3806
hasso16705132003-05-25 14:49:19 +00003807void
3808rip_if_rmap_update (struct if_rmap *if_rmap)
3809{
3810 struct interface *ifp;
3811 struct rip_interface *ri;
3812 struct route_map *rmap;
3813
3814 ifp = if_lookup_by_name (if_rmap->ifname);
3815 if (ifp == NULL)
3816 return;
3817
3818 ri = ifp->info;
3819
3820 if (if_rmap->routemap[IF_RMAP_IN])
3821 {
3822 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3823 if (rmap)
3824 ri->routemap[IF_RMAP_IN] = rmap;
3825 else
3826 ri->routemap[IF_RMAP_IN] = NULL;
3827 }
3828 else
3829 ri->routemap[RIP_FILTER_IN] = NULL;
3830
3831 if (if_rmap->routemap[IF_RMAP_OUT])
3832 {
3833 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3834 if (rmap)
3835 ri->routemap[IF_RMAP_OUT] = rmap;
3836 else
3837 ri->routemap[IF_RMAP_OUT] = NULL;
3838 }
3839 else
3840 ri->routemap[RIP_FILTER_OUT] = NULL;
3841}
3842
3843void
3844rip_if_rmap_update_interface (struct interface *ifp)
3845{
3846 struct if_rmap *if_rmap;
3847
3848 if_rmap = if_rmap_lookup (ifp->name);
3849 if (if_rmap)
3850 rip_if_rmap_update (if_rmap);
3851}
3852
3853void
3854rip_routemap_update_redistribute (void)
3855{
3856 int i;
3857
3858 if (rip)
3859 {
3860 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3861 {
3862 if (rip->route_map[i].name)
3863 rip->route_map[i].map =
3864 route_map_lookup_by_name (rip->route_map[i].name);
3865 }
3866 }
3867}
3868
3869void
3870rip_routemap_update ()
3871{
3872 struct interface *ifp;
3873 listnode node;
3874
3875 for (node = listhead (iflist); node; nextnode (node))
3876 {
3877 ifp = getdata (node);
3878 rip_if_rmap_update_interface (ifp);
3879 }
3880
3881 rip_routemap_update_redistribute ();
3882}
3883
paul718e3742002-12-13 20:15:29 +00003884/* Allocate new rip structure and set default value. */
3885void
3886rip_init ()
3887{
3888 /* Randomize for triggered update random(). */
3889 srand (time (NULL));
3890
3891 /* Install top nodes. */
3892 install_node (&rip_node, config_write_rip);
3893
3894 /* Install rip commands. */
3895 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003896 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003897 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003898 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003899 install_element (CONFIG_NODE, &router_rip_cmd);
3900 install_element (CONFIG_NODE, &no_router_rip_cmd);
3901
3902 install_default (RIP_NODE);
3903 install_element (RIP_NODE, &rip_version_cmd);
3904 install_element (RIP_NODE, &no_rip_version_cmd);
3905 install_element (RIP_NODE, &no_rip_version_val_cmd);
3906 install_element (RIP_NODE, &rip_default_metric_cmd);
3907 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3908 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3909 install_element (RIP_NODE, &rip_timers_cmd);
3910 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003911 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003912 install_element (RIP_NODE, &rip_route_cmd);
3913 install_element (RIP_NODE, &no_rip_route_cmd);
3914 install_element (RIP_NODE, &rip_distance_cmd);
3915 install_element (RIP_NODE, &no_rip_distance_cmd);
3916 install_element (RIP_NODE, &rip_distance_source_cmd);
3917 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3918 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3919 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3920
3921 /* Debug related init. */
3922 rip_debug_init ();
3923
paul718e3742002-12-13 20:15:29 +00003924 /* SNMP init. */
3925#ifdef HAVE_SNMP
3926 rip_snmp_init ();
3927#endif /* HAVE_SNMP */
3928
3929 /* Access list install. */
3930 access_list_init ();
3931 access_list_add_hook (rip_distribute_update_all);
3932 access_list_delete_hook (rip_distribute_update_all);
3933
3934 /* Prefix list initialize.*/
3935 prefix_list_init ();
3936 prefix_list_add_hook (rip_distribute_update_all);
3937 prefix_list_delete_hook (rip_distribute_update_all);
3938
3939 /* Distribute list install. */
3940 distribute_list_init (RIP_NODE);
3941 distribute_list_add_hook (rip_distribute_update);
3942 distribute_list_delete_hook (rip_distribute_update);
3943
hasso16705132003-05-25 14:49:19 +00003944 /* Route-map */
3945 rip_route_map_init ();
3946 rip_offset_init ();
3947
3948 route_map_add_hook (rip_routemap_update);
3949 route_map_delete_hook (rip_routemap_update);
3950
3951 if_rmap_init (RIP_NODE);
3952 if_rmap_hook_add (rip_if_rmap_update);
3953 if_rmap_hook_delete (rip_if_rmap_update);
3954
paul718e3742002-12-13 20:15:29 +00003955 /* Distance control. */
3956 rip_distance_table = route_table_init ();
3957}