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