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