blob: d520af0e46bb9fbb8c20001b480389aa3d4342cf [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{
2713 return ((rand () % (time + 1)) - (time / 2));
2714}
2715
2716void
2717rip_event (enum rip_event event, int sock)
2718{
2719 int jitter = 0;
2720
2721 switch (event)
2722 {
2723 case RIP_READ:
2724 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2725 break;
2726 case RIP_UPDATE_EVENT:
2727 if (rip->t_update)
2728 {
2729 thread_cancel (rip->t_update);
2730 rip->t_update = NULL;
2731 }
2732 jitter = rip_update_jitter (rip->update_time);
2733 rip->t_update =
2734 thread_add_timer (master, rip_update, NULL,
2735 sock ? 2 : rip->update_time + jitter);
2736 break;
2737 case RIP_TRIGGERED_UPDATE:
2738 if (rip->t_triggered_interval)
2739 rip->trigger = 1;
2740 else if (! rip->t_triggered_update)
2741 rip->t_triggered_update =
2742 thread_add_event (master, rip_triggered_update, NULL, 0);
2743 break;
2744 default:
2745 break;
2746 }
2747}
2748
2749DEFUN (router_rip,
2750 router_rip_cmd,
2751 "router rip",
2752 "Enable a routing process\n"
2753 "Routing Information Protocol (RIP)\n")
2754{
2755 int ret;
2756
2757 /* If rip is not enabled before. */
2758 if (! rip)
2759 {
2760 ret = rip_create ();
2761 if (ret < 0)
2762 {
2763 zlog_info ("Can't create RIP");
2764 return CMD_WARNING;
2765 }
2766 }
2767 vty->node = RIP_NODE;
2768 vty->index = rip;
2769
2770 return CMD_SUCCESS;
2771}
2772
2773DEFUN (no_router_rip,
2774 no_router_rip_cmd,
2775 "no router rip",
2776 NO_STR
2777 "Enable a routing process\n"
2778 "Routing Information Protocol (RIP)\n")
2779{
2780 if (rip)
2781 rip_clean ();
2782 return CMD_SUCCESS;
2783}
2784
2785DEFUN (rip_version,
2786 rip_version_cmd,
2787 "version <1-2>",
2788 "Set routing protocol version\n"
2789 "version\n")
2790{
2791 int version;
2792
2793 version = atoi (argv[0]);
2794 if (version != RIPv1 && version != RIPv2)
2795 {
2796 vty_out (vty, "invalid rip version %d%s", version,
2797 VTY_NEWLINE);
2798 return CMD_WARNING;
2799 }
paulf38a4712003-06-07 01:10:00 +00002800 rip->version_send = version;
2801 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002802
2803 return CMD_SUCCESS;
2804}
2805
2806DEFUN (no_rip_version,
2807 no_rip_version_cmd,
2808 "no version",
2809 NO_STR
2810 "Set routing protocol version\n")
2811{
2812 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002813 rip->version_send = RI_RIP_VERSION_2;
2814 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002815
2816 return CMD_SUCCESS;
2817}
2818
2819ALIAS (no_rip_version,
2820 no_rip_version_val_cmd,
2821 "no version <1-2>",
2822 NO_STR
2823 "Set routing protocol version\n"
2824 "version\n")
2825
2826DEFUN (rip_route,
2827 rip_route_cmd,
2828 "route A.B.C.D/M",
2829 "RIP static route configuration\n"
2830 "IP prefix <network>/<length>\n")
2831{
2832 int ret;
2833 struct prefix_ipv4 p;
2834 struct route_node *node;
2835
2836 ret = str2prefix_ipv4 (argv[0], &p);
2837 if (ret < 0)
2838 {
2839 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2840 return CMD_WARNING;
2841 }
2842 apply_mask_ipv4 (&p);
2843
2844 /* For router rip configuration. */
2845 node = route_node_get (rip->route, (struct prefix *) &p);
2846
2847 if (node->info)
2848 {
2849 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2850 route_unlock_node (node);
2851 return CMD_WARNING;
2852 }
2853
2854 node->info = "static";
2855
2856 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2857
2858 return CMD_SUCCESS;
2859}
2860
2861DEFUN (no_rip_route,
2862 no_rip_route_cmd,
2863 "no route A.B.C.D/M",
2864 NO_STR
2865 "RIP static route configuration\n"
2866 "IP prefix <network>/<length>\n")
2867{
2868 int ret;
2869 struct prefix_ipv4 p;
2870 struct route_node *node;
2871
2872 ret = str2prefix_ipv4 (argv[0], &p);
2873 if (ret < 0)
2874 {
2875 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2876 return CMD_WARNING;
2877 }
2878 apply_mask_ipv4 (&p);
2879
2880 /* For router rip configuration. */
2881 node = route_node_lookup (rip->route, (struct prefix *) &p);
2882 if (! node)
2883 {
2884 vty_out (vty, "Can't find route %s.%s", argv[0],
2885 VTY_NEWLINE);
2886 return CMD_WARNING;
2887 }
2888
2889 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2890 route_unlock_node (node);
2891
2892 node->info = NULL;
2893 route_unlock_node (node);
2894
2895 return CMD_SUCCESS;
2896}
2897
2898void
2899rip_update_default_metric ()
2900{
2901 struct route_node *np;
2902 struct rip_info *rinfo;
2903
2904 for (np = route_top (rip->table); np; np = route_next (np))
2905 if ((rinfo = np->info) != NULL)
2906 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2907 rinfo->metric = rip->default_metric;
2908}
2909
2910DEFUN (rip_default_metric,
2911 rip_default_metric_cmd,
2912 "default-metric <1-16>",
2913 "Set a metric of redistribute routes\n"
2914 "Default metric\n")
2915{
2916 if (rip)
2917 {
2918 rip->default_metric = atoi (argv[0]);
2919 /* rip_update_default_metric (); */
2920 }
2921 return CMD_SUCCESS;
2922}
2923
2924DEFUN (no_rip_default_metric,
2925 no_rip_default_metric_cmd,
2926 "no default-metric",
2927 NO_STR
2928 "Set a metric of redistribute routes\n"
2929 "Default metric\n")
2930{
2931 if (rip)
2932 {
2933 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2934 /* rip_update_default_metric (); */
2935 }
2936 return CMD_SUCCESS;
2937}
2938
2939ALIAS (no_rip_default_metric,
2940 no_rip_default_metric_val_cmd,
2941 "no default-metric <1-16>",
2942 NO_STR
2943 "Set a metric of redistribute routes\n"
2944 "Default metric\n")
2945
2946DEFUN (rip_timers,
2947 rip_timers_cmd,
2948 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
2949 "Adjust routing timers\n"
2950 "Basic routing protocol update timers\n"
2951 "Routing table update timer value in second. Default is 30.\n"
2952 "Routing information timeout timer. Default is 180.\n"
2953 "Garbage collection timer. Default is 120.\n")
2954{
2955 unsigned long update;
2956 unsigned long timeout;
2957 unsigned long garbage;
2958 char *endptr = NULL;
2959 unsigned long RIP_TIMER_MAX = 2147483647;
2960 unsigned long RIP_TIMER_MIN = 5;
2961
2962 update = strtoul (argv[0], &endptr, 10);
2963 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
2964 {
2965 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2966 return CMD_WARNING;
2967 }
2968
2969 timeout = strtoul (argv[1], &endptr, 10);
2970 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
2971 {
2972 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2973 return CMD_WARNING;
2974 }
2975
2976 garbage = strtoul (argv[2], &endptr, 10);
2977 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
2978 {
2979 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2980 return CMD_WARNING;
2981 }
2982
2983 /* Set each timer value. */
2984 rip->update_time = update;
2985 rip->timeout_time = timeout;
2986 rip->garbage_time = garbage;
2987
2988 /* Reset update timer thread. */
2989 rip_event (RIP_UPDATE_EVENT, 0);
2990
2991 return CMD_SUCCESS;
2992}
2993
2994DEFUN (no_rip_timers,
2995 no_rip_timers_cmd,
2996 "no timers basic",
2997 NO_STR
2998 "Adjust routing timers\n"
2999 "Basic routing protocol update timers\n")
3000{
3001 /* Set each timer value to the default. */
3002 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3003 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3004 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3005
3006 /* Reset update timer thread. */
3007 rip_event (RIP_UPDATE_EVENT, 0);
3008
3009 return CMD_SUCCESS;
3010}
hasso16705132003-05-25 14:49:19 +00003011
3012ALIAS (no_rip_timers,
3013 no_rip_timers_val_cmd,
3014 "no timers basic <0-65535> <0-65535> <0-65535>",
3015 NO_STR
3016 "Adjust routing timers\n"
3017 "Basic routing protocol update timers\n"
3018 "Routing table update timer value in second. Default is 30.\n"
3019 "Routing information timeout timer. Default is 180.\n"
3020 "Garbage collection timer. Default is 120.\n")
3021
paul718e3742002-12-13 20:15:29 +00003022
3023struct route_table *rip_distance_table;
3024
3025struct rip_distance
3026{
3027 /* Distance value for the IP source prefix. */
3028 u_char distance;
3029
3030 /* Name of the access-list to be matched. */
3031 char *access_list;
3032};
3033
3034struct rip_distance *
3035rip_distance_new ()
3036{
3037 struct rip_distance *new;
3038 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3039 memset (new, 0, sizeof (struct rip_distance));
3040 return new;
3041}
3042
3043void
3044rip_distance_free (struct rip_distance *rdistance)
3045{
3046 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3047}
3048
3049int
3050rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3051 char *access_list_str)
3052{
3053 int ret;
3054 struct prefix_ipv4 p;
3055 u_char distance;
3056 struct route_node *rn;
3057 struct rip_distance *rdistance;
3058
3059 ret = str2prefix_ipv4 (ip_str, &p);
3060 if (ret == 0)
3061 {
3062 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3063 return CMD_WARNING;
3064 }
3065
3066 distance = atoi (distance_str);
3067
3068 /* Get RIP distance node. */
3069 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3070 if (rn->info)
3071 {
3072 rdistance = rn->info;
3073 route_unlock_node (rn);
3074 }
3075 else
3076 {
3077 rdistance = rip_distance_new ();
3078 rn->info = rdistance;
3079 }
3080
3081 /* Set distance value. */
3082 rdistance->distance = distance;
3083
3084 /* Reset access-list configuration. */
3085 if (rdistance->access_list)
3086 {
3087 free (rdistance->access_list);
3088 rdistance->access_list = NULL;
3089 }
3090 if (access_list_str)
3091 rdistance->access_list = strdup (access_list_str);
3092
3093 return CMD_SUCCESS;
3094}
3095
3096int
3097rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3098 char *access_list_str)
3099{
3100 int ret;
3101 struct prefix_ipv4 p;
3102 u_char distance;
3103 struct route_node *rn;
3104 struct rip_distance *rdistance;
3105
3106 ret = str2prefix_ipv4 (ip_str, &p);
3107 if (ret == 0)
3108 {
3109 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3110 return CMD_WARNING;
3111 }
3112
3113 distance = atoi (distance_str);
3114
3115 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3116 if (! rn)
3117 {
3118 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3119 return CMD_WARNING;
3120 }
3121
3122 rdistance = rn->info;
3123
3124 if (rdistance->access_list)
3125 free (rdistance->access_list);
3126 rip_distance_free (rdistance);
3127
3128 rn->info = NULL;
3129 route_unlock_node (rn);
3130 route_unlock_node (rn);
3131
3132 return CMD_SUCCESS;
3133}
3134
3135void
3136rip_distance_reset ()
3137{
3138 struct route_node *rn;
3139 struct rip_distance *rdistance;
3140
3141 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3142 if ((rdistance = rn->info) != NULL)
3143 {
3144 if (rdistance->access_list)
3145 free (rdistance->access_list);
3146 rip_distance_free (rdistance);
3147 rn->info = NULL;
3148 route_unlock_node (rn);
3149 }
3150}
3151
3152/* Apply RIP information to distance method. */
3153u_char
3154rip_distance_apply (struct rip_info *rinfo)
3155{
3156 struct route_node *rn;
3157 struct prefix_ipv4 p;
3158 struct rip_distance *rdistance;
3159 struct access_list *alist;
3160
3161 if (! rip)
3162 return 0;
3163
3164 memset (&p, 0, sizeof (struct prefix_ipv4));
3165 p.family = AF_INET;
3166 p.prefix = rinfo->from;
3167 p.prefixlen = IPV4_MAX_BITLEN;
3168
3169 /* Check source address. */
3170 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3171 if (rn)
3172 {
3173 rdistance = rn->info;
3174 route_unlock_node (rn);
3175
3176 if (rdistance->access_list)
3177 {
3178 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3179 if (alist == NULL)
3180 return 0;
3181 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3182 return 0;
3183
3184 return rdistance->distance;
3185 }
3186 else
3187 return rdistance->distance;
3188 }
3189
3190 if (rip->distance)
3191 return rip->distance;
3192
3193 return 0;
3194}
3195
3196void
3197rip_distance_show (struct vty *vty)
3198{
3199 struct route_node *rn;
3200 struct rip_distance *rdistance;
3201 int header = 1;
3202 char buf[BUFSIZ];
3203
3204 vty_out (vty, " Distance: (default is %d)%s",
3205 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3206 VTY_NEWLINE);
3207
3208 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3209 if ((rdistance = rn->info) != NULL)
3210 {
3211 if (header)
3212 {
3213 vty_out (vty, " Address Distance List%s",
3214 VTY_NEWLINE);
3215 header = 0;
3216 }
3217 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3218 vty_out (vty, " %-20s %4d %s%s",
3219 buf, rdistance->distance,
3220 rdistance->access_list ? rdistance->access_list : "",
3221 VTY_NEWLINE);
3222 }
3223}
3224
3225DEFUN (rip_distance,
3226 rip_distance_cmd,
3227 "distance <1-255>",
3228 "Administrative distance\n"
3229 "Distance value\n")
3230{
3231 rip->distance = atoi (argv[0]);
3232 return CMD_SUCCESS;
3233}
3234
3235DEFUN (no_rip_distance,
3236 no_rip_distance_cmd,
3237 "no distance <1-255>",
3238 NO_STR
3239 "Administrative distance\n"
3240 "Distance value\n")
3241{
3242 rip->distance = 0;
3243 return CMD_SUCCESS;
3244}
3245
3246DEFUN (rip_distance_source,
3247 rip_distance_source_cmd,
3248 "distance <1-255> A.B.C.D/M",
3249 "Administrative distance\n"
3250 "Distance value\n"
3251 "IP source prefix\n")
3252{
3253 rip_distance_set (vty, argv[0], argv[1], NULL);
3254 return CMD_SUCCESS;
3255}
3256
3257DEFUN (no_rip_distance_source,
3258 no_rip_distance_source_cmd,
3259 "no distance <1-255> A.B.C.D/M",
3260 NO_STR
3261 "Administrative distance\n"
3262 "Distance value\n"
3263 "IP source prefix\n")
3264{
3265 rip_distance_unset (vty, argv[0], argv[1], NULL);
3266 return CMD_SUCCESS;
3267}
3268
3269DEFUN (rip_distance_source_access_list,
3270 rip_distance_source_access_list_cmd,
3271 "distance <1-255> A.B.C.D/M WORD",
3272 "Administrative distance\n"
3273 "Distance value\n"
3274 "IP source prefix\n"
3275 "Access list name\n")
3276{
3277 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3278 return CMD_SUCCESS;
3279}
3280
3281DEFUN (no_rip_distance_source_access_list,
3282 no_rip_distance_source_access_list_cmd,
3283 "no distance <1-255> A.B.C.D/M WORD",
3284 NO_STR
3285 "Administrative distance\n"
3286 "Distance value\n"
3287 "IP source prefix\n"
3288 "Access list name\n")
3289{
3290 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3291 return CMD_SUCCESS;
3292}
3293
3294/* Print out routes update time. */
3295void
3296rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3297{
3298 struct timeval timer_now;
3299 time_t clock;
3300 struct tm *tm;
3301#define TIME_BUF 25
3302 char timebuf [TIME_BUF];
3303 struct thread *thread;
3304
3305 gettimeofday (&timer_now, NULL);
3306
3307 if ((thread = rinfo->t_timeout) != NULL)
3308 {
3309 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3310 tm = gmtime (&clock);
3311 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3312 vty_out (vty, "%5s", timebuf);
3313 }
3314 else if ((thread = rinfo->t_garbage_collect) != NULL)
3315 {
3316 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3317 tm = gmtime (&clock);
3318 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3319 vty_out (vty, "%5s", timebuf);
3320 }
3321}
3322
3323char *
3324rip_route_type_print (int sub_type)
3325{
3326 switch (sub_type)
3327 {
3328 case RIP_ROUTE_RTE:
3329 return "n";
3330 case RIP_ROUTE_STATIC:
3331 return "s";
3332 case RIP_ROUTE_DEFAULT:
3333 return "d";
3334 case RIP_ROUTE_REDISTRIBUTE:
3335 return "r";
3336 case RIP_ROUTE_INTERFACE:
3337 return "i";
3338 default:
3339 return "?";
3340 }
3341}
3342
3343DEFUN (show_ip_rip,
3344 show_ip_rip_cmd,
3345 "show ip rip",
3346 SHOW_STR
3347 IP_STR
3348 "Show RIP routes\n")
3349{
3350 struct route_node *np;
3351 struct rip_info *rinfo;
3352
3353 if (! rip)
3354 return CMD_SUCCESS;
3355
hasso16705132003-05-25 14:49:19 +00003356 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3357 "Sub-codes:%s"
3358 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003359 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003360 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003361 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003362
3363 for (np = route_top (rip->table); np; np = route_next (np))
3364 if ((rinfo = np->info) != NULL)
3365 {
3366 int len;
3367
3368 len = vty_out (vty, "%s(%s) %s/%d",
3369 /* np->lock, For debugging. */
3370 route_info[rinfo->type].str,
3371 rip_route_type_print (rinfo->sub_type),
3372 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3373
hassoa1455d82004-03-03 19:36:24 +00003374 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003375
3376 if (len > 0)
3377 vty_out (vty, "%*s", len, " ");
3378
3379 if (rinfo->nexthop.s_addr)
3380 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3381 rinfo->metric);
3382 else
3383 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3384
3385 /* Route which exist in kernel routing table. */
3386 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3387 (rinfo->sub_type == RIP_ROUTE_RTE))
3388 {
3389 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003390 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003391 rip_vty_out_uptime (vty, rinfo);
3392 }
3393 else if (rinfo->metric == RIP_METRIC_INFINITY)
3394 {
3395 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003396 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003397 rip_vty_out_uptime (vty, rinfo);
3398 }
3399 else
hasso16705132003-05-25 14:49:19 +00003400 {
3401 vty_out (vty, "self ");
3402 vty_out (vty, "%3d", rinfo->tag);
3403 }
paul718e3742002-12-13 20:15:29 +00003404
3405 vty_out (vty, "%s", VTY_NEWLINE);
3406 }
3407 return CMD_SUCCESS;
3408}
3409
3410/* Return next event time. */
3411int
3412rip_next_thread_timer (struct thread *thread)
3413{
3414 struct timeval timer_now;
3415
3416 gettimeofday (&timer_now, NULL);
3417
3418 return thread->u.sands.tv_sec - timer_now.tv_sec;
3419}
3420
hasso16705132003-05-25 14:49:19 +00003421/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3422DEFUN (show_ip_rip_status,
3423 show_ip_rip_status_cmd,
3424 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003425 SHOW_STR
3426 IP_STR
hasso16705132003-05-25 14:49:19 +00003427 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003428 "IP routing protocol process parameters and statistics\n")
3429{
3430 listnode node;
3431 struct interface *ifp;
3432 struct rip_interface *ri;
3433 extern struct message ri_version_msg[];
3434 char *send_version;
3435 char *receive_version;
3436
3437 if (! rip)
3438 return CMD_SUCCESS;
3439
3440 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3441 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3442 rip->update_time);
3443 vty_out (vty, " next due in %d seconds%s",
3444 rip_next_thread_timer (rip->t_update),
3445 VTY_NEWLINE);
3446 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3447 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3448 VTY_NEWLINE);
3449
3450 /* Filtering status show. */
3451 config_show_distribute (vty);
3452
3453 /* Default metric information. */
3454 vty_out (vty, " Default redistribution metric is %d%s",
3455 rip->default_metric, VTY_NEWLINE);
3456
3457 /* Redistribute information. */
3458 vty_out (vty, " Redistributing:");
3459 config_write_rip_redistribute (vty, 0);
3460 vty_out (vty, "%s", VTY_NEWLINE);
3461
paulf38a4712003-06-07 01:10:00 +00003462 vty_out (vty, " Default version control: send version %s,",
3463 lookup(ri_version_msg,rip->version_send));
3464 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3465 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3466 else
3467 vty_out (vty, " receive version %s %s",
3468 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003469
3470 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3471
3472 for (node = listhead (iflist); node; node = nextnode (node))
3473 {
3474 ifp = getdata (node);
3475 ri = ifp->info;
3476
3477 if (ri->enable_network || ri->enable_interface)
3478 {
3479 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003480 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003481 else
3482 send_version = lookup (ri_version_msg, ri->ri_send);
3483
3484 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003485 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003486 else
3487 receive_version = lookup (ri_version_msg, ri->ri_receive);
3488
3489 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3490 send_version,
3491 receive_version,
3492 ri->key_chain ? ri->key_chain : "",
3493 VTY_NEWLINE);
3494 }
3495 }
3496
3497 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3498 config_write_rip_network (vty, 0);
3499
paul4aaff3f2003-06-07 01:04:45 +00003500 {
3501 int found_passive = 0;
3502 for (node = listhead (iflist); node; node = nextnode (node))
3503 {
3504 ifp = getdata (node);
3505 ri = ifp->info;
3506
3507 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3508 {
3509 if (!found_passive)
3510 {
3511 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3512 found_passive = 1;
3513 }
3514 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3515 }
3516 }
3517 }
3518
paul718e3742002-12-13 20:15:29 +00003519 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3520 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3521 rip_peer_display (vty);
3522
3523 rip_distance_show (vty);
3524
3525 return CMD_SUCCESS;
3526}
3527
3528/* RIP configuration write function. */
3529int
3530config_write_rip (struct vty *vty)
3531{
3532 int write = 0;
3533 struct route_node *rn;
3534 struct rip_distance *rdistance;
3535
3536 if (rip)
3537 {
3538 /* Router RIP statement. */
3539 vty_out (vty, "router rip%s", VTY_NEWLINE);
3540 write++;
3541
3542 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003543 if (rip->version_send != RI_RIP_VERSION_2
3544 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3545 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003546 VTY_NEWLINE);
3547
3548 /* RIP timer configuration. */
3549 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3550 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3551 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3552 vty_out (vty, " timers basic %lu %lu %lu%s",
3553 rip->update_time,
3554 rip->timeout_time,
3555 rip->garbage_time,
3556 VTY_NEWLINE);
3557
3558 /* Default information configuration. */
3559 if (rip->default_information)
3560 {
3561 if (rip->default_information_route_map)
3562 vty_out (vty, " default-information originate route-map %s%s",
3563 rip->default_information_route_map, VTY_NEWLINE);
3564 else
3565 vty_out (vty, " default-information originate%s",
3566 VTY_NEWLINE);
3567 }
3568
3569 /* Redistribute configuration. */
3570 config_write_rip_redistribute (vty, 1);
3571
3572 /* RIP offset-list configuration. */
3573 config_write_rip_offset_list (vty);
3574
3575 /* RIP enabled network and interface configuration. */
3576 config_write_rip_network (vty, 1);
3577
3578 /* RIP default metric configuration */
3579 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3580 vty_out (vty, " default-metric %d%s",
3581 rip->default_metric, VTY_NEWLINE);
3582
3583 /* Distribute configuration. */
3584 write += config_write_distribute (vty);
3585
hasso16705132003-05-25 14:49:19 +00003586 /* Interface routemap configuration */
3587 write += config_write_if_rmap (vty);
3588
paul718e3742002-12-13 20:15:29 +00003589 /* Distance configuration. */
3590 if (rip->distance)
3591 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3592
3593 /* RIP source IP prefix distance configuration. */
3594 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3595 if ((rdistance = rn->info) != NULL)
3596 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3597 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3598 rdistance->access_list ? rdistance->access_list : "",
3599 VTY_NEWLINE);
3600
3601 /* RIP static route configuration. */
3602 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3603 if (rn->info)
3604 vty_out (vty, " route %s/%d%s",
3605 inet_ntoa (rn->p.u.prefix4),
3606 rn->p.prefixlen,
3607 VTY_NEWLINE);
3608
3609 }
3610 return write;
3611}
3612
3613/* RIP node structure. */
3614struct cmd_node rip_node =
3615{
3616 RIP_NODE,
3617 "%s(config-router)# ",
3618 1
3619};
3620
3621/* Distribute-list update functions. */
3622void
3623rip_distribute_update (struct distribute *dist)
3624{
3625 struct interface *ifp;
3626 struct rip_interface *ri;
3627 struct access_list *alist;
3628 struct prefix_list *plist;
3629
3630 if (! dist->ifname)
3631 return;
3632
3633 ifp = if_lookup_by_name (dist->ifname);
3634 if (ifp == NULL)
3635 return;
3636
3637 ri = ifp->info;
3638
3639 if (dist->list[DISTRIBUTE_IN])
3640 {
3641 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3642 if (alist)
3643 ri->list[RIP_FILTER_IN] = alist;
3644 else
3645 ri->list[RIP_FILTER_IN] = NULL;
3646 }
3647 else
3648 ri->list[RIP_FILTER_IN] = NULL;
3649
3650 if (dist->list[DISTRIBUTE_OUT])
3651 {
3652 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3653 if (alist)
3654 ri->list[RIP_FILTER_OUT] = alist;
3655 else
3656 ri->list[RIP_FILTER_OUT] = NULL;
3657 }
3658 else
3659 ri->list[RIP_FILTER_OUT] = NULL;
3660
3661 if (dist->prefix[DISTRIBUTE_IN])
3662 {
3663 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3664 if (plist)
3665 ri->prefix[RIP_FILTER_IN] = plist;
3666 else
3667 ri->prefix[RIP_FILTER_IN] = NULL;
3668 }
3669 else
3670 ri->prefix[RIP_FILTER_IN] = NULL;
3671
3672 if (dist->prefix[DISTRIBUTE_OUT])
3673 {
3674 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3675 if (plist)
3676 ri->prefix[RIP_FILTER_OUT] = plist;
3677 else
3678 ri->prefix[RIP_FILTER_OUT] = NULL;
3679 }
3680 else
3681 ri->prefix[RIP_FILTER_OUT] = NULL;
3682}
3683
3684void
3685rip_distribute_update_interface (struct interface *ifp)
3686{
3687 struct distribute *dist;
3688
3689 dist = distribute_lookup (ifp->name);
3690 if (dist)
3691 rip_distribute_update (dist);
3692}
3693
3694/* Update all interface's distribute list. */
3695void
3696rip_distribute_update_all ()
3697{
3698 struct interface *ifp;
3699 listnode node;
3700
3701 for (node = listhead (iflist); node; nextnode (node))
3702 {
3703 ifp = getdata (node);
3704 rip_distribute_update_interface (ifp);
3705 }
3706}
3707
3708/* Delete all added rip route. */
3709void
3710rip_clean ()
3711{
3712 int i;
3713 struct route_node *rp;
3714 struct rip_info *rinfo;
3715
3716 if (rip)
3717 {
3718 /* Clear RIP routes */
3719 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3720 if ((rinfo = rp->info) != NULL)
3721 {
3722 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3723 rinfo->sub_type == RIP_ROUTE_RTE)
3724 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3725 &rinfo->nexthop, rinfo->metric);
3726
3727 RIP_TIMER_OFF (rinfo->t_timeout);
3728 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3729
3730 rp->info = NULL;
3731 route_unlock_node (rp);
3732
3733 rip_info_free (rinfo);
3734 }
3735
3736 /* Cancel RIP related timers. */
3737 RIP_TIMER_OFF (rip->t_update);
3738 RIP_TIMER_OFF (rip->t_triggered_update);
3739 RIP_TIMER_OFF (rip->t_triggered_interval);
3740
3741 /* Cancel read thread. */
3742 if (rip->t_read)
3743 {
3744 thread_cancel (rip->t_read);
3745 rip->t_read = NULL;
3746 }
3747
3748 /* Close RIP socket. */
3749 if (rip->sock >= 0)
3750 {
3751 close (rip->sock);
3752 rip->sock = -1;
3753 }
3754
3755 /* Static RIP route configuration. */
3756 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3757 if (rp->info)
3758 {
3759 rp->info = NULL;
3760 route_unlock_node (rp);
3761 }
3762
3763 /* RIP neighbor configuration. */
3764 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3765 if (rp->info)
3766 {
3767 rp->info = NULL;
3768 route_unlock_node (rp);
3769 }
3770
3771 /* Redistribute related clear. */
3772 if (rip->default_information_route_map)
3773 free (rip->default_information_route_map);
3774
3775 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3776 if (rip->route_map[i].name)
3777 free (rip->route_map[i].name);
3778
3779 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3780 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3781 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3782
3783 XFREE (MTYPE_RIP, rip);
3784 rip = NULL;
3785 }
3786
3787 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003788 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003789 rip_offset_clean ();
3790 rip_interface_clean ();
3791 rip_distance_reset ();
3792 rip_redistribute_clean ();
3793}
3794
3795/* Reset all values to the default settings. */
3796void
3797rip_reset ()
3798{
3799 /* Reset global counters. */
3800 rip_global_route_changes = 0;
3801 rip_global_queries = 0;
3802
3803 /* Call ripd related reset functions. */
3804 rip_debug_reset ();
3805 rip_route_map_reset ();
3806
3807 /* Call library reset functions. */
3808 vty_reset ();
3809 access_list_reset ();
3810 prefix_list_reset ();
3811
3812 distribute_list_reset ();
3813
3814 rip_interface_reset ();
3815 rip_distance_reset ();
3816
3817 rip_zclient_reset ();
3818}
3819
hasso16705132003-05-25 14:49:19 +00003820void
3821rip_if_rmap_update (struct if_rmap *if_rmap)
3822{
3823 struct interface *ifp;
3824 struct rip_interface *ri;
3825 struct route_map *rmap;
3826
3827 ifp = if_lookup_by_name (if_rmap->ifname);
3828 if (ifp == NULL)
3829 return;
3830
3831 ri = ifp->info;
3832
3833 if (if_rmap->routemap[IF_RMAP_IN])
3834 {
3835 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3836 if (rmap)
3837 ri->routemap[IF_RMAP_IN] = rmap;
3838 else
3839 ri->routemap[IF_RMAP_IN] = NULL;
3840 }
3841 else
3842 ri->routemap[RIP_FILTER_IN] = NULL;
3843
3844 if (if_rmap->routemap[IF_RMAP_OUT])
3845 {
3846 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3847 if (rmap)
3848 ri->routemap[IF_RMAP_OUT] = rmap;
3849 else
3850 ri->routemap[IF_RMAP_OUT] = NULL;
3851 }
3852 else
3853 ri->routemap[RIP_FILTER_OUT] = NULL;
3854}
3855
3856void
3857rip_if_rmap_update_interface (struct interface *ifp)
3858{
3859 struct if_rmap *if_rmap;
3860
3861 if_rmap = if_rmap_lookup (ifp->name);
3862 if (if_rmap)
3863 rip_if_rmap_update (if_rmap);
3864}
3865
3866void
3867rip_routemap_update_redistribute (void)
3868{
3869 int i;
3870
3871 if (rip)
3872 {
3873 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3874 {
3875 if (rip->route_map[i].name)
3876 rip->route_map[i].map =
3877 route_map_lookup_by_name (rip->route_map[i].name);
3878 }
3879 }
3880}
3881
3882void
3883rip_routemap_update ()
3884{
3885 struct interface *ifp;
3886 listnode node;
3887
3888 for (node = listhead (iflist); node; nextnode (node))
3889 {
3890 ifp = getdata (node);
3891 rip_if_rmap_update_interface (ifp);
3892 }
3893
3894 rip_routemap_update_redistribute ();
3895}
3896
paul718e3742002-12-13 20:15:29 +00003897/* Allocate new rip structure and set default value. */
3898void
3899rip_init ()
3900{
3901 /* Randomize for triggered update random(). */
3902 srand (time (NULL));
3903
3904 /* Install top nodes. */
3905 install_node (&rip_node, config_write_rip);
3906
3907 /* Install rip commands. */
3908 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003909 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003910 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003911 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003912 install_element (CONFIG_NODE, &router_rip_cmd);
3913 install_element (CONFIG_NODE, &no_router_rip_cmd);
3914
3915 install_default (RIP_NODE);
3916 install_element (RIP_NODE, &rip_version_cmd);
3917 install_element (RIP_NODE, &no_rip_version_cmd);
3918 install_element (RIP_NODE, &no_rip_version_val_cmd);
3919 install_element (RIP_NODE, &rip_default_metric_cmd);
3920 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3921 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3922 install_element (RIP_NODE, &rip_timers_cmd);
3923 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003924 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003925 install_element (RIP_NODE, &rip_route_cmd);
3926 install_element (RIP_NODE, &no_rip_route_cmd);
3927 install_element (RIP_NODE, &rip_distance_cmd);
3928 install_element (RIP_NODE, &no_rip_distance_cmd);
3929 install_element (RIP_NODE, &rip_distance_source_cmd);
3930 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3931 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3932 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3933
3934 /* Debug related init. */
3935 rip_debug_init ();
3936
paul718e3742002-12-13 20:15:29 +00003937 /* SNMP init. */
3938#ifdef HAVE_SNMP
3939 rip_snmp_init ();
3940#endif /* HAVE_SNMP */
3941
3942 /* Access list install. */
3943 access_list_init ();
3944 access_list_add_hook (rip_distribute_update_all);
3945 access_list_delete_hook (rip_distribute_update_all);
3946
3947 /* Prefix list initialize.*/
3948 prefix_list_init ();
3949 prefix_list_add_hook (rip_distribute_update_all);
3950 prefix_list_delete_hook (rip_distribute_update_all);
3951
3952 /* Distribute list install. */
3953 distribute_list_init (RIP_NODE);
3954 distribute_list_add_hook (rip_distribute_update);
3955 distribute_list_delete_hook (rip_distribute_update);
3956
hasso16705132003-05-25 14:49:19 +00003957 /* Route-map */
3958 rip_route_map_init ();
3959 rip_offset_init ();
3960
3961 route_map_add_hook (rip_routemap_update);
3962 route_map_delete_hook (rip_routemap_update);
3963
3964 if_rmap_init (RIP_NODE);
3965 if_rmap_hook_add (rip_if_rmap_update);
3966 if_rmap_hook_delete (rip_if_rmap_update);
3967
paul718e3742002-12-13 20:15:29 +00003968 /* Distance control. */
3969 rip_distance_table = route_table_init ();
3970}