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