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