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