blob: 691482272946ccae71cb5e033be2c7dd6a0c18bd [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
paulca5e5162004-06-06 22:06:33 +0000704 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000705 {
paulca5e5162004-06-06 22:06:33 +0000706 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000707 {
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 }
paulca5e5162004-06-06 22:06:33 +0000713 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000714 {
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"
paulca5e5162004-06-06 22:06:33 +0000722 " Auth Data len %d",
723 ntohs (md5->packet_len), md5->keyid,
724 md5->auth_len);
725 zlog_info (" Sequence Number %ld",
726 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000727 }
paulca5e5162004-06-06 22:06:33 +0000728 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000729 {
730 p = (u_char *)&rte->prefix;
731
732 zlog_info (" family 0x%X type %d (MD5 data)",
733 ntohs (rte->family), ntohs (rte->tag));
734 zlog_info (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
735 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000736 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
737 p[7], p[9], p[10], p[11], p[12], p[13],
738 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000739 }
740 else
741 {
742 zlog_info (" family 0x%X type %d (Unknown auth type)",
743 ntohs (rte->family), ntohs (rte->tag));
744 }
745 }
746 else
747 zlog_info (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000748 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
749 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
750 BUFSIZ), ntohs (rte->family),
751 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000752 }
753 else
754 {
755 zlog_info (" %s family %d tag %d metric %ld",
756 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
757 ntohs (rte->family), ntohs (rte->tag),
758 (u_long)ntohl (rte->metric));
759 }
760 }
761}
762
763/* Check if the destination address is valid (unicast; not net 0
764 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
765 check net 0 because we accept default route. */
766int
767rip_destination_check (struct in_addr addr)
768{
769 u_int32_t destination;
770
771 /* Convert to host byte order. */
772 destination = ntohl (addr.s_addr);
773
774 if (IPV4_NET127 (destination))
775 return 0;
776
777 /* Net 0 may match to the default route. */
778 if (IPV4_NET0 (destination) && destination != 0)
779 return 0;
780
781 /* Unicast address must belong to class A, B, C. */
782 if (IN_CLASSA (destination))
783 return 1;
784 if (IN_CLASSB (destination))
785 return 1;
786 if (IN_CLASSC (destination))
787 return 1;
788
789 return 0;
790}
791
792/* RIP version 2 authentication. */
793int
794rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
795 struct interface *ifp)
796{
797 struct rip_interface *ri;
798 char *auth_str;
799
800 if (IS_RIP_DEBUG_EVENT)
801 zlog_info ("RIPv2 simple password authentication from %s",
802 inet_ntoa (from->sin_addr));
803
804 ri = ifp->info;
805
806 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000807 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000808 return 0;
809
810 /* Simple password authentication. */
811 if (ri->auth_str)
812 {
813 auth_str = (char *) &rte->prefix;
814
815 if (strncmp (auth_str, ri->auth_str, 16) == 0)
816 return 1;
817 }
818 if (ri->key_chain)
819 {
820 struct keychain *keychain;
821 struct key *key;
822
823 keychain = keychain_lookup (ri->key_chain);
824 if (keychain == NULL)
825 return 0;
826
827 key = key_match_for_accept (keychain, (char *) &rte->prefix);
828 if (key)
829 return 1;
830 }
831 return 0;
832}
833
834/* RIP version 2 authentication with MD5. */
835int
836rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000837 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000838{
839 struct rip_interface *ri;
840 struct rip_md5_info *md5;
841 struct rip_md5_data *md5data;
842 struct keychain *keychain;
843 struct key *key;
844 struct md5_ctx ctx;
845 u_char pdigest[RIP_AUTH_MD5_SIZE];
846 u_char digest[RIP_AUTH_MD5_SIZE];
847 u_int16_t packet_len;
848 char *auth_str = NULL;
849
850 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000851 zlog_info ("RIPv2 MD5 authentication from %s",
852 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000853
854 ri = ifp->info;
855 md5 = (struct rip_md5_info *) &packet->rte;
856
857 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000858 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000859 return 0;
860
paulca5e5162004-06-06 22:06:33 +0000861 /* If the authentication length is less than 16, then it must be wrong for
862 * any interpretation of rfc2082. Some implementations also interpret
863 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000864 */
paulca5e5162004-06-06 22:06:33 +0000865 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
866 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000867 {
868 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000869 zlog_warn ("RIPv2 MD5 authentication, strange authentication "
870 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000871 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000872 }
paul718e3742002-12-13 20:15:29 +0000873
paulca5e5162004-06-06 22:06:33 +0000874 /* grab and verify check packet length */
875 packet_len = ntohs (md5->packet_len);
876
877 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
878 {
879 if (IS_RIP_DEBUG_EVENT)
880 zlog_warn ("RIPv2 MD5 authentication, packet length field %d "
881 "greater than received length %d!",
882 md5->packet_len, length);
883 return 0;
884 }
885
886 /* retrieve authentication data */
887 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
888
paul718e3742002-12-13 20:15:29 +0000889 if (ri->key_chain)
890 {
891 keychain = keychain_lookup (ri->key_chain);
892 if (keychain == NULL)
893 return 0;
894
895 key = key_lookup_for_accept (keychain, md5->keyid);
896 if (key == NULL)
897 return 0;
898
899 auth_str = key->string;
900 }
901
902 if (ri->auth_str)
903 auth_str = ri->auth_str;
904
905 if (! auth_str)
906 return 0;
907
908 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000909
910 /* Save digest to pdigest. */
911 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
912
913 /* Overwrite digest by my secret. */
914 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000915 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000916
917 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000918 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000919 &ctx);
paul718e3742002-12-13 20:15:29 +0000920 md5_finish_ctx (&ctx, digest);
921
922 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
923 return packet_len;
924 else
925 return 0;
926}
927
928void
929rip_auth_md5_set (struct stream *s, struct interface *ifp)
930{
931 struct rip_interface *ri;
932 struct keychain *keychain = NULL;
933 struct key *key = NULL;
934 unsigned long len;
935 struct md5_ctx ctx;
936 unsigned char secret[RIP_AUTH_MD5_SIZE];
937 unsigned char digest[RIP_AUTH_MD5_SIZE];
938 char *auth_str = NULL;
939
940 ri = ifp->info;
941
942 /* Make it sure this interface is configured as MD5
943 authentication. */
944 if (ri->auth_type != RIP_AUTH_MD5)
945 return;
946
947 /* Lookup key chain. */
948 if (ri->key_chain)
949 {
950 keychain = keychain_lookup (ri->key_chain);
951 if (keychain == NULL)
952 return;
953
954 /* Lookup key. */
955 key = key_lookup_for_send (keychain);
956 if (key == NULL)
957 return;
958
959 auth_str = key->string;
960 }
961
962 if (ri->auth_str)
963 auth_str = ri->auth_str;
964
965 if (! auth_str)
966 return;
967
968 /* Get packet length. */
969 len = s->putp;
970
971 /* Check packet length. */
972 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
973 {
974 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
975 return;
976 }
977
978 /* Move RTE. */
979 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
980 s->data + RIP_HEADER_SIZE,
981 len - RIP_HEADER_SIZE);
982
983 /* Set pointer to authentication header. */
984 stream_set_putp (s, RIP_HEADER_SIZE);
985 len += RIP_RTE_SIZE;
986
987 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000988 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000989 stream_putw (s, RIP_AUTH_MD5);
990
991 /* RIP-2 Packet length. Actual value is filled in
992 rip_auth_md5_set(). */
993 stream_putw (s, len);
994
995 /* Key ID. */
996 if (key)
997 stream_putc (s, key->index % 256);
998 else
999 stream_putc (s, 1);
1000
paulca5e5162004-06-06 22:06:33 +00001001 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1002 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1003 * to be configurable.
1004 */
1005 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001006
1007 /* Sequence Number (non-decreasing). */
1008 /* RFC2080: The value used in the sequence number is
1009 arbitrary, but two suggestions are the time of the
1010 message's creation or a simple message counter. */
1011 stream_putl (s, time (NULL));
1012
1013 /* Reserved field must be zero. */
1014 stream_putl (s, 0);
1015 stream_putl (s, 0);
1016
1017 /* Set pointer to authentication data. */
1018 stream_set_putp (s, len);
1019
1020 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001021 stream_putw (s, RIP_FAMILY_AUTH);
1022 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001023
1024 /* Generate a digest for the RIP packet. */
1025 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001026 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001027 md5_init_ctx (&ctx);
1028 md5_process_bytes (s->data, s->endp, &ctx);
1029 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1030 md5_finish_ctx (&ctx, digest);
1031
1032 /* Copy the digest to the packet. */
1033 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1034}
1035
1036/* RIP routing information. */
1037void
1038rip_response_process (struct rip_packet *packet, int size,
1039 struct sockaddr_in *from, struct interface *ifp)
1040{
1041 caddr_t lim;
1042 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001043 struct prefix_ipv4 ifaddr;
1044 struct prefix_ipv4 ifaddrclass;
1045 struct connected *c;
1046 int subnetted;
paul718e3742002-12-13 20:15:29 +00001047
paul727d1042002-12-13 20:50:29 +00001048 /* We don't know yet. */
1049 subnetted = -1;
1050
paul718e3742002-12-13 20:15:29 +00001051 /* The Response must be ignored if it is not from the RIP
1052 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001053 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001054 {
1055 zlog_info ("response doesn't come from RIP port: %d",
1056 from->sin_port);
1057 rip_peer_bad_packet (from);
1058 return;
1059 }
1060
1061 /* The datagram's IPv4 source address should be checked to see
1062 whether the datagram is from a valid neighbor; the source of the
1063 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001064 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001065 {
1066 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1067 inet_ntoa (from->sin_addr));
1068 rip_peer_bad_packet (from);
1069 return;
1070 }
1071
1072 /* It is also worth checking to see whether the response is from one
1073 of the router's own addresses. */
1074
1075 ; /* Alredy done in rip_read () */
1076
1077 /* Update RIP peer. */
1078 rip_peer_update (from, packet->version);
1079
1080 /* Set RTE pointer. */
1081 rte = packet->rte;
1082
1083 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1084 {
1085 /* RIPv2 authentication check. */
1086 /* If the Address Family Identifier of the first (and only the
1087 first) entry in the message is 0xFFFF, then the remainder of
1088 the entry contains the authentication. */
1089 /* If the packet gets here it means authentication enabled */
1090 /* Check is done in rip_read(). So, just skipping it */
1091 if (packet->version == RIPv2 &&
1092 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001093 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001094 continue;
1095
paulca5e5162004-06-06 22:06:33 +00001096 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001097 {
1098 /* Address family check. RIP only supports AF_INET. */
1099 zlog_info ("Unsupported family %d from %s.",
1100 ntohs (rte->family), inet_ntoa (from->sin_addr));
1101 continue;
1102 }
1103
1104 /* - is the destination address valid (e.g., unicast; not net 0
1105 or 127) */
1106 if (! rip_destination_check (rte->prefix))
1107 {
1108 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1109 rip_peer_bad_route (from);
1110 continue;
1111 }
1112
1113 /* Convert metric value to host byte order. */
1114 rte->metric = ntohl (rte->metric);
1115
1116 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1117 if (! (rte->metric >= 1 && rte->metric <= 16))
1118 {
1119 zlog_info ("Route's metric is not in the 1-16 range.");
1120 rip_peer_bad_route (from);
1121 continue;
1122 }
1123
1124 /* RIPv1 does not have nexthop value. */
1125 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1126 {
1127 zlog_info ("RIPv1 packet with nexthop value %s",
1128 inet_ntoa (rte->nexthop));
1129 rip_peer_bad_route (from);
1130 continue;
1131 }
1132
1133 /* That is, if the provided information is ignored, a possibly
1134 sub-optimal, but absolutely valid, route may be taken. If
1135 the received Next Hop is not directly reachable, it should be
1136 treated as 0.0.0.0. */
1137 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1138 {
1139 u_int32_t addrval;
1140
1141 /* Multicast address check. */
1142 addrval = ntohl (rte->nexthop.s_addr);
1143 if (IN_CLASSD (addrval))
1144 {
1145 zlog_info ("Nexthop %s is multicast address, skip this rte",
1146 inet_ntoa (rte->nexthop));
1147 continue;
1148 }
1149
1150 if (! if_lookup_address (rte->nexthop))
1151 {
1152 struct route_node *rn;
1153 struct rip_info *rinfo;
1154
1155 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1156
1157 if (rn)
1158 {
1159 rinfo = rn->info;
1160
1161 if (rinfo->type == ZEBRA_ROUTE_RIP
1162 && rinfo->sub_type == RIP_ROUTE_RTE)
1163 {
1164 if (IS_RIP_DEBUG_EVENT)
1165 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1166 rte->nexthop = rinfo->from;
1167 }
1168 else
1169 {
1170 if (IS_RIP_DEBUG_EVENT)
1171 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1172 rte->nexthop.s_addr = 0;
1173 }
1174
1175 route_unlock_node (rn);
1176 }
1177 else
1178 {
1179 if (IS_RIP_DEBUG_EVENT)
1180 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1181 rte->nexthop.s_addr = 0;
1182 }
1183
1184 }
1185 }
1186
1187 /* For RIPv1, there won't be a valid netmask.
1188
1189 This is a best guess at the masks. If everyone was using old
1190 Ciscos before the 'ip subnet zero' option, it would be almost
1191 right too :-)
1192
1193 Cisco summarize ripv1 advertisments to the classful boundary
1194 (/16 for class B's) except when the RIP packet does to inside
1195 the classful network in question. */
1196
1197 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1198 || (packet->version == RIPv2
1199 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1200 {
1201 u_int32_t destination;
1202
paul727d1042002-12-13 20:50:29 +00001203 if (subnetted == -1)
1204 {
1205 c = connected_lookup_address (ifp, from->sin_addr);
1206 if (c != NULL)
1207 {
1208 memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
1209 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1210 apply_classful_mask_ipv4 (&ifaddrclass);
1211 subnetted = 0;
1212 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1213 subnetted = 1;
1214 }
1215 }
1216
paul718e3742002-12-13 20:15:29 +00001217 destination = ntohl (rte->prefix.s_addr);
1218
paul727d1042002-12-13 20:50:29 +00001219 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001220 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001221 else if (IN_CLASSB (destination))
1222 masklen2ip (16, &rte->mask);
1223 else if (IN_CLASSC (destination))
1224 masklen2ip (24, &rte->mask);
1225
1226 if (subnetted == 1)
1227 masklen2ip (ifaddrclass.prefixlen,
1228 (struct in_addr *) &destination);
1229 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1230 ifaddrclass.prefix.s_addr))
1231 {
1232 masklen2ip (ifaddr.prefixlen, &rte->mask);
1233 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1234 masklen2ip (32, &rte->mask);
1235 if (IS_RIP_DEBUG_EVENT)
1236 zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
1237 }
1238 else
1239 {
1240 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1241 continue;
1242 }
1243
1244 if (IS_RIP_DEBUG_EVENT)
1245 {
1246 zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
1247 zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001248 }
1249 }
1250
1251 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1252 ignore the entry. */
1253 if ((packet->version == RIPv2)
1254 && (rte->mask.s_addr != 0)
1255 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1256 {
1257 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1258 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1259 rip_peer_bad_route (from);
1260 continue;
1261 }
1262
1263 /* Default route's netmask is ignored. */
1264 if (packet->version == RIPv2
1265 && (rte->prefix.s_addr == 0)
1266 && (rte->mask.s_addr != 0))
1267 {
1268 if (IS_RIP_DEBUG_EVENT)
1269 zlog_info ("Default route with non-zero netmask. Set zero to netmask");
1270 rte->mask.s_addr = 0;
1271 }
1272
1273 /* Routing table updates. */
1274 rip_rte_process (rte, from, ifp);
1275 }
1276}
1277
1278/* RIP packet send to destination address. */
1279int
paul11dde9c2004-05-31 14:00:00 +00001280rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
paul931cd542004-01-23 15:31:42 +00001281 struct interface *ifp, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00001282{
paul931cd542004-01-23 15:31:42 +00001283 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001284 struct sockaddr_in sin;
paul718e3742002-12-13 20:15:29 +00001285
paul931cd542004-01-23 15:31:42 +00001286 if (IS_RIP_DEBUG_PACKET)
1287 {
1288 char dst[20];
1289 if (to)
1290 {
1291 strcpy(dst, inet_ntoa(to->sin_addr));
1292 }
1293 else
1294 {
1295 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1296 strcpy(dst, inet_ntoa(sin.sin_addr));
1297 }
1298 zlog_info("rip_send_packet %s > %s (%s)",
hassoda9c9a22004-03-18 02:40:55 +00001299 (connected ? inet_ntoa(connected->address->u.prefix4) : ""),
1300 dst, ifp->name);
paul931cd542004-01-23 15:31:42 +00001301 }
hassoda9c9a22004-03-18 02:40:55 +00001302 if (connected && connected->flags & ZEBRA_IFA_SECONDARY)
paul931cd542004-01-23 15:31:42 +00001303 {
1304 /*
1305 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1306 * with multiple addresses on the same subnet: the first address
1307 * on the subnet is configured "primary", and all subsequent addresses
1308 * on that subnet are treated as "secondary" addresses.
1309 * In order to avoid routing-table bloat on other rip listeners,
1310 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1311 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1312 * flag is set, we would end up sending a packet for a "secondary"
1313 * source address on non-linux systems.
1314 */
1315 if (IS_RIP_DEBUG_PACKET)
1316 zlog_info("duplicate dropped");
1317 return 0;
1318 }
1319
paul718e3742002-12-13 20:15:29 +00001320 /* Make destination address. */
1321 memset (&sin, 0, sizeof (struct sockaddr_in));
1322 sin.sin_family = AF_INET;
1323#ifdef HAVE_SIN_LEN
1324 sin.sin_len = sizeof (struct sockaddr_in);
1325#endif /* HAVE_SIN_LEN */
1326
1327 /* When destination is specified, use it's port and address. */
1328 if (to)
1329 {
paul718e3742002-12-13 20:15:29 +00001330 sin.sin_port = to->sin_port;
1331 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001332 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001333 }
1334 else
1335 {
paul718e3742002-12-13 20:15:29 +00001336
1337 sin.sin_port = htons (RIP_PORT_DEFAULT);
1338 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1339
paul931cd542004-01-23 15:31:42 +00001340 /*
1341 * we have to open a new socket for each packet because this
1342 * is the most portable way to bind to a different source
1343 * ipv4 address for each packet.
1344 */
1345 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1346 if (send_sock < 0)
1347 {
1348 zlog_warn("rip_send_packet could not create socket %s",
1349 strerror(errno));
1350 return -1;
1351 }
1352 sockopt_broadcast (send_sock);
1353 sockopt_reuseaddr (send_sock);
1354 sockopt_reuseport (send_sock);
1355#ifdef RIP_RECVMSG
1356 setsockopt_pktinfo (send_sock);
1357#endif /* RIP_RECVMSG */
1358 rip_interface_multicast_set(send_sock, connected, if_is_pointopoint(ifp));
paul718e3742002-12-13 20:15:29 +00001359 }
1360
paul931cd542004-01-23 15:31:42 +00001361 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001362 sizeof (struct sockaddr_in));
1363
1364 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001365 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1366 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001367
1368 if (ret < 0)
1369 zlog_warn ("can't send packet : %s", strerror (errno));
1370
paul931cd542004-01-23 15:31:42 +00001371 if (!to)
1372 close(send_sock);
1373
paul718e3742002-12-13 20:15:29 +00001374 return ret;
1375}
1376
1377/* Add redistributed route to RIP table. */
1378void
1379rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1380 unsigned int ifindex, struct in_addr *nexthop)
1381{
1382 int ret;
1383 struct route_node *rp;
1384 struct rip_info *rinfo;
1385
1386 /* Redistribute route */
1387 ret = rip_destination_check (p->prefix);
1388 if (! ret)
1389 return;
1390
1391 rp = route_node_get (rip->table, (struct prefix *) p);
1392
1393 rinfo = rp->info;
1394
1395 if (rinfo)
1396 {
1397 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1398 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1399 && rinfo->metric != RIP_METRIC_INFINITY)
1400 {
1401 route_unlock_node (rp);
1402 return;
1403 }
1404
1405 /* Manually configured RIP route check. */
1406 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001407 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1408 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001409 {
hasso16705132003-05-25 14:49:19 +00001410 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1411 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001412 {
1413 route_unlock_node (rp);
1414 return;
1415 }
1416 }
1417
1418 RIP_TIMER_OFF (rinfo->t_timeout);
1419 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1420
1421 if (rip_route_rte (rinfo))
1422 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1423 rinfo->metric);
1424 rp->info = NULL;
1425 rip_info_free (rinfo);
1426
1427 route_unlock_node (rp);
1428 }
1429
1430 rinfo = rip_info_new ();
1431
1432 rinfo->type = type;
1433 rinfo->sub_type = sub_type;
1434 rinfo->ifindex = ifindex;
1435 rinfo->metric = 1;
1436 rinfo->rp = rp;
1437
1438 if (nexthop)
1439 rinfo->nexthop = *nexthop;
1440
1441 rinfo->flags |= RIP_RTF_FIB;
1442 rp->info = rinfo;
1443
1444 rinfo->flags |= RIP_RTF_CHANGED;
1445
hasso16705132003-05-25 14:49:19 +00001446 if (IS_RIP_DEBUG_EVENT) {
1447 if (!nexthop)
1448 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1449 inet_ntoa(p->prefix), p->prefixlen,
1450 ifindex2ifname(ifindex));
1451 else
1452 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1453 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1454 ifindex2ifname(ifindex));
1455 }
1456
1457
paul718e3742002-12-13 20:15:29 +00001458 rip_event (RIP_TRIGGERED_UPDATE, 0);
1459}
1460
1461/* Delete redistributed route from RIP table. */
1462void
1463rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1464 unsigned int ifindex)
1465{
1466 int ret;
1467 struct route_node *rp;
1468 struct rip_info *rinfo;
1469
1470 ret = rip_destination_check (p->prefix);
1471 if (! ret)
1472 return;
1473
1474 rp = route_node_lookup (rip->table, (struct prefix *) p);
1475 if (rp)
1476 {
1477 rinfo = rp->info;
1478
1479 if (rinfo != NULL
1480 && rinfo->type == type
1481 && rinfo->sub_type == sub_type
1482 && rinfo->ifindex == ifindex)
1483 {
1484 /* Perform poisoned reverse. */
1485 rinfo->metric = RIP_METRIC_INFINITY;
1486 RIP_TIMER_ON (rinfo->t_garbage_collect,
1487 rip_garbage_collect, rip->garbage_time);
1488 RIP_TIMER_OFF (rinfo->t_timeout);
1489 rinfo->flags |= RIP_RTF_CHANGED;
1490
hasso16705132003-05-25 14:49:19 +00001491 if (IS_RIP_DEBUG_EVENT)
1492 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1493 inet_ntoa(p->prefix), p->prefixlen,
1494 ifindex2ifname(ifindex));
1495
paul718e3742002-12-13 20:15:29 +00001496 rip_event (RIP_TRIGGERED_UPDATE, 0);
1497 }
1498 }
1499}
1500
1501/* Response to request called from rip_read ().*/
1502void
1503rip_request_process (struct rip_packet *packet, int size,
1504 struct sockaddr_in *from, struct interface *ifp)
1505{
1506 caddr_t lim;
1507 struct rte *rte;
1508 struct prefix_ipv4 p;
1509 struct route_node *rp;
1510 struct rip_info *rinfo;
1511 struct rip_interface *ri;
1512
hasso16705132003-05-25 14:49:19 +00001513 /* Does not reponse to the requests on the loopback interfaces */
1514 if (if_is_loopback (ifp))
1515 return;
1516
hasso429a0f82004-02-22 23:42:22 +00001517 /* Check RIP process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001518 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001519 if (! ri->running)
1520 return;
paul718e3742002-12-13 20:15:29 +00001521
1522 /* When passive interface is specified, suppress responses */
1523 if (ri->passive)
1524 return;
1525
1526 /* RIP peer update. */
1527 rip_peer_update (from, packet->version);
1528
1529 lim = ((caddr_t) packet) + size;
1530 rte = packet->rte;
1531
1532 /* The Request is processed entry by entry. If there are no
1533 entries, no response is given. */
1534 if (lim == (caddr_t) rte)
1535 return;
1536
1537 /* There is one special case. If there is exactly one entry in the
1538 request, and it has an address family identifier of zero and a
1539 metric of infinity (i.e., 16), then this is a request to send the
1540 entire routing table. */
1541 if (lim == ((caddr_t) (rte + 1)) &&
1542 ntohs (rte->family) == 0 &&
1543 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1544 {
paulcc1131a2003-10-15 23:20:17 +00001545 struct prefix_ipv4 saddr;
1546
1547 /* saddr will be used for determining which routes to split-horizon.
1548 Since the source address we'll pick will be on the same subnet as the
1549 destination, for the purpose of split-horizoning, we'll
1550 pretend that "from" is our source address. */
1551 saddr.family = AF_INET;
1552 saddr.prefixlen = IPV4_MAX_BITLEN;
1553 saddr.prefix = from->sin_addr;
1554
paul718e3742002-12-13 20:15:29 +00001555 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001556 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001557 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001558 }
1559 else
1560 {
1561 /* Examine the list of RTEs in the Request one by one. For each
1562 entry, look up the destination in the router's routing
1563 database and, if there is a route, put that route's metric in
1564 the metric field of the RTE. If there is no explicit route
1565 to the specified destination, put infinity in the metric
1566 field. Once all the entries have been filled in, change the
1567 command from Request to Response and send the datagram back
1568 to the requestor. */
1569 p.family = AF_INET;
1570
1571 for (; ((caddr_t) rte) < lim; rte++)
1572 {
1573 p.prefix = rte->prefix;
1574 p.prefixlen = ip_masklen (rte->mask);
1575 apply_mask_ipv4 (&p);
1576
1577 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1578 if (rp)
1579 {
1580 rinfo = rp->info;
1581 rte->metric = htonl (rinfo->metric);
1582 route_unlock_node (rp);
1583 }
1584 else
1585 rte->metric = htonl (RIP_METRIC_INFINITY);
1586 }
1587 packet->command = RIP_RESPONSE;
1588
paul11dde9c2004-05-31 14:00:00 +00001589 rip_send_packet ((u_char *)packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001590 }
1591 rip_global_queries++;
1592}
1593
1594#if RIP_RECVMSG
1595/* Set IPv6 packet info to the socket. */
1596static int
1597setsockopt_pktinfo (int sock)
1598{
1599 int ret;
1600 int val = 1;
1601
1602 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1603 if (ret < 0)
1604 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1605 return ret;
1606}
1607
1608/* Read RIP packet by recvmsg function. */
1609int
1610rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1611 int *ifindex)
1612{
1613 int ret;
1614 struct msghdr msg;
1615 struct iovec iov;
1616 struct cmsghdr *ptr;
1617 char adata[1024];
1618
1619 msg.msg_name = (void *) from;
1620 msg.msg_namelen = sizeof (struct sockaddr_in);
1621 msg.msg_iov = &iov;
1622 msg.msg_iovlen = 1;
1623 msg.msg_control = (void *) adata;
1624 msg.msg_controllen = sizeof adata;
1625 iov.iov_base = buf;
1626 iov.iov_len = size;
1627
1628 ret = recvmsg (sock, &msg, 0);
1629 if (ret < 0)
1630 return ret;
1631
1632 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1633 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1634 {
1635 struct in_pktinfo *pktinfo;
1636 int i;
1637
1638 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1639 i = pktinfo->ipi_ifindex;
1640 }
1641 return ret;
1642}
1643
1644/* RIP packet read function. */
1645int
1646rip_read_new (struct thread *t)
1647{
1648 int ret;
1649 int sock;
1650 char buf[RIP_PACKET_MAXSIZ];
1651 struct sockaddr_in from;
1652 unsigned int ifindex;
1653
1654 /* Fetch socket then register myself. */
1655 sock = THREAD_FD (t);
1656 rip_event (RIP_READ, sock);
1657
1658 /* Read RIP packet. */
1659 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1660 if (ret < 0)
1661 {
1662 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1663 return ret;
1664 }
1665
1666 return ret;
1667}
1668#endif /* RIP_RECVMSG */
1669
1670/* First entry point of RIP packet. */
1671int
1672rip_read (struct thread *t)
1673{
1674 int sock;
1675 int ret;
1676 int rtenum;
1677 union rip_buf rip_buf;
1678 struct rip_packet *packet;
1679 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001680 int len;
1681 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001682 struct interface *ifp;
1683 struct rip_interface *ri;
1684
1685 /* Fetch socket then register myself. */
1686 sock = THREAD_FD (t);
1687 rip->t_read = NULL;
1688
1689 /* Add myself to tne next event */
1690 rip_event (RIP_READ, sock);
1691
1692 /* RIPd manages only IPv4. */
1693 memset (&from, 0, sizeof (struct sockaddr_in));
1694 fromlen = sizeof (struct sockaddr_in);
1695
1696 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1697 (struct sockaddr *) &from, &fromlen);
1698 if (len < 0)
1699 {
1700 zlog_info ("recvfrom failed: %s", strerror (errno));
1701 return len;
1702 }
1703
1704 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001705 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001706 {
1707 if (IS_RIP_DEBUG_PACKET)
1708 zlog_warn ("ignore packet comes from myself");
1709 return -1;
1710 }
1711
1712 /* Which interface is this packet comes from. */
1713 ifp = if_lookup_address (from.sin_addr);
1714
1715 /* RIP packet received */
1716 if (IS_RIP_DEBUG_EVENT)
1717 zlog_info ("RECV packet from %s port %d on %s",
1718 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1719 ifp ? ifp->name : "unknown");
1720
1721 /* If this packet come from unknown interface, ignore it. */
1722 if (ifp == NULL)
1723 {
1724 zlog_info ("packet comes from unknown interface");
1725 return -1;
1726 }
1727
1728 /* Packet length check. */
1729 if (len < RIP_PACKET_MINSIZ)
1730 {
1731 zlog_warn ("packet size %d is smaller than minimum size %d",
1732 len, RIP_PACKET_MINSIZ);
1733 rip_peer_bad_packet (&from);
1734 return len;
1735 }
1736 if (len > RIP_PACKET_MAXSIZ)
1737 {
1738 zlog_warn ("packet size %d is larger than max size %d",
1739 len, RIP_PACKET_MAXSIZ);
1740 rip_peer_bad_packet (&from);
1741 return len;
1742 }
1743
1744 /* Packet alignment check. */
1745 if ((len - RIP_PACKET_MINSIZ) % 20)
1746 {
1747 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1748 rip_peer_bad_packet (&from);
1749 return len;
1750 }
1751
1752 /* Set RTE number. */
1753 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1754
1755 /* For easy to handle. */
1756 packet = &rip_buf.rip_packet;
1757
1758 /* RIP version check. */
1759 if (packet->version == 0)
1760 {
1761 zlog_info ("version 0 with command %d received.", packet->command);
1762 rip_peer_bad_packet (&from);
1763 return -1;
1764 }
1765
1766 /* Dump RIP packet. */
1767 if (IS_RIP_DEBUG_RECV)
1768 rip_packet_dump (packet, len, "RECV");
1769
1770 /* RIP version adjust. This code should rethink now. RFC1058 says
1771 that "Version 1 implementations are to ignore this extra data and
1772 process only the fields specified in this document.". So RIPv3
1773 packet should be treated as RIPv1 ignoring must be zero field. */
1774 if (packet->version > RIPv2)
1775 packet->version = RIPv2;
1776
1777 /* Is RIP running or is this RIP neighbor ?*/
1778 ri = ifp->info;
1779 if (! ri->running && ! rip_neighbor_lookup (&from))
1780 {
1781 if (IS_RIP_DEBUG_EVENT)
1782 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1783 rip_peer_bad_packet (&from);
1784 return -1;
1785 }
1786
1787 /* RIP Version check. */
1788 if (packet->command == RIP_RESPONSE)
1789 {
paulf38a4712003-06-07 01:10:00 +00001790 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1791 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001792 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001793 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001794 {
1795 if (IS_RIP_DEBUG_PACKET)
1796 zlog_warn (" packet's v%d doesn't fit to if version spec",
1797 packet->version);
1798 rip_peer_bad_packet (&from);
1799 return -1;
1800 }
1801 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001802 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001803 {
1804 if (IS_RIP_DEBUG_PACKET)
1805 zlog_warn (" packet's v%d doesn't fit to if version spec",
1806 packet->version);
1807 rip_peer_bad_packet (&from);
1808 return -1;
1809 }
paul718e3742002-12-13 20:15:29 +00001810 }
1811
1812 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1813 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1814 accepted; authenticated RIP-2 messages shall be discarded. */
1815
1816 if ((ri->auth_type == RIP_NO_AUTH)
1817 && rtenum
paulca5e5162004-06-06 22:06:33 +00001818 && (packet->version == RIPv2)
1819 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001820 {
1821 if (IS_RIP_DEBUG_EVENT)
1822 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1823 packet->version);
1824 rip_peer_bad_packet (&from);
1825 return -1;
1826 }
1827
1828 /* If the router is configured to authenticate RIP-2 messages, then
1829 RIP-1 messages and RIP-2 messages which pass authentication
1830 testing shall be accepted; unauthenticated and failed
1831 authentication RIP-2 messages shall be discarded. For maximum
1832 security, RIP-1 messages should be ignored when authentication is
1833 in use (see section 4.1); otherwise, the routing information from
1834 authenticated messages will be propagated by RIP-1 routers in an
1835 unauthenticated manner. */
1836
1837 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001838 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001839 {
1840 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001841 if (packet->version == RIPv1
1842 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001843 {
1844 if (IS_RIP_DEBUG_PACKET)
paulca5e5162004-06-06 22:06:33 +00001845 zlog_warn
1846 ("packet RIPv%d is dropped because authentication enabled",
1847 packet->version);
paul718e3742002-12-13 20:15:29 +00001848 rip_peer_bad_packet (&from);
1849 return -1;
1850 }
1851
1852 /* Check RIPv2 authentication. */
1853 if (packet->version == RIPv2)
1854 {
paulca5e5162004-06-06 22:06:33 +00001855 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001856 {
paulca5e5162004-06-06 22:06:33 +00001857 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001858 {
1859 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1860 if (! ret)
1861 {
1862 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001863 zlog_warn
1864 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001865 rip_peer_bad_packet (&from);
1866 return -1;
1867 }
1868 else
1869 {
1870 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001871 zlog_info
1872 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001873 }
1874 }
paulca5e5162004-06-06 22:06:33 +00001875 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001876 {
paulca5e5162004-06-06 22:06:33 +00001877 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001878 if (! ret)
1879 {
1880 if (IS_RIP_DEBUG_EVENT)
1881 zlog_warn ("RIPv2 MD5 authentication failed");
1882 rip_peer_bad_packet (&from);
1883 return -1;
1884 }
1885 else
1886 {
1887 if (IS_RIP_DEBUG_EVENT)
1888 zlog_info ("RIPv2 MD5 authentication success");
1889 }
1890 /* Reset RIP packet length to trim MD5 data. */
1891 len = ret;
1892 }
1893 else
1894 {
1895 if (IS_RIP_DEBUG_EVENT)
1896 zlog_warn ("Unknown authentication type %d",
1897 ntohs (packet->rte->tag));
1898 rip_peer_bad_packet (&from);
1899 return -1;
1900 }
1901 }
1902 else
1903 {
1904 /* There is no authentication in the packet. */
1905 if (ri->auth_str || ri->key_chain)
1906 {
1907 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001908 zlog_warn
1909 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001910 rip_peer_bad_packet (&from);
1911 return -1;
1912 }
1913 }
1914 }
1915 }
1916
1917 /* Process each command. */
1918 switch (packet->command)
1919 {
1920 case RIP_RESPONSE:
1921 rip_response_process (packet, len, &from, ifp);
1922 break;
1923 case RIP_REQUEST:
1924 case RIP_POLL:
1925 rip_request_process (packet, len, &from, ifp);
1926 break;
1927 case RIP_TRACEON:
1928 case RIP_TRACEOFF:
1929 zlog_info ("Obsolete command %s received, please sent it to routed",
1930 lookup (rip_msg, packet->command));
1931 rip_peer_bad_packet (&from);
1932 break;
1933 case RIP_POLL_ENTRY:
1934 zlog_info ("Obsolete command %s received",
1935 lookup (rip_msg, packet->command));
1936 rip_peer_bad_packet (&from);
1937 break;
1938 default:
1939 zlog_info ("Unknown RIP command %d received", packet->command);
1940 rip_peer_bad_packet (&from);
1941 break;
1942 }
1943
1944 return len;
1945}
1946
1947/* Make socket for RIP protocol. */
1948int
1949rip_create_socket ()
1950{
1951 int ret;
1952 int sock;
1953 struct sockaddr_in addr;
1954 struct servent *sp;
1955
1956 memset (&addr, 0, sizeof (struct sockaddr_in));
1957
1958 /* Set RIP port. */
1959 sp = getservbyname ("router", "udp");
1960 if (sp)
1961 addr.sin_port = sp->s_port;
1962 else
1963 addr.sin_port = htons (RIP_PORT_DEFAULT);
1964
1965 /* Address shoud be any address. */
1966 addr.sin_family = AF_INET;
1967 addr.sin_addr.s_addr = INADDR_ANY;
1968
1969 /* Make datagram socket. */
1970 sock = socket (AF_INET, SOCK_DGRAM, 0);
1971 if (sock < 0)
1972 {
1973 perror ("socket");
1974 exit (1);
1975 }
1976
1977 sockopt_broadcast (sock);
1978 sockopt_reuseaddr (sock);
1979 sockopt_reuseport (sock);
1980#ifdef RIP_RECVMSG
1981 setsockopt_pktinfo (sock);
1982#endif /* RIP_RECVMSG */
1983
pauledd7c242003-06-04 13:59:38 +00001984 if (ripd_privs.change (ZPRIVS_RAISE))
1985 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001986 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1987 if (ret < 0)
1988 {
1989 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001990 if (ripd_privs.change (ZPRIVS_LOWER))
1991 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001992 return ret;
1993 }
pauledd7c242003-06-04 13:59:38 +00001994 if (ripd_privs.change (ZPRIVS_LOWER))
1995 zlog_err ("rip_create_socket: could not lower privs");
1996
paul718e3742002-12-13 20:15:29 +00001997 return sock;
1998}
1999
2000/* Write routing table entry to the stream and return next index of
2001 the routing table entry in the stream. */
2002int
2003rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2004 u_char version, struct rip_info *rinfo, struct interface *ifp)
2005{
2006 struct in_addr mask;
2007 struct rip_interface *ri;
2008
2009 /* RIP packet header. */
2010 if (num == 0)
2011 {
2012 stream_putc (s, RIP_RESPONSE);
2013 stream_putc (s, version);
2014 stream_putw (s, 0);
2015
2016 /* In case of we need RIPv2 authentication. */
2017 if (version == RIPv2 && ifp)
2018 {
2019 ri = ifp->info;
2020
2021 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2022 {
2023 if (ri->auth_str)
2024 {
paulca5e5162004-06-06 22:06:33 +00002025 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002026 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2027
2028 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002029 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002030 stream_set_putp (s, s->putp + 16);
2031
2032 num++;
2033 }
2034 if (ri->key_chain)
2035 {
2036 struct keychain *keychain;
2037 struct key *key;
2038
2039 keychain = keychain_lookup (ri->key_chain);
2040
2041 if (keychain)
2042 {
2043 key = key_lookup_for_send (keychain);
2044
2045 if (key)
2046 {
paulca5e5162004-06-06 22:06:33 +00002047 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002048 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2049
2050 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002051 strncpy ((char *)(s->data + s->putp),
2052 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002053 stream_set_putp (s, s->putp + 16);
2054
2055 num++;
2056 }
2057 }
2058 }
2059 }
2060 }
2061 }
2062
2063 /* Write routing table entry. */
2064 if (version == RIPv1)
2065 {
2066 stream_putw (s, AF_INET);
2067 stream_putw (s, 0);
2068 stream_put_ipv4 (s, p->prefix.s_addr);
2069 stream_put_ipv4 (s, 0);
2070 stream_put_ipv4 (s, 0);
2071 stream_putl (s, rinfo->metric_out);
2072 }
2073 else
2074 {
2075 masklen2ip (p->prefixlen, &mask);
2076
2077 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002078 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002079 stream_put_ipv4 (s, p->prefix.s_addr);
2080 stream_put_ipv4 (s, mask.s_addr);
2081 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2082 stream_putl (s, rinfo->metric_out);
2083 }
2084
2085 return ++num;
2086}
2087
2088/* Send update to the ifp or spcified neighbor. */
2089void
paul727d1042002-12-13 20:50:29 +00002090rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002091 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002092 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002093{
2094 int ret;
2095 struct stream *s;
2096 struct route_node *rp;
2097 struct rip_info *rinfo;
2098 struct rip_interface *ri;
2099 struct prefix_ipv4 *p;
2100 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002101 struct prefix_ipv4 ifaddrclass;
2102 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002103 int num;
2104 int rtemax;
paul01d09082003-06-08 21:22:18 +00002105 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002106
2107 /* Logging output event. */
2108 if (IS_RIP_DEBUG_EVENT)
2109 {
2110 if (to)
2111 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2112 else
2113 zlog_info ("update routes on interface %s ifindex %d",
2114 ifp->name, ifp->ifindex);
2115 }
2116
2117 /* Set output stream. */
2118 s = rip->obuf;
2119
2120 /* Reset stream and RTE counter. */
2121 stream_reset (s);
2122 num = 0;
2123 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2124
2125 /* Get RIP interface. */
2126 ri = ifp->info;
2127
2128 /* If output interface is in simple password authentication mode, we
2129 need space for authentication data. */
2130 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2131 rtemax -= 1;
2132
2133 /* If output interface is in MD5 authentication mode, we need space
2134 for authentication header and data. */
2135 if (ri->auth_type == RIP_AUTH_MD5)
2136 rtemax -= 2;
2137
2138 /* If output interface is in simple password authentication mode
2139 and string or keychain is specified we need space for auth. data */
2140 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2141 {
2142 if (ri->key_chain)
2143 {
2144 struct keychain *keychain;
2145
2146 keychain = keychain_lookup (ri->key_chain);
2147 if (keychain)
2148 if (key_lookup_for_send (keychain))
2149 rtemax -=1;
2150 }
2151 else
2152 if (ri->auth_str)
2153 rtemax -=1;
2154 }
2155
paul727d1042002-12-13 20:50:29 +00002156 if (version == RIPv1)
2157 {
2158 if (ifaddr == NULL)
2159 {
2160 c = connected_lookup_address (ifp, to->sin_addr);
2161 if (c != NULL)
2162 ifaddr = c->address;
2163 }
2164 if (ifaddr == NULL)
2165 {
2166 zlog_warn ("cannot find source address for packets to neighbor %s",
2167 inet_ntoa (to->sin_addr));
2168 return;
2169 }
2170 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2171 apply_classful_mask_ipv4 (&ifaddrclass);
2172 subnetted = 0;
2173 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002174 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002175 }
2176
paul718e3742002-12-13 20:15:29 +00002177 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2178 if ((rinfo = rp->info) != NULL)
2179 {
paul727d1042002-12-13 20:50:29 +00002180 /* For RIPv1, if we are subnetted, output subnets in our network */
2181 /* that have the same mask as the output "interface". For other */
2182 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002183
2184 if (version == RIPv1)
2185 {
paul727d1042002-12-13 20:50:29 +00002186 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002187
2188 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002189 zlog_info("RIPv1 mask check, %s/%d considered for output",
2190 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002191
paul727d1042002-12-13 20:50:29 +00002192 if (subnetted &&
2193 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2194 {
2195 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2196 (rp->p.prefixlen != 32))
2197 continue;
2198 }
2199 else
2200 {
2201 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2202 apply_classful_mask_ipv4(&classfull);
2203 if (rp->p.u.prefix4.s_addr != 0 &&
2204 classfull.prefixlen != rp->p.prefixlen)
2205 continue;
2206 }
paul718e3742002-12-13 20:15:29 +00002207 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002208 zlog_info("RIPv1 mask check, %s/%d made it through",
2209 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002210 }
2211 else
2212 p = (struct prefix_ipv4 *) &rp->p;
2213
2214 /* Apply output filters. */
2215 ret = rip_outgoing_filter (p, ri);
2216 if (ret < 0)
2217 continue;
2218
2219 /* Changed route only output. */
2220 if (route_type == rip_changed_route &&
2221 (! (rinfo->flags & RIP_RTF_CHANGED)))
2222 continue;
2223
2224 /* Split horizon. */
2225 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002226 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002227 {
paul42d14d92003-11-17 09:15:18 +00002228 /*
2229 * We perform split horizon for RIP and connected route.
2230 * For rip routes, we want to suppress the route if we would
2231 * end up sending the route back on the interface that we
2232 * learned it from, with a higher metric. For connected routes,
2233 * we suppress the route if the prefix is a subset of the
2234 * source address that we are going to use for the packet
2235 * (in order to handle the case when multiple subnets are
2236 * configured on the same interface).
2237 */
2238 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2239 rinfo->ifindex == ifp->ifindex)
2240 continue;
2241 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002242 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002243 continue;
2244 }
2245
2246 /* Preparation for route-map. */
2247 rinfo->metric_set = 0;
2248 rinfo->nexthop_out.s_addr = 0;
2249 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002250 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002251 rinfo->ifindex_out = ifp->ifindex;
2252
hasso16705132003-05-25 14:49:19 +00002253 /* In order to avoid some local loops,
2254 * if the RIP route has a nexthop via this interface, keep the nexthop,
2255 * otherwise set it to 0. The nexthop should not be propagated
2256 * beyond the local broadcast/multicast area in order
2257 * to avoid an IGP multi-level recursive look-up.
2258 * see (4.4)
2259 */
2260 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002261 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002262
2263 /* Interface route-map */
2264 if (ri->routemap[RIP_FILTER_OUT])
2265 {
2266 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2267 (struct prefix *) p, RMAP_RIP,
2268 rinfo);
2269
2270 if (ret == RMAP_DENYMATCH)
2271 {
2272 if (IS_RIP_DEBUG_PACKET)
2273 zlog_info ("RIP %s/%d is filtered by route-map out",
2274 inet_ntoa (p->prefix), p->prefixlen);
2275 continue;
2276 }
2277 }
paul718e3742002-12-13 20:15:29 +00002278
hasso16705132003-05-25 14:49:19 +00002279 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002280 if (rip->route_map[rinfo->type].name
2281 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2282 {
2283 ret = route_map_apply (rip->route_map[rinfo->type].map,
2284 (struct prefix *)p, RMAP_RIP, rinfo);
2285
2286 if (ret == RMAP_DENYMATCH)
2287 {
2288 if (IS_RIP_DEBUG_PACKET)
2289 zlog_info ("%s/%d is filtered by route-map",
2290 inet_ntoa (p->prefix), p->prefixlen);
2291 continue;
2292 }
2293 }
2294
2295 /* When route-map does not set metric. */
2296 if (! rinfo->metric_set)
2297 {
2298 /* If redistribute metric is set. */
2299 if (rip->route_map[rinfo->type].metric_config
2300 && rinfo->metric != RIP_METRIC_INFINITY)
2301 {
2302 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2303 }
2304 else
2305 {
2306 /* If the route is not connected or localy generated
2307 one, use default-metric value*/
2308 if (rinfo->type != ZEBRA_ROUTE_RIP
2309 && rinfo->type != ZEBRA_ROUTE_CONNECT
2310 && rinfo->metric != RIP_METRIC_INFINITY)
2311 rinfo->metric_out = rip->default_metric;
2312 }
2313 }
2314
2315 /* Apply offset-list */
2316 if (rinfo->metric != RIP_METRIC_INFINITY)
2317 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2318
2319 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2320 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002321
2322 /* Perform split-horizon with poisoned reverse
2323 * for RIP and connected routes.
2324 **/
2325 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002326 /*
2327 * We perform split horizon for RIP and connected route.
2328 * For rip routes, we want to suppress the route if we would
2329 * end up sending the route back on the interface that we
2330 * learned it from, with a higher metric. For connected routes,
2331 * we suppress the route if the prefix is a subset of the
2332 * source address that we are going to use for the packet
2333 * (in order to handle the case when multiple subnets are
2334 * configured on the same interface).
2335 */
2336 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002337 rinfo->ifindex == ifp->ifindex)
2338 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002339 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2340 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2341 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002342 }
2343
paul718e3742002-12-13 20:15:29 +00002344 /* Write RTE to the stream. */
2345 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2346 if (num == rtemax)
2347 {
2348 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2349 rip_auth_md5_set (s, ifp);
2350
2351 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002352 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002353
2354 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2355 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2356 stream_get_endp(s), "SEND");
2357 num = 0;
2358 stream_reset (s);
2359 }
2360 }
2361
2362 /* Flush unwritten RTE. */
2363 if (num != 0)
2364 {
2365 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2366 rip_auth_md5_set (s, ifp);
2367
paul931cd542004-01-23 15:31:42 +00002368 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2369 connected);
paul718e3742002-12-13 20:15:29 +00002370
2371 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2372 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2373 stream_get_endp (s), "SEND");
2374 num = 0;
2375 stream_reset (s);
2376 }
2377
2378 /* Statistics updates. */
2379 ri->sent_updates++;
2380}
2381
2382/* Send RIP packet to the interface. */
2383void
paulcc1131a2003-10-15 23:20:17 +00002384rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002385 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002386{
2387 struct prefix_ipv4 *p;
2388 struct connected *connected;
2389 listnode node;
2390 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002391 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002392
2393 /* When RIP version is 2 and multicast enable interface. */
2394 if (version == RIPv2 && if_is_multicast (ifp))
2395 {
2396 if (IS_RIP_DEBUG_EVENT)
2397 zlog_info ("multicast announce on %s ", ifp->name);
2398
hassocaa6f8a2004-03-03 19:48:48 +00002399 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002400 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002401 return;
2402 }
2403
2404 /* If we can't send multicast packet, send it with unicast. */
2405 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2406 {
2407 for (node = listhead (ifp->connected); node; nextnode (node))
2408 {
2409 connected = getdata (node);
2410
2411 /* Fetch broadcast address or poin-to-point destination
2412 address . */
2413 p = (struct prefix_ipv4 *) connected->destination;
2414
2415 if (p->family == AF_INET)
2416 {
2417 /* Destination address and port setting. */
2418 memset (&to, 0, sizeof (struct sockaddr_in));
2419 to.sin_addr = p->prefix;
2420 to.sin_port = htons (RIP_PORT_DEFAULT);
2421
2422 if (IS_RIP_DEBUG_EVENT)
2423 zlog_info ("%s announce to %s on %s",
2424 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2425 inet_ntoa (to.sin_addr), ifp->name);
2426
paul727d1042002-12-13 20:50:29 +00002427 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002428 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002429 }
2430 }
2431 }
2432}
2433
2434/* Update send to all interface and neighbor. */
2435void
2436rip_update_process (int route_type)
2437{
paulcc1131a2003-10-15 23:20:17 +00002438 listnode node, ifnode;
2439 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002440 struct interface *ifp;
2441 struct rip_interface *ri;
2442 struct route_node *rp;
2443 struct sockaddr_in to;
2444 struct prefix_ipv4 *p;
2445
2446 /* Send RIP update to each interface. */
2447 for (node = listhead (iflist); node; nextnode (node))
2448 {
2449 ifp = getdata (node);
2450
2451 if (if_is_loopback (ifp))
2452 continue;
2453
paul2e3b2e42002-12-13 21:03:13 +00002454 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002455 continue;
2456
2457 /* Fetch RIP interface information. */
2458 ri = ifp->info;
2459
2460 /* When passive interface is specified, suppress announce to the
2461 interface. */
2462 if (ri->passive)
2463 continue;
2464
2465 if (ri->running)
2466 {
2467 if (IS_RIP_DEBUG_EVENT)
2468 {
2469 if (ifp->name)
2470 zlog_info ("SEND UPDATE to %s ifindex %d",
2471 ifp->name, ifp->ifindex);
2472 else
2473 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2474 ifp->ifindex);
2475 }
2476
paulcc1131a2003-10-15 23:20:17 +00002477 /* send update on each connected network */
2478
2479 LIST_LOOP(ifp->connected, connected, ifnode)
2480 {
2481 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002482 int done = 0;
2483 /*
2484 * If there is no version configuration in the interface,
2485 * use rip's version setting.
2486 */
paulf38a4712003-06-07 01:10:00 +00002487 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2488 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002489
2490 ifaddr = (struct prefix_ipv4 *) connected->address;
2491
2492 if (ifaddr->family != AF_INET)
2493 continue;
2494
paul931cd542004-01-23 15:31:42 +00002495 if ((vsend & RIPv1) && !done)
2496 rip_update_interface (ifp, RIPv1, route_type, connected);
2497 if ((vsend & RIPv2) && if_is_multicast(ifp))
2498 rip_update_interface (ifp, RIPv2, route_type, connected);
2499 done = 1;
2500 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2501 break;
2502
paulf38a4712003-06-07 01:10:00 +00002503 }
paul718e3742002-12-13 20:15:29 +00002504 }
2505 }
2506
2507 /* RIP send updates to each neighbor. */
2508 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2509 if (rp->info != NULL)
2510 {
2511 p = (struct prefix_ipv4 *) &rp->p;
2512
2513 ifp = if_lookup_address (p->prefix);
2514 if (! ifp)
2515 {
2516 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2517 inet_ntoa (p->prefix));
2518 continue;
2519 }
2520
2521 /* Set destination address and port */
2522 memset (&to, 0, sizeof (struct sockaddr_in));
2523 to.sin_addr = p->prefix;
2524 to.sin_port = htons (RIP_PORT_DEFAULT);
2525
2526 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002527 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2528 NULL, p);
paul718e3742002-12-13 20:15:29 +00002529 }
2530}
2531
2532/* RIP's periodical timer. */
2533int
2534rip_update (struct thread *t)
2535{
2536 /* Clear timer pointer. */
2537 rip->t_update = NULL;
2538
2539 if (IS_RIP_DEBUG_EVENT)
2540 zlog_info ("update timer fire!");
2541
2542 /* Process update output. */
2543 rip_update_process (rip_all_route);
2544
2545 /* Triggered updates may be suppressed if a regular update is due by
2546 the time the triggered update would be sent. */
2547 if (rip->t_triggered_interval)
2548 {
2549 thread_cancel (rip->t_triggered_interval);
2550 rip->t_triggered_interval = NULL;
2551 }
2552 rip->trigger = 0;
2553
2554 /* Register myself. */
2555 rip_event (RIP_UPDATE_EVENT, 0);
2556
2557 return 0;
2558}
2559
2560/* Walk down the RIP routing table then clear changed flag. */
2561void
2562rip_clear_changed_flag ()
2563{
2564 struct route_node *rp;
2565 struct rip_info *rinfo;
2566
2567 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2568 if ((rinfo = rp->info) != NULL)
2569 if (rinfo->flags & RIP_RTF_CHANGED)
2570 rinfo->flags &= ~RIP_RTF_CHANGED;
2571}
2572
2573/* Triggered update interval timer. */
2574int
2575rip_triggered_interval (struct thread *t)
2576{
2577 int rip_triggered_update (struct thread *);
2578
2579 rip->t_triggered_interval = NULL;
2580
2581 if (rip->trigger)
2582 {
2583 rip->trigger = 0;
2584 rip_triggered_update (t);
2585 }
2586 return 0;
2587}
2588
2589/* Execute triggered update. */
2590int
2591rip_triggered_update (struct thread *t)
2592{
2593 int interval;
2594
2595 /* Clear thred pointer. */
2596 rip->t_triggered_update = NULL;
2597
2598 /* Cancel interval timer. */
2599 if (rip->t_triggered_interval)
2600 {
2601 thread_cancel (rip->t_triggered_interval);
2602 rip->t_triggered_interval = NULL;
2603 }
2604 rip->trigger = 0;
2605
2606 /* Logging triggered update. */
2607 if (IS_RIP_DEBUG_EVENT)
2608 zlog_info ("triggered update!");
2609
2610 /* Split Horizon processing is done when generating triggered
2611 updates as well as normal updates (see section 2.6). */
2612 rip_update_process (rip_changed_route);
2613
2614 /* Once all of the triggered updates have been generated, the route
2615 change flags should be cleared. */
2616 rip_clear_changed_flag ();
2617
2618 /* After a triggered update is sent, a timer should be set for a
2619 random interval between 1 and 5 seconds. If other changes that
2620 would trigger updates occur before the timer expires, a single
2621 update is triggered when the timer expires. */
2622 interval = (random () % 5) + 1;
2623
2624 rip->t_triggered_interval =
2625 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2626
2627 return 0;
2628}
2629
2630/* Withdraw redistributed route. */
2631void
2632rip_redistribute_withdraw (int type)
2633{
2634 struct route_node *rp;
2635 struct rip_info *rinfo;
2636
2637 if (!rip)
2638 return;
2639
2640 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2641 if ((rinfo = rp->info) != NULL)
2642 {
2643 if (rinfo->type == type
2644 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2645 {
2646 /* Perform poisoned reverse. */
2647 rinfo->metric = RIP_METRIC_INFINITY;
2648 RIP_TIMER_ON (rinfo->t_garbage_collect,
2649 rip_garbage_collect, rip->garbage_time);
2650 RIP_TIMER_OFF (rinfo->t_timeout);
2651 rinfo->flags |= RIP_RTF_CHANGED;
2652
hasso16705132003-05-25 14:49:19 +00002653 if (IS_RIP_DEBUG_EVENT) {
2654 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2655
2656 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2657 inet_ntoa(p->prefix), p->prefixlen,
2658 ifindex2ifname(rinfo->ifindex));
2659 }
2660
paul718e3742002-12-13 20:15:29 +00002661 rip_event (RIP_TRIGGERED_UPDATE, 0);
2662 }
2663 }
2664}
2665
2666/* Create new RIP instance and set it to global variable. */
2667int
2668rip_create ()
2669{
2670 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2671 memset (rip, 0, sizeof (struct rip));
2672
2673 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002674 rip->version_send = RI_RIP_VERSION_2;
2675 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002676 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2677 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2678 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2679 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2680
2681 /* Initialize RIP routig table. */
2682 rip->table = route_table_init ();
2683 rip->route = route_table_init ();
2684 rip->neighbor = route_table_init ();
2685
2686 /* Make output stream. */
2687 rip->obuf = stream_new (1500);
2688
2689 /* Make socket. */
2690 rip->sock = rip_create_socket ();
2691 if (rip->sock < 0)
2692 return rip->sock;
2693
2694 /* Create read and timer thread. */
2695 rip_event (RIP_READ, rip->sock);
2696 rip_event (RIP_UPDATE_EVENT, 1);
2697
2698 return 0;
2699}
2700
2701/* Sned RIP request to the destination. */
2702int
2703rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002704 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002705{
2706 struct rte *rte;
2707 struct rip_packet rip_packet;
paulcc1131a2003-10-15 23:20:17 +00002708 listnode node;
paul718e3742002-12-13 20:15:29 +00002709
2710 memset (&rip_packet, 0, sizeof (rip_packet));
2711
2712 rip_packet.command = RIP_REQUEST;
2713 rip_packet.version = version;
2714 rte = rip_packet.rte;
2715 rte->metric = htonl (RIP_METRIC_INFINITY);
2716
paul931cd542004-01-23 15:31:42 +00002717 if (connected)
2718 {
2719 /*
2720 * connected is only sent for ripv1 case, or when
2721 * interface does not support multicast. Caller loops
2722 * over each connected address for this case.
2723 */
paul11dde9c2004-05-31 14:00:00 +00002724 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002725 to, ifp, connected) != sizeof (rip_packet))
2726 return -1;
2727 else
2728 return sizeof (rip_packet);
2729 }
2730
paulcc1131a2003-10-15 23:20:17 +00002731 /* send request on each connected network */
2732 LIST_LOOP(ifp->connected, connected, node)
2733 {
2734 struct prefix_ipv4 *p;
2735
2736 p = (struct prefix_ipv4 *) connected->address;
2737
2738 if (p->family != AF_INET)
2739 continue;
2740
paul11dde9c2004-05-31 14:00:00 +00002741 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002742 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002743 return -1;
2744 }
2745 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002746}
2747
2748int
2749rip_update_jitter (unsigned long time)
2750{
paul239389b2004-05-05 14:09:37 +00002751#define JITTER_BOUND 4
2752 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2753 Given that, we cannot let time be less than JITTER_BOUND seconds.
2754 The RIPv2 RFC says jitter should be small compared to
2755 update_time. We consider 1/JITTER_BOUND to be small.
2756 */
2757
2758 int jitter_input = time;
2759 int jitter;
2760
2761 if (jitter_input < JITTER_BOUND)
2762 jitter_input = JITTER_BOUND;
2763
2764 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2765
2766 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002767}
2768
2769void
2770rip_event (enum rip_event event, int sock)
2771{
2772 int jitter = 0;
2773
2774 switch (event)
2775 {
2776 case RIP_READ:
2777 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2778 break;
2779 case RIP_UPDATE_EVENT:
2780 if (rip->t_update)
2781 {
2782 thread_cancel (rip->t_update);
2783 rip->t_update = NULL;
2784 }
2785 jitter = rip_update_jitter (rip->update_time);
2786 rip->t_update =
2787 thread_add_timer (master, rip_update, NULL,
2788 sock ? 2 : rip->update_time + jitter);
2789 break;
2790 case RIP_TRIGGERED_UPDATE:
2791 if (rip->t_triggered_interval)
2792 rip->trigger = 1;
2793 else if (! rip->t_triggered_update)
2794 rip->t_triggered_update =
2795 thread_add_event (master, rip_triggered_update, NULL, 0);
2796 break;
2797 default:
2798 break;
2799 }
2800}
2801
2802DEFUN (router_rip,
2803 router_rip_cmd,
2804 "router rip",
2805 "Enable a routing process\n"
2806 "Routing Information Protocol (RIP)\n")
2807{
2808 int ret;
2809
2810 /* If rip is not enabled before. */
2811 if (! rip)
2812 {
2813 ret = rip_create ();
2814 if (ret < 0)
2815 {
2816 zlog_info ("Can't create RIP");
2817 return CMD_WARNING;
2818 }
2819 }
2820 vty->node = RIP_NODE;
2821 vty->index = rip;
2822
2823 return CMD_SUCCESS;
2824}
2825
2826DEFUN (no_router_rip,
2827 no_router_rip_cmd,
2828 "no router rip",
2829 NO_STR
2830 "Enable a routing process\n"
2831 "Routing Information Protocol (RIP)\n")
2832{
2833 if (rip)
2834 rip_clean ();
2835 return CMD_SUCCESS;
2836}
2837
2838DEFUN (rip_version,
2839 rip_version_cmd,
2840 "version <1-2>",
2841 "Set routing protocol version\n"
2842 "version\n")
2843{
2844 int version;
2845
2846 version = atoi (argv[0]);
2847 if (version != RIPv1 && version != RIPv2)
2848 {
2849 vty_out (vty, "invalid rip version %d%s", version,
2850 VTY_NEWLINE);
2851 return CMD_WARNING;
2852 }
paulf38a4712003-06-07 01:10:00 +00002853 rip->version_send = version;
2854 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002855
2856 return CMD_SUCCESS;
2857}
2858
2859DEFUN (no_rip_version,
2860 no_rip_version_cmd,
2861 "no version",
2862 NO_STR
2863 "Set routing protocol version\n")
2864{
2865 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002866 rip->version_send = RI_RIP_VERSION_2;
2867 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002868
2869 return CMD_SUCCESS;
2870}
2871
2872ALIAS (no_rip_version,
2873 no_rip_version_val_cmd,
2874 "no version <1-2>",
2875 NO_STR
2876 "Set routing protocol version\n"
2877 "version\n")
2878
2879DEFUN (rip_route,
2880 rip_route_cmd,
2881 "route A.B.C.D/M",
2882 "RIP static route configuration\n"
2883 "IP prefix <network>/<length>\n")
2884{
2885 int ret;
2886 struct prefix_ipv4 p;
2887 struct route_node *node;
2888
2889 ret = str2prefix_ipv4 (argv[0], &p);
2890 if (ret < 0)
2891 {
2892 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2893 return CMD_WARNING;
2894 }
2895 apply_mask_ipv4 (&p);
2896
2897 /* For router rip configuration. */
2898 node = route_node_get (rip->route, (struct prefix *) &p);
2899
2900 if (node->info)
2901 {
2902 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2903 route_unlock_node (node);
2904 return CMD_WARNING;
2905 }
2906
2907 node->info = "static";
2908
2909 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2910
2911 return CMD_SUCCESS;
2912}
2913
2914DEFUN (no_rip_route,
2915 no_rip_route_cmd,
2916 "no route A.B.C.D/M",
2917 NO_STR
2918 "RIP static route configuration\n"
2919 "IP prefix <network>/<length>\n")
2920{
2921 int ret;
2922 struct prefix_ipv4 p;
2923 struct route_node *node;
2924
2925 ret = str2prefix_ipv4 (argv[0], &p);
2926 if (ret < 0)
2927 {
2928 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2929 return CMD_WARNING;
2930 }
2931 apply_mask_ipv4 (&p);
2932
2933 /* For router rip configuration. */
2934 node = route_node_lookup (rip->route, (struct prefix *) &p);
2935 if (! node)
2936 {
2937 vty_out (vty, "Can't find route %s.%s", argv[0],
2938 VTY_NEWLINE);
2939 return CMD_WARNING;
2940 }
2941
2942 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2943 route_unlock_node (node);
2944
2945 node->info = NULL;
2946 route_unlock_node (node);
2947
2948 return CMD_SUCCESS;
2949}
2950
2951void
2952rip_update_default_metric ()
2953{
2954 struct route_node *np;
2955 struct rip_info *rinfo;
2956
2957 for (np = route_top (rip->table); np; np = route_next (np))
2958 if ((rinfo = np->info) != NULL)
2959 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2960 rinfo->metric = rip->default_metric;
2961}
2962
2963DEFUN (rip_default_metric,
2964 rip_default_metric_cmd,
2965 "default-metric <1-16>",
2966 "Set a metric of redistribute routes\n"
2967 "Default metric\n")
2968{
2969 if (rip)
2970 {
2971 rip->default_metric = atoi (argv[0]);
2972 /* rip_update_default_metric (); */
2973 }
2974 return CMD_SUCCESS;
2975}
2976
2977DEFUN (no_rip_default_metric,
2978 no_rip_default_metric_cmd,
2979 "no default-metric",
2980 NO_STR
2981 "Set a metric of redistribute routes\n"
2982 "Default metric\n")
2983{
2984 if (rip)
2985 {
2986 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2987 /* rip_update_default_metric (); */
2988 }
2989 return CMD_SUCCESS;
2990}
2991
2992ALIAS (no_rip_default_metric,
2993 no_rip_default_metric_val_cmd,
2994 "no default-metric <1-16>",
2995 NO_STR
2996 "Set a metric of redistribute routes\n"
2997 "Default metric\n")
2998
2999DEFUN (rip_timers,
3000 rip_timers_cmd,
3001 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3002 "Adjust routing timers\n"
3003 "Basic routing protocol update timers\n"
3004 "Routing table update timer value in second. Default is 30.\n"
3005 "Routing information timeout timer. Default is 180.\n"
3006 "Garbage collection timer. Default is 120.\n")
3007{
3008 unsigned long update;
3009 unsigned long timeout;
3010 unsigned long garbage;
3011 char *endptr = NULL;
3012 unsigned long RIP_TIMER_MAX = 2147483647;
3013 unsigned long RIP_TIMER_MIN = 5;
3014
3015 update = strtoul (argv[0], &endptr, 10);
3016 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3017 {
3018 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3019 return CMD_WARNING;
3020 }
3021
3022 timeout = strtoul (argv[1], &endptr, 10);
3023 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3024 {
3025 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3026 return CMD_WARNING;
3027 }
3028
3029 garbage = strtoul (argv[2], &endptr, 10);
3030 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3031 {
3032 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3033 return CMD_WARNING;
3034 }
3035
3036 /* Set each timer value. */
3037 rip->update_time = update;
3038 rip->timeout_time = timeout;
3039 rip->garbage_time = garbage;
3040
3041 /* Reset update timer thread. */
3042 rip_event (RIP_UPDATE_EVENT, 0);
3043
3044 return CMD_SUCCESS;
3045}
3046
3047DEFUN (no_rip_timers,
3048 no_rip_timers_cmd,
3049 "no timers basic",
3050 NO_STR
3051 "Adjust routing timers\n"
3052 "Basic routing protocol update timers\n")
3053{
3054 /* Set each timer value to the default. */
3055 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3056 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3057 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3058
3059 /* Reset update timer thread. */
3060 rip_event (RIP_UPDATE_EVENT, 0);
3061
3062 return CMD_SUCCESS;
3063}
hasso16705132003-05-25 14:49:19 +00003064
3065ALIAS (no_rip_timers,
3066 no_rip_timers_val_cmd,
3067 "no timers basic <0-65535> <0-65535> <0-65535>",
3068 NO_STR
3069 "Adjust routing timers\n"
3070 "Basic routing protocol update timers\n"
3071 "Routing table update timer value in second. Default is 30.\n"
3072 "Routing information timeout timer. Default is 180.\n"
3073 "Garbage collection timer. Default is 120.\n")
3074
paul718e3742002-12-13 20:15:29 +00003075
3076struct route_table *rip_distance_table;
3077
3078struct rip_distance
3079{
3080 /* Distance value for the IP source prefix. */
3081 u_char distance;
3082
3083 /* Name of the access-list to be matched. */
3084 char *access_list;
3085};
3086
3087struct rip_distance *
3088rip_distance_new ()
3089{
3090 struct rip_distance *new;
3091 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3092 memset (new, 0, sizeof (struct rip_distance));
3093 return new;
3094}
3095
3096void
3097rip_distance_free (struct rip_distance *rdistance)
3098{
3099 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3100}
3101
3102int
3103rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3104 char *access_list_str)
3105{
3106 int ret;
3107 struct prefix_ipv4 p;
3108 u_char distance;
3109 struct route_node *rn;
3110 struct rip_distance *rdistance;
3111
3112 ret = str2prefix_ipv4 (ip_str, &p);
3113 if (ret == 0)
3114 {
3115 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3116 return CMD_WARNING;
3117 }
3118
3119 distance = atoi (distance_str);
3120
3121 /* Get RIP distance node. */
3122 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3123 if (rn->info)
3124 {
3125 rdistance = rn->info;
3126 route_unlock_node (rn);
3127 }
3128 else
3129 {
3130 rdistance = rip_distance_new ();
3131 rn->info = rdistance;
3132 }
3133
3134 /* Set distance value. */
3135 rdistance->distance = distance;
3136
3137 /* Reset access-list configuration. */
3138 if (rdistance->access_list)
3139 {
3140 free (rdistance->access_list);
3141 rdistance->access_list = NULL;
3142 }
3143 if (access_list_str)
3144 rdistance->access_list = strdup (access_list_str);
3145
3146 return CMD_SUCCESS;
3147}
3148
3149int
3150rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3151 char *access_list_str)
3152{
3153 int ret;
3154 struct prefix_ipv4 p;
3155 u_char distance;
3156 struct route_node *rn;
3157 struct rip_distance *rdistance;
3158
3159 ret = str2prefix_ipv4 (ip_str, &p);
3160 if (ret == 0)
3161 {
3162 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3163 return CMD_WARNING;
3164 }
3165
3166 distance = atoi (distance_str);
3167
3168 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3169 if (! rn)
3170 {
3171 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3172 return CMD_WARNING;
3173 }
3174
3175 rdistance = rn->info;
3176
3177 if (rdistance->access_list)
3178 free (rdistance->access_list);
3179 rip_distance_free (rdistance);
3180
3181 rn->info = NULL;
3182 route_unlock_node (rn);
3183 route_unlock_node (rn);
3184
3185 return CMD_SUCCESS;
3186}
3187
3188void
3189rip_distance_reset ()
3190{
3191 struct route_node *rn;
3192 struct rip_distance *rdistance;
3193
3194 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3195 if ((rdistance = rn->info) != NULL)
3196 {
3197 if (rdistance->access_list)
3198 free (rdistance->access_list);
3199 rip_distance_free (rdistance);
3200 rn->info = NULL;
3201 route_unlock_node (rn);
3202 }
3203}
3204
3205/* Apply RIP information to distance method. */
3206u_char
3207rip_distance_apply (struct rip_info *rinfo)
3208{
3209 struct route_node *rn;
3210 struct prefix_ipv4 p;
3211 struct rip_distance *rdistance;
3212 struct access_list *alist;
3213
3214 if (! rip)
3215 return 0;
3216
3217 memset (&p, 0, sizeof (struct prefix_ipv4));
3218 p.family = AF_INET;
3219 p.prefix = rinfo->from;
3220 p.prefixlen = IPV4_MAX_BITLEN;
3221
3222 /* Check source address. */
3223 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3224 if (rn)
3225 {
3226 rdistance = rn->info;
3227 route_unlock_node (rn);
3228
3229 if (rdistance->access_list)
3230 {
3231 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3232 if (alist == NULL)
3233 return 0;
3234 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3235 return 0;
3236
3237 return rdistance->distance;
3238 }
3239 else
3240 return rdistance->distance;
3241 }
3242
3243 if (rip->distance)
3244 return rip->distance;
3245
3246 return 0;
3247}
3248
3249void
3250rip_distance_show (struct vty *vty)
3251{
3252 struct route_node *rn;
3253 struct rip_distance *rdistance;
3254 int header = 1;
3255 char buf[BUFSIZ];
3256
3257 vty_out (vty, " Distance: (default is %d)%s",
3258 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3259 VTY_NEWLINE);
3260
3261 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3262 if ((rdistance = rn->info) != NULL)
3263 {
3264 if (header)
3265 {
3266 vty_out (vty, " Address Distance List%s",
3267 VTY_NEWLINE);
3268 header = 0;
3269 }
3270 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3271 vty_out (vty, " %-20s %4d %s%s",
3272 buf, rdistance->distance,
3273 rdistance->access_list ? rdistance->access_list : "",
3274 VTY_NEWLINE);
3275 }
3276}
3277
3278DEFUN (rip_distance,
3279 rip_distance_cmd,
3280 "distance <1-255>",
3281 "Administrative distance\n"
3282 "Distance value\n")
3283{
3284 rip->distance = atoi (argv[0]);
3285 return CMD_SUCCESS;
3286}
3287
3288DEFUN (no_rip_distance,
3289 no_rip_distance_cmd,
3290 "no distance <1-255>",
3291 NO_STR
3292 "Administrative distance\n"
3293 "Distance value\n")
3294{
3295 rip->distance = 0;
3296 return CMD_SUCCESS;
3297}
3298
3299DEFUN (rip_distance_source,
3300 rip_distance_source_cmd,
3301 "distance <1-255> A.B.C.D/M",
3302 "Administrative distance\n"
3303 "Distance value\n"
3304 "IP source prefix\n")
3305{
3306 rip_distance_set (vty, argv[0], argv[1], NULL);
3307 return CMD_SUCCESS;
3308}
3309
3310DEFUN (no_rip_distance_source,
3311 no_rip_distance_source_cmd,
3312 "no distance <1-255> A.B.C.D/M",
3313 NO_STR
3314 "Administrative distance\n"
3315 "Distance value\n"
3316 "IP source prefix\n")
3317{
3318 rip_distance_unset (vty, argv[0], argv[1], NULL);
3319 return CMD_SUCCESS;
3320}
3321
3322DEFUN (rip_distance_source_access_list,
3323 rip_distance_source_access_list_cmd,
3324 "distance <1-255> A.B.C.D/M WORD",
3325 "Administrative distance\n"
3326 "Distance value\n"
3327 "IP source prefix\n"
3328 "Access list name\n")
3329{
3330 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3331 return CMD_SUCCESS;
3332}
3333
3334DEFUN (no_rip_distance_source_access_list,
3335 no_rip_distance_source_access_list_cmd,
3336 "no distance <1-255> A.B.C.D/M WORD",
3337 NO_STR
3338 "Administrative distance\n"
3339 "Distance value\n"
3340 "IP source prefix\n"
3341 "Access list name\n")
3342{
3343 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3344 return CMD_SUCCESS;
3345}
3346
3347/* Print out routes update time. */
3348void
3349rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3350{
3351 struct timeval timer_now;
3352 time_t clock;
3353 struct tm *tm;
3354#define TIME_BUF 25
3355 char timebuf [TIME_BUF];
3356 struct thread *thread;
3357
3358 gettimeofday (&timer_now, NULL);
3359
3360 if ((thread = rinfo->t_timeout) != NULL)
3361 {
3362 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3363 tm = gmtime (&clock);
3364 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3365 vty_out (vty, "%5s", timebuf);
3366 }
3367 else if ((thread = rinfo->t_garbage_collect) != NULL)
3368 {
3369 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3370 tm = gmtime (&clock);
3371 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3372 vty_out (vty, "%5s", timebuf);
3373 }
3374}
3375
3376char *
3377rip_route_type_print (int sub_type)
3378{
3379 switch (sub_type)
3380 {
3381 case RIP_ROUTE_RTE:
3382 return "n";
3383 case RIP_ROUTE_STATIC:
3384 return "s";
3385 case RIP_ROUTE_DEFAULT:
3386 return "d";
3387 case RIP_ROUTE_REDISTRIBUTE:
3388 return "r";
3389 case RIP_ROUTE_INTERFACE:
3390 return "i";
3391 default:
3392 return "?";
3393 }
3394}
3395
3396DEFUN (show_ip_rip,
3397 show_ip_rip_cmd,
3398 "show ip rip",
3399 SHOW_STR
3400 IP_STR
3401 "Show RIP routes\n")
3402{
3403 struct route_node *np;
3404 struct rip_info *rinfo;
3405
3406 if (! rip)
3407 return CMD_SUCCESS;
3408
hasso16705132003-05-25 14:49:19 +00003409 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3410 "Sub-codes:%s"
3411 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003412 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003413 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003414 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003415
3416 for (np = route_top (rip->table); np; np = route_next (np))
3417 if ((rinfo = np->info) != NULL)
3418 {
3419 int len;
3420
3421 len = vty_out (vty, "%s(%s) %s/%d",
3422 /* np->lock, For debugging. */
3423 route_info[rinfo->type].str,
3424 rip_route_type_print (rinfo->sub_type),
3425 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3426
hassoa1455d82004-03-03 19:36:24 +00003427 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003428
3429 if (len > 0)
3430 vty_out (vty, "%*s", len, " ");
3431
3432 if (rinfo->nexthop.s_addr)
3433 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3434 rinfo->metric);
3435 else
3436 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3437
3438 /* Route which exist in kernel routing table. */
3439 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3440 (rinfo->sub_type == RIP_ROUTE_RTE))
3441 {
3442 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003443 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003444 rip_vty_out_uptime (vty, rinfo);
3445 }
3446 else if (rinfo->metric == RIP_METRIC_INFINITY)
3447 {
3448 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003449 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003450 rip_vty_out_uptime (vty, rinfo);
3451 }
3452 else
hasso16705132003-05-25 14:49:19 +00003453 {
3454 vty_out (vty, "self ");
3455 vty_out (vty, "%3d", rinfo->tag);
3456 }
paul718e3742002-12-13 20:15:29 +00003457
3458 vty_out (vty, "%s", VTY_NEWLINE);
3459 }
3460 return CMD_SUCCESS;
3461}
3462
3463/* Return next event time. */
3464int
3465rip_next_thread_timer (struct thread *thread)
3466{
3467 struct timeval timer_now;
3468
3469 gettimeofday (&timer_now, NULL);
3470
3471 return thread->u.sands.tv_sec - timer_now.tv_sec;
3472}
3473
hasso16705132003-05-25 14:49:19 +00003474/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3475DEFUN (show_ip_rip_status,
3476 show_ip_rip_status_cmd,
3477 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003478 SHOW_STR
3479 IP_STR
hasso16705132003-05-25 14:49:19 +00003480 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003481 "IP routing protocol process parameters and statistics\n")
3482{
3483 listnode node;
3484 struct interface *ifp;
3485 struct rip_interface *ri;
3486 extern struct message ri_version_msg[];
3487 char *send_version;
3488 char *receive_version;
3489
3490 if (! rip)
3491 return CMD_SUCCESS;
3492
3493 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3494 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3495 rip->update_time);
3496 vty_out (vty, " next due in %d seconds%s",
3497 rip_next_thread_timer (rip->t_update),
3498 VTY_NEWLINE);
3499 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3500 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3501 VTY_NEWLINE);
3502
3503 /* Filtering status show. */
3504 config_show_distribute (vty);
3505
3506 /* Default metric information. */
3507 vty_out (vty, " Default redistribution metric is %d%s",
3508 rip->default_metric, VTY_NEWLINE);
3509
3510 /* Redistribute information. */
3511 vty_out (vty, " Redistributing:");
3512 config_write_rip_redistribute (vty, 0);
3513 vty_out (vty, "%s", VTY_NEWLINE);
3514
paulf38a4712003-06-07 01:10:00 +00003515 vty_out (vty, " Default version control: send version %s,",
3516 lookup(ri_version_msg,rip->version_send));
3517 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3518 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3519 else
3520 vty_out (vty, " receive version %s %s",
3521 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003522
3523 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3524
3525 for (node = listhead (iflist); node; node = nextnode (node))
3526 {
3527 ifp = getdata (node);
3528 ri = ifp->info;
3529
3530 if (ri->enable_network || ri->enable_interface)
3531 {
3532 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003533 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003534 else
3535 send_version = lookup (ri_version_msg, ri->ri_send);
3536
3537 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003538 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003539 else
3540 receive_version = lookup (ri_version_msg, ri->ri_receive);
3541
3542 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3543 send_version,
3544 receive_version,
3545 ri->key_chain ? ri->key_chain : "",
3546 VTY_NEWLINE);
3547 }
3548 }
3549
3550 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3551 config_write_rip_network (vty, 0);
3552
paul4aaff3f2003-06-07 01:04:45 +00003553 {
3554 int found_passive = 0;
3555 for (node = listhead (iflist); node; node = nextnode (node))
3556 {
3557 ifp = getdata (node);
3558 ri = ifp->info;
3559
3560 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3561 {
3562 if (!found_passive)
3563 {
3564 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3565 found_passive = 1;
3566 }
3567 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3568 }
3569 }
3570 }
3571
paul718e3742002-12-13 20:15:29 +00003572 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3573 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3574 rip_peer_display (vty);
3575
3576 rip_distance_show (vty);
3577
3578 return CMD_SUCCESS;
3579}
3580
3581/* RIP configuration write function. */
3582int
3583config_write_rip (struct vty *vty)
3584{
3585 int write = 0;
3586 struct route_node *rn;
3587 struct rip_distance *rdistance;
3588
3589 if (rip)
3590 {
3591 /* Router RIP statement. */
3592 vty_out (vty, "router rip%s", VTY_NEWLINE);
3593 write++;
3594
3595 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003596 if (rip->version_send != RI_RIP_VERSION_2
3597 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3598 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003599 VTY_NEWLINE);
3600
3601 /* RIP timer configuration. */
3602 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3603 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3604 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3605 vty_out (vty, " timers basic %lu %lu %lu%s",
3606 rip->update_time,
3607 rip->timeout_time,
3608 rip->garbage_time,
3609 VTY_NEWLINE);
3610
3611 /* Default information configuration. */
3612 if (rip->default_information)
3613 {
3614 if (rip->default_information_route_map)
3615 vty_out (vty, " default-information originate route-map %s%s",
3616 rip->default_information_route_map, VTY_NEWLINE);
3617 else
3618 vty_out (vty, " default-information originate%s",
3619 VTY_NEWLINE);
3620 }
3621
3622 /* Redistribute configuration. */
3623 config_write_rip_redistribute (vty, 1);
3624
3625 /* RIP offset-list configuration. */
3626 config_write_rip_offset_list (vty);
3627
3628 /* RIP enabled network and interface configuration. */
3629 config_write_rip_network (vty, 1);
3630
3631 /* RIP default metric configuration */
3632 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3633 vty_out (vty, " default-metric %d%s",
3634 rip->default_metric, VTY_NEWLINE);
3635
3636 /* Distribute configuration. */
3637 write += config_write_distribute (vty);
3638
hasso16705132003-05-25 14:49:19 +00003639 /* Interface routemap configuration */
3640 write += config_write_if_rmap (vty);
3641
paul718e3742002-12-13 20:15:29 +00003642 /* Distance configuration. */
3643 if (rip->distance)
3644 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3645
3646 /* RIP source IP prefix distance configuration. */
3647 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3648 if ((rdistance = rn->info) != NULL)
3649 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3650 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3651 rdistance->access_list ? rdistance->access_list : "",
3652 VTY_NEWLINE);
3653
3654 /* RIP static route configuration. */
3655 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3656 if (rn->info)
3657 vty_out (vty, " route %s/%d%s",
3658 inet_ntoa (rn->p.u.prefix4),
3659 rn->p.prefixlen,
3660 VTY_NEWLINE);
3661
3662 }
3663 return write;
3664}
3665
3666/* RIP node structure. */
3667struct cmd_node rip_node =
3668{
3669 RIP_NODE,
3670 "%s(config-router)# ",
3671 1
3672};
3673
3674/* Distribute-list update functions. */
3675void
3676rip_distribute_update (struct distribute *dist)
3677{
3678 struct interface *ifp;
3679 struct rip_interface *ri;
3680 struct access_list *alist;
3681 struct prefix_list *plist;
3682
3683 if (! dist->ifname)
3684 return;
3685
3686 ifp = if_lookup_by_name (dist->ifname);
3687 if (ifp == NULL)
3688 return;
3689
3690 ri = ifp->info;
3691
3692 if (dist->list[DISTRIBUTE_IN])
3693 {
3694 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3695 if (alist)
3696 ri->list[RIP_FILTER_IN] = alist;
3697 else
3698 ri->list[RIP_FILTER_IN] = NULL;
3699 }
3700 else
3701 ri->list[RIP_FILTER_IN] = NULL;
3702
3703 if (dist->list[DISTRIBUTE_OUT])
3704 {
3705 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3706 if (alist)
3707 ri->list[RIP_FILTER_OUT] = alist;
3708 else
3709 ri->list[RIP_FILTER_OUT] = NULL;
3710 }
3711 else
3712 ri->list[RIP_FILTER_OUT] = NULL;
3713
3714 if (dist->prefix[DISTRIBUTE_IN])
3715 {
3716 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3717 if (plist)
3718 ri->prefix[RIP_FILTER_IN] = plist;
3719 else
3720 ri->prefix[RIP_FILTER_IN] = NULL;
3721 }
3722 else
3723 ri->prefix[RIP_FILTER_IN] = NULL;
3724
3725 if (dist->prefix[DISTRIBUTE_OUT])
3726 {
3727 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3728 if (plist)
3729 ri->prefix[RIP_FILTER_OUT] = plist;
3730 else
3731 ri->prefix[RIP_FILTER_OUT] = NULL;
3732 }
3733 else
3734 ri->prefix[RIP_FILTER_OUT] = NULL;
3735}
3736
3737void
3738rip_distribute_update_interface (struct interface *ifp)
3739{
3740 struct distribute *dist;
3741
3742 dist = distribute_lookup (ifp->name);
3743 if (dist)
3744 rip_distribute_update (dist);
3745}
3746
3747/* Update all interface's distribute list. */
3748void
3749rip_distribute_update_all ()
3750{
3751 struct interface *ifp;
3752 listnode node;
3753
3754 for (node = listhead (iflist); node; nextnode (node))
3755 {
3756 ifp = getdata (node);
3757 rip_distribute_update_interface (ifp);
3758 }
3759}
paul11dde9c2004-05-31 14:00:00 +00003760/* ARGSUSED */
3761void
3762rip_distribute_update_all_wrapper(struct access_list *notused)
3763{
3764 rip_distribute_update_all();
3765}
paul718e3742002-12-13 20:15:29 +00003766
3767/* Delete all added rip route. */
3768void
3769rip_clean ()
3770{
3771 int i;
3772 struct route_node *rp;
3773 struct rip_info *rinfo;
3774
3775 if (rip)
3776 {
3777 /* Clear RIP routes */
3778 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3779 if ((rinfo = rp->info) != NULL)
3780 {
3781 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3782 rinfo->sub_type == RIP_ROUTE_RTE)
3783 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3784 &rinfo->nexthop, rinfo->metric);
3785
3786 RIP_TIMER_OFF (rinfo->t_timeout);
3787 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3788
3789 rp->info = NULL;
3790 route_unlock_node (rp);
3791
3792 rip_info_free (rinfo);
3793 }
3794
3795 /* Cancel RIP related timers. */
3796 RIP_TIMER_OFF (rip->t_update);
3797 RIP_TIMER_OFF (rip->t_triggered_update);
3798 RIP_TIMER_OFF (rip->t_triggered_interval);
3799
3800 /* Cancel read thread. */
3801 if (rip->t_read)
3802 {
3803 thread_cancel (rip->t_read);
3804 rip->t_read = NULL;
3805 }
3806
3807 /* Close RIP socket. */
3808 if (rip->sock >= 0)
3809 {
3810 close (rip->sock);
3811 rip->sock = -1;
3812 }
3813
3814 /* Static RIP route configuration. */
3815 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3816 if (rp->info)
3817 {
3818 rp->info = NULL;
3819 route_unlock_node (rp);
3820 }
3821
3822 /* RIP neighbor configuration. */
3823 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3824 if (rp->info)
3825 {
3826 rp->info = NULL;
3827 route_unlock_node (rp);
3828 }
3829
3830 /* Redistribute related clear. */
3831 if (rip->default_information_route_map)
3832 free (rip->default_information_route_map);
3833
3834 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3835 if (rip->route_map[i].name)
3836 free (rip->route_map[i].name);
3837
3838 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3839 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3840 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3841
3842 XFREE (MTYPE_RIP, rip);
3843 rip = NULL;
3844 }
3845
3846 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003847 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003848 rip_offset_clean ();
3849 rip_interface_clean ();
3850 rip_distance_reset ();
3851 rip_redistribute_clean ();
3852}
3853
3854/* Reset all values to the default settings. */
3855void
3856rip_reset ()
3857{
3858 /* Reset global counters. */
3859 rip_global_route_changes = 0;
3860 rip_global_queries = 0;
3861
3862 /* Call ripd related reset functions. */
3863 rip_debug_reset ();
3864 rip_route_map_reset ();
3865
3866 /* Call library reset functions. */
3867 vty_reset ();
3868 access_list_reset ();
3869 prefix_list_reset ();
3870
3871 distribute_list_reset ();
3872
3873 rip_interface_reset ();
3874 rip_distance_reset ();
3875
3876 rip_zclient_reset ();
3877}
3878
hasso16705132003-05-25 14:49:19 +00003879void
3880rip_if_rmap_update (struct if_rmap *if_rmap)
3881{
3882 struct interface *ifp;
3883 struct rip_interface *ri;
3884 struct route_map *rmap;
3885
3886 ifp = if_lookup_by_name (if_rmap->ifname);
3887 if (ifp == NULL)
3888 return;
3889
3890 ri = ifp->info;
3891
3892 if (if_rmap->routemap[IF_RMAP_IN])
3893 {
3894 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3895 if (rmap)
3896 ri->routemap[IF_RMAP_IN] = rmap;
3897 else
3898 ri->routemap[IF_RMAP_IN] = NULL;
3899 }
3900 else
3901 ri->routemap[RIP_FILTER_IN] = NULL;
3902
3903 if (if_rmap->routemap[IF_RMAP_OUT])
3904 {
3905 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3906 if (rmap)
3907 ri->routemap[IF_RMAP_OUT] = rmap;
3908 else
3909 ri->routemap[IF_RMAP_OUT] = NULL;
3910 }
3911 else
3912 ri->routemap[RIP_FILTER_OUT] = NULL;
3913}
3914
3915void
3916rip_if_rmap_update_interface (struct interface *ifp)
3917{
3918 struct if_rmap *if_rmap;
3919
3920 if_rmap = if_rmap_lookup (ifp->name);
3921 if (if_rmap)
3922 rip_if_rmap_update (if_rmap);
3923}
3924
3925void
3926rip_routemap_update_redistribute (void)
3927{
3928 int i;
3929
3930 if (rip)
3931 {
3932 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3933 {
3934 if (rip->route_map[i].name)
3935 rip->route_map[i].map =
3936 route_map_lookup_by_name (rip->route_map[i].name);
3937 }
3938 }
3939}
3940
paul11dde9c2004-05-31 14:00:00 +00003941/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003942void
paul11dde9c2004-05-31 14:00:00 +00003943rip_routemap_update (char *notused)
hasso16705132003-05-25 14:49:19 +00003944{
3945 struct interface *ifp;
3946 listnode node;
3947
3948 for (node = listhead (iflist); node; nextnode (node))
3949 {
3950 ifp = getdata (node);
3951 rip_if_rmap_update_interface (ifp);
3952 }
3953
3954 rip_routemap_update_redistribute ();
3955}
3956
paul718e3742002-12-13 20:15:29 +00003957/* Allocate new rip structure and set default value. */
3958void
3959rip_init ()
3960{
3961 /* Randomize for triggered update random(). */
3962 srand (time (NULL));
3963
3964 /* Install top nodes. */
3965 install_node (&rip_node, config_write_rip);
3966
3967 /* Install rip commands. */
3968 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003969 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003970 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003971 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003972 install_element (CONFIG_NODE, &router_rip_cmd);
3973 install_element (CONFIG_NODE, &no_router_rip_cmd);
3974
3975 install_default (RIP_NODE);
3976 install_element (RIP_NODE, &rip_version_cmd);
3977 install_element (RIP_NODE, &no_rip_version_cmd);
3978 install_element (RIP_NODE, &no_rip_version_val_cmd);
3979 install_element (RIP_NODE, &rip_default_metric_cmd);
3980 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3981 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3982 install_element (RIP_NODE, &rip_timers_cmd);
3983 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003984 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003985 install_element (RIP_NODE, &rip_route_cmd);
3986 install_element (RIP_NODE, &no_rip_route_cmd);
3987 install_element (RIP_NODE, &rip_distance_cmd);
3988 install_element (RIP_NODE, &no_rip_distance_cmd);
3989 install_element (RIP_NODE, &rip_distance_source_cmd);
3990 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3991 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3992 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3993
3994 /* Debug related init. */
3995 rip_debug_init ();
3996
paul718e3742002-12-13 20:15:29 +00003997 /* SNMP init. */
3998#ifdef HAVE_SNMP
3999 rip_snmp_init ();
4000#endif /* HAVE_SNMP */
4001
4002 /* Access list install. */
4003 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004004 access_list_add_hook (rip_distribute_update_all_wrapper);
4005 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004006
4007 /* Prefix list initialize.*/
4008 prefix_list_init ();
4009 prefix_list_add_hook (rip_distribute_update_all);
4010 prefix_list_delete_hook (rip_distribute_update_all);
4011
4012 /* Distribute list install. */
4013 distribute_list_init (RIP_NODE);
4014 distribute_list_add_hook (rip_distribute_update);
4015 distribute_list_delete_hook (rip_distribute_update);
4016
hasso16705132003-05-25 14:49:19 +00004017 /* Route-map */
4018 rip_route_map_init ();
4019 rip_offset_init ();
4020
4021 route_map_add_hook (rip_routemap_update);
4022 route_map_delete_hook (rip_routemap_update);
4023
4024 if_rmap_init (RIP_NODE);
4025 if_rmap_hook_add (rip_if_rmap_update);
4026 if_rmap_hook_delete (rip_if_rmap_update);
4027
paul718e3742002-12-13 20:15:29 +00004028 /* Distance control. */
4029 rip_distance_table = route_table_init ();
4030}