blob: 4b5a19a92637eaea85a5c8da310ba5fe376f1912 [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)",
1256 inet_ntoa(connected->address->u.prefix4), dst, ifp->name);
1257 }
1258 if (connected->flags & ZEBRA_IFA_SECONDARY)
1259 {
1260 /*
1261 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1262 * with multiple addresses on the same subnet: the first address
1263 * on the subnet is configured "primary", and all subsequent addresses
1264 * on that subnet are treated as "secondary" addresses.
1265 * In order to avoid routing-table bloat on other rip listeners,
1266 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1267 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1268 * flag is set, we would end up sending a packet for a "secondary"
1269 * source address on non-linux systems.
1270 */
1271 if (IS_RIP_DEBUG_PACKET)
1272 zlog_info("duplicate dropped");
1273 return 0;
1274 }
1275
paul718e3742002-12-13 20:15:29 +00001276 /* Make destination address. */
1277 memset (&sin, 0, sizeof (struct sockaddr_in));
1278 sin.sin_family = AF_INET;
1279#ifdef HAVE_SIN_LEN
1280 sin.sin_len = sizeof (struct sockaddr_in);
1281#endif /* HAVE_SIN_LEN */
1282
1283 /* When destination is specified, use it's port and address. */
1284 if (to)
1285 {
paul718e3742002-12-13 20:15:29 +00001286 sin.sin_port = to->sin_port;
1287 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001288 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001289 }
1290 else
1291 {
paul718e3742002-12-13 20:15:29 +00001292
1293 sin.sin_port = htons (RIP_PORT_DEFAULT);
1294 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1295
paul931cd542004-01-23 15:31:42 +00001296 /*
1297 * we have to open a new socket for each packet because this
1298 * is the most portable way to bind to a different source
1299 * ipv4 address for each packet.
1300 */
1301 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1302 if (send_sock < 0)
1303 {
1304 zlog_warn("rip_send_packet could not create socket %s",
1305 strerror(errno));
1306 return -1;
1307 }
1308 sockopt_broadcast (send_sock);
1309 sockopt_reuseaddr (send_sock);
1310 sockopt_reuseport (send_sock);
1311#ifdef RIP_RECVMSG
1312 setsockopt_pktinfo (send_sock);
1313#endif /* RIP_RECVMSG */
1314 rip_interface_multicast_set(send_sock, connected, if_is_pointopoint(ifp));
paul718e3742002-12-13 20:15:29 +00001315 }
1316
paul931cd542004-01-23 15:31:42 +00001317 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001318 sizeof (struct sockaddr_in));
1319
1320 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001321 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1322 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001323
1324 if (ret < 0)
1325 zlog_warn ("can't send packet : %s", strerror (errno));
1326
paul931cd542004-01-23 15:31:42 +00001327 if (!to)
1328 close(send_sock);
1329
paul718e3742002-12-13 20:15:29 +00001330 return ret;
1331}
1332
1333/* Add redistributed route to RIP table. */
1334void
1335rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1336 unsigned int ifindex, struct in_addr *nexthop)
1337{
1338 int ret;
1339 struct route_node *rp;
1340 struct rip_info *rinfo;
1341
1342 /* Redistribute route */
1343 ret = rip_destination_check (p->prefix);
1344 if (! ret)
1345 return;
1346
1347 rp = route_node_get (rip->table, (struct prefix *) p);
1348
1349 rinfo = rp->info;
1350
1351 if (rinfo)
1352 {
1353 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1354 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1355 && rinfo->metric != RIP_METRIC_INFINITY)
1356 {
1357 route_unlock_node (rp);
1358 return;
1359 }
1360
1361 /* Manually configured RIP route check. */
1362 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001363 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1364 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001365 {
hasso16705132003-05-25 14:49:19 +00001366 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1367 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001368 {
1369 route_unlock_node (rp);
1370 return;
1371 }
1372 }
1373
1374 RIP_TIMER_OFF (rinfo->t_timeout);
1375 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1376
1377 if (rip_route_rte (rinfo))
1378 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1379 rinfo->metric);
1380 rp->info = NULL;
1381 rip_info_free (rinfo);
1382
1383 route_unlock_node (rp);
1384 }
1385
1386 rinfo = rip_info_new ();
1387
1388 rinfo->type = type;
1389 rinfo->sub_type = sub_type;
1390 rinfo->ifindex = ifindex;
1391 rinfo->metric = 1;
1392 rinfo->rp = rp;
1393
1394 if (nexthop)
1395 rinfo->nexthop = *nexthop;
1396
1397 rinfo->flags |= RIP_RTF_FIB;
1398 rp->info = rinfo;
1399
1400 rinfo->flags |= RIP_RTF_CHANGED;
1401
hasso16705132003-05-25 14:49:19 +00001402 if (IS_RIP_DEBUG_EVENT) {
1403 if (!nexthop)
1404 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1405 inet_ntoa(p->prefix), p->prefixlen,
1406 ifindex2ifname(ifindex));
1407 else
1408 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1409 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1410 ifindex2ifname(ifindex));
1411 }
1412
1413
paul718e3742002-12-13 20:15:29 +00001414 rip_event (RIP_TRIGGERED_UPDATE, 0);
1415}
1416
1417/* Delete redistributed route from RIP table. */
1418void
1419rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1420 unsigned int ifindex)
1421{
1422 int ret;
1423 struct route_node *rp;
1424 struct rip_info *rinfo;
1425
1426 ret = rip_destination_check (p->prefix);
1427 if (! ret)
1428 return;
1429
1430 rp = route_node_lookup (rip->table, (struct prefix *) p);
1431 if (rp)
1432 {
1433 rinfo = rp->info;
1434
1435 if (rinfo != NULL
1436 && rinfo->type == type
1437 && rinfo->sub_type == sub_type
1438 && rinfo->ifindex == ifindex)
1439 {
1440 /* Perform poisoned reverse. */
1441 rinfo->metric = RIP_METRIC_INFINITY;
1442 RIP_TIMER_ON (rinfo->t_garbage_collect,
1443 rip_garbage_collect, rip->garbage_time);
1444 RIP_TIMER_OFF (rinfo->t_timeout);
1445 rinfo->flags |= RIP_RTF_CHANGED;
1446
hasso16705132003-05-25 14:49:19 +00001447 if (IS_RIP_DEBUG_EVENT)
1448 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1449 inet_ntoa(p->prefix), p->prefixlen,
1450 ifindex2ifname(ifindex));
1451
paul718e3742002-12-13 20:15:29 +00001452 rip_event (RIP_TRIGGERED_UPDATE, 0);
1453 }
1454 }
1455}
1456
1457/* Response to request called from rip_read ().*/
1458void
1459rip_request_process (struct rip_packet *packet, int size,
1460 struct sockaddr_in *from, struct interface *ifp)
1461{
1462 caddr_t lim;
1463 struct rte *rte;
1464 struct prefix_ipv4 p;
1465 struct route_node *rp;
1466 struct rip_info *rinfo;
1467 struct rip_interface *ri;
1468
hasso16705132003-05-25 14:49:19 +00001469 /* Does not reponse to the requests on the loopback interfaces */
1470 if (if_is_loopback (ifp))
1471 return;
1472
1473 /* Check RIPng process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001474 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001475 if (! ri->running)
1476 return;
paul718e3742002-12-13 20:15:29 +00001477
1478 /* When passive interface is specified, suppress responses */
1479 if (ri->passive)
1480 return;
1481
1482 /* RIP peer update. */
1483 rip_peer_update (from, packet->version);
1484
1485 lim = ((caddr_t) packet) + size;
1486 rte = packet->rte;
1487
1488 /* The Request is processed entry by entry. If there are no
1489 entries, no response is given. */
1490 if (lim == (caddr_t) rte)
1491 return;
1492
1493 /* There is one special case. If there is exactly one entry in the
1494 request, and it has an address family identifier of zero and a
1495 metric of infinity (i.e., 16), then this is a request to send the
1496 entire routing table. */
1497 if (lim == ((caddr_t) (rte + 1)) &&
1498 ntohs (rte->family) == 0 &&
1499 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1500 {
paulcc1131a2003-10-15 23:20:17 +00001501 struct prefix_ipv4 saddr;
1502
1503 /* saddr will be used for determining which routes to split-horizon.
1504 Since the source address we'll pick will be on the same subnet as the
1505 destination, for the purpose of split-horizoning, we'll
1506 pretend that "from" is our source address. */
1507 saddr.family = AF_INET;
1508 saddr.prefixlen = IPV4_MAX_BITLEN;
1509 saddr.prefix = from->sin_addr;
1510
paul718e3742002-12-13 20:15:29 +00001511 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001512 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001513 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001514 }
1515 else
1516 {
1517 /* Examine the list of RTEs in the Request one by one. For each
1518 entry, look up the destination in the router's routing
1519 database and, if there is a route, put that route's metric in
1520 the metric field of the RTE. If there is no explicit route
1521 to the specified destination, put infinity in the metric
1522 field. Once all the entries have been filled in, change the
1523 command from Request to Response and send the datagram back
1524 to the requestor. */
1525 p.family = AF_INET;
1526
1527 for (; ((caddr_t) rte) < lim; rte++)
1528 {
1529 p.prefix = rte->prefix;
1530 p.prefixlen = ip_masklen (rte->mask);
1531 apply_mask_ipv4 (&p);
1532
1533 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1534 if (rp)
1535 {
1536 rinfo = rp->info;
1537 rte->metric = htonl (rinfo->metric);
1538 route_unlock_node (rp);
1539 }
1540 else
1541 rte->metric = htonl (RIP_METRIC_INFINITY);
1542 }
1543 packet->command = RIP_RESPONSE;
1544
paul931cd542004-01-23 15:31:42 +00001545 rip_send_packet ((caddr_t) packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001546 }
1547 rip_global_queries++;
1548}
1549
1550#if RIP_RECVMSG
1551/* Set IPv6 packet info to the socket. */
1552static int
1553setsockopt_pktinfo (int sock)
1554{
1555 int ret;
1556 int val = 1;
1557
1558 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1559 if (ret < 0)
1560 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1561 return ret;
1562}
1563
1564/* Read RIP packet by recvmsg function. */
1565int
1566rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1567 int *ifindex)
1568{
1569 int ret;
1570 struct msghdr msg;
1571 struct iovec iov;
1572 struct cmsghdr *ptr;
1573 char adata[1024];
1574
1575 msg.msg_name = (void *) from;
1576 msg.msg_namelen = sizeof (struct sockaddr_in);
1577 msg.msg_iov = &iov;
1578 msg.msg_iovlen = 1;
1579 msg.msg_control = (void *) adata;
1580 msg.msg_controllen = sizeof adata;
1581 iov.iov_base = buf;
1582 iov.iov_len = size;
1583
1584 ret = recvmsg (sock, &msg, 0);
1585 if (ret < 0)
1586 return ret;
1587
1588 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1589 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1590 {
1591 struct in_pktinfo *pktinfo;
1592 int i;
1593
1594 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1595 i = pktinfo->ipi_ifindex;
1596 }
1597 return ret;
1598}
1599
1600/* RIP packet read function. */
1601int
1602rip_read_new (struct thread *t)
1603{
1604 int ret;
1605 int sock;
1606 char buf[RIP_PACKET_MAXSIZ];
1607 struct sockaddr_in from;
1608 unsigned int ifindex;
1609
1610 /* Fetch socket then register myself. */
1611 sock = THREAD_FD (t);
1612 rip_event (RIP_READ, sock);
1613
1614 /* Read RIP packet. */
1615 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1616 if (ret < 0)
1617 {
1618 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1619 return ret;
1620 }
1621
1622 return ret;
1623}
1624#endif /* RIP_RECVMSG */
1625
1626/* First entry point of RIP packet. */
1627int
1628rip_read (struct thread *t)
1629{
1630 int sock;
1631 int ret;
1632 int rtenum;
1633 union rip_buf rip_buf;
1634 struct rip_packet *packet;
1635 struct sockaddr_in from;
1636 int fromlen, len;
1637 struct interface *ifp;
1638 struct rip_interface *ri;
1639
1640 /* Fetch socket then register myself. */
1641 sock = THREAD_FD (t);
1642 rip->t_read = NULL;
1643
1644 /* Add myself to tne next event */
1645 rip_event (RIP_READ, sock);
1646
1647 /* RIPd manages only IPv4. */
1648 memset (&from, 0, sizeof (struct sockaddr_in));
1649 fromlen = sizeof (struct sockaddr_in);
1650
1651 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1652 (struct sockaddr *) &from, &fromlen);
1653 if (len < 0)
1654 {
1655 zlog_info ("recvfrom failed: %s", strerror (errno));
1656 return len;
1657 }
1658
1659 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001660 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001661 {
1662 if (IS_RIP_DEBUG_PACKET)
1663 zlog_warn ("ignore packet comes from myself");
1664 return -1;
1665 }
1666
1667 /* Which interface is this packet comes from. */
1668 ifp = if_lookup_address (from.sin_addr);
1669
1670 /* RIP packet received */
1671 if (IS_RIP_DEBUG_EVENT)
1672 zlog_info ("RECV packet from %s port %d on %s",
1673 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1674 ifp ? ifp->name : "unknown");
1675
1676 /* If this packet come from unknown interface, ignore it. */
1677 if (ifp == NULL)
1678 {
1679 zlog_info ("packet comes from unknown interface");
1680 return -1;
1681 }
1682
1683 /* Packet length check. */
1684 if (len < RIP_PACKET_MINSIZ)
1685 {
1686 zlog_warn ("packet size %d is smaller than minimum size %d",
1687 len, RIP_PACKET_MINSIZ);
1688 rip_peer_bad_packet (&from);
1689 return len;
1690 }
1691 if (len > RIP_PACKET_MAXSIZ)
1692 {
1693 zlog_warn ("packet size %d is larger than max size %d",
1694 len, RIP_PACKET_MAXSIZ);
1695 rip_peer_bad_packet (&from);
1696 return len;
1697 }
1698
1699 /* Packet alignment check. */
1700 if ((len - RIP_PACKET_MINSIZ) % 20)
1701 {
1702 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1703 rip_peer_bad_packet (&from);
1704 return len;
1705 }
1706
1707 /* Set RTE number. */
1708 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1709
1710 /* For easy to handle. */
1711 packet = &rip_buf.rip_packet;
1712
1713 /* RIP version check. */
1714 if (packet->version == 0)
1715 {
1716 zlog_info ("version 0 with command %d received.", packet->command);
1717 rip_peer_bad_packet (&from);
1718 return -1;
1719 }
1720
1721 /* Dump RIP packet. */
1722 if (IS_RIP_DEBUG_RECV)
1723 rip_packet_dump (packet, len, "RECV");
1724
1725 /* RIP version adjust. This code should rethink now. RFC1058 says
1726 that "Version 1 implementations are to ignore this extra data and
1727 process only the fields specified in this document.". So RIPv3
1728 packet should be treated as RIPv1 ignoring must be zero field. */
1729 if (packet->version > RIPv2)
1730 packet->version = RIPv2;
1731
1732 /* Is RIP running or is this RIP neighbor ?*/
1733 ri = ifp->info;
1734 if (! ri->running && ! rip_neighbor_lookup (&from))
1735 {
1736 if (IS_RIP_DEBUG_EVENT)
1737 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1738 rip_peer_bad_packet (&from);
1739 return -1;
1740 }
1741
1742 /* RIP Version check. */
1743 if (packet->command == RIP_RESPONSE)
1744 {
paulf38a4712003-06-07 01:10:00 +00001745 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1746 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001747 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001748 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001749 {
1750 if (IS_RIP_DEBUG_PACKET)
1751 zlog_warn (" packet's v%d doesn't fit to if version spec",
1752 packet->version);
1753 rip_peer_bad_packet (&from);
1754 return -1;
1755 }
1756 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001757 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001758 {
1759 if (IS_RIP_DEBUG_PACKET)
1760 zlog_warn (" packet's v%d doesn't fit to if version spec",
1761 packet->version);
1762 rip_peer_bad_packet (&from);
1763 return -1;
1764 }
paul718e3742002-12-13 20:15:29 +00001765 }
1766
1767 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1768 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1769 accepted; authenticated RIP-2 messages shall be discarded. */
1770
1771 if ((ri->auth_type == RIP_NO_AUTH)
1772 && rtenum
1773 && (packet->version == RIPv2) && (packet->rte->family == 0xffff))
1774 {
1775 if (IS_RIP_DEBUG_EVENT)
1776 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1777 packet->version);
1778 rip_peer_bad_packet (&from);
1779 return -1;
1780 }
1781
1782 /* If the router is configured to authenticate RIP-2 messages, then
1783 RIP-1 messages and RIP-2 messages which pass authentication
1784 testing shall be accepted; unauthenticated and failed
1785 authentication RIP-2 messages shall be discarded. For maximum
1786 security, RIP-1 messages should be ignored when authentication is
1787 in use (see section 4.1); otherwise, the routing information from
1788 authenticated messages will be propagated by RIP-1 routers in an
1789 unauthenticated manner. */
1790
1791 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
1792 || ri->auth_type == RIP_AUTH_MD5)
1793 && rtenum)
1794 {
1795 /* We follow maximum security. */
1796 if (packet->version == RIPv1 && packet->rte->family == 0xffff)
1797 {
1798 if (IS_RIP_DEBUG_PACKET)
1799 zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version);
1800 rip_peer_bad_packet (&from);
1801 return -1;
1802 }
1803
1804 /* Check RIPv2 authentication. */
1805 if (packet->version == RIPv2)
1806 {
1807 if (packet->rte->family == 0xffff)
1808 {
1809 if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)
1810 {
1811 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1812 if (! ret)
1813 {
1814 if (IS_RIP_DEBUG_EVENT)
1815 zlog_warn ("RIPv2 simple password authentication failed");
1816 rip_peer_bad_packet (&from);
1817 return -1;
1818 }
1819 else
1820 {
1821 if (IS_RIP_DEBUG_EVENT)
1822 zlog_info ("RIPv2 simple password authentication success");
1823 }
1824 }
1825 else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5)
1826 {
1827 ret = rip_auth_md5 (packet, &from, ifp);
1828 if (! ret)
1829 {
1830 if (IS_RIP_DEBUG_EVENT)
1831 zlog_warn ("RIPv2 MD5 authentication failed");
1832 rip_peer_bad_packet (&from);
1833 return -1;
1834 }
1835 else
1836 {
1837 if (IS_RIP_DEBUG_EVENT)
1838 zlog_info ("RIPv2 MD5 authentication success");
1839 }
1840 /* Reset RIP packet length to trim MD5 data. */
1841 len = ret;
1842 }
1843 else
1844 {
1845 if (IS_RIP_DEBUG_EVENT)
1846 zlog_warn ("Unknown authentication type %d",
1847 ntohs (packet->rte->tag));
1848 rip_peer_bad_packet (&from);
1849 return -1;
1850 }
1851 }
1852 else
1853 {
1854 /* There is no authentication in the packet. */
1855 if (ri->auth_str || ri->key_chain)
1856 {
1857 if (IS_RIP_DEBUG_EVENT)
1858 zlog_warn ("RIPv2 authentication failed: no authentication in packet");
1859 rip_peer_bad_packet (&from);
1860 return -1;
1861 }
1862 }
1863 }
1864 }
1865
1866 /* Process each command. */
1867 switch (packet->command)
1868 {
1869 case RIP_RESPONSE:
1870 rip_response_process (packet, len, &from, ifp);
1871 break;
1872 case RIP_REQUEST:
1873 case RIP_POLL:
1874 rip_request_process (packet, len, &from, ifp);
1875 break;
1876 case RIP_TRACEON:
1877 case RIP_TRACEOFF:
1878 zlog_info ("Obsolete command %s received, please sent it to routed",
1879 lookup (rip_msg, packet->command));
1880 rip_peer_bad_packet (&from);
1881 break;
1882 case RIP_POLL_ENTRY:
1883 zlog_info ("Obsolete command %s received",
1884 lookup (rip_msg, packet->command));
1885 rip_peer_bad_packet (&from);
1886 break;
1887 default:
1888 zlog_info ("Unknown RIP command %d received", packet->command);
1889 rip_peer_bad_packet (&from);
1890 break;
1891 }
1892
1893 return len;
1894}
1895
1896/* Make socket for RIP protocol. */
1897int
1898rip_create_socket ()
1899{
1900 int ret;
1901 int sock;
1902 struct sockaddr_in addr;
1903 struct servent *sp;
1904
1905 memset (&addr, 0, sizeof (struct sockaddr_in));
1906
1907 /* Set RIP port. */
1908 sp = getservbyname ("router", "udp");
1909 if (sp)
1910 addr.sin_port = sp->s_port;
1911 else
1912 addr.sin_port = htons (RIP_PORT_DEFAULT);
1913
1914 /* Address shoud be any address. */
1915 addr.sin_family = AF_INET;
1916 addr.sin_addr.s_addr = INADDR_ANY;
1917
1918 /* Make datagram socket. */
1919 sock = socket (AF_INET, SOCK_DGRAM, 0);
1920 if (sock < 0)
1921 {
1922 perror ("socket");
1923 exit (1);
1924 }
1925
1926 sockopt_broadcast (sock);
1927 sockopt_reuseaddr (sock);
1928 sockopt_reuseport (sock);
1929#ifdef RIP_RECVMSG
1930 setsockopt_pktinfo (sock);
1931#endif /* RIP_RECVMSG */
1932
pauledd7c242003-06-04 13:59:38 +00001933 if (ripd_privs.change (ZPRIVS_RAISE))
1934 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001935 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1936 if (ret < 0)
1937 {
1938 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001939 if (ripd_privs.change (ZPRIVS_LOWER))
1940 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001941 return ret;
1942 }
pauledd7c242003-06-04 13:59:38 +00001943 if (ripd_privs.change (ZPRIVS_LOWER))
1944 zlog_err ("rip_create_socket: could not lower privs");
1945
paul718e3742002-12-13 20:15:29 +00001946 return sock;
1947}
1948
1949/* Write routing table entry to the stream and return next index of
1950 the routing table entry in the stream. */
1951int
1952rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
1953 u_char version, struct rip_info *rinfo, struct interface *ifp)
1954{
1955 struct in_addr mask;
1956 struct rip_interface *ri;
1957
1958 /* RIP packet header. */
1959 if (num == 0)
1960 {
1961 stream_putc (s, RIP_RESPONSE);
1962 stream_putc (s, version);
1963 stream_putw (s, 0);
1964
1965 /* In case of we need RIPv2 authentication. */
1966 if (version == RIPv2 && ifp)
1967 {
1968 ri = ifp->info;
1969
1970 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
1971 {
1972 if (ri->auth_str)
1973 {
1974 stream_putw (s, 0xffff);
1975 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1976
1977 memset ((s->data + s->putp), 0, 16);
1978 strncpy ((s->data + s->putp), ri->auth_str, 16);
1979 stream_set_putp (s, s->putp + 16);
1980
1981 num++;
1982 }
1983 if (ri->key_chain)
1984 {
1985 struct keychain *keychain;
1986 struct key *key;
1987
1988 keychain = keychain_lookup (ri->key_chain);
1989
1990 if (keychain)
1991 {
1992 key = key_lookup_for_send (keychain);
1993
1994 if (key)
1995 {
1996 stream_putw (s, 0xffff);
1997 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1998
1999 memset ((s->data + s->putp), 0, 16);
2000 strncpy ((s->data + s->putp), key->string, 16);
2001 stream_set_putp (s, s->putp + 16);
2002
2003 num++;
2004 }
2005 }
2006 }
2007 }
2008 }
2009 }
2010
2011 /* Write routing table entry. */
2012 if (version == RIPv1)
2013 {
2014 stream_putw (s, AF_INET);
2015 stream_putw (s, 0);
2016 stream_put_ipv4 (s, p->prefix.s_addr);
2017 stream_put_ipv4 (s, 0);
2018 stream_put_ipv4 (s, 0);
2019 stream_putl (s, rinfo->metric_out);
2020 }
2021 else
2022 {
2023 masklen2ip (p->prefixlen, &mask);
2024
2025 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002026 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002027 stream_put_ipv4 (s, p->prefix.s_addr);
2028 stream_put_ipv4 (s, mask.s_addr);
2029 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2030 stream_putl (s, rinfo->metric_out);
2031 }
2032
2033 return ++num;
2034}
2035
2036/* Send update to the ifp or spcified neighbor. */
2037void
paul727d1042002-12-13 20:50:29 +00002038rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002039 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002040 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002041{
2042 int ret;
2043 struct stream *s;
2044 struct route_node *rp;
2045 struct rip_info *rinfo;
2046 struct rip_interface *ri;
2047 struct prefix_ipv4 *p;
2048 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002049 struct prefix_ipv4 ifaddrclass;
2050 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002051 int num;
2052 int rtemax;
paul01d09082003-06-08 21:22:18 +00002053 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002054
2055 /* Logging output event. */
2056 if (IS_RIP_DEBUG_EVENT)
2057 {
2058 if (to)
2059 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2060 else
2061 zlog_info ("update routes on interface %s ifindex %d",
2062 ifp->name, ifp->ifindex);
2063 }
2064
2065 /* Set output stream. */
2066 s = rip->obuf;
2067
2068 /* Reset stream and RTE counter. */
2069 stream_reset (s);
2070 num = 0;
2071 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2072
2073 /* Get RIP interface. */
2074 ri = ifp->info;
2075
2076 /* If output interface is in simple password authentication mode, we
2077 need space for authentication data. */
2078 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2079 rtemax -= 1;
2080
2081 /* If output interface is in MD5 authentication mode, we need space
2082 for authentication header and data. */
2083 if (ri->auth_type == RIP_AUTH_MD5)
2084 rtemax -= 2;
2085
2086 /* If output interface is in simple password authentication mode
2087 and string or keychain is specified we need space for auth. data */
2088 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2089 {
2090 if (ri->key_chain)
2091 {
2092 struct keychain *keychain;
2093
2094 keychain = keychain_lookup (ri->key_chain);
2095 if (keychain)
2096 if (key_lookup_for_send (keychain))
2097 rtemax -=1;
2098 }
2099 else
2100 if (ri->auth_str)
2101 rtemax -=1;
2102 }
2103
paul727d1042002-12-13 20:50:29 +00002104 if (version == RIPv1)
2105 {
2106 if (ifaddr == NULL)
2107 {
2108 c = connected_lookup_address (ifp, to->sin_addr);
2109 if (c != NULL)
2110 ifaddr = c->address;
2111 }
2112 if (ifaddr == NULL)
2113 {
2114 zlog_warn ("cannot find source address for packets to neighbor %s",
2115 inet_ntoa (to->sin_addr));
2116 return;
2117 }
2118 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2119 apply_classful_mask_ipv4 (&ifaddrclass);
2120 subnetted = 0;
2121 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002122 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002123 }
2124
paul718e3742002-12-13 20:15:29 +00002125 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2126 if ((rinfo = rp->info) != NULL)
2127 {
paul727d1042002-12-13 20:50:29 +00002128 /* For RIPv1, if we are subnetted, output subnets in our network */
2129 /* that have the same mask as the output "interface". For other */
2130 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002131
2132 if (version == RIPv1)
2133 {
paul727d1042002-12-13 20:50:29 +00002134 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002135
2136 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002137 zlog_info("RIPv1 mask check, %s/%d considered for output",
2138 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002139
paul727d1042002-12-13 20:50:29 +00002140 if (subnetted &&
2141 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2142 {
2143 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2144 (rp->p.prefixlen != 32))
2145 continue;
2146 }
2147 else
2148 {
2149 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2150 apply_classful_mask_ipv4(&classfull);
2151 if (rp->p.u.prefix4.s_addr != 0 &&
2152 classfull.prefixlen != rp->p.prefixlen)
2153 continue;
2154 }
paul718e3742002-12-13 20:15:29 +00002155 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002156 zlog_info("RIPv1 mask check, %s/%d made it through",
2157 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002158 }
2159 else
2160 p = (struct prefix_ipv4 *) &rp->p;
2161
2162 /* Apply output filters. */
2163 ret = rip_outgoing_filter (p, ri);
2164 if (ret < 0)
2165 continue;
2166
2167 /* Changed route only output. */
2168 if (route_type == rip_changed_route &&
2169 (! (rinfo->flags & RIP_RTF_CHANGED)))
2170 continue;
2171
2172 /* Split horizon. */
2173 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002174 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002175 {
paul42d14d92003-11-17 09:15:18 +00002176 /*
2177 * We perform split horizon for RIP and connected route.
2178 * For rip routes, we want to suppress the route if we would
2179 * end up sending the route back on the interface that we
2180 * learned it from, with a higher metric. For connected routes,
2181 * we suppress the route if the prefix is a subset of the
2182 * source address that we are going to use for the packet
2183 * (in order to handle the case when multiple subnets are
2184 * configured on the same interface).
2185 */
2186 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2187 rinfo->ifindex == ifp->ifindex)
2188 continue;
2189 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002190 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002191 continue;
2192 }
2193
2194 /* Preparation for route-map. */
2195 rinfo->metric_set = 0;
2196 rinfo->nexthop_out.s_addr = 0;
2197 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002198 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002199 rinfo->ifindex_out = ifp->ifindex;
2200
hasso16705132003-05-25 14:49:19 +00002201 /* In order to avoid some local loops,
2202 * if the RIP route has a nexthop via this interface, keep the nexthop,
2203 * otherwise set it to 0. The nexthop should not be propagated
2204 * beyond the local broadcast/multicast area in order
2205 * to avoid an IGP multi-level recursive look-up.
2206 * see (4.4)
2207 */
2208 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002209 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002210
2211 /* Interface route-map */
2212 if (ri->routemap[RIP_FILTER_OUT])
2213 {
2214 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2215 (struct prefix *) p, RMAP_RIP,
2216 rinfo);
2217
2218 if (ret == RMAP_DENYMATCH)
2219 {
2220 if (IS_RIP_DEBUG_PACKET)
2221 zlog_info ("RIP %s/%d is filtered by route-map out",
2222 inet_ntoa (p->prefix), p->prefixlen);
2223 continue;
2224 }
2225 }
paul718e3742002-12-13 20:15:29 +00002226
hasso16705132003-05-25 14:49:19 +00002227 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002228 if (rip->route_map[rinfo->type].name
2229 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2230 {
2231 ret = route_map_apply (rip->route_map[rinfo->type].map,
2232 (struct prefix *)p, RMAP_RIP, rinfo);
2233
2234 if (ret == RMAP_DENYMATCH)
2235 {
2236 if (IS_RIP_DEBUG_PACKET)
2237 zlog_info ("%s/%d is filtered by route-map",
2238 inet_ntoa (p->prefix), p->prefixlen);
2239 continue;
2240 }
2241 }
2242
2243 /* When route-map does not set metric. */
2244 if (! rinfo->metric_set)
2245 {
2246 /* If redistribute metric is set. */
2247 if (rip->route_map[rinfo->type].metric_config
2248 && rinfo->metric != RIP_METRIC_INFINITY)
2249 {
2250 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2251 }
2252 else
2253 {
2254 /* If the route is not connected or localy generated
2255 one, use default-metric value*/
2256 if (rinfo->type != ZEBRA_ROUTE_RIP
2257 && rinfo->type != ZEBRA_ROUTE_CONNECT
2258 && rinfo->metric != RIP_METRIC_INFINITY)
2259 rinfo->metric_out = rip->default_metric;
2260 }
2261 }
2262
2263 /* Apply offset-list */
2264 if (rinfo->metric != RIP_METRIC_INFINITY)
2265 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2266
2267 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2268 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002269
2270 /* Perform split-horizon with poisoned reverse
2271 * for RIP and connected routes.
2272 **/
2273 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002274 /*
2275 * We perform split horizon for RIP and connected route.
2276 * For rip routes, we want to suppress the route if we would
2277 * end up sending the route back on the interface that we
2278 * learned it from, with a higher metric. For connected routes,
2279 * we suppress the route if the prefix is a subset of the
2280 * source address that we are going to use for the packet
2281 * (in order to handle the case when multiple subnets are
2282 * configured on the same interface).
2283 */
2284 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002285 rinfo->ifindex == ifp->ifindex)
2286 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002287 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2288 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2289 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002290 }
2291
paul718e3742002-12-13 20:15:29 +00002292 /* Write RTE to the stream. */
2293 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2294 if (num == rtemax)
2295 {
2296 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2297 rip_auth_md5_set (s, ifp);
2298
2299 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002300 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002301
2302 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2303 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2304 stream_get_endp(s), "SEND");
2305 num = 0;
2306 stream_reset (s);
2307 }
2308 }
2309
2310 /* Flush unwritten RTE. */
2311 if (num != 0)
2312 {
2313 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2314 rip_auth_md5_set (s, ifp);
2315
paul931cd542004-01-23 15:31:42 +00002316 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2317 connected);
paul718e3742002-12-13 20:15:29 +00002318
2319 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2320 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2321 stream_get_endp (s), "SEND");
2322 num = 0;
2323 stream_reset (s);
2324 }
2325
2326 /* Statistics updates. */
2327 ri->sent_updates++;
2328}
2329
2330/* Send RIP packet to the interface. */
2331void
paulcc1131a2003-10-15 23:20:17 +00002332rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002333 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002334{
2335 struct prefix_ipv4 *p;
2336 struct connected *connected;
2337 listnode node;
2338 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002339 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002340
2341 /* When RIP version is 2 and multicast enable interface. */
2342 if (version == RIPv2 && if_is_multicast (ifp))
2343 {
2344 if (IS_RIP_DEBUG_EVENT)
2345 zlog_info ("multicast announce on %s ", ifp->name);
2346
paulcc1131a2003-10-15 23:20:17 +00002347 rip_output_process (ifp, NULL, NULL, route_type, rip->version_send,
paul931cd542004-01-23 15:31:42 +00002348 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002349 return;
2350 }
2351
2352 /* If we can't send multicast packet, send it with unicast. */
2353 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2354 {
2355 for (node = listhead (ifp->connected); node; nextnode (node))
2356 {
2357 connected = getdata (node);
2358
2359 /* Fetch broadcast address or poin-to-point destination
2360 address . */
2361 p = (struct prefix_ipv4 *) connected->destination;
2362
2363 if (p->family == AF_INET)
2364 {
2365 /* Destination address and port setting. */
2366 memset (&to, 0, sizeof (struct sockaddr_in));
2367 to.sin_addr = p->prefix;
2368 to.sin_port = htons (RIP_PORT_DEFAULT);
2369
2370 if (IS_RIP_DEBUG_EVENT)
2371 zlog_info ("%s announce to %s on %s",
2372 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2373 inet_ntoa (to.sin_addr), ifp->name);
2374
paul727d1042002-12-13 20:50:29 +00002375 rip_output_process (ifp, connected->address, &to, route_type,
paul931cd542004-01-23 15:31:42 +00002376 rip->version_send, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002377 }
2378 }
2379 }
2380}
2381
2382/* Update send to all interface and neighbor. */
2383void
2384rip_update_process (int route_type)
2385{
paulcc1131a2003-10-15 23:20:17 +00002386 listnode node, ifnode;
2387 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002388 struct interface *ifp;
2389 struct rip_interface *ri;
2390 struct route_node *rp;
2391 struct sockaddr_in to;
2392 struct prefix_ipv4 *p;
2393
2394 /* Send RIP update to each interface. */
2395 for (node = listhead (iflist); node; nextnode (node))
2396 {
2397 ifp = getdata (node);
2398
2399 if (if_is_loopback (ifp))
2400 continue;
2401
paul2e3b2e42002-12-13 21:03:13 +00002402 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002403 continue;
2404
2405 /* Fetch RIP interface information. */
2406 ri = ifp->info;
2407
2408 /* When passive interface is specified, suppress announce to the
2409 interface. */
2410 if (ri->passive)
2411 continue;
2412
2413 if (ri->running)
2414 {
2415 if (IS_RIP_DEBUG_EVENT)
2416 {
2417 if (ifp->name)
2418 zlog_info ("SEND UPDATE to %s ifindex %d",
2419 ifp->name, ifp->ifindex);
2420 else
2421 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2422 ifp->ifindex);
2423 }
2424
paulcc1131a2003-10-15 23:20:17 +00002425 /* send update on each connected network */
2426
2427 LIST_LOOP(ifp->connected, connected, ifnode)
2428 {
2429 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002430 int done = 0;
2431 /*
2432 * If there is no version configuration in the interface,
2433 * use rip's version setting.
2434 */
paulf38a4712003-06-07 01:10:00 +00002435 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2436 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002437
2438 ifaddr = (struct prefix_ipv4 *) connected->address;
2439
2440 if (ifaddr->family != AF_INET)
2441 continue;
2442
paul931cd542004-01-23 15:31:42 +00002443 if ((vsend & RIPv1) && !done)
2444 rip_update_interface (ifp, RIPv1, route_type, connected);
2445 if ((vsend & RIPv2) && if_is_multicast(ifp))
2446 rip_update_interface (ifp, RIPv2, route_type, connected);
2447 done = 1;
2448 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2449 break;
2450
paulf38a4712003-06-07 01:10:00 +00002451 }
paul718e3742002-12-13 20:15:29 +00002452 }
2453 }
2454
2455 /* RIP send updates to each neighbor. */
2456 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2457 if (rp->info != NULL)
2458 {
2459 p = (struct prefix_ipv4 *) &rp->p;
2460
2461 ifp = if_lookup_address (p->prefix);
2462 if (! ifp)
2463 {
2464 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2465 inet_ntoa (p->prefix));
2466 continue;
2467 }
2468
2469 /* Set destination address and port */
2470 memset (&to, 0, sizeof (struct sockaddr_in));
2471 to.sin_addr = p->prefix;
2472 to.sin_port = htons (RIP_PORT_DEFAULT);
2473
2474 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002475 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2476 NULL, p);
paul718e3742002-12-13 20:15:29 +00002477 }
2478}
2479
2480/* RIP's periodical timer. */
2481int
2482rip_update (struct thread *t)
2483{
2484 /* Clear timer pointer. */
2485 rip->t_update = NULL;
2486
2487 if (IS_RIP_DEBUG_EVENT)
2488 zlog_info ("update timer fire!");
2489
2490 /* Process update output. */
2491 rip_update_process (rip_all_route);
2492
2493 /* Triggered updates may be suppressed if a regular update is due by
2494 the time the triggered update would be sent. */
2495 if (rip->t_triggered_interval)
2496 {
2497 thread_cancel (rip->t_triggered_interval);
2498 rip->t_triggered_interval = NULL;
2499 }
2500 rip->trigger = 0;
2501
2502 /* Register myself. */
2503 rip_event (RIP_UPDATE_EVENT, 0);
2504
2505 return 0;
2506}
2507
2508/* Walk down the RIP routing table then clear changed flag. */
2509void
2510rip_clear_changed_flag ()
2511{
2512 struct route_node *rp;
2513 struct rip_info *rinfo;
2514
2515 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2516 if ((rinfo = rp->info) != NULL)
2517 if (rinfo->flags & RIP_RTF_CHANGED)
2518 rinfo->flags &= ~RIP_RTF_CHANGED;
2519}
2520
2521/* Triggered update interval timer. */
2522int
2523rip_triggered_interval (struct thread *t)
2524{
2525 int rip_triggered_update (struct thread *);
2526
2527 rip->t_triggered_interval = NULL;
2528
2529 if (rip->trigger)
2530 {
2531 rip->trigger = 0;
2532 rip_triggered_update (t);
2533 }
2534 return 0;
2535}
2536
2537/* Execute triggered update. */
2538int
2539rip_triggered_update (struct thread *t)
2540{
2541 int interval;
2542
2543 /* Clear thred pointer. */
2544 rip->t_triggered_update = NULL;
2545
2546 /* Cancel interval timer. */
2547 if (rip->t_triggered_interval)
2548 {
2549 thread_cancel (rip->t_triggered_interval);
2550 rip->t_triggered_interval = NULL;
2551 }
2552 rip->trigger = 0;
2553
2554 /* Logging triggered update. */
2555 if (IS_RIP_DEBUG_EVENT)
2556 zlog_info ("triggered update!");
2557
2558 /* Split Horizon processing is done when generating triggered
2559 updates as well as normal updates (see section 2.6). */
2560 rip_update_process (rip_changed_route);
2561
2562 /* Once all of the triggered updates have been generated, the route
2563 change flags should be cleared. */
2564 rip_clear_changed_flag ();
2565
2566 /* After a triggered update is sent, a timer should be set for a
2567 random interval between 1 and 5 seconds. If other changes that
2568 would trigger updates occur before the timer expires, a single
2569 update is triggered when the timer expires. */
2570 interval = (random () % 5) + 1;
2571
2572 rip->t_triggered_interval =
2573 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2574
2575 return 0;
2576}
2577
2578/* Withdraw redistributed route. */
2579void
2580rip_redistribute_withdraw (int type)
2581{
2582 struct route_node *rp;
2583 struct rip_info *rinfo;
2584
2585 if (!rip)
2586 return;
2587
2588 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2589 if ((rinfo = rp->info) != NULL)
2590 {
2591 if (rinfo->type == type
2592 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2593 {
2594 /* Perform poisoned reverse. */
2595 rinfo->metric = RIP_METRIC_INFINITY;
2596 RIP_TIMER_ON (rinfo->t_garbage_collect,
2597 rip_garbage_collect, rip->garbage_time);
2598 RIP_TIMER_OFF (rinfo->t_timeout);
2599 rinfo->flags |= RIP_RTF_CHANGED;
2600
hasso16705132003-05-25 14:49:19 +00002601 if (IS_RIP_DEBUG_EVENT) {
2602 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2603
2604 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2605 inet_ntoa(p->prefix), p->prefixlen,
2606 ifindex2ifname(rinfo->ifindex));
2607 }
2608
paul718e3742002-12-13 20:15:29 +00002609 rip_event (RIP_TRIGGERED_UPDATE, 0);
2610 }
2611 }
2612}
2613
2614/* Create new RIP instance and set it to global variable. */
2615int
2616rip_create ()
2617{
2618 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2619 memset (rip, 0, sizeof (struct rip));
2620
2621 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002622 rip->version_send = RI_RIP_VERSION_2;
2623 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002624 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2625 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2626 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2627 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2628
2629 /* Initialize RIP routig table. */
2630 rip->table = route_table_init ();
2631 rip->route = route_table_init ();
2632 rip->neighbor = route_table_init ();
2633
2634 /* Make output stream. */
2635 rip->obuf = stream_new (1500);
2636
2637 /* Make socket. */
2638 rip->sock = rip_create_socket ();
2639 if (rip->sock < 0)
2640 return rip->sock;
2641
2642 /* Create read and timer thread. */
2643 rip_event (RIP_READ, rip->sock);
2644 rip_event (RIP_UPDATE_EVENT, 1);
2645
2646 return 0;
2647}
2648
2649/* Sned RIP request to the destination. */
2650int
2651rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002652 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002653{
2654 struct rte *rte;
2655 struct rip_packet rip_packet;
paulcc1131a2003-10-15 23:20:17 +00002656 listnode node;
paul718e3742002-12-13 20:15:29 +00002657
2658 memset (&rip_packet, 0, sizeof (rip_packet));
2659
2660 rip_packet.command = RIP_REQUEST;
2661 rip_packet.version = version;
2662 rte = rip_packet.rte;
2663 rte->metric = htonl (RIP_METRIC_INFINITY);
2664
paul931cd542004-01-23 15:31:42 +00002665 if (connected)
2666 {
2667 /*
2668 * connected is only sent for ripv1 case, or when
2669 * interface does not support multicast. Caller loops
2670 * over each connected address for this case.
2671 */
2672 if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet),
2673 to, ifp, connected) != sizeof (rip_packet))
2674 return -1;
2675 else
2676 return sizeof (rip_packet);
2677 }
2678
paulcc1131a2003-10-15 23:20:17 +00002679 /* send request on each connected network */
2680 LIST_LOOP(ifp->connected, connected, node)
2681 {
2682 struct prefix_ipv4 *p;
2683
2684 p = (struct prefix_ipv4 *) connected->address;
2685
2686 if (p->family != AF_INET)
2687 continue;
2688
paulcc1131a2003-10-15 23:20:17 +00002689 if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002690 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002691 return -1;
2692 }
2693 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002694}
2695
2696int
2697rip_update_jitter (unsigned long time)
2698{
2699 return ((rand () % (time + 1)) - (time / 2));
2700}
2701
2702void
2703rip_event (enum rip_event event, int sock)
2704{
2705 int jitter = 0;
2706
2707 switch (event)
2708 {
2709 case RIP_READ:
2710 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2711 break;
2712 case RIP_UPDATE_EVENT:
2713 if (rip->t_update)
2714 {
2715 thread_cancel (rip->t_update);
2716 rip->t_update = NULL;
2717 }
2718 jitter = rip_update_jitter (rip->update_time);
2719 rip->t_update =
2720 thread_add_timer (master, rip_update, NULL,
2721 sock ? 2 : rip->update_time + jitter);
2722 break;
2723 case RIP_TRIGGERED_UPDATE:
2724 if (rip->t_triggered_interval)
2725 rip->trigger = 1;
2726 else if (! rip->t_triggered_update)
2727 rip->t_triggered_update =
2728 thread_add_event (master, rip_triggered_update, NULL, 0);
2729 break;
2730 default:
2731 break;
2732 }
2733}
2734
2735DEFUN (router_rip,
2736 router_rip_cmd,
2737 "router rip",
2738 "Enable a routing process\n"
2739 "Routing Information Protocol (RIP)\n")
2740{
2741 int ret;
2742
2743 /* If rip is not enabled before. */
2744 if (! rip)
2745 {
2746 ret = rip_create ();
2747 if (ret < 0)
2748 {
2749 zlog_info ("Can't create RIP");
2750 return CMD_WARNING;
2751 }
2752 }
2753 vty->node = RIP_NODE;
2754 vty->index = rip;
2755
2756 return CMD_SUCCESS;
2757}
2758
2759DEFUN (no_router_rip,
2760 no_router_rip_cmd,
2761 "no router rip",
2762 NO_STR
2763 "Enable a routing process\n"
2764 "Routing Information Protocol (RIP)\n")
2765{
2766 if (rip)
2767 rip_clean ();
2768 return CMD_SUCCESS;
2769}
2770
2771DEFUN (rip_version,
2772 rip_version_cmd,
2773 "version <1-2>",
2774 "Set routing protocol version\n"
2775 "version\n")
2776{
2777 int version;
2778
2779 version = atoi (argv[0]);
2780 if (version != RIPv1 && version != RIPv2)
2781 {
2782 vty_out (vty, "invalid rip version %d%s", version,
2783 VTY_NEWLINE);
2784 return CMD_WARNING;
2785 }
paulf38a4712003-06-07 01:10:00 +00002786 rip->version_send = version;
2787 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002788
2789 return CMD_SUCCESS;
2790}
2791
2792DEFUN (no_rip_version,
2793 no_rip_version_cmd,
2794 "no version",
2795 NO_STR
2796 "Set routing protocol version\n")
2797{
2798 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002799 rip->version_send = RI_RIP_VERSION_2;
2800 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002801
2802 return CMD_SUCCESS;
2803}
2804
2805ALIAS (no_rip_version,
2806 no_rip_version_val_cmd,
2807 "no version <1-2>",
2808 NO_STR
2809 "Set routing protocol version\n"
2810 "version\n")
2811
2812DEFUN (rip_route,
2813 rip_route_cmd,
2814 "route A.B.C.D/M",
2815 "RIP static route configuration\n"
2816 "IP prefix <network>/<length>\n")
2817{
2818 int ret;
2819 struct prefix_ipv4 p;
2820 struct route_node *node;
2821
2822 ret = str2prefix_ipv4 (argv[0], &p);
2823 if (ret < 0)
2824 {
2825 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2826 return CMD_WARNING;
2827 }
2828 apply_mask_ipv4 (&p);
2829
2830 /* For router rip configuration. */
2831 node = route_node_get (rip->route, (struct prefix *) &p);
2832
2833 if (node->info)
2834 {
2835 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2836 route_unlock_node (node);
2837 return CMD_WARNING;
2838 }
2839
2840 node->info = "static";
2841
2842 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2843
2844 return CMD_SUCCESS;
2845}
2846
2847DEFUN (no_rip_route,
2848 no_rip_route_cmd,
2849 "no route A.B.C.D/M",
2850 NO_STR
2851 "RIP static route configuration\n"
2852 "IP prefix <network>/<length>\n")
2853{
2854 int ret;
2855 struct prefix_ipv4 p;
2856 struct route_node *node;
2857
2858 ret = str2prefix_ipv4 (argv[0], &p);
2859 if (ret < 0)
2860 {
2861 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2862 return CMD_WARNING;
2863 }
2864 apply_mask_ipv4 (&p);
2865
2866 /* For router rip configuration. */
2867 node = route_node_lookup (rip->route, (struct prefix *) &p);
2868 if (! node)
2869 {
2870 vty_out (vty, "Can't find route %s.%s", argv[0],
2871 VTY_NEWLINE);
2872 return CMD_WARNING;
2873 }
2874
2875 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2876 route_unlock_node (node);
2877
2878 node->info = NULL;
2879 route_unlock_node (node);
2880
2881 return CMD_SUCCESS;
2882}
2883
2884void
2885rip_update_default_metric ()
2886{
2887 struct route_node *np;
2888 struct rip_info *rinfo;
2889
2890 for (np = route_top (rip->table); np; np = route_next (np))
2891 if ((rinfo = np->info) != NULL)
2892 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2893 rinfo->metric = rip->default_metric;
2894}
2895
2896DEFUN (rip_default_metric,
2897 rip_default_metric_cmd,
2898 "default-metric <1-16>",
2899 "Set a metric of redistribute routes\n"
2900 "Default metric\n")
2901{
2902 if (rip)
2903 {
2904 rip->default_metric = atoi (argv[0]);
2905 /* rip_update_default_metric (); */
2906 }
2907 return CMD_SUCCESS;
2908}
2909
2910DEFUN (no_rip_default_metric,
2911 no_rip_default_metric_cmd,
2912 "no default-metric",
2913 NO_STR
2914 "Set a metric of redistribute routes\n"
2915 "Default metric\n")
2916{
2917 if (rip)
2918 {
2919 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2920 /* rip_update_default_metric (); */
2921 }
2922 return CMD_SUCCESS;
2923}
2924
2925ALIAS (no_rip_default_metric,
2926 no_rip_default_metric_val_cmd,
2927 "no default-metric <1-16>",
2928 NO_STR
2929 "Set a metric of redistribute routes\n"
2930 "Default metric\n")
2931
2932DEFUN (rip_timers,
2933 rip_timers_cmd,
2934 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
2935 "Adjust routing timers\n"
2936 "Basic routing protocol update timers\n"
2937 "Routing table update timer value in second. Default is 30.\n"
2938 "Routing information timeout timer. Default is 180.\n"
2939 "Garbage collection timer. Default is 120.\n")
2940{
2941 unsigned long update;
2942 unsigned long timeout;
2943 unsigned long garbage;
2944 char *endptr = NULL;
2945 unsigned long RIP_TIMER_MAX = 2147483647;
2946 unsigned long RIP_TIMER_MIN = 5;
2947
2948 update = strtoul (argv[0], &endptr, 10);
2949 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
2950 {
2951 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2952 return CMD_WARNING;
2953 }
2954
2955 timeout = strtoul (argv[1], &endptr, 10);
2956 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
2957 {
2958 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2959 return CMD_WARNING;
2960 }
2961
2962 garbage = strtoul (argv[2], &endptr, 10);
2963 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
2964 {
2965 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2966 return CMD_WARNING;
2967 }
2968
2969 /* Set each timer value. */
2970 rip->update_time = update;
2971 rip->timeout_time = timeout;
2972 rip->garbage_time = garbage;
2973
2974 /* Reset update timer thread. */
2975 rip_event (RIP_UPDATE_EVENT, 0);
2976
2977 return CMD_SUCCESS;
2978}
2979
2980DEFUN (no_rip_timers,
2981 no_rip_timers_cmd,
2982 "no timers basic",
2983 NO_STR
2984 "Adjust routing timers\n"
2985 "Basic routing protocol update timers\n")
2986{
2987 /* Set each timer value to the default. */
2988 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2989 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2990 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2991
2992 /* Reset update timer thread. */
2993 rip_event (RIP_UPDATE_EVENT, 0);
2994
2995 return CMD_SUCCESS;
2996}
hasso16705132003-05-25 14:49:19 +00002997
2998ALIAS (no_rip_timers,
2999 no_rip_timers_val_cmd,
3000 "no timers basic <0-65535> <0-65535> <0-65535>",
3001 NO_STR
3002 "Adjust routing timers\n"
3003 "Basic routing protocol update timers\n"
3004 "Routing table update timer value in second. Default is 30.\n"
3005 "Routing information timeout timer. Default is 180.\n"
3006 "Garbage collection timer. Default is 120.\n")
3007
paul718e3742002-12-13 20:15:29 +00003008
3009struct route_table *rip_distance_table;
3010
3011struct rip_distance
3012{
3013 /* Distance value for the IP source prefix. */
3014 u_char distance;
3015
3016 /* Name of the access-list to be matched. */
3017 char *access_list;
3018};
3019
3020struct rip_distance *
3021rip_distance_new ()
3022{
3023 struct rip_distance *new;
3024 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3025 memset (new, 0, sizeof (struct rip_distance));
3026 return new;
3027}
3028
3029void
3030rip_distance_free (struct rip_distance *rdistance)
3031{
3032 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3033}
3034
3035int
3036rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3037 char *access_list_str)
3038{
3039 int ret;
3040 struct prefix_ipv4 p;
3041 u_char distance;
3042 struct route_node *rn;
3043 struct rip_distance *rdistance;
3044
3045 ret = str2prefix_ipv4 (ip_str, &p);
3046 if (ret == 0)
3047 {
3048 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3049 return CMD_WARNING;
3050 }
3051
3052 distance = atoi (distance_str);
3053
3054 /* Get RIP distance node. */
3055 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3056 if (rn->info)
3057 {
3058 rdistance = rn->info;
3059 route_unlock_node (rn);
3060 }
3061 else
3062 {
3063 rdistance = rip_distance_new ();
3064 rn->info = rdistance;
3065 }
3066
3067 /* Set distance value. */
3068 rdistance->distance = distance;
3069
3070 /* Reset access-list configuration. */
3071 if (rdistance->access_list)
3072 {
3073 free (rdistance->access_list);
3074 rdistance->access_list = NULL;
3075 }
3076 if (access_list_str)
3077 rdistance->access_list = strdup (access_list_str);
3078
3079 return CMD_SUCCESS;
3080}
3081
3082int
3083rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3084 char *access_list_str)
3085{
3086 int ret;
3087 struct prefix_ipv4 p;
3088 u_char distance;
3089 struct route_node *rn;
3090 struct rip_distance *rdistance;
3091
3092 ret = str2prefix_ipv4 (ip_str, &p);
3093 if (ret == 0)
3094 {
3095 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3096 return CMD_WARNING;
3097 }
3098
3099 distance = atoi (distance_str);
3100
3101 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3102 if (! rn)
3103 {
3104 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3105 return CMD_WARNING;
3106 }
3107
3108 rdistance = rn->info;
3109
3110 if (rdistance->access_list)
3111 free (rdistance->access_list);
3112 rip_distance_free (rdistance);
3113
3114 rn->info = NULL;
3115 route_unlock_node (rn);
3116 route_unlock_node (rn);
3117
3118 return CMD_SUCCESS;
3119}
3120
3121void
3122rip_distance_reset ()
3123{
3124 struct route_node *rn;
3125 struct rip_distance *rdistance;
3126
3127 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3128 if ((rdistance = rn->info) != NULL)
3129 {
3130 if (rdistance->access_list)
3131 free (rdistance->access_list);
3132 rip_distance_free (rdistance);
3133 rn->info = NULL;
3134 route_unlock_node (rn);
3135 }
3136}
3137
3138/* Apply RIP information to distance method. */
3139u_char
3140rip_distance_apply (struct rip_info *rinfo)
3141{
3142 struct route_node *rn;
3143 struct prefix_ipv4 p;
3144 struct rip_distance *rdistance;
3145 struct access_list *alist;
3146
3147 if (! rip)
3148 return 0;
3149
3150 memset (&p, 0, sizeof (struct prefix_ipv4));
3151 p.family = AF_INET;
3152 p.prefix = rinfo->from;
3153 p.prefixlen = IPV4_MAX_BITLEN;
3154
3155 /* Check source address. */
3156 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3157 if (rn)
3158 {
3159 rdistance = rn->info;
3160 route_unlock_node (rn);
3161
3162 if (rdistance->access_list)
3163 {
3164 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3165 if (alist == NULL)
3166 return 0;
3167 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3168 return 0;
3169
3170 return rdistance->distance;
3171 }
3172 else
3173 return rdistance->distance;
3174 }
3175
3176 if (rip->distance)
3177 return rip->distance;
3178
3179 return 0;
3180}
3181
3182void
3183rip_distance_show (struct vty *vty)
3184{
3185 struct route_node *rn;
3186 struct rip_distance *rdistance;
3187 int header = 1;
3188 char buf[BUFSIZ];
3189
3190 vty_out (vty, " Distance: (default is %d)%s",
3191 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3192 VTY_NEWLINE);
3193
3194 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3195 if ((rdistance = rn->info) != NULL)
3196 {
3197 if (header)
3198 {
3199 vty_out (vty, " Address Distance List%s",
3200 VTY_NEWLINE);
3201 header = 0;
3202 }
3203 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3204 vty_out (vty, " %-20s %4d %s%s",
3205 buf, rdistance->distance,
3206 rdistance->access_list ? rdistance->access_list : "",
3207 VTY_NEWLINE);
3208 }
3209}
3210
3211DEFUN (rip_distance,
3212 rip_distance_cmd,
3213 "distance <1-255>",
3214 "Administrative distance\n"
3215 "Distance value\n")
3216{
3217 rip->distance = atoi (argv[0]);
3218 return CMD_SUCCESS;
3219}
3220
3221DEFUN (no_rip_distance,
3222 no_rip_distance_cmd,
3223 "no distance <1-255>",
3224 NO_STR
3225 "Administrative distance\n"
3226 "Distance value\n")
3227{
3228 rip->distance = 0;
3229 return CMD_SUCCESS;
3230}
3231
3232DEFUN (rip_distance_source,
3233 rip_distance_source_cmd,
3234 "distance <1-255> A.B.C.D/M",
3235 "Administrative distance\n"
3236 "Distance value\n"
3237 "IP source prefix\n")
3238{
3239 rip_distance_set (vty, argv[0], argv[1], NULL);
3240 return CMD_SUCCESS;
3241}
3242
3243DEFUN (no_rip_distance_source,
3244 no_rip_distance_source_cmd,
3245 "no distance <1-255> A.B.C.D/M",
3246 NO_STR
3247 "Administrative distance\n"
3248 "Distance value\n"
3249 "IP source prefix\n")
3250{
3251 rip_distance_unset (vty, argv[0], argv[1], NULL);
3252 return CMD_SUCCESS;
3253}
3254
3255DEFUN (rip_distance_source_access_list,
3256 rip_distance_source_access_list_cmd,
3257 "distance <1-255> A.B.C.D/M WORD",
3258 "Administrative distance\n"
3259 "Distance value\n"
3260 "IP source prefix\n"
3261 "Access list name\n")
3262{
3263 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3264 return CMD_SUCCESS;
3265}
3266
3267DEFUN (no_rip_distance_source_access_list,
3268 no_rip_distance_source_access_list_cmd,
3269 "no distance <1-255> A.B.C.D/M WORD",
3270 NO_STR
3271 "Administrative distance\n"
3272 "Distance value\n"
3273 "IP source prefix\n"
3274 "Access list name\n")
3275{
3276 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3277 return CMD_SUCCESS;
3278}
3279
3280/* Print out routes update time. */
3281void
3282rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3283{
3284 struct timeval timer_now;
3285 time_t clock;
3286 struct tm *tm;
3287#define TIME_BUF 25
3288 char timebuf [TIME_BUF];
3289 struct thread *thread;
3290
3291 gettimeofday (&timer_now, NULL);
3292
3293 if ((thread = rinfo->t_timeout) != NULL)
3294 {
3295 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3296 tm = gmtime (&clock);
3297 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3298 vty_out (vty, "%5s", timebuf);
3299 }
3300 else if ((thread = rinfo->t_garbage_collect) != NULL)
3301 {
3302 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3303 tm = gmtime (&clock);
3304 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3305 vty_out (vty, "%5s", timebuf);
3306 }
3307}
3308
3309char *
3310rip_route_type_print (int sub_type)
3311{
3312 switch (sub_type)
3313 {
3314 case RIP_ROUTE_RTE:
3315 return "n";
3316 case RIP_ROUTE_STATIC:
3317 return "s";
3318 case RIP_ROUTE_DEFAULT:
3319 return "d";
3320 case RIP_ROUTE_REDISTRIBUTE:
3321 return "r";
3322 case RIP_ROUTE_INTERFACE:
3323 return "i";
3324 default:
3325 return "?";
3326 }
3327}
3328
3329DEFUN (show_ip_rip,
3330 show_ip_rip_cmd,
3331 "show ip rip",
3332 SHOW_STR
3333 IP_STR
3334 "Show RIP routes\n")
3335{
3336 struct route_node *np;
3337 struct rip_info *rinfo;
3338
3339 if (! rip)
3340 return CMD_SUCCESS;
3341
hasso16705132003-05-25 14:49:19 +00003342 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3343 "Sub-codes:%s"
3344 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003345 " (i) - interface%s%s"
hasso16705132003-05-25 14:49:19 +00003346 " Network Next Hop Metric From Tag Time%s",
3347 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003348
3349 for (np = route_top (rip->table); np; np = route_next (np))
3350 if ((rinfo = np->info) != NULL)
3351 {
3352 int len;
3353
3354 len = vty_out (vty, "%s(%s) %s/%d",
3355 /* np->lock, For debugging. */
3356 route_info[rinfo->type].str,
3357 rip_route_type_print (rinfo->sub_type),
3358 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3359
hasso16705132003-05-25 14:49:19 +00003360 len = 21 - len;
paul718e3742002-12-13 20:15:29 +00003361
3362 if (len > 0)
3363 vty_out (vty, "%*s", len, " ");
3364
3365 if (rinfo->nexthop.s_addr)
3366 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3367 rinfo->metric);
3368 else
3369 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3370
3371 /* Route which exist in kernel routing table. */
3372 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3373 (rinfo->sub_type == RIP_ROUTE_RTE))
3374 {
3375 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003376 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003377 rip_vty_out_uptime (vty, rinfo);
3378 }
3379 else if (rinfo->metric == RIP_METRIC_INFINITY)
3380 {
3381 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003382 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003383 rip_vty_out_uptime (vty, rinfo);
3384 }
3385 else
hasso16705132003-05-25 14:49:19 +00003386 {
3387 vty_out (vty, "self ");
3388 vty_out (vty, "%3d", rinfo->tag);
3389 }
paul718e3742002-12-13 20:15:29 +00003390
3391 vty_out (vty, "%s", VTY_NEWLINE);
3392 }
3393 return CMD_SUCCESS;
3394}
3395
3396/* Return next event time. */
3397int
3398rip_next_thread_timer (struct thread *thread)
3399{
3400 struct timeval timer_now;
3401
3402 gettimeofday (&timer_now, NULL);
3403
3404 return thread->u.sands.tv_sec - timer_now.tv_sec;
3405}
3406
hasso16705132003-05-25 14:49:19 +00003407/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3408DEFUN (show_ip_rip_status,
3409 show_ip_rip_status_cmd,
3410 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003411 SHOW_STR
3412 IP_STR
hasso16705132003-05-25 14:49:19 +00003413 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003414 "IP routing protocol process parameters and statistics\n")
3415{
3416 listnode node;
3417 struct interface *ifp;
3418 struct rip_interface *ri;
3419 extern struct message ri_version_msg[];
3420 char *send_version;
3421 char *receive_version;
3422
3423 if (! rip)
3424 return CMD_SUCCESS;
3425
3426 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3427 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3428 rip->update_time);
3429 vty_out (vty, " next due in %d seconds%s",
3430 rip_next_thread_timer (rip->t_update),
3431 VTY_NEWLINE);
3432 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3433 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3434 VTY_NEWLINE);
3435
3436 /* Filtering status show. */
3437 config_show_distribute (vty);
3438
3439 /* Default metric information. */
3440 vty_out (vty, " Default redistribution metric is %d%s",
3441 rip->default_metric, VTY_NEWLINE);
3442
3443 /* Redistribute information. */
3444 vty_out (vty, " Redistributing:");
3445 config_write_rip_redistribute (vty, 0);
3446 vty_out (vty, "%s", VTY_NEWLINE);
3447
paulf38a4712003-06-07 01:10:00 +00003448 vty_out (vty, " Default version control: send version %s,",
3449 lookup(ri_version_msg,rip->version_send));
3450 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3451 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3452 else
3453 vty_out (vty, " receive version %s %s",
3454 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003455
3456 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3457
3458 for (node = listhead (iflist); node; node = nextnode (node))
3459 {
3460 ifp = getdata (node);
3461 ri = ifp->info;
3462
3463 if (ri->enable_network || ri->enable_interface)
3464 {
3465 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003466 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003467 else
3468 send_version = lookup (ri_version_msg, ri->ri_send);
3469
3470 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003471 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003472 else
3473 receive_version = lookup (ri_version_msg, ri->ri_receive);
3474
3475 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3476 send_version,
3477 receive_version,
3478 ri->key_chain ? ri->key_chain : "",
3479 VTY_NEWLINE);
3480 }
3481 }
3482
3483 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3484 config_write_rip_network (vty, 0);
3485
paul4aaff3f2003-06-07 01:04:45 +00003486 {
3487 int found_passive = 0;
3488 for (node = listhead (iflist); node; node = nextnode (node))
3489 {
3490 ifp = getdata (node);
3491 ri = ifp->info;
3492
3493 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3494 {
3495 if (!found_passive)
3496 {
3497 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3498 found_passive = 1;
3499 }
3500 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3501 }
3502 }
3503 }
3504
paul718e3742002-12-13 20:15:29 +00003505 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3506 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3507 rip_peer_display (vty);
3508
3509 rip_distance_show (vty);
3510
3511 return CMD_SUCCESS;
3512}
3513
3514/* RIP configuration write function. */
3515int
3516config_write_rip (struct vty *vty)
3517{
3518 int write = 0;
3519 struct route_node *rn;
3520 struct rip_distance *rdistance;
3521
3522 if (rip)
3523 {
3524 /* Router RIP statement. */
3525 vty_out (vty, "router rip%s", VTY_NEWLINE);
3526 write++;
3527
3528 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003529 if (rip->version_send != RI_RIP_VERSION_2
3530 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3531 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003532 VTY_NEWLINE);
3533
3534 /* RIP timer configuration. */
3535 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3536 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3537 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3538 vty_out (vty, " timers basic %lu %lu %lu%s",
3539 rip->update_time,
3540 rip->timeout_time,
3541 rip->garbage_time,
3542 VTY_NEWLINE);
3543
3544 /* Default information configuration. */
3545 if (rip->default_information)
3546 {
3547 if (rip->default_information_route_map)
3548 vty_out (vty, " default-information originate route-map %s%s",
3549 rip->default_information_route_map, VTY_NEWLINE);
3550 else
3551 vty_out (vty, " default-information originate%s",
3552 VTY_NEWLINE);
3553 }
3554
3555 /* Redistribute configuration. */
3556 config_write_rip_redistribute (vty, 1);
3557
3558 /* RIP offset-list configuration. */
3559 config_write_rip_offset_list (vty);
3560
3561 /* RIP enabled network and interface configuration. */
3562 config_write_rip_network (vty, 1);
3563
3564 /* RIP default metric configuration */
3565 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3566 vty_out (vty, " default-metric %d%s",
3567 rip->default_metric, VTY_NEWLINE);
3568
3569 /* Distribute configuration. */
3570 write += config_write_distribute (vty);
3571
hasso16705132003-05-25 14:49:19 +00003572 /* Interface routemap configuration */
3573 write += config_write_if_rmap (vty);
3574
paul718e3742002-12-13 20:15:29 +00003575 /* Distance configuration. */
3576 if (rip->distance)
3577 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3578
3579 /* RIP source IP prefix distance configuration. */
3580 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3581 if ((rdistance = rn->info) != NULL)
3582 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3583 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3584 rdistance->access_list ? rdistance->access_list : "",
3585 VTY_NEWLINE);
3586
3587 /* RIP static route configuration. */
3588 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3589 if (rn->info)
3590 vty_out (vty, " route %s/%d%s",
3591 inet_ntoa (rn->p.u.prefix4),
3592 rn->p.prefixlen,
3593 VTY_NEWLINE);
3594
3595 }
3596 return write;
3597}
3598
3599/* RIP node structure. */
3600struct cmd_node rip_node =
3601{
3602 RIP_NODE,
3603 "%s(config-router)# ",
3604 1
3605};
3606
3607/* Distribute-list update functions. */
3608void
3609rip_distribute_update (struct distribute *dist)
3610{
3611 struct interface *ifp;
3612 struct rip_interface *ri;
3613 struct access_list *alist;
3614 struct prefix_list *plist;
3615
3616 if (! dist->ifname)
3617 return;
3618
3619 ifp = if_lookup_by_name (dist->ifname);
3620 if (ifp == NULL)
3621 return;
3622
3623 ri = ifp->info;
3624
3625 if (dist->list[DISTRIBUTE_IN])
3626 {
3627 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3628 if (alist)
3629 ri->list[RIP_FILTER_IN] = alist;
3630 else
3631 ri->list[RIP_FILTER_IN] = NULL;
3632 }
3633 else
3634 ri->list[RIP_FILTER_IN] = NULL;
3635
3636 if (dist->list[DISTRIBUTE_OUT])
3637 {
3638 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3639 if (alist)
3640 ri->list[RIP_FILTER_OUT] = alist;
3641 else
3642 ri->list[RIP_FILTER_OUT] = NULL;
3643 }
3644 else
3645 ri->list[RIP_FILTER_OUT] = NULL;
3646
3647 if (dist->prefix[DISTRIBUTE_IN])
3648 {
3649 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3650 if (plist)
3651 ri->prefix[RIP_FILTER_IN] = plist;
3652 else
3653 ri->prefix[RIP_FILTER_IN] = NULL;
3654 }
3655 else
3656 ri->prefix[RIP_FILTER_IN] = NULL;
3657
3658 if (dist->prefix[DISTRIBUTE_OUT])
3659 {
3660 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3661 if (plist)
3662 ri->prefix[RIP_FILTER_OUT] = plist;
3663 else
3664 ri->prefix[RIP_FILTER_OUT] = NULL;
3665 }
3666 else
3667 ri->prefix[RIP_FILTER_OUT] = NULL;
3668}
3669
3670void
3671rip_distribute_update_interface (struct interface *ifp)
3672{
3673 struct distribute *dist;
3674
3675 dist = distribute_lookup (ifp->name);
3676 if (dist)
3677 rip_distribute_update (dist);
3678}
3679
3680/* Update all interface's distribute list. */
3681void
3682rip_distribute_update_all ()
3683{
3684 struct interface *ifp;
3685 listnode node;
3686
3687 for (node = listhead (iflist); node; nextnode (node))
3688 {
3689 ifp = getdata (node);
3690 rip_distribute_update_interface (ifp);
3691 }
3692}
3693
3694/* Delete all added rip route. */
3695void
3696rip_clean ()
3697{
3698 int i;
3699 struct route_node *rp;
3700 struct rip_info *rinfo;
3701
3702 if (rip)
3703 {
3704 /* Clear RIP routes */
3705 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3706 if ((rinfo = rp->info) != NULL)
3707 {
3708 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3709 rinfo->sub_type == RIP_ROUTE_RTE)
3710 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3711 &rinfo->nexthop, rinfo->metric);
3712
3713 RIP_TIMER_OFF (rinfo->t_timeout);
3714 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3715
3716 rp->info = NULL;
3717 route_unlock_node (rp);
3718
3719 rip_info_free (rinfo);
3720 }
3721
3722 /* Cancel RIP related timers. */
3723 RIP_TIMER_OFF (rip->t_update);
3724 RIP_TIMER_OFF (rip->t_triggered_update);
3725 RIP_TIMER_OFF (rip->t_triggered_interval);
3726
3727 /* Cancel read thread. */
3728 if (rip->t_read)
3729 {
3730 thread_cancel (rip->t_read);
3731 rip->t_read = NULL;
3732 }
3733
3734 /* Close RIP socket. */
3735 if (rip->sock >= 0)
3736 {
3737 close (rip->sock);
3738 rip->sock = -1;
3739 }
3740
3741 /* Static RIP route configuration. */
3742 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3743 if (rp->info)
3744 {
3745 rp->info = NULL;
3746 route_unlock_node (rp);
3747 }
3748
3749 /* RIP neighbor configuration. */
3750 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3751 if (rp->info)
3752 {
3753 rp->info = NULL;
3754 route_unlock_node (rp);
3755 }
3756
3757 /* Redistribute related clear. */
3758 if (rip->default_information_route_map)
3759 free (rip->default_information_route_map);
3760
3761 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3762 if (rip->route_map[i].name)
3763 free (rip->route_map[i].name);
3764
3765 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3766 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3767 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3768
3769 XFREE (MTYPE_RIP, rip);
3770 rip = NULL;
3771 }
3772
3773 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003774 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003775 rip_offset_clean ();
3776 rip_interface_clean ();
3777 rip_distance_reset ();
3778 rip_redistribute_clean ();
3779}
3780
3781/* Reset all values to the default settings. */
3782void
3783rip_reset ()
3784{
3785 /* Reset global counters. */
3786 rip_global_route_changes = 0;
3787 rip_global_queries = 0;
3788
3789 /* Call ripd related reset functions. */
3790 rip_debug_reset ();
3791 rip_route_map_reset ();
3792
3793 /* Call library reset functions. */
3794 vty_reset ();
3795 access_list_reset ();
3796 prefix_list_reset ();
3797
3798 distribute_list_reset ();
3799
3800 rip_interface_reset ();
3801 rip_distance_reset ();
3802
3803 rip_zclient_reset ();
3804}
3805
hasso16705132003-05-25 14:49:19 +00003806void
3807rip_if_rmap_update (struct if_rmap *if_rmap)
3808{
3809 struct interface *ifp;
3810 struct rip_interface *ri;
3811 struct route_map *rmap;
3812
3813 ifp = if_lookup_by_name (if_rmap->ifname);
3814 if (ifp == NULL)
3815 return;
3816
3817 ri = ifp->info;
3818
3819 if (if_rmap->routemap[IF_RMAP_IN])
3820 {
3821 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3822 if (rmap)
3823 ri->routemap[IF_RMAP_IN] = rmap;
3824 else
3825 ri->routemap[IF_RMAP_IN] = NULL;
3826 }
3827 else
3828 ri->routemap[RIP_FILTER_IN] = NULL;
3829
3830 if (if_rmap->routemap[IF_RMAP_OUT])
3831 {
3832 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3833 if (rmap)
3834 ri->routemap[IF_RMAP_OUT] = rmap;
3835 else
3836 ri->routemap[IF_RMAP_OUT] = NULL;
3837 }
3838 else
3839 ri->routemap[RIP_FILTER_OUT] = NULL;
3840}
3841
3842void
3843rip_if_rmap_update_interface (struct interface *ifp)
3844{
3845 struct if_rmap *if_rmap;
3846
3847 if_rmap = if_rmap_lookup (ifp->name);
3848 if (if_rmap)
3849 rip_if_rmap_update (if_rmap);
3850}
3851
3852void
3853rip_routemap_update_redistribute (void)
3854{
3855 int i;
3856
3857 if (rip)
3858 {
3859 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3860 {
3861 if (rip->route_map[i].name)
3862 rip->route_map[i].map =
3863 route_map_lookup_by_name (rip->route_map[i].name);
3864 }
3865 }
3866}
3867
3868void
3869rip_routemap_update ()
3870{
3871 struct interface *ifp;
3872 listnode node;
3873
3874 for (node = listhead (iflist); node; nextnode (node))
3875 {
3876 ifp = getdata (node);
3877 rip_if_rmap_update_interface (ifp);
3878 }
3879
3880 rip_routemap_update_redistribute ();
3881}
3882
paul718e3742002-12-13 20:15:29 +00003883/* Allocate new rip structure and set default value. */
3884void
3885rip_init ()
3886{
3887 /* Randomize for triggered update random(). */
3888 srand (time (NULL));
3889
3890 /* Install top nodes. */
3891 install_node (&rip_node, config_write_rip);
3892
3893 /* Install rip commands. */
3894 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003895 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003896 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003897 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003898 install_element (CONFIG_NODE, &router_rip_cmd);
3899 install_element (CONFIG_NODE, &no_router_rip_cmd);
3900
3901 install_default (RIP_NODE);
3902 install_element (RIP_NODE, &rip_version_cmd);
3903 install_element (RIP_NODE, &no_rip_version_cmd);
3904 install_element (RIP_NODE, &no_rip_version_val_cmd);
3905 install_element (RIP_NODE, &rip_default_metric_cmd);
3906 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3907 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3908 install_element (RIP_NODE, &rip_timers_cmd);
3909 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003910 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003911 install_element (RIP_NODE, &rip_route_cmd);
3912 install_element (RIP_NODE, &no_rip_route_cmd);
3913 install_element (RIP_NODE, &rip_distance_cmd);
3914 install_element (RIP_NODE, &no_rip_distance_cmd);
3915 install_element (RIP_NODE, &rip_distance_source_cmd);
3916 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3917 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3918 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3919
3920 /* Debug related init. */
3921 rip_debug_init ();
3922
paul718e3742002-12-13 20:15:29 +00003923 /* SNMP init. */
3924#ifdef HAVE_SNMP
3925 rip_snmp_init ();
3926#endif /* HAVE_SNMP */
3927
3928 /* Access list install. */
3929 access_list_init ();
3930 access_list_add_hook (rip_distribute_update_all);
3931 access_list_delete_hook (rip_distribute_update_all);
3932
3933 /* Prefix list initialize.*/
3934 prefix_list_init ();
3935 prefix_list_add_hook (rip_distribute_update_all);
3936 prefix_list_delete_hook (rip_distribute_update_all);
3937
3938 /* Distribute list install. */
3939 distribute_list_init (RIP_NODE);
3940 distribute_list_add_hook (rip_distribute_update);
3941 distribute_list_delete_hook (rip_distribute_update);
3942
hasso16705132003-05-25 14:49:19 +00003943 /* Route-map */
3944 rip_route_map_init ();
3945 rip_offset_init ();
3946
3947 route_map_add_hook (rip_routemap_update);
3948 route_map_delete_hook (rip_routemap_update);
3949
3950 if_rmap_init (RIP_NODE);
3951 if_rmap_hook_add (rip_if_rmap_update);
3952 if_rmap_hook_delete (rip_if_rmap_update);
3953
paul718e3742002-12-13 20:15:29 +00003954 /* Distance control. */
3955 rip_distance_table = route_table_init ();
3956}