blob: 7567ba2c96a8cc7b457792a2be2aef4f275e7539 [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
paulc2bfbcc2004-06-04 01:42:38 +0000857/*
858 * If the authentication length is less than 16, then it must be wrong for
859 * any interpretation of rfc2082.
860 */
861 if (md5->auth_len < RIP_AUTH_MD5_SIZE)
862 {
863 if (IS_RIP_DEBUG_EVENT)
864 zlog_info ("RIPv2 MD5 authentication, authentication length field too \
865 short");
paul718e3742002-12-13 20:15:29 +0000866 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000867 }
paul718e3742002-12-13 20:15:29 +0000868
869 if (ri->key_chain)
870 {
871 keychain = keychain_lookup (ri->key_chain);
872 if (keychain == NULL)
873 return 0;
874
875 key = key_lookup_for_accept (keychain, md5->keyid);
876 if (key == NULL)
877 return 0;
878
879 auth_str = key->string;
880 }
881
882 if (ri->auth_str)
883 auth_str = ri->auth_str;
884
885 if (! auth_str)
886 return 0;
887
888 /* MD5 digest authentication. */
889 packet_len = ntohs (md5->packet_len);
890 md5data = (struct rip_md5_data *)(((u_char *) packet) + packet_len);
891
892 /* Save digest to pdigest. */
893 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
894
895 /* Overwrite digest by my secret. */
896 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000897 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000898
899 md5_init_ctx (&ctx);
paulc2bfbcc2004-06-04 01:42:38 +0000900 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE, \
901 &ctx);
paul718e3742002-12-13 20:15:29 +0000902 md5_finish_ctx (&ctx, digest);
903
904 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
905 return packet_len;
906 else
907 return 0;
908}
909
910void
911rip_auth_md5_set (struct stream *s, struct interface *ifp)
912{
913 struct rip_interface *ri;
914 struct keychain *keychain = NULL;
915 struct key *key = NULL;
916 unsigned long len;
917 struct md5_ctx ctx;
918 unsigned char secret[RIP_AUTH_MD5_SIZE];
919 unsigned char digest[RIP_AUTH_MD5_SIZE];
920 char *auth_str = NULL;
921
922 ri = ifp->info;
923
924 /* Make it sure this interface is configured as MD5
925 authentication. */
926 if (ri->auth_type != RIP_AUTH_MD5)
927 return;
928
929 /* Lookup key chain. */
930 if (ri->key_chain)
931 {
932 keychain = keychain_lookup (ri->key_chain);
933 if (keychain == NULL)
934 return;
935
936 /* Lookup key. */
937 key = key_lookup_for_send (keychain);
938 if (key == NULL)
939 return;
940
941 auth_str = key->string;
942 }
943
944 if (ri->auth_str)
945 auth_str = ri->auth_str;
946
947 if (! auth_str)
948 return;
949
950 /* Get packet length. */
951 len = s->putp;
952
953 /* Check packet length. */
954 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
955 {
956 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
957 return;
958 }
959
960 /* Move RTE. */
961 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
962 s->data + RIP_HEADER_SIZE,
963 len - RIP_HEADER_SIZE);
964
965 /* Set pointer to authentication header. */
966 stream_set_putp (s, RIP_HEADER_SIZE);
967 len += RIP_RTE_SIZE;
968
969 /* MD5 authentication. */
970 stream_putw (s, 0xffff);
971 stream_putw (s, RIP_AUTH_MD5);
972
973 /* RIP-2 Packet length. Actual value is filled in
974 rip_auth_md5_set(). */
975 stream_putw (s, len);
976
977 /* Key ID. */
978 if (key)
979 stream_putc (s, key->index % 256);
980 else
981 stream_putc (s, 1);
982
983 /* Auth Data Len. Set 16 for MD5 authentication
984 data. */
paulc2bfbcc2004-06-04 01:42:38 +0000985 stream_putc (s, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000986
987 /* Sequence Number (non-decreasing). */
988 /* RFC2080: The value used in the sequence number is
989 arbitrary, but two suggestions are the time of the
990 message's creation or a simple message counter. */
991 stream_putl (s, time (NULL));
992
993 /* Reserved field must be zero. */
994 stream_putl (s, 0);
995 stream_putl (s, 0);
996
997 /* Set pointer to authentication data. */
998 stream_set_putp (s, len);
999
1000 /* Set authentication data. */
1001 stream_putw (s, 0xffff);
1002 stream_putw (s, 0x01);
1003
1004 /* Generate a digest for the RIP packet. */
1005 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001006 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001007 md5_init_ctx (&ctx);
1008 md5_process_bytes (s->data, s->endp, &ctx);
1009 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1010 md5_finish_ctx (&ctx, digest);
1011
1012 /* Copy the digest to the packet. */
1013 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1014}
1015
1016/* RIP routing information. */
1017void
1018rip_response_process (struct rip_packet *packet, int size,
1019 struct sockaddr_in *from, struct interface *ifp)
1020{
1021 caddr_t lim;
1022 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001023 struct prefix_ipv4 ifaddr;
1024 struct prefix_ipv4 ifaddrclass;
1025 struct connected *c;
1026 int subnetted;
paul718e3742002-12-13 20:15:29 +00001027
paul727d1042002-12-13 20:50:29 +00001028 /* We don't know yet. */
1029 subnetted = -1;
1030
paul718e3742002-12-13 20:15:29 +00001031 /* The Response must be ignored if it is not from the RIP
1032 port. (RFC2453 - Sec. 3.9.2)*/
1033 if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)
1034 {
1035 zlog_info ("response doesn't come from RIP port: %d",
1036 from->sin_port);
1037 rip_peer_bad_packet (from);
1038 return;
1039 }
1040
1041 /* The datagram's IPv4 source address should be checked to see
1042 whether the datagram is from a valid neighbor; the source of the
1043 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001044 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001045 {
1046 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1047 inet_ntoa (from->sin_addr));
1048 rip_peer_bad_packet (from);
1049 return;
1050 }
1051
1052 /* It is also worth checking to see whether the response is from one
1053 of the router's own addresses. */
1054
1055 ; /* Alredy done in rip_read () */
1056
1057 /* Update RIP peer. */
1058 rip_peer_update (from, packet->version);
1059
1060 /* Set RTE pointer. */
1061 rte = packet->rte;
1062
1063 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1064 {
1065 /* RIPv2 authentication check. */
1066 /* If the Address Family Identifier of the first (and only the
1067 first) entry in the message is 0xFFFF, then the remainder of
1068 the entry contains the authentication. */
1069 /* If the packet gets here it means authentication enabled */
1070 /* Check is done in rip_read(). So, just skipping it */
1071 if (packet->version == RIPv2 &&
1072 rte == packet->rte &&
1073 rte->family == 0xffff)
1074 continue;
1075
1076 if (ntohs (rte->family) != AF_INET)
1077 {
1078 /* Address family check. RIP only supports AF_INET. */
1079 zlog_info ("Unsupported family %d from %s.",
1080 ntohs (rte->family), inet_ntoa (from->sin_addr));
1081 continue;
1082 }
1083
1084 /* - is the destination address valid (e.g., unicast; not net 0
1085 or 127) */
1086 if (! rip_destination_check (rte->prefix))
1087 {
1088 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1089 rip_peer_bad_route (from);
1090 continue;
1091 }
1092
1093 /* Convert metric value to host byte order. */
1094 rte->metric = ntohl (rte->metric);
1095
1096 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1097 if (! (rte->metric >= 1 && rte->metric <= 16))
1098 {
1099 zlog_info ("Route's metric is not in the 1-16 range.");
1100 rip_peer_bad_route (from);
1101 continue;
1102 }
1103
1104 /* RIPv1 does not have nexthop value. */
1105 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1106 {
1107 zlog_info ("RIPv1 packet with nexthop value %s",
1108 inet_ntoa (rte->nexthop));
1109 rip_peer_bad_route (from);
1110 continue;
1111 }
1112
1113 /* That is, if the provided information is ignored, a possibly
1114 sub-optimal, but absolutely valid, route may be taken. If
1115 the received Next Hop is not directly reachable, it should be
1116 treated as 0.0.0.0. */
1117 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1118 {
1119 u_int32_t addrval;
1120
1121 /* Multicast address check. */
1122 addrval = ntohl (rte->nexthop.s_addr);
1123 if (IN_CLASSD (addrval))
1124 {
1125 zlog_info ("Nexthop %s is multicast address, skip this rte",
1126 inet_ntoa (rte->nexthop));
1127 continue;
1128 }
1129
1130 if (! if_lookup_address (rte->nexthop))
1131 {
1132 struct route_node *rn;
1133 struct rip_info *rinfo;
1134
1135 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1136
1137 if (rn)
1138 {
1139 rinfo = rn->info;
1140
1141 if (rinfo->type == ZEBRA_ROUTE_RIP
1142 && rinfo->sub_type == RIP_ROUTE_RTE)
1143 {
1144 if (IS_RIP_DEBUG_EVENT)
1145 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1146 rte->nexthop = rinfo->from;
1147 }
1148 else
1149 {
1150 if (IS_RIP_DEBUG_EVENT)
1151 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1152 rte->nexthop.s_addr = 0;
1153 }
1154
1155 route_unlock_node (rn);
1156 }
1157 else
1158 {
1159 if (IS_RIP_DEBUG_EVENT)
1160 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1161 rte->nexthop.s_addr = 0;
1162 }
1163
1164 }
1165 }
1166
1167 /* For RIPv1, there won't be a valid netmask.
1168
1169 This is a best guess at the masks. If everyone was using old
1170 Ciscos before the 'ip subnet zero' option, it would be almost
1171 right too :-)
1172
1173 Cisco summarize ripv1 advertisments to the classful boundary
1174 (/16 for class B's) except when the RIP packet does to inside
1175 the classful network in question. */
1176
1177 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1178 || (packet->version == RIPv2
1179 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1180 {
1181 u_int32_t destination;
1182
paul727d1042002-12-13 20:50:29 +00001183 if (subnetted == -1)
1184 {
1185 c = connected_lookup_address (ifp, from->sin_addr);
1186 if (c != NULL)
1187 {
1188 memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
1189 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1190 apply_classful_mask_ipv4 (&ifaddrclass);
1191 subnetted = 0;
1192 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1193 subnetted = 1;
1194 }
1195 }
1196
paul718e3742002-12-13 20:15:29 +00001197 destination = ntohl (rte->prefix.s_addr);
1198
paul727d1042002-12-13 20:50:29 +00001199 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001200 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001201 else if (IN_CLASSB (destination))
1202 masklen2ip (16, &rte->mask);
1203 else if (IN_CLASSC (destination))
1204 masklen2ip (24, &rte->mask);
1205
1206 if (subnetted == 1)
1207 masklen2ip (ifaddrclass.prefixlen,
1208 (struct in_addr *) &destination);
1209 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1210 ifaddrclass.prefix.s_addr))
1211 {
1212 masklen2ip (ifaddr.prefixlen, &rte->mask);
1213 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1214 masklen2ip (32, &rte->mask);
1215 if (IS_RIP_DEBUG_EVENT)
1216 zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
1217 }
1218 else
1219 {
1220 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1221 continue;
1222 }
1223
1224 if (IS_RIP_DEBUG_EVENT)
1225 {
1226 zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
1227 zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001228 }
1229 }
1230
1231 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1232 ignore the entry. */
1233 if ((packet->version == RIPv2)
1234 && (rte->mask.s_addr != 0)
1235 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1236 {
1237 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1238 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1239 rip_peer_bad_route (from);
1240 continue;
1241 }
1242
1243 /* Default route's netmask is ignored. */
1244 if (packet->version == RIPv2
1245 && (rte->prefix.s_addr == 0)
1246 && (rte->mask.s_addr != 0))
1247 {
1248 if (IS_RIP_DEBUG_EVENT)
1249 zlog_info ("Default route with non-zero netmask. Set zero to netmask");
1250 rte->mask.s_addr = 0;
1251 }
1252
1253 /* Routing table updates. */
1254 rip_rte_process (rte, from, ifp);
1255 }
1256}
1257
1258/* RIP packet send to destination address. */
1259int
paul11dde9c2004-05-31 14:00:00 +00001260rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
paul931cd542004-01-23 15:31:42 +00001261 struct interface *ifp, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00001262{
paul931cd542004-01-23 15:31:42 +00001263 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001264 struct sockaddr_in sin;
paul718e3742002-12-13 20:15:29 +00001265
paul931cd542004-01-23 15:31:42 +00001266 if (IS_RIP_DEBUG_PACKET)
1267 {
1268 char dst[20];
1269 if (to)
1270 {
1271 strcpy(dst, inet_ntoa(to->sin_addr));
1272 }
1273 else
1274 {
1275 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1276 strcpy(dst, inet_ntoa(sin.sin_addr));
1277 }
1278 zlog_info("rip_send_packet %s > %s (%s)",
hassoda9c9a22004-03-18 02:40:55 +00001279 (connected ? inet_ntoa(connected->address->u.prefix4) : ""),
1280 dst, ifp->name);
paul931cd542004-01-23 15:31:42 +00001281 }
hassoda9c9a22004-03-18 02:40:55 +00001282 if (connected && connected->flags & ZEBRA_IFA_SECONDARY)
paul931cd542004-01-23 15:31:42 +00001283 {
1284 /*
1285 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1286 * with multiple addresses on the same subnet: the first address
1287 * on the subnet is configured "primary", and all subsequent addresses
1288 * on that subnet are treated as "secondary" addresses.
1289 * In order to avoid routing-table bloat on other rip listeners,
1290 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1291 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1292 * flag is set, we would end up sending a packet for a "secondary"
1293 * source address on non-linux systems.
1294 */
1295 if (IS_RIP_DEBUG_PACKET)
1296 zlog_info("duplicate dropped");
1297 return 0;
1298 }
1299
paul718e3742002-12-13 20:15:29 +00001300 /* Make destination address. */
1301 memset (&sin, 0, sizeof (struct sockaddr_in));
1302 sin.sin_family = AF_INET;
1303#ifdef HAVE_SIN_LEN
1304 sin.sin_len = sizeof (struct sockaddr_in);
1305#endif /* HAVE_SIN_LEN */
1306
1307 /* When destination is specified, use it's port and address. */
1308 if (to)
1309 {
paul718e3742002-12-13 20:15:29 +00001310 sin.sin_port = to->sin_port;
1311 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001312 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001313 }
1314 else
1315 {
paul718e3742002-12-13 20:15:29 +00001316
1317 sin.sin_port = htons (RIP_PORT_DEFAULT);
1318 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1319
paul931cd542004-01-23 15:31:42 +00001320 /*
1321 * we have to open a new socket for each packet because this
1322 * is the most portable way to bind to a different source
1323 * ipv4 address for each packet.
1324 */
1325 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1326 if (send_sock < 0)
1327 {
1328 zlog_warn("rip_send_packet could not create socket %s",
1329 strerror(errno));
1330 return -1;
1331 }
1332 sockopt_broadcast (send_sock);
1333 sockopt_reuseaddr (send_sock);
1334 sockopt_reuseport (send_sock);
1335#ifdef RIP_RECVMSG
1336 setsockopt_pktinfo (send_sock);
1337#endif /* RIP_RECVMSG */
1338 rip_interface_multicast_set(send_sock, connected, if_is_pointopoint(ifp));
paul718e3742002-12-13 20:15:29 +00001339 }
1340
paul931cd542004-01-23 15:31:42 +00001341 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001342 sizeof (struct sockaddr_in));
1343
1344 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001345 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1346 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001347
1348 if (ret < 0)
1349 zlog_warn ("can't send packet : %s", strerror (errno));
1350
paul931cd542004-01-23 15:31:42 +00001351 if (!to)
1352 close(send_sock);
1353
paul718e3742002-12-13 20:15:29 +00001354 return ret;
1355}
1356
1357/* Add redistributed route to RIP table. */
1358void
1359rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1360 unsigned int ifindex, struct in_addr *nexthop)
1361{
1362 int ret;
1363 struct route_node *rp;
1364 struct rip_info *rinfo;
1365
1366 /* Redistribute route */
1367 ret = rip_destination_check (p->prefix);
1368 if (! ret)
1369 return;
1370
1371 rp = route_node_get (rip->table, (struct prefix *) p);
1372
1373 rinfo = rp->info;
1374
1375 if (rinfo)
1376 {
1377 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1378 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1379 && rinfo->metric != RIP_METRIC_INFINITY)
1380 {
1381 route_unlock_node (rp);
1382 return;
1383 }
1384
1385 /* Manually configured RIP route check. */
1386 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001387 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1388 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001389 {
hasso16705132003-05-25 14:49:19 +00001390 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1391 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001392 {
1393 route_unlock_node (rp);
1394 return;
1395 }
1396 }
1397
1398 RIP_TIMER_OFF (rinfo->t_timeout);
1399 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1400
1401 if (rip_route_rte (rinfo))
1402 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1403 rinfo->metric);
1404 rp->info = NULL;
1405 rip_info_free (rinfo);
1406
1407 route_unlock_node (rp);
1408 }
1409
1410 rinfo = rip_info_new ();
1411
1412 rinfo->type = type;
1413 rinfo->sub_type = sub_type;
1414 rinfo->ifindex = ifindex;
1415 rinfo->metric = 1;
1416 rinfo->rp = rp;
1417
1418 if (nexthop)
1419 rinfo->nexthop = *nexthop;
1420
1421 rinfo->flags |= RIP_RTF_FIB;
1422 rp->info = rinfo;
1423
1424 rinfo->flags |= RIP_RTF_CHANGED;
1425
hasso16705132003-05-25 14:49:19 +00001426 if (IS_RIP_DEBUG_EVENT) {
1427 if (!nexthop)
1428 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1429 inet_ntoa(p->prefix), p->prefixlen,
1430 ifindex2ifname(ifindex));
1431 else
1432 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1433 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1434 ifindex2ifname(ifindex));
1435 }
1436
1437
paul718e3742002-12-13 20:15:29 +00001438 rip_event (RIP_TRIGGERED_UPDATE, 0);
1439}
1440
1441/* Delete redistributed route from RIP table. */
1442void
1443rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1444 unsigned int ifindex)
1445{
1446 int ret;
1447 struct route_node *rp;
1448 struct rip_info *rinfo;
1449
1450 ret = rip_destination_check (p->prefix);
1451 if (! ret)
1452 return;
1453
1454 rp = route_node_lookup (rip->table, (struct prefix *) p);
1455 if (rp)
1456 {
1457 rinfo = rp->info;
1458
1459 if (rinfo != NULL
1460 && rinfo->type == type
1461 && rinfo->sub_type == sub_type
1462 && rinfo->ifindex == ifindex)
1463 {
1464 /* Perform poisoned reverse. */
1465 rinfo->metric = RIP_METRIC_INFINITY;
1466 RIP_TIMER_ON (rinfo->t_garbage_collect,
1467 rip_garbage_collect, rip->garbage_time);
1468 RIP_TIMER_OFF (rinfo->t_timeout);
1469 rinfo->flags |= RIP_RTF_CHANGED;
1470
hasso16705132003-05-25 14:49:19 +00001471 if (IS_RIP_DEBUG_EVENT)
1472 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1473 inet_ntoa(p->prefix), p->prefixlen,
1474 ifindex2ifname(ifindex));
1475
paul718e3742002-12-13 20:15:29 +00001476 rip_event (RIP_TRIGGERED_UPDATE, 0);
1477 }
1478 }
1479}
1480
1481/* Response to request called from rip_read ().*/
1482void
1483rip_request_process (struct rip_packet *packet, int size,
1484 struct sockaddr_in *from, struct interface *ifp)
1485{
1486 caddr_t lim;
1487 struct rte *rte;
1488 struct prefix_ipv4 p;
1489 struct route_node *rp;
1490 struct rip_info *rinfo;
1491 struct rip_interface *ri;
1492
hasso16705132003-05-25 14:49:19 +00001493 /* Does not reponse to the requests on the loopback interfaces */
1494 if (if_is_loopback (ifp))
1495 return;
1496
hasso429a0f82004-02-22 23:42:22 +00001497 /* Check RIP process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001498 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001499 if (! ri->running)
1500 return;
paul718e3742002-12-13 20:15:29 +00001501
1502 /* When passive interface is specified, suppress responses */
1503 if (ri->passive)
1504 return;
1505
1506 /* RIP peer update. */
1507 rip_peer_update (from, packet->version);
1508
1509 lim = ((caddr_t) packet) + size;
1510 rte = packet->rte;
1511
1512 /* The Request is processed entry by entry. If there are no
1513 entries, no response is given. */
1514 if (lim == (caddr_t) rte)
1515 return;
1516
1517 /* There is one special case. If there is exactly one entry in the
1518 request, and it has an address family identifier of zero and a
1519 metric of infinity (i.e., 16), then this is a request to send the
1520 entire routing table. */
1521 if (lim == ((caddr_t) (rte + 1)) &&
1522 ntohs (rte->family) == 0 &&
1523 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1524 {
paulcc1131a2003-10-15 23:20:17 +00001525 struct prefix_ipv4 saddr;
1526
1527 /* saddr will be used for determining which routes to split-horizon.
1528 Since the source address we'll pick will be on the same subnet as the
1529 destination, for the purpose of split-horizoning, we'll
1530 pretend that "from" is our source address. */
1531 saddr.family = AF_INET;
1532 saddr.prefixlen = IPV4_MAX_BITLEN;
1533 saddr.prefix = from->sin_addr;
1534
paul718e3742002-12-13 20:15:29 +00001535 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001536 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001537 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001538 }
1539 else
1540 {
1541 /* Examine the list of RTEs in the Request one by one. For each
1542 entry, look up the destination in the router's routing
1543 database and, if there is a route, put that route's metric in
1544 the metric field of the RTE. If there is no explicit route
1545 to the specified destination, put infinity in the metric
1546 field. Once all the entries have been filled in, change the
1547 command from Request to Response and send the datagram back
1548 to the requestor. */
1549 p.family = AF_INET;
1550
1551 for (; ((caddr_t) rte) < lim; rte++)
1552 {
1553 p.prefix = rte->prefix;
1554 p.prefixlen = ip_masklen (rte->mask);
1555 apply_mask_ipv4 (&p);
1556
1557 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1558 if (rp)
1559 {
1560 rinfo = rp->info;
1561 rte->metric = htonl (rinfo->metric);
1562 route_unlock_node (rp);
1563 }
1564 else
1565 rte->metric = htonl (RIP_METRIC_INFINITY);
1566 }
1567 packet->command = RIP_RESPONSE;
1568
paul11dde9c2004-05-31 14:00:00 +00001569 rip_send_packet ((u_char *)packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001570 }
1571 rip_global_queries++;
1572}
1573
1574#if RIP_RECVMSG
1575/* Set IPv6 packet info to the socket. */
1576static int
1577setsockopt_pktinfo (int sock)
1578{
1579 int ret;
1580 int val = 1;
1581
1582 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1583 if (ret < 0)
1584 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1585 return ret;
1586}
1587
1588/* Read RIP packet by recvmsg function. */
1589int
1590rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1591 int *ifindex)
1592{
1593 int ret;
1594 struct msghdr msg;
1595 struct iovec iov;
1596 struct cmsghdr *ptr;
1597 char adata[1024];
1598
1599 msg.msg_name = (void *) from;
1600 msg.msg_namelen = sizeof (struct sockaddr_in);
1601 msg.msg_iov = &iov;
1602 msg.msg_iovlen = 1;
1603 msg.msg_control = (void *) adata;
1604 msg.msg_controllen = sizeof adata;
1605 iov.iov_base = buf;
1606 iov.iov_len = size;
1607
1608 ret = recvmsg (sock, &msg, 0);
1609 if (ret < 0)
1610 return ret;
1611
1612 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1613 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1614 {
1615 struct in_pktinfo *pktinfo;
1616 int i;
1617
1618 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1619 i = pktinfo->ipi_ifindex;
1620 }
1621 return ret;
1622}
1623
1624/* RIP packet read function. */
1625int
1626rip_read_new (struct thread *t)
1627{
1628 int ret;
1629 int sock;
1630 char buf[RIP_PACKET_MAXSIZ];
1631 struct sockaddr_in from;
1632 unsigned int ifindex;
1633
1634 /* Fetch socket then register myself. */
1635 sock = THREAD_FD (t);
1636 rip_event (RIP_READ, sock);
1637
1638 /* Read RIP packet. */
1639 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1640 if (ret < 0)
1641 {
1642 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1643 return ret;
1644 }
1645
1646 return ret;
1647}
1648#endif /* RIP_RECVMSG */
1649
1650/* First entry point of RIP packet. */
1651int
1652rip_read (struct thread *t)
1653{
1654 int sock;
1655 int ret;
1656 int rtenum;
1657 union rip_buf rip_buf;
1658 struct rip_packet *packet;
1659 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001660 int len;
1661 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001662 struct interface *ifp;
1663 struct rip_interface *ri;
1664
1665 /* Fetch socket then register myself. */
1666 sock = THREAD_FD (t);
1667 rip->t_read = NULL;
1668
1669 /* Add myself to tne next event */
1670 rip_event (RIP_READ, sock);
1671
1672 /* RIPd manages only IPv4. */
1673 memset (&from, 0, sizeof (struct sockaddr_in));
1674 fromlen = sizeof (struct sockaddr_in);
1675
1676 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1677 (struct sockaddr *) &from, &fromlen);
1678 if (len < 0)
1679 {
1680 zlog_info ("recvfrom failed: %s", strerror (errno));
1681 return len;
1682 }
1683
1684 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001685 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001686 {
1687 if (IS_RIP_DEBUG_PACKET)
1688 zlog_warn ("ignore packet comes from myself");
1689 return -1;
1690 }
1691
1692 /* Which interface is this packet comes from. */
1693 ifp = if_lookup_address (from.sin_addr);
1694
1695 /* RIP packet received */
1696 if (IS_RIP_DEBUG_EVENT)
1697 zlog_info ("RECV packet from %s port %d on %s",
1698 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1699 ifp ? ifp->name : "unknown");
1700
1701 /* If this packet come from unknown interface, ignore it. */
1702 if (ifp == NULL)
1703 {
1704 zlog_info ("packet comes from unknown interface");
1705 return -1;
1706 }
1707
1708 /* Packet length check. */
1709 if (len < RIP_PACKET_MINSIZ)
1710 {
1711 zlog_warn ("packet size %d is smaller than minimum size %d",
1712 len, RIP_PACKET_MINSIZ);
1713 rip_peer_bad_packet (&from);
1714 return len;
1715 }
1716 if (len > RIP_PACKET_MAXSIZ)
1717 {
1718 zlog_warn ("packet size %d is larger than max size %d",
1719 len, RIP_PACKET_MAXSIZ);
1720 rip_peer_bad_packet (&from);
1721 return len;
1722 }
1723
1724 /* Packet alignment check. */
1725 if ((len - RIP_PACKET_MINSIZ) % 20)
1726 {
1727 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1728 rip_peer_bad_packet (&from);
1729 return len;
1730 }
1731
1732 /* Set RTE number. */
1733 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1734
1735 /* For easy to handle. */
1736 packet = &rip_buf.rip_packet;
1737
1738 /* RIP version check. */
1739 if (packet->version == 0)
1740 {
1741 zlog_info ("version 0 with command %d received.", packet->command);
1742 rip_peer_bad_packet (&from);
1743 return -1;
1744 }
1745
1746 /* Dump RIP packet. */
1747 if (IS_RIP_DEBUG_RECV)
1748 rip_packet_dump (packet, len, "RECV");
1749
1750 /* RIP version adjust. This code should rethink now. RFC1058 says
1751 that "Version 1 implementations are to ignore this extra data and
1752 process only the fields specified in this document.". So RIPv3
1753 packet should be treated as RIPv1 ignoring must be zero field. */
1754 if (packet->version > RIPv2)
1755 packet->version = RIPv2;
1756
1757 /* Is RIP running or is this RIP neighbor ?*/
1758 ri = ifp->info;
1759 if (! ri->running && ! rip_neighbor_lookup (&from))
1760 {
1761 if (IS_RIP_DEBUG_EVENT)
1762 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1763 rip_peer_bad_packet (&from);
1764 return -1;
1765 }
1766
1767 /* RIP Version check. */
1768 if (packet->command == RIP_RESPONSE)
1769 {
paulf38a4712003-06-07 01:10:00 +00001770 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1771 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001772 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001773 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001774 {
1775 if (IS_RIP_DEBUG_PACKET)
1776 zlog_warn (" packet's v%d doesn't fit to if version spec",
1777 packet->version);
1778 rip_peer_bad_packet (&from);
1779 return -1;
1780 }
1781 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001782 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001783 {
1784 if (IS_RIP_DEBUG_PACKET)
1785 zlog_warn (" packet's v%d doesn't fit to if version spec",
1786 packet->version);
1787 rip_peer_bad_packet (&from);
1788 return -1;
1789 }
paul718e3742002-12-13 20:15:29 +00001790 }
1791
1792 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1793 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1794 accepted; authenticated RIP-2 messages shall be discarded. */
1795
1796 if ((ri->auth_type == RIP_NO_AUTH)
1797 && rtenum
1798 && (packet->version == RIPv2) && (packet->rte->family == 0xffff))
1799 {
1800 if (IS_RIP_DEBUG_EVENT)
1801 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1802 packet->version);
1803 rip_peer_bad_packet (&from);
1804 return -1;
1805 }
1806
1807 /* If the router is configured to authenticate RIP-2 messages, then
1808 RIP-1 messages and RIP-2 messages which pass authentication
1809 testing shall be accepted; unauthenticated and failed
1810 authentication RIP-2 messages shall be discarded. For maximum
1811 security, RIP-1 messages should be ignored when authentication is
1812 in use (see section 4.1); otherwise, the routing information from
1813 authenticated messages will be propagated by RIP-1 routers in an
1814 unauthenticated manner. */
1815
1816 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
1817 || ri->auth_type == RIP_AUTH_MD5)
1818 && rtenum)
1819 {
1820 /* We follow maximum security. */
1821 if (packet->version == RIPv1 && packet->rte->family == 0xffff)
1822 {
1823 if (IS_RIP_DEBUG_PACKET)
1824 zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version);
1825 rip_peer_bad_packet (&from);
1826 return -1;
1827 }
1828
1829 /* Check RIPv2 authentication. */
1830 if (packet->version == RIPv2)
1831 {
1832 if (packet->rte->family == 0xffff)
1833 {
1834 if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)
1835 {
1836 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1837 if (! ret)
1838 {
1839 if (IS_RIP_DEBUG_EVENT)
1840 zlog_warn ("RIPv2 simple password authentication failed");
1841 rip_peer_bad_packet (&from);
1842 return -1;
1843 }
1844 else
1845 {
1846 if (IS_RIP_DEBUG_EVENT)
1847 zlog_info ("RIPv2 simple password authentication success");
1848 }
1849 }
1850 else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5)
1851 {
1852 ret = rip_auth_md5 (packet, &from, ifp);
1853 if (! ret)
1854 {
1855 if (IS_RIP_DEBUG_EVENT)
1856 zlog_warn ("RIPv2 MD5 authentication failed");
1857 rip_peer_bad_packet (&from);
1858 return -1;
1859 }
1860 else
1861 {
1862 if (IS_RIP_DEBUG_EVENT)
1863 zlog_info ("RIPv2 MD5 authentication success");
1864 }
1865 /* Reset RIP packet length to trim MD5 data. */
1866 len = ret;
1867 }
1868 else
1869 {
1870 if (IS_RIP_DEBUG_EVENT)
1871 zlog_warn ("Unknown authentication type %d",
1872 ntohs (packet->rte->tag));
1873 rip_peer_bad_packet (&from);
1874 return -1;
1875 }
1876 }
1877 else
1878 {
1879 /* There is no authentication in the packet. */
1880 if (ri->auth_str || ri->key_chain)
1881 {
1882 if (IS_RIP_DEBUG_EVENT)
1883 zlog_warn ("RIPv2 authentication failed: no authentication in packet");
1884 rip_peer_bad_packet (&from);
1885 return -1;
1886 }
1887 }
1888 }
1889 }
1890
1891 /* Process each command. */
1892 switch (packet->command)
1893 {
1894 case RIP_RESPONSE:
1895 rip_response_process (packet, len, &from, ifp);
1896 break;
1897 case RIP_REQUEST:
1898 case RIP_POLL:
1899 rip_request_process (packet, len, &from, ifp);
1900 break;
1901 case RIP_TRACEON:
1902 case RIP_TRACEOFF:
1903 zlog_info ("Obsolete command %s received, please sent it to routed",
1904 lookup (rip_msg, packet->command));
1905 rip_peer_bad_packet (&from);
1906 break;
1907 case RIP_POLL_ENTRY:
1908 zlog_info ("Obsolete command %s received",
1909 lookup (rip_msg, packet->command));
1910 rip_peer_bad_packet (&from);
1911 break;
1912 default:
1913 zlog_info ("Unknown RIP command %d received", packet->command);
1914 rip_peer_bad_packet (&from);
1915 break;
1916 }
1917
1918 return len;
1919}
1920
1921/* Make socket for RIP protocol. */
1922int
1923rip_create_socket ()
1924{
1925 int ret;
1926 int sock;
1927 struct sockaddr_in addr;
1928 struct servent *sp;
1929
1930 memset (&addr, 0, sizeof (struct sockaddr_in));
1931
1932 /* Set RIP port. */
1933 sp = getservbyname ("router", "udp");
1934 if (sp)
1935 addr.sin_port = sp->s_port;
1936 else
1937 addr.sin_port = htons (RIP_PORT_DEFAULT);
1938
1939 /* Address shoud be any address. */
1940 addr.sin_family = AF_INET;
1941 addr.sin_addr.s_addr = INADDR_ANY;
1942
1943 /* Make datagram socket. */
1944 sock = socket (AF_INET, SOCK_DGRAM, 0);
1945 if (sock < 0)
1946 {
1947 perror ("socket");
1948 exit (1);
1949 }
1950
1951 sockopt_broadcast (sock);
1952 sockopt_reuseaddr (sock);
1953 sockopt_reuseport (sock);
1954#ifdef RIP_RECVMSG
1955 setsockopt_pktinfo (sock);
1956#endif /* RIP_RECVMSG */
1957
pauledd7c242003-06-04 13:59:38 +00001958 if (ripd_privs.change (ZPRIVS_RAISE))
1959 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001960 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1961 if (ret < 0)
1962 {
1963 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001964 if (ripd_privs.change (ZPRIVS_LOWER))
1965 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001966 return ret;
1967 }
pauledd7c242003-06-04 13:59:38 +00001968 if (ripd_privs.change (ZPRIVS_LOWER))
1969 zlog_err ("rip_create_socket: could not lower privs");
1970
paul718e3742002-12-13 20:15:29 +00001971 return sock;
1972}
1973
1974/* Write routing table entry to the stream and return next index of
1975 the routing table entry in the stream. */
1976int
1977rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
1978 u_char version, struct rip_info *rinfo, struct interface *ifp)
1979{
1980 struct in_addr mask;
1981 struct rip_interface *ri;
1982
1983 /* RIP packet header. */
1984 if (num == 0)
1985 {
1986 stream_putc (s, RIP_RESPONSE);
1987 stream_putc (s, version);
1988 stream_putw (s, 0);
1989
1990 /* In case of we need RIPv2 authentication. */
1991 if (version == RIPv2 && ifp)
1992 {
1993 ri = ifp->info;
1994
1995 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
1996 {
1997 if (ri->auth_str)
1998 {
1999 stream_putw (s, 0xffff);
2000 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2001
2002 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002003 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002004 stream_set_putp (s, s->putp + 16);
2005
2006 num++;
2007 }
2008 if (ri->key_chain)
2009 {
2010 struct keychain *keychain;
2011 struct key *key;
2012
2013 keychain = keychain_lookup (ri->key_chain);
2014
2015 if (keychain)
2016 {
2017 key = key_lookup_for_send (keychain);
2018
2019 if (key)
2020 {
2021 stream_putw (s, 0xffff);
2022 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2023
2024 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002025 strncpy ((char *)(s->data + s->putp),
2026 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002027 stream_set_putp (s, s->putp + 16);
2028
2029 num++;
2030 }
2031 }
2032 }
2033 }
2034 }
2035 }
2036
2037 /* Write routing table entry. */
2038 if (version == RIPv1)
2039 {
2040 stream_putw (s, AF_INET);
2041 stream_putw (s, 0);
2042 stream_put_ipv4 (s, p->prefix.s_addr);
2043 stream_put_ipv4 (s, 0);
2044 stream_put_ipv4 (s, 0);
2045 stream_putl (s, rinfo->metric_out);
2046 }
2047 else
2048 {
2049 masklen2ip (p->prefixlen, &mask);
2050
2051 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002052 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002053 stream_put_ipv4 (s, p->prefix.s_addr);
2054 stream_put_ipv4 (s, mask.s_addr);
2055 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2056 stream_putl (s, rinfo->metric_out);
2057 }
2058
2059 return ++num;
2060}
2061
2062/* Send update to the ifp or spcified neighbor. */
2063void
paul727d1042002-12-13 20:50:29 +00002064rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002065 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002066 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002067{
2068 int ret;
2069 struct stream *s;
2070 struct route_node *rp;
2071 struct rip_info *rinfo;
2072 struct rip_interface *ri;
2073 struct prefix_ipv4 *p;
2074 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002075 struct prefix_ipv4 ifaddrclass;
2076 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002077 int num;
2078 int rtemax;
paul01d09082003-06-08 21:22:18 +00002079 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002080
2081 /* Logging output event. */
2082 if (IS_RIP_DEBUG_EVENT)
2083 {
2084 if (to)
2085 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2086 else
2087 zlog_info ("update routes on interface %s ifindex %d",
2088 ifp->name, ifp->ifindex);
2089 }
2090
2091 /* Set output stream. */
2092 s = rip->obuf;
2093
2094 /* Reset stream and RTE counter. */
2095 stream_reset (s);
2096 num = 0;
2097 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2098
2099 /* Get RIP interface. */
2100 ri = ifp->info;
2101
2102 /* If output interface is in simple password authentication mode, we
2103 need space for authentication data. */
2104 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2105 rtemax -= 1;
2106
2107 /* If output interface is in MD5 authentication mode, we need space
2108 for authentication header and data. */
2109 if (ri->auth_type == RIP_AUTH_MD5)
2110 rtemax -= 2;
2111
2112 /* If output interface is in simple password authentication mode
2113 and string or keychain is specified we need space for auth. data */
2114 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2115 {
2116 if (ri->key_chain)
2117 {
2118 struct keychain *keychain;
2119
2120 keychain = keychain_lookup (ri->key_chain);
2121 if (keychain)
2122 if (key_lookup_for_send (keychain))
2123 rtemax -=1;
2124 }
2125 else
2126 if (ri->auth_str)
2127 rtemax -=1;
2128 }
2129
paul727d1042002-12-13 20:50:29 +00002130 if (version == RIPv1)
2131 {
2132 if (ifaddr == NULL)
2133 {
2134 c = connected_lookup_address (ifp, to->sin_addr);
2135 if (c != NULL)
2136 ifaddr = c->address;
2137 }
2138 if (ifaddr == NULL)
2139 {
2140 zlog_warn ("cannot find source address for packets to neighbor %s",
2141 inet_ntoa (to->sin_addr));
2142 return;
2143 }
2144 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2145 apply_classful_mask_ipv4 (&ifaddrclass);
2146 subnetted = 0;
2147 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002148 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002149 }
2150
paul718e3742002-12-13 20:15:29 +00002151 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2152 if ((rinfo = rp->info) != NULL)
2153 {
paul727d1042002-12-13 20:50:29 +00002154 /* For RIPv1, if we are subnetted, output subnets in our network */
2155 /* that have the same mask as the output "interface". For other */
2156 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002157
2158 if (version == RIPv1)
2159 {
paul727d1042002-12-13 20:50:29 +00002160 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002161
2162 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002163 zlog_info("RIPv1 mask check, %s/%d considered for output",
2164 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002165
paul727d1042002-12-13 20:50:29 +00002166 if (subnetted &&
2167 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2168 {
2169 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2170 (rp->p.prefixlen != 32))
2171 continue;
2172 }
2173 else
2174 {
2175 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2176 apply_classful_mask_ipv4(&classfull);
2177 if (rp->p.u.prefix4.s_addr != 0 &&
2178 classfull.prefixlen != rp->p.prefixlen)
2179 continue;
2180 }
paul718e3742002-12-13 20:15:29 +00002181 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002182 zlog_info("RIPv1 mask check, %s/%d made it through",
2183 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002184 }
2185 else
2186 p = (struct prefix_ipv4 *) &rp->p;
2187
2188 /* Apply output filters. */
2189 ret = rip_outgoing_filter (p, ri);
2190 if (ret < 0)
2191 continue;
2192
2193 /* Changed route only output. */
2194 if (route_type == rip_changed_route &&
2195 (! (rinfo->flags & RIP_RTF_CHANGED)))
2196 continue;
2197
2198 /* Split horizon. */
2199 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002200 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002201 {
paul42d14d92003-11-17 09:15:18 +00002202 /*
2203 * We perform split horizon for RIP and connected route.
2204 * For rip routes, we want to suppress the route if we would
2205 * end up sending the route back on the interface that we
2206 * learned it from, with a higher metric. For connected routes,
2207 * we suppress the route if the prefix is a subset of the
2208 * source address that we are going to use for the packet
2209 * (in order to handle the case when multiple subnets are
2210 * configured on the same interface).
2211 */
2212 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2213 rinfo->ifindex == ifp->ifindex)
2214 continue;
2215 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002216 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002217 continue;
2218 }
2219
2220 /* Preparation for route-map. */
2221 rinfo->metric_set = 0;
2222 rinfo->nexthop_out.s_addr = 0;
2223 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002224 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002225 rinfo->ifindex_out = ifp->ifindex;
2226
hasso16705132003-05-25 14:49:19 +00002227 /* In order to avoid some local loops,
2228 * if the RIP route has a nexthop via this interface, keep the nexthop,
2229 * otherwise set it to 0. The nexthop should not be propagated
2230 * beyond the local broadcast/multicast area in order
2231 * to avoid an IGP multi-level recursive look-up.
2232 * see (4.4)
2233 */
2234 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002235 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002236
2237 /* Interface route-map */
2238 if (ri->routemap[RIP_FILTER_OUT])
2239 {
2240 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2241 (struct prefix *) p, RMAP_RIP,
2242 rinfo);
2243
2244 if (ret == RMAP_DENYMATCH)
2245 {
2246 if (IS_RIP_DEBUG_PACKET)
2247 zlog_info ("RIP %s/%d is filtered by route-map out",
2248 inet_ntoa (p->prefix), p->prefixlen);
2249 continue;
2250 }
2251 }
paul718e3742002-12-13 20:15:29 +00002252
hasso16705132003-05-25 14:49:19 +00002253 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002254 if (rip->route_map[rinfo->type].name
2255 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2256 {
2257 ret = route_map_apply (rip->route_map[rinfo->type].map,
2258 (struct prefix *)p, RMAP_RIP, rinfo);
2259
2260 if (ret == RMAP_DENYMATCH)
2261 {
2262 if (IS_RIP_DEBUG_PACKET)
2263 zlog_info ("%s/%d is filtered by route-map",
2264 inet_ntoa (p->prefix), p->prefixlen);
2265 continue;
2266 }
2267 }
2268
2269 /* When route-map does not set metric. */
2270 if (! rinfo->metric_set)
2271 {
2272 /* If redistribute metric is set. */
2273 if (rip->route_map[rinfo->type].metric_config
2274 && rinfo->metric != RIP_METRIC_INFINITY)
2275 {
2276 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2277 }
2278 else
2279 {
2280 /* If the route is not connected or localy generated
2281 one, use default-metric value*/
2282 if (rinfo->type != ZEBRA_ROUTE_RIP
2283 && rinfo->type != ZEBRA_ROUTE_CONNECT
2284 && rinfo->metric != RIP_METRIC_INFINITY)
2285 rinfo->metric_out = rip->default_metric;
2286 }
2287 }
2288
2289 /* Apply offset-list */
2290 if (rinfo->metric != RIP_METRIC_INFINITY)
2291 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2292
2293 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2294 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002295
2296 /* Perform split-horizon with poisoned reverse
2297 * for RIP and connected routes.
2298 **/
2299 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002300 /*
2301 * We perform split horizon for RIP and connected route.
2302 * For rip routes, we want to suppress the route if we would
2303 * end up sending the route back on the interface that we
2304 * learned it from, with a higher metric. For connected routes,
2305 * we suppress the route if the prefix is a subset of the
2306 * source address that we are going to use for the packet
2307 * (in order to handle the case when multiple subnets are
2308 * configured on the same interface).
2309 */
2310 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002311 rinfo->ifindex == ifp->ifindex)
2312 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002313 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2314 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2315 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002316 }
2317
paul718e3742002-12-13 20:15:29 +00002318 /* Write RTE to the stream. */
2319 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2320 if (num == rtemax)
2321 {
2322 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2323 rip_auth_md5_set (s, ifp);
2324
2325 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002326 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002327
2328 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2329 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2330 stream_get_endp(s), "SEND");
2331 num = 0;
2332 stream_reset (s);
2333 }
2334 }
2335
2336 /* Flush unwritten RTE. */
2337 if (num != 0)
2338 {
2339 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2340 rip_auth_md5_set (s, ifp);
2341
paul931cd542004-01-23 15:31:42 +00002342 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2343 connected);
paul718e3742002-12-13 20:15:29 +00002344
2345 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2346 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2347 stream_get_endp (s), "SEND");
2348 num = 0;
2349 stream_reset (s);
2350 }
2351
2352 /* Statistics updates. */
2353 ri->sent_updates++;
2354}
2355
2356/* Send RIP packet to the interface. */
2357void
paulcc1131a2003-10-15 23:20:17 +00002358rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002359 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002360{
2361 struct prefix_ipv4 *p;
2362 struct connected *connected;
2363 listnode node;
2364 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002365 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002366
2367 /* When RIP version is 2 and multicast enable interface. */
2368 if (version == RIPv2 && if_is_multicast (ifp))
2369 {
2370 if (IS_RIP_DEBUG_EVENT)
2371 zlog_info ("multicast announce on %s ", ifp->name);
2372
hassocaa6f8a2004-03-03 19:48:48 +00002373 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002374 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002375 return;
2376 }
2377
2378 /* If we can't send multicast packet, send it with unicast. */
2379 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2380 {
2381 for (node = listhead (ifp->connected); node; nextnode (node))
2382 {
2383 connected = getdata (node);
2384
2385 /* Fetch broadcast address or poin-to-point destination
2386 address . */
2387 p = (struct prefix_ipv4 *) connected->destination;
2388
2389 if (p->family == AF_INET)
2390 {
2391 /* Destination address and port setting. */
2392 memset (&to, 0, sizeof (struct sockaddr_in));
2393 to.sin_addr = p->prefix;
2394 to.sin_port = htons (RIP_PORT_DEFAULT);
2395
2396 if (IS_RIP_DEBUG_EVENT)
2397 zlog_info ("%s announce to %s on %s",
2398 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2399 inet_ntoa (to.sin_addr), ifp->name);
2400
paul727d1042002-12-13 20:50:29 +00002401 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002402 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002403 }
2404 }
2405 }
2406}
2407
2408/* Update send to all interface and neighbor. */
2409void
2410rip_update_process (int route_type)
2411{
paulcc1131a2003-10-15 23:20:17 +00002412 listnode node, ifnode;
2413 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002414 struct interface *ifp;
2415 struct rip_interface *ri;
2416 struct route_node *rp;
2417 struct sockaddr_in to;
2418 struct prefix_ipv4 *p;
2419
2420 /* Send RIP update to each interface. */
2421 for (node = listhead (iflist); node; nextnode (node))
2422 {
2423 ifp = getdata (node);
2424
2425 if (if_is_loopback (ifp))
2426 continue;
2427
paul2e3b2e42002-12-13 21:03:13 +00002428 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002429 continue;
2430
2431 /* Fetch RIP interface information. */
2432 ri = ifp->info;
2433
2434 /* When passive interface is specified, suppress announce to the
2435 interface. */
2436 if (ri->passive)
2437 continue;
2438
2439 if (ri->running)
2440 {
2441 if (IS_RIP_DEBUG_EVENT)
2442 {
2443 if (ifp->name)
2444 zlog_info ("SEND UPDATE to %s ifindex %d",
2445 ifp->name, ifp->ifindex);
2446 else
2447 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2448 ifp->ifindex);
2449 }
2450
paulcc1131a2003-10-15 23:20:17 +00002451 /* send update on each connected network */
2452
2453 LIST_LOOP(ifp->connected, connected, ifnode)
2454 {
2455 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002456 int done = 0;
2457 /*
2458 * If there is no version configuration in the interface,
2459 * use rip's version setting.
2460 */
paulf38a4712003-06-07 01:10:00 +00002461 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2462 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002463
2464 ifaddr = (struct prefix_ipv4 *) connected->address;
2465
2466 if (ifaddr->family != AF_INET)
2467 continue;
2468
paul931cd542004-01-23 15:31:42 +00002469 if ((vsend & RIPv1) && !done)
2470 rip_update_interface (ifp, RIPv1, route_type, connected);
2471 if ((vsend & RIPv2) && if_is_multicast(ifp))
2472 rip_update_interface (ifp, RIPv2, route_type, connected);
2473 done = 1;
2474 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2475 break;
2476
paulf38a4712003-06-07 01:10:00 +00002477 }
paul718e3742002-12-13 20:15:29 +00002478 }
2479 }
2480
2481 /* RIP send updates to each neighbor. */
2482 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2483 if (rp->info != NULL)
2484 {
2485 p = (struct prefix_ipv4 *) &rp->p;
2486
2487 ifp = if_lookup_address (p->prefix);
2488 if (! ifp)
2489 {
2490 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2491 inet_ntoa (p->prefix));
2492 continue;
2493 }
2494
2495 /* Set destination address and port */
2496 memset (&to, 0, sizeof (struct sockaddr_in));
2497 to.sin_addr = p->prefix;
2498 to.sin_port = htons (RIP_PORT_DEFAULT);
2499
2500 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002501 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2502 NULL, p);
paul718e3742002-12-13 20:15:29 +00002503 }
2504}
2505
2506/* RIP's periodical timer. */
2507int
2508rip_update (struct thread *t)
2509{
2510 /* Clear timer pointer. */
2511 rip->t_update = NULL;
2512
2513 if (IS_RIP_DEBUG_EVENT)
2514 zlog_info ("update timer fire!");
2515
2516 /* Process update output. */
2517 rip_update_process (rip_all_route);
2518
2519 /* Triggered updates may be suppressed if a regular update is due by
2520 the time the triggered update would be sent. */
2521 if (rip->t_triggered_interval)
2522 {
2523 thread_cancel (rip->t_triggered_interval);
2524 rip->t_triggered_interval = NULL;
2525 }
2526 rip->trigger = 0;
2527
2528 /* Register myself. */
2529 rip_event (RIP_UPDATE_EVENT, 0);
2530
2531 return 0;
2532}
2533
2534/* Walk down the RIP routing table then clear changed flag. */
2535void
2536rip_clear_changed_flag ()
2537{
2538 struct route_node *rp;
2539 struct rip_info *rinfo;
2540
2541 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2542 if ((rinfo = rp->info) != NULL)
2543 if (rinfo->flags & RIP_RTF_CHANGED)
2544 rinfo->flags &= ~RIP_RTF_CHANGED;
2545}
2546
2547/* Triggered update interval timer. */
2548int
2549rip_triggered_interval (struct thread *t)
2550{
2551 int rip_triggered_update (struct thread *);
2552
2553 rip->t_triggered_interval = NULL;
2554
2555 if (rip->trigger)
2556 {
2557 rip->trigger = 0;
2558 rip_triggered_update (t);
2559 }
2560 return 0;
2561}
2562
2563/* Execute triggered update. */
2564int
2565rip_triggered_update (struct thread *t)
2566{
2567 int interval;
2568
2569 /* Clear thred pointer. */
2570 rip->t_triggered_update = NULL;
2571
2572 /* Cancel interval timer. */
2573 if (rip->t_triggered_interval)
2574 {
2575 thread_cancel (rip->t_triggered_interval);
2576 rip->t_triggered_interval = NULL;
2577 }
2578 rip->trigger = 0;
2579
2580 /* Logging triggered update. */
2581 if (IS_RIP_DEBUG_EVENT)
2582 zlog_info ("triggered update!");
2583
2584 /* Split Horizon processing is done when generating triggered
2585 updates as well as normal updates (see section 2.6). */
2586 rip_update_process (rip_changed_route);
2587
2588 /* Once all of the triggered updates have been generated, the route
2589 change flags should be cleared. */
2590 rip_clear_changed_flag ();
2591
2592 /* After a triggered update is sent, a timer should be set for a
2593 random interval between 1 and 5 seconds. If other changes that
2594 would trigger updates occur before the timer expires, a single
2595 update is triggered when the timer expires. */
2596 interval = (random () % 5) + 1;
2597
2598 rip->t_triggered_interval =
2599 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2600
2601 return 0;
2602}
2603
2604/* Withdraw redistributed route. */
2605void
2606rip_redistribute_withdraw (int type)
2607{
2608 struct route_node *rp;
2609 struct rip_info *rinfo;
2610
2611 if (!rip)
2612 return;
2613
2614 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2615 if ((rinfo = rp->info) != NULL)
2616 {
2617 if (rinfo->type == type
2618 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2619 {
2620 /* Perform poisoned reverse. */
2621 rinfo->metric = RIP_METRIC_INFINITY;
2622 RIP_TIMER_ON (rinfo->t_garbage_collect,
2623 rip_garbage_collect, rip->garbage_time);
2624 RIP_TIMER_OFF (rinfo->t_timeout);
2625 rinfo->flags |= RIP_RTF_CHANGED;
2626
hasso16705132003-05-25 14:49:19 +00002627 if (IS_RIP_DEBUG_EVENT) {
2628 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2629
2630 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2631 inet_ntoa(p->prefix), p->prefixlen,
2632 ifindex2ifname(rinfo->ifindex));
2633 }
2634
paul718e3742002-12-13 20:15:29 +00002635 rip_event (RIP_TRIGGERED_UPDATE, 0);
2636 }
2637 }
2638}
2639
2640/* Create new RIP instance and set it to global variable. */
2641int
2642rip_create ()
2643{
2644 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2645 memset (rip, 0, sizeof (struct rip));
2646
2647 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002648 rip->version_send = RI_RIP_VERSION_2;
2649 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002650 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2651 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2652 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2653 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2654
2655 /* Initialize RIP routig table. */
2656 rip->table = route_table_init ();
2657 rip->route = route_table_init ();
2658 rip->neighbor = route_table_init ();
2659
2660 /* Make output stream. */
2661 rip->obuf = stream_new (1500);
2662
2663 /* Make socket. */
2664 rip->sock = rip_create_socket ();
2665 if (rip->sock < 0)
2666 return rip->sock;
2667
2668 /* Create read and timer thread. */
2669 rip_event (RIP_READ, rip->sock);
2670 rip_event (RIP_UPDATE_EVENT, 1);
2671
2672 return 0;
2673}
2674
2675/* Sned RIP request to the destination. */
2676int
2677rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002678 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002679{
2680 struct rte *rte;
2681 struct rip_packet rip_packet;
paulcc1131a2003-10-15 23:20:17 +00002682 listnode node;
paul718e3742002-12-13 20:15:29 +00002683
2684 memset (&rip_packet, 0, sizeof (rip_packet));
2685
2686 rip_packet.command = RIP_REQUEST;
2687 rip_packet.version = version;
2688 rte = rip_packet.rte;
2689 rte->metric = htonl (RIP_METRIC_INFINITY);
2690
paul931cd542004-01-23 15:31:42 +00002691 if (connected)
2692 {
2693 /*
2694 * connected is only sent for ripv1 case, or when
2695 * interface does not support multicast. Caller loops
2696 * over each connected address for this case.
2697 */
paul11dde9c2004-05-31 14:00:00 +00002698 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002699 to, ifp, connected) != sizeof (rip_packet))
2700 return -1;
2701 else
2702 return sizeof (rip_packet);
2703 }
2704
paulcc1131a2003-10-15 23:20:17 +00002705 /* send request on each connected network */
2706 LIST_LOOP(ifp->connected, connected, node)
2707 {
2708 struct prefix_ipv4 *p;
2709
2710 p = (struct prefix_ipv4 *) connected->address;
2711
2712 if (p->family != AF_INET)
2713 continue;
2714
paul11dde9c2004-05-31 14:00:00 +00002715 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002716 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002717 return -1;
2718 }
2719 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002720}
2721
2722int
2723rip_update_jitter (unsigned long time)
2724{
paul239389b2004-05-05 14:09:37 +00002725#define JITTER_BOUND 4
2726 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2727 Given that, we cannot let time be less than JITTER_BOUND seconds.
2728 The RIPv2 RFC says jitter should be small compared to
2729 update_time. We consider 1/JITTER_BOUND to be small.
2730 */
2731
2732 int jitter_input = time;
2733 int jitter;
2734
2735 if (jitter_input < JITTER_BOUND)
2736 jitter_input = JITTER_BOUND;
2737
2738 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2739
2740 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002741}
2742
2743void
2744rip_event (enum rip_event event, int sock)
2745{
2746 int jitter = 0;
2747
2748 switch (event)
2749 {
2750 case RIP_READ:
2751 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2752 break;
2753 case RIP_UPDATE_EVENT:
2754 if (rip->t_update)
2755 {
2756 thread_cancel (rip->t_update);
2757 rip->t_update = NULL;
2758 }
2759 jitter = rip_update_jitter (rip->update_time);
2760 rip->t_update =
2761 thread_add_timer (master, rip_update, NULL,
2762 sock ? 2 : rip->update_time + jitter);
2763 break;
2764 case RIP_TRIGGERED_UPDATE:
2765 if (rip->t_triggered_interval)
2766 rip->trigger = 1;
2767 else if (! rip->t_triggered_update)
2768 rip->t_triggered_update =
2769 thread_add_event (master, rip_triggered_update, NULL, 0);
2770 break;
2771 default:
2772 break;
2773 }
2774}
2775
2776DEFUN (router_rip,
2777 router_rip_cmd,
2778 "router rip",
2779 "Enable a routing process\n"
2780 "Routing Information Protocol (RIP)\n")
2781{
2782 int ret;
2783
2784 /* If rip is not enabled before. */
2785 if (! rip)
2786 {
2787 ret = rip_create ();
2788 if (ret < 0)
2789 {
2790 zlog_info ("Can't create RIP");
2791 return CMD_WARNING;
2792 }
2793 }
2794 vty->node = RIP_NODE;
2795 vty->index = rip;
2796
2797 return CMD_SUCCESS;
2798}
2799
2800DEFUN (no_router_rip,
2801 no_router_rip_cmd,
2802 "no router rip",
2803 NO_STR
2804 "Enable a routing process\n"
2805 "Routing Information Protocol (RIP)\n")
2806{
2807 if (rip)
2808 rip_clean ();
2809 return CMD_SUCCESS;
2810}
2811
2812DEFUN (rip_version,
2813 rip_version_cmd,
2814 "version <1-2>",
2815 "Set routing protocol version\n"
2816 "version\n")
2817{
2818 int version;
2819
2820 version = atoi (argv[0]);
2821 if (version != RIPv1 && version != RIPv2)
2822 {
2823 vty_out (vty, "invalid rip version %d%s", version,
2824 VTY_NEWLINE);
2825 return CMD_WARNING;
2826 }
paulf38a4712003-06-07 01:10:00 +00002827 rip->version_send = version;
2828 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002829
2830 return CMD_SUCCESS;
2831}
2832
2833DEFUN (no_rip_version,
2834 no_rip_version_cmd,
2835 "no version",
2836 NO_STR
2837 "Set routing protocol version\n")
2838{
2839 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002840 rip->version_send = RI_RIP_VERSION_2;
2841 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002842
2843 return CMD_SUCCESS;
2844}
2845
2846ALIAS (no_rip_version,
2847 no_rip_version_val_cmd,
2848 "no version <1-2>",
2849 NO_STR
2850 "Set routing protocol version\n"
2851 "version\n")
2852
2853DEFUN (rip_route,
2854 rip_route_cmd,
2855 "route A.B.C.D/M",
2856 "RIP static route configuration\n"
2857 "IP prefix <network>/<length>\n")
2858{
2859 int ret;
2860 struct prefix_ipv4 p;
2861 struct route_node *node;
2862
2863 ret = str2prefix_ipv4 (argv[0], &p);
2864 if (ret < 0)
2865 {
2866 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2867 return CMD_WARNING;
2868 }
2869 apply_mask_ipv4 (&p);
2870
2871 /* For router rip configuration. */
2872 node = route_node_get (rip->route, (struct prefix *) &p);
2873
2874 if (node->info)
2875 {
2876 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2877 route_unlock_node (node);
2878 return CMD_WARNING;
2879 }
2880
2881 node->info = "static";
2882
2883 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2884
2885 return CMD_SUCCESS;
2886}
2887
2888DEFUN (no_rip_route,
2889 no_rip_route_cmd,
2890 "no route A.B.C.D/M",
2891 NO_STR
2892 "RIP static route configuration\n"
2893 "IP prefix <network>/<length>\n")
2894{
2895 int ret;
2896 struct prefix_ipv4 p;
2897 struct route_node *node;
2898
2899 ret = str2prefix_ipv4 (argv[0], &p);
2900 if (ret < 0)
2901 {
2902 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2903 return CMD_WARNING;
2904 }
2905 apply_mask_ipv4 (&p);
2906
2907 /* For router rip configuration. */
2908 node = route_node_lookup (rip->route, (struct prefix *) &p);
2909 if (! node)
2910 {
2911 vty_out (vty, "Can't find route %s.%s", argv[0],
2912 VTY_NEWLINE);
2913 return CMD_WARNING;
2914 }
2915
2916 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2917 route_unlock_node (node);
2918
2919 node->info = NULL;
2920 route_unlock_node (node);
2921
2922 return CMD_SUCCESS;
2923}
2924
2925void
2926rip_update_default_metric ()
2927{
2928 struct route_node *np;
2929 struct rip_info *rinfo;
2930
2931 for (np = route_top (rip->table); np; np = route_next (np))
2932 if ((rinfo = np->info) != NULL)
2933 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2934 rinfo->metric = rip->default_metric;
2935}
2936
2937DEFUN (rip_default_metric,
2938 rip_default_metric_cmd,
2939 "default-metric <1-16>",
2940 "Set a metric of redistribute routes\n"
2941 "Default metric\n")
2942{
2943 if (rip)
2944 {
2945 rip->default_metric = atoi (argv[0]);
2946 /* rip_update_default_metric (); */
2947 }
2948 return CMD_SUCCESS;
2949}
2950
2951DEFUN (no_rip_default_metric,
2952 no_rip_default_metric_cmd,
2953 "no default-metric",
2954 NO_STR
2955 "Set a metric of redistribute routes\n"
2956 "Default metric\n")
2957{
2958 if (rip)
2959 {
2960 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2961 /* rip_update_default_metric (); */
2962 }
2963 return CMD_SUCCESS;
2964}
2965
2966ALIAS (no_rip_default_metric,
2967 no_rip_default_metric_val_cmd,
2968 "no default-metric <1-16>",
2969 NO_STR
2970 "Set a metric of redistribute routes\n"
2971 "Default metric\n")
2972
2973DEFUN (rip_timers,
2974 rip_timers_cmd,
2975 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
2976 "Adjust routing timers\n"
2977 "Basic routing protocol update timers\n"
2978 "Routing table update timer value in second. Default is 30.\n"
2979 "Routing information timeout timer. Default is 180.\n"
2980 "Garbage collection timer. Default is 120.\n")
2981{
2982 unsigned long update;
2983 unsigned long timeout;
2984 unsigned long garbage;
2985 char *endptr = NULL;
2986 unsigned long RIP_TIMER_MAX = 2147483647;
2987 unsigned long RIP_TIMER_MIN = 5;
2988
2989 update = strtoul (argv[0], &endptr, 10);
2990 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
2991 {
2992 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2993 return CMD_WARNING;
2994 }
2995
2996 timeout = strtoul (argv[1], &endptr, 10);
2997 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
2998 {
2999 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3000 return CMD_WARNING;
3001 }
3002
3003 garbage = strtoul (argv[2], &endptr, 10);
3004 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3005 {
3006 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3007 return CMD_WARNING;
3008 }
3009
3010 /* Set each timer value. */
3011 rip->update_time = update;
3012 rip->timeout_time = timeout;
3013 rip->garbage_time = garbage;
3014
3015 /* Reset update timer thread. */
3016 rip_event (RIP_UPDATE_EVENT, 0);
3017
3018 return CMD_SUCCESS;
3019}
3020
3021DEFUN (no_rip_timers,
3022 no_rip_timers_cmd,
3023 "no timers basic",
3024 NO_STR
3025 "Adjust routing timers\n"
3026 "Basic routing protocol update timers\n")
3027{
3028 /* Set each timer value to the default. */
3029 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3030 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3031 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3032
3033 /* Reset update timer thread. */
3034 rip_event (RIP_UPDATE_EVENT, 0);
3035
3036 return CMD_SUCCESS;
3037}
hasso16705132003-05-25 14:49:19 +00003038
3039ALIAS (no_rip_timers,
3040 no_rip_timers_val_cmd,
3041 "no timers basic <0-65535> <0-65535> <0-65535>",
3042 NO_STR
3043 "Adjust routing timers\n"
3044 "Basic routing protocol update timers\n"
3045 "Routing table update timer value in second. Default is 30.\n"
3046 "Routing information timeout timer. Default is 180.\n"
3047 "Garbage collection timer. Default is 120.\n")
3048
paul718e3742002-12-13 20:15:29 +00003049
3050struct route_table *rip_distance_table;
3051
3052struct rip_distance
3053{
3054 /* Distance value for the IP source prefix. */
3055 u_char distance;
3056
3057 /* Name of the access-list to be matched. */
3058 char *access_list;
3059};
3060
3061struct rip_distance *
3062rip_distance_new ()
3063{
3064 struct rip_distance *new;
3065 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3066 memset (new, 0, sizeof (struct rip_distance));
3067 return new;
3068}
3069
3070void
3071rip_distance_free (struct rip_distance *rdistance)
3072{
3073 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3074}
3075
3076int
3077rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3078 char *access_list_str)
3079{
3080 int ret;
3081 struct prefix_ipv4 p;
3082 u_char distance;
3083 struct route_node *rn;
3084 struct rip_distance *rdistance;
3085
3086 ret = str2prefix_ipv4 (ip_str, &p);
3087 if (ret == 0)
3088 {
3089 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3090 return CMD_WARNING;
3091 }
3092
3093 distance = atoi (distance_str);
3094
3095 /* Get RIP distance node. */
3096 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3097 if (rn->info)
3098 {
3099 rdistance = rn->info;
3100 route_unlock_node (rn);
3101 }
3102 else
3103 {
3104 rdistance = rip_distance_new ();
3105 rn->info = rdistance;
3106 }
3107
3108 /* Set distance value. */
3109 rdistance->distance = distance;
3110
3111 /* Reset access-list configuration. */
3112 if (rdistance->access_list)
3113 {
3114 free (rdistance->access_list);
3115 rdistance->access_list = NULL;
3116 }
3117 if (access_list_str)
3118 rdistance->access_list = strdup (access_list_str);
3119
3120 return CMD_SUCCESS;
3121}
3122
3123int
3124rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3125 char *access_list_str)
3126{
3127 int ret;
3128 struct prefix_ipv4 p;
3129 u_char distance;
3130 struct route_node *rn;
3131 struct rip_distance *rdistance;
3132
3133 ret = str2prefix_ipv4 (ip_str, &p);
3134 if (ret == 0)
3135 {
3136 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3137 return CMD_WARNING;
3138 }
3139
3140 distance = atoi (distance_str);
3141
3142 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3143 if (! rn)
3144 {
3145 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3146 return CMD_WARNING;
3147 }
3148
3149 rdistance = rn->info;
3150
3151 if (rdistance->access_list)
3152 free (rdistance->access_list);
3153 rip_distance_free (rdistance);
3154
3155 rn->info = NULL;
3156 route_unlock_node (rn);
3157 route_unlock_node (rn);
3158
3159 return CMD_SUCCESS;
3160}
3161
3162void
3163rip_distance_reset ()
3164{
3165 struct route_node *rn;
3166 struct rip_distance *rdistance;
3167
3168 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3169 if ((rdistance = rn->info) != NULL)
3170 {
3171 if (rdistance->access_list)
3172 free (rdistance->access_list);
3173 rip_distance_free (rdistance);
3174 rn->info = NULL;
3175 route_unlock_node (rn);
3176 }
3177}
3178
3179/* Apply RIP information to distance method. */
3180u_char
3181rip_distance_apply (struct rip_info *rinfo)
3182{
3183 struct route_node *rn;
3184 struct prefix_ipv4 p;
3185 struct rip_distance *rdistance;
3186 struct access_list *alist;
3187
3188 if (! rip)
3189 return 0;
3190
3191 memset (&p, 0, sizeof (struct prefix_ipv4));
3192 p.family = AF_INET;
3193 p.prefix = rinfo->from;
3194 p.prefixlen = IPV4_MAX_BITLEN;
3195
3196 /* Check source address. */
3197 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3198 if (rn)
3199 {
3200 rdistance = rn->info;
3201 route_unlock_node (rn);
3202
3203 if (rdistance->access_list)
3204 {
3205 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3206 if (alist == NULL)
3207 return 0;
3208 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3209 return 0;
3210
3211 return rdistance->distance;
3212 }
3213 else
3214 return rdistance->distance;
3215 }
3216
3217 if (rip->distance)
3218 return rip->distance;
3219
3220 return 0;
3221}
3222
3223void
3224rip_distance_show (struct vty *vty)
3225{
3226 struct route_node *rn;
3227 struct rip_distance *rdistance;
3228 int header = 1;
3229 char buf[BUFSIZ];
3230
3231 vty_out (vty, " Distance: (default is %d)%s",
3232 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3233 VTY_NEWLINE);
3234
3235 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3236 if ((rdistance = rn->info) != NULL)
3237 {
3238 if (header)
3239 {
3240 vty_out (vty, " Address Distance List%s",
3241 VTY_NEWLINE);
3242 header = 0;
3243 }
3244 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3245 vty_out (vty, " %-20s %4d %s%s",
3246 buf, rdistance->distance,
3247 rdistance->access_list ? rdistance->access_list : "",
3248 VTY_NEWLINE);
3249 }
3250}
3251
3252DEFUN (rip_distance,
3253 rip_distance_cmd,
3254 "distance <1-255>",
3255 "Administrative distance\n"
3256 "Distance value\n")
3257{
3258 rip->distance = atoi (argv[0]);
3259 return CMD_SUCCESS;
3260}
3261
3262DEFUN (no_rip_distance,
3263 no_rip_distance_cmd,
3264 "no distance <1-255>",
3265 NO_STR
3266 "Administrative distance\n"
3267 "Distance value\n")
3268{
3269 rip->distance = 0;
3270 return CMD_SUCCESS;
3271}
3272
3273DEFUN (rip_distance_source,
3274 rip_distance_source_cmd,
3275 "distance <1-255> A.B.C.D/M",
3276 "Administrative distance\n"
3277 "Distance value\n"
3278 "IP source prefix\n")
3279{
3280 rip_distance_set (vty, argv[0], argv[1], NULL);
3281 return CMD_SUCCESS;
3282}
3283
3284DEFUN (no_rip_distance_source,
3285 no_rip_distance_source_cmd,
3286 "no distance <1-255> A.B.C.D/M",
3287 NO_STR
3288 "Administrative distance\n"
3289 "Distance value\n"
3290 "IP source prefix\n")
3291{
3292 rip_distance_unset (vty, argv[0], argv[1], NULL);
3293 return CMD_SUCCESS;
3294}
3295
3296DEFUN (rip_distance_source_access_list,
3297 rip_distance_source_access_list_cmd,
3298 "distance <1-255> A.B.C.D/M WORD",
3299 "Administrative distance\n"
3300 "Distance value\n"
3301 "IP source prefix\n"
3302 "Access list name\n")
3303{
3304 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3305 return CMD_SUCCESS;
3306}
3307
3308DEFUN (no_rip_distance_source_access_list,
3309 no_rip_distance_source_access_list_cmd,
3310 "no distance <1-255> A.B.C.D/M WORD",
3311 NO_STR
3312 "Administrative distance\n"
3313 "Distance value\n"
3314 "IP source prefix\n"
3315 "Access list name\n")
3316{
3317 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3318 return CMD_SUCCESS;
3319}
3320
3321/* Print out routes update time. */
3322void
3323rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3324{
3325 struct timeval timer_now;
3326 time_t clock;
3327 struct tm *tm;
3328#define TIME_BUF 25
3329 char timebuf [TIME_BUF];
3330 struct thread *thread;
3331
3332 gettimeofday (&timer_now, NULL);
3333
3334 if ((thread = rinfo->t_timeout) != NULL)
3335 {
3336 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3337 tm = gmtime (&clock);
3338 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3339 vty_out (vty, "%5s", timebuf);
3340 }
3341 else if ((thread = rinfo->t_garbage_collect) != NULL)
3342 {
3343 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3344 tm = gmtime (&clock);
3345 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3346 vty_out (vty, "%5s", timebuf);
3347 }
3348}
3349
3350char *
3351rip_route_type_print (int sub_type)
3352{
3353 switch (sub_type)
3354 {
3355 case RIP_ROUTE_RTE:
3356 return "n";
3357 case RIP_ROUTE_STATIC:
3358 return "s";
3359 case RIP_ROUTE_DEFAULT:
3360 return "d";
3361 case RIP_ROUTE_REDISTRIBUTE:
3362 return "r";
3363 case RIP_ROUTE_INTERFACE:
3364 return "i";
3365 default:
3366 return "?";
3367 }
3368}
3369
3370DEFUN (show_ip_rip,
3371 show_ip_rip_cmd,
3372 "show ip rip",
3373 SHOW_STR
3374 IP_STR
3375 "Show RIP routes\n")
3376{
3377 struct route_node *np;
3378 struct rip_info *rinfo;
3379
3380 if (! rip)
3381 return CMD_SUCCESS;
3382
hasso16705132003-05-25 14:49:19 +00003383 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3384 "Sub-codes:%s"
3385 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003386 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003387 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003388 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003389
3390 for (np = route_top (rip->table); np; np = route_next (np))
3391 if ((rinfo = np->info) != NULL)
3392 {
3393 int len;
3394
3395 len = vty_out (vty, "%s(%s) %s/%d",
3396 /* np->lock, For debugging. */
3397 route_info[rinfo->type].str,
3398 rip_route_type_print (rinfo->sub_type),
3399 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3400
hassoa1455d82004-03-03 19:36:24 +00003401 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003402
3403 if (len > 0)
3404 vty_out (vty, "%*s", len, " ");
3405
3406 if (rinfo->nexthop.s_addr)
3407 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3408 rinfo->metric);
3409 else
3410 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3411
3412 /* Route which exist in kernel routing table. */
3413 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3414 (rinfo->sub_type == RIP_ROUTE_RTE))
3415 {
3416 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003417 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003418 rip_vty_out_uptime (vty, rinfo);
3419 }
3420 else if (rinfo->metric == RIP_METRIC_INFINITY)
3421 {
3422 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003423 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003424 rip_vty_out_uptime (vty, rinfo);
3425 }
3426 else
hasso16705132003-05-25 14:49:19 +00003427 {
3428 vty_out (vty, "self ");
3429 vty_out (vty, "%3d", rinfo->tag);
3430 }
paul718e3742002-12-13 20:15:29 +00003431
3432 vty_out (vty, "%s", VTY_NEWLINE);
3433 }
3434 return CMD_SUCCESS;
3435}
3436
3437/* Return next event time. */
3438int
3439rip_next_thread_timer (struct thread *thread)
3440{
3441 struct timeval timer_now;
3442
3443 gettimeofday (&timer_now, NULL);
3444
3445 return thread->u.sands.tv_sec - timer_now.tv_sec;
3446}
3447
hasso16705132003-05-25 14:49:19 +00003448/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3449DEFUN (show_ip_rip_status,
3450 show_ip_rip_status_cmd,
3451 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003452 SHOW_STR
3453 IP_STR
hasso16705132003-05-25 14:49:19 +00003454 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003455 "IP routing protocol process parameters and statistics\n")
3456{
3457 listnode node;
3458 struct interface *ifp;
3459 struct rip_interface *ri;
3460 extern struct message ri_version_msg[];
3461 char *send_version;
3462 char *receive_version;
3463
3464 if (! rip)
3465 return CMD_SUCCESS;
3466
3467 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3468 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3469 rip->update_time);
3470 vty_out (vty, " next due in %d seconds%s",
3471 rip_next_thread_timer (rip->t_update),
3472 VTY_NEWLINE);
3473 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3474 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3475 VTY_NEWLINE);
3476
3477 /* Filtering status show. */
3478 config_show_distribute (vty);
3479
3480 /* Default metric information. */
3481 vty_out (vty, " Default redistribution metric is %d%s",
3482 rip->default_metric, VTY_NEWLINE);
3483
3484 /* Redistribute information. */
3485 vty_out (vty, " Redistributing:");
3486 config_write_rip_redistribute (vty, 0);
3487 vty_out (vty, "%s", VTY_NEWLINE);
3488
paulf38a4712003-06-07 01:10:00 +00003489 vty_out (vty, " Default version control: send version %s,",
3490 lookup(ri_version_msg,rip->version_send));
3491 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3492 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3493 else
3494 vty_out (vty, " receive version %s %s",
3495 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003496
3497 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3498
3499 for (node = listhead (iflist); node; node = nextnode (node))
3500 {
3501 ifp = getdata (node);
3502 ri = ifp->info;
3503
3504 if (ri->enable_network || ri->enable_interface)
3505 {
3506 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003507 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003508 else
3509 send_version = lookup (ri_version_msg, ri->ri_send);
3510
3511 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003512 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003513 else
3514 receive_version = lookup (ri_version_msg, ri->ri_receive);
3515
3516 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3517 send_version,
3518 receive_version,
3519 ri->key_chain ? ri->key_chain : "",
3520 VTY_NEWLINE);
3521 }
3522 }
3523
3524 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3525 config_write_rip_network (vty, 0);
3526
paul4aaff3f2003-06-07 01:04:45 +00003527 {
3528 int found_passive = 0;
3529 for (node = listhead (iflist); node; node = nextnode (node))
3530 {
3531 ifp = getdata (node);
3532 ri = ifp->info;
3533
3534 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3535 {
3536 if (!found_passive)
3537 {
3538 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3539 found_passive = 1;
3540 }
3541 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3542 }
3543 }
3544 }
3545
paul718e3742002-12-13 20:15:29 +00003546 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3547 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3548 rip_peer_display (vty);
3549
3550 rip_distance_show (vty);
3551
3552 return CMD_SUCCESS;
3553}
3554
3555/* RIP configuration write function. */
3556int
3557config_write_rip (struct vty *vty)
3558{
3559 int write = 0;
3560 struct route_node *rn;
3561 struct rip_distance *rdistance;
3562
3563 if (rip)
3564 {
3565 /* Router RIP statement. */
3566 vty_out (vty, "router rip%s", VTY_NEWLINE);
3567 write++;
3568
3569 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003570 if (rip->version_send != RI_RIP_VERSION_2
3571 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3572 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003573 VTY_NEWLINE);
3574
3575 /* RIP timer configuration. */
3576 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3577 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3578 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3579 vty_out (vty, " timers basic %lu %lu %lu%s",
3580 rip->update_time,
3581 rip->timeout_time,
3582 rip->garbage_time,
3583 VTY_NEWLINE);
3584
3585 /* Default information configuration. */
3586 if (rip->default_information)
3587 {
3588 if (rip->default_information_route_map)
3589 vty_out (vty, " default-information originate route-map %s%s",
3590 rip->default_information_route_map, VTY_NEWLINE);
3591 else
3592 vty_out (vty, " default-information originate%s",
3593 VTY_NEWLINE);
3594 }
3595
3596 /* Redistribute configuration. */
3597 config_write_rip_redistribute (vty, 1);
3598
3599 /* RIP offset-list configuration. */
3600 config_write_rip_offset_list (vty);
3601
3602 /* RIP enabled network and interface configuration. */
3603 config_write_rip_network (vty, 1);
3604
3605 /* RIP default metric configuration */
3606 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3607 vty_out (vty, " default-metric %d%s",
3608 rip->default_metric, VTY_NEWLINE);
3609
3610 /* Distribute configuration. */
3611 write += config_write_distribute (vty);
3612
hasso16705132003-05-25 14:49:19 +00003613 /* Interface routemap configuration */
3614 write += config_write_if_rmap (vty);
3615
paul718e3742002-12-13 20:15:29 +00003616 /* Distance configuration. */
3617 if (rip->distance)
3618 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3619
3620 /* RIP source IP prefix distance configuration. */
3621 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3622 if ((rdistance = rn->info) != NULL)
3623 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3624 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3625 rdistance->access_list ? rdistance->access_list : "",
3626 VTY_NEWLINE);
3627
3628 /* RIP static route configuration. */
3629 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3630 if (rn->info)
3631 vty_out (vty, " route %s/%d%s",
3632 inet_ntoa (rn->p.u.prefix4),
3633 rn->p.prefixlen,
3634 VTY_NEWLINE);
3635
3636 }
3637 return write;
3638}
3639
3640/* RIP node structure. */
3641struct cmd_node rip_node =
3642{
3643 RIP_NODE,
3644 "%s(config-router)# ",
3645 1
3646};
3647
3648/* Distribute-list update functions. */
3649void
3650rip_distribute_update (struct distribute *dist)
3651{
3652 struct interface *ifp;
3653 struct rip_interface *ri;
3654 struct access_list *alist;
3655 struct prefix_list *plist;
3656
3657 if (! dist->ifname)
3658 return;
3659
3660 ifp = if_lookup_by_name (dist->ifname);
3661 if (ifp == NULL)
3662 return;
3663
3664 ri = ifp->info;
3665
3666 if (dist->list[DISTRIBUTE_IN])
3667 {
3668 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3669 if (alist)
3670 ri->list[RIP_FILTER_IN] = alist;
3671 else
3672 ri->list[RIP_FILTER_IN] = NULL;
3673 }
3674 else
3675 ri->list[RIP_FILTER_IN] = NULL;
3676
3677 if (dist->list[DISTRIBUTE_OUT])
3678 {
3679 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3680 if (alist)
3681 ri->list[RIP_FILTER_OUT] = alist;
3682 else
3683 ri->list[RIP_FILTER_OUT] = NULL;
3684 }
3685 else
3686 ri->list[RIP_FILTER_OUT] = NULL;
3687
3688 if (dist->prefix[DISTRIBUTE_IN])
3689 {
3690 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3691 if (plist)
3692 ri->prefix[RIP_FILTER_IN] = plist;
3693 else
3694 ri->prefix[RIP_FILTER_IN] = NULL;
3695 }
3696 else
3697 ri->prefix[RIP_FILTER_IN] = NULL;
3698
3699 if (dist->prefix[DISTRIBUTE_OUT])
3700 {
3701 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3702 if (plist)
3703 ri->prefix[RIP_FILTER_OUT] = plist;
3704 else
3705 ri->prefix[RIP_FILTER_OUT] = NULL;
3706 }
3707 else
3708 ri->prefix[RIP_FILTER_OUT] = NULL;
3709}
3710
3711void
3712rip_distribute_update_interface (struct interface *ifp)
3713{
3714 struct distribute *dist;
3715
3716 dist = distribute_lookup (ifp->name);
3717 if (dist)
3718 rip_distribute_update (dist);
3719}
3720
3721/* Update all interface's distribute list. */
3722void
3723rip_distribute_update_all ()
3724{
3725 struct interface *ifp;
3726 listnode node;
3727
3728 for (node = listhead (iflist); node; nextnode (node))
3729 {
3730 ifp = getdata (node);
3731 rip_distribute_update_interface (ifp);
3732 }
3733}
paul11dde9c2004-05-31 14:00:00 +00003734/* ARGSUSED */
3735void
3736rip_distribute_update_all_wrapper(struct access_list *notused)
3737{
3738 rip_distribute_update_all();
3739}
paul718e3742002-12-13 20:15:29 +00003740
3741/* Delete all added rip route. */
3742void
3743rip_clean ()
3744{
3745 int i;
3746 struct route_node *rp;
3747 struct rip_info *rinfo;
3748
3749 if (rip)
3750 {
3751 /* Clear RIP routes */
3752 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3753 if ((rinfo = rp->info) != NULL)
3754 {
3755 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3756 rinfo->sub_type == RIP_ROUTE_RTE)
3757 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3758 &rinfo->nexthop, rinfo->metric);
3759
3760 RIP_TIMER_OFF (rinfo->t_timeout);
3761 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3762
3763 rp->info = NULL;
3764 route_unlock_node (rp);
3765
3766 rip_info_free (rinfo);
3767 }
3768
3769 /* Cancel RIP related timers. */
3770 RIP_TIMER_OFF (rip->t_update);
3771 RIP_TIMER_OFF (rip->t_triggered_update);
3772 RIP_TIMER_OFF (rip->t_triggered_interval);
3773
3774 /* Cancel read thread. */
3775 if (rip->t_read)
3776 {
3777 thread_cancel (rip->t_read);
3778 rip->t_read = NULL;
3779 }
3780
3781 /* Close RIP socket. */
3782 if (rip->sock >= 0)
3783 {
3784 close (rip->sock);
3785 rip->sock = -1;
3786 }
3787
3788 /* Static RIP route configuration. */
3789 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3790 if (rp->info)
3791 {
3792 rp->info = NULL;
3793 route_unlock_node (rp);
3794 }
3795
3796 /* RIP neighbor configuration. */
3797 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3798 if (rp->info)
3799 {
3800 rp->info = NULL;
3801 route_unlock_node (rp);
3802 }
3803
3804 /* Redistribute related clear. */
3805 if (rip->default_information_route_map)
3806 free (rip->default_information_route_map);
3807
3808 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3809 if (rip->route_map[i].name)
3810 free (rip->route_map[i].name);
3811
3812 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3813 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3814 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3815
3816 XFREE (MTYPE_RIP, rip);
3817 rip = NULL;
3818 }
3819
3820 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003821 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003822 rip_offset_clean ();
3823 rip_interface_clean ();
3824 rip_distance_reset ();
3825 rip_redistribute_clean ();
3826}
3827
3828/* Reset all values to the default settings. */
3829void
3830rip_reset ()
3831{
3832 /* Reset global counters. */
3833 rip_global_route_changes = 0;
3834 rip_global_queries = 0;
3835
3836 /* Call ripd related reset functions. */
3837 rip_debug_reset ();
3838 rip_route_map_reset ();
3839
3840 /* Call library reset functions. */
3841 vty_reset ();
3842 access_list_reset ();
3843 prefix_list_reset ();
3844
3845 distribute_list_reset ();
3846
3847 rip_interface_reset ();
3848 rip_distance_reset ();
3849
3850 rip_zclient_reset ();
3851}
3852
hasso16705132003-05-25 14:49:19 +00003853void
3854rip_if_rmap_update (struct if_rmap *if_rmap)
3855{
3856 struct interface *ifp;
3857 struct rip_interface *ri;
3858 struct route_map *rmap;
3859
3860 ifp = if_lookup_by_name (if_rmap->ifname);
3861 if (ifp == NULL)
3862 return;
3863
3864 ri = ifp->info;
3865
3866 if (if_rmap->routemap[IF_RMAP_IN])
3867 {
3868 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3869 if (rmap)
3870 ri->routemap[IF_RMAP_IN] = rmap;
3871 else
3872 ri->routemap[IF_RMAP_IN] = NULL;
3873 }
3874 else
3875 ri->routemap[RIP_FILTER_IN] = NULL;
3876
3877 if (if_rmap->routemap[IF_RMAP_OUT])
3878 {
3879 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3880 if (rmap)
3881 ri->routemap[IF_RMAP_OUT] = rmap;
3882 else
3883 ri->routemap[IF_RMAP_OUT] = NULL;
3884 }
3885 else
3886 ri->routemap[RIP_FILTER_OUT] = NULL;
3887}
3888
3889void
3890rip_if_rmap_update_interface (struct interface *ifp)
3891{
3892 struct if_rmap *if_rmap;
3893
3894 if_rmap = if_rmap_lookup (ifp->name);
3895 if (if_rmap)
3896 rip_if_rmap_update (if_rmap);
3897}
3898
3899void
3900rip_routemap_update_redistribute (void)
3901{
3902 int i;
3903
3904 if (rip)
3905 {
3906 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3907 {
3908 if (rip->route_map[i].name)
3909 rip->route_map[i].map =
3910 route_map_lookup_by_name (rip->route_map[i].name);
3911 }
3912 }
3913}
3914
paul11dde9c2004-05-31 14:00:00 +00003915/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003916void
paul11dde9c2004-05-31 14:00:00 +00003917rip_routemap_update (char *notused)
hasso16705132003-05-25 14:49:19 +00003918{
3919 struct interface *ifp;
3920 listnode node;
3921
3922 for (node = listhead (iflist); node; nextnode (node))
3923 {
3924 ifp = getdata (node);
3925 rip_if_rmap_update_interface (ifp);
3926 }
3927
3928 rip_routemap_update_redistribute ();
3929}
3930
paul718e3742002-12-13 20:15:29 +00003931/* Allocate new rip structure and set default value. */
3932void
3933rip_init ()
3934{
3935 /* Randomize for triggered update random(). */
3936 srand (time (NULL));
3937
3938 /* Install top nodes. */
3939 install_node (&rip_node, config_write_rip);
3940
3941 /* Install rip commands. */
3942 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003943 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003944 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003945 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003946 install_element (CONFIG_NODE, &router_rip_cmd);
3947 install_element (CONFIG_NODE, &no_router_rip_cmd);
3948
3949 install_default (RIP_NODE);
3950 install_element (RIP_NODE, &rip_version_cmd);
3951 install_element (RIP_NODE, &no_rip_version_cmd);
3952 install_element (RIP_NODE, &no_rip_version_val_cmd);
3953 install_element (RIP_NODE, &rip_default_metric_cmd);
3954 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3955 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3956 install_element (RIP_NODE, &rip_timers_cmd);
3957 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003958 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003959 install_element (RIP_NODE, &rip_route_cmd);
3960 install_element (RIP_NODE, &no_rip_route_cmd);
3961 install_element (RIP_NODE, &rip_distance_cmd);
3962 install_element (RIP_NODE, &no_rip_distance_cmd);
3963 install_element (RIP_NODE, &rip_distance_source_cmd);
3964 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3965 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3966 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3967
3968 /* Debug related init. */
3969 rip_debug_init ();
3970
paul718e3742002-12-13 20:15:29 +00003971 /* SNMP init. */
3972#ifdef HAVE_SNMP
3973 rip_snmp_init ();
3974#endif /* HAVE_SNMP */
3975
3976 /* Access list install. */
3977 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00003978 access_list_add_hook (rip_distribute_update_all_wrapper);
3979 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00003980
3981 /* Prefix list initialize.*/
3982 prefix_list_init ();
3983 prefix_list_add_hook (rip_distribute_update_all);
3984 prefix_list_delete_hook (rip_distribute_update_all);
3985
3986 /* Distribute list install. */
3987 distribute_list_init (RIP_NODE);
3988 distribute_list_add_hook (rip_distribute_update);
3989 distribute_list_delete_hook (rip_distribute_update);
3990
hasso16705132003-05-25 14:49:19 +00003991 /* Route-map */
3992 rip_route_map_init ();
3993 rip_offset_init ();
3994
3995 route_map_add_hook (rip_routemap_update);
3996 route_map_delete_hook (rip_routemap_update);
3997
3998 if_rmap_init (RIP_NODE);
3999 if_rmap_hook_add (rip_if_rmap_update);
4000 if_rmap_hook_delete (rip_if_rmap_update);
4001
paul718e3742002-12-13 20:15:29 +00004002 /* Distance control. */
4003 rip_distance_table = route_table_init ();
4004}