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