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