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