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