blob: c7ae00dad58cd74139e2e3c0b500b9d0c8338ab1 [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"
hasso1af81932004-09-26 16:11:14 +000034#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000035#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000036#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000037#include "plist.h"
38#include "distribute.h"
39#include "md5-gnu.h"
40#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000041#include "privs.h"
paul718e3742002-12-13 20:15:29 +000042
43#include "ripd/ripd.h"
44#include "ripd/rip_debug.h"
45
paul0b3acf42004-09-17 08:39:08 +000046/* UDP receive buffer size */
47#define RIP_UDP_RCV_BUF 41600
48
49/* privileges global */
pauledd7c242003-06-04 13:59:38 +000050extern struct zebra_privs_t ripd_privs;
51
paul718e3742002-12-13 20:15:29 +000052/* RIP Structure. */
53struct rip *rip = NULL;
54
55/* RIP neighbor address table. */
56struct route_table *rip_neighbor_table;
57
58/* RIP route changes. */
59long rip_global_route_changes = 0;
60
61/* RIP queries. */
62long rip_global_queries = 0;
63
64/* Prototypes. */
65void rip_event (enum rip_event, int);
66
paulc49ad8f2004-10-22 10:27:28 +000067void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
paul718e3742002-12-13 20:15:29 +000068
69/* RIP output routes type. */
70enum
71{
72 rip_all_route,
73 rip_changed_route
74};
75
76/* RIP command strings. */
77struct message rip_msg[] =
78{
79 {RIP_REQUEST, "REQUEST"},
80 {RIP_RESPONSE, "RESPONSE"},
81 {RIP_TRACEON, "TRACEON"},
82 {RIP_TRACEOFF, "TRACEOFF"},
83 {RIP_POLL, "POLL"},
84 {RIP_POLL_ENTRY, "POLL ENTRY"},
85 {0, NULL}
86};
87
88/* Each route type's strings and default preference. */
89struct
90{
91 int key;
hasso8a676be2004-10-08 06:36:38 +000092 const char *str;
93 const char *str_long;
paul718e3742002-12-13 20:15:29 +000094} route_info[] =
95{
96 { ZEBRA_ROUTE_SYSTEM, "X", "system"},
97 { ZEBRA_ROUTE_KERNEL, "K", "kernel"},
98 { ZEBRA_ROUTE_CONNECT, "C", "connected"},
99 { ZEBRA_ROUTE_STATIC, "S", "static"},
100 { ZEBRA_ROUTE_RIP, "R", "rip"},
101 { ZEBRA_ROUTE_RIPNG, "R", "ripng"},
102 { ZEBRA_ROUTE_OSPF, "O", "ospf"},
103 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"},
hasso8a676be2004-10-08 06:36:38 +0000104 { ZEBRA_ROUTE_ISIS, "I", "isis"},
paul718e3742002-12-13 20:15:29 +0000105 { ZEBRA_ROUTE_BGP, "B", "bgp"}
106};
107
108/* Utility function to set boradcast option to the socket. */
109int
110sockopt_broadcast (int sock)
111{
112 int ret;
113 int on = 1;
114
115 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
116 if (ret < 0)
117 {
118 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
119 return -1;
120 }
121 return 0;
122}
123
124int
125rip_route_rte (struct rip_info *rinfo)
126{
127 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
128}
129
130struct rip_info *
131rip_info_new ()
132{
133 struct rip_info *new;
134
135 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
136 memset (new, 0, sizeof (struct rip_info));
137 return new;
138}
139
140void
141rip_info_free (struct rip_info *rinfo)
142{
143 XFREE (MTYPE_RIP_INFO, rinfo);
144}
145
146/* RIP route garbage collect timer. */
147int
148rip_garbage_collect (struct thread *t)
149{
150 struct rip_info *rinfo;
151 struct route_node *rp;
152
153 rinfo = THREAD_ARG (t);
154 rinfo->t_garbage_collect = NULL;
155
156 /* Off timeout timer. */
157 RIP_TIMER_OFF (rinfo->t_timeout);
158
159 /* Get route_node pointer. */
160 rp = rinfo->rp;
161
162 /* Unlock route_node. */
163 rp->info = NULL;
164 route_unlock_node (rp);
165
166 /* Free RIP routing information. */
167 rip_info_free (rinfo);
168
169 return 0;
170}
171
172/* Timeout RIP routes. */
173int
174rip_timeout (struct thread *t)
175{
176 struct rip_info *rinfo;
177 struct route_node *rn;
178
179 rinfo = THREAD_ARG (t);
180 rinfo->t_timeout = NULL;
181
182 rn = rinfo->rp;
183
184 /* - The garbage-collection timer is set for 120 seconds. */
185 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
186 rip->garbage_time);
187
188 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
189 rinfo->metric);
190 /* - The metric for the route is set to 16 (infinity). This causes
191 the route to be removed from service. */
192 rinfo->metric = RIP_METRIC_INFINITY;
193 rinfo->flags &= ~RIP_RTF_FIB;
194
195 /* - The route change flag is to indicate that this entry has been
196 changed. */
197 rinfo->flags |= RIP_RTF_CHANGED;
198
199 /* - The output process is signalled to trigger a response. */
200 rip_event (RIP_TRIGGERED_UPDATE, 0);
201
202 return 0;
203}
204
205void
206rip_timeout_update (struct rip_info *rinfo)
207{
208 if (rinfo->metric != RIP_METRIC_INFINITY)
209 {
210 RIP_TIMER_OFF (rinfo->t_timeout);
211 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
212 }
213}
214
215int
216rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
217{
218 struct distribute *dist;
219 struct access_list *alist;
220 struct prefix_list *plist;
221
222 /* Input distribute-list filtering. */
223 if (ri->list[RIP_FILTER_IN])
224 {
225 if (access_list_apply (ri->list[RIP_FILTER_IN],
226 (struct prefix *) p) == FILTER_DENY)
227 {
228 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000229 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000230 inet_ntoa (p->prefix), p->prefixlen);
231 return -1;
232 }
233 }
234 if (ri->prefix[RIP_FILTER_IN])
235 {
236 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
237 (struct prefix *) p) == PREFIX_DENY)
238 {
239 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000240 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000241 inet_ntoa (p->prefix), p->prefixlen);
242 return -1;
243 }
244 }
245
246 /* All interface filter check. */
247 dist = distribute_lookup (NULL);
248 if (dist)
249 {
250 if (dist->list[DISTRIBUTE_IN])
251 {
252 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
253
254 if (alist)
255 {
256 if (access_list_apply (alist,
257 (struct prefix *) p) == FILTER_DENY)
258 {
259 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000260 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000261 inet_ntoa (p->prefix), p->prefixlen);
262 return -1;
263 }
264 }
265 }
266 if (dist->prefix[DISTRIBUTE_IN])
267 {
268 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
269
270 if (plist)
271 {
272 if (prefix_list_apply (plist,
273 (struct prefix *) p) == PREFIX_DENY)
274 {
275 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000276 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000277 inet_ntoa (p->prefix), p->prefixlen);
278 return -1;
279 }
280 }
281 }
282 }
283 return 0;
284}
285
286int
287rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
288{
289 struct distribute *dist;
290 struct access_list *alist;
291 struct prefix_list *plist;
292
293 if (ri->list[RIP_FILTER_OUT])
294 {
295 if (access_list_apply (ri->list[RIP_FILTER_OUT],
296 (struct prefix *) p) == FILTER_DENY)
297 {
298 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000299 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000300 inet_ntoa (p->prefix), p->prefixlen);
301 return -1;
302 }
303 }
304 if (ri->prefix[RIP_FILTER_OUT])
305 {
306 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
307 (struct prefix *) p) == PREFIX_DENY)
308 {
309 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000310 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000311 inet_ntoa (p->prefix), p->prefixlen);
312 return -1;
313 }
314 }
315
316 /* All interface filter check. */
317 dist = distribute_lookup (NULL);
318 if (dist)
319 {
320 if (dist->list[DISTRIBUTE_OUT])
321 {
322 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
323
324 if (alist)
325 {
326 if (access_list_apply (alist,
327 (struct prefix *) p) == FILTER_DENY)
328 {
329 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000330 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000331 inet_ntoa (p->prefix), p->prefixlen);
332 return -1;
333 }
334 }
335 }
336 if (dist->prefix[DISTRIBUTE_OUT])
337 {
338 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
339
340 if (plist)
341 {
342 if (prefix_list_apply (plist,
343 (struct prefix *) p) == PREFIX_DENY)
344 {
345 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000346 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000347 inet_ntoa (p->prefix), p->prefixlen);
348 return -1;
349 }
350 }
351 }
352 }
353 return 0;
354}
355
356/* Check nexthop address validity. */
357static int
358rip_nexthop_check (struct in_addr *addr)
359{
hasso52dc7ee2004-09-23 19:18:23 +0000360 struct listnode *node;
361 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000362 struct interface *ifp;
363 struct connected *ifc;
364 struct prefix *p;
365
366 /* If nexthop address matches local configured address then it is
367 invalid nexthop. */
368 for (node = listhead (iflist); node; nextnode (node))
369 {
370 ifp = getdata (node);
371
372 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
373 {
374 ifc = getdata (cnode);
375 p = ifc->address;
376
377 if (p->family == AF_INET
378 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
379 return -1;
380 }
381 }
382 return 0;
383}
384
385/* RIP add route to routing table. */
386void
387rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000388 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000389{
390 int ret;
391 struct prefix_ipv4 p;
392 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000393 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000394 struct rip_interface *ri;
395 struct in_addr *nexthop;
396 u_char oldmetric;
397 int same = 0;
398
399 /* Make prefix structure. */
400 memset (&p, 0, sizeof (struct prefix_ipv4));
401 p.family = AF_INET;
402 p.prefix = rte->prefix;
403 p.prefixlen = ip_masklen (rte->mask);
404
405 /* Make sure mask is applied. */
406 apply_mask_ipv4 (&p);
407
408 /* Apply input filters. */
409 ri = ifp->info;
410
411 ret = rip_incoming_filter (&p, ri);
412 if (ret < 0)
413 return;
414
hasso16705132003-05-25 14:49:19 +0000415 /* Modify entry according to the interface routemap. */
416 if (ri->routemap[RIP_FILTER_IN])
417 {
418 int ret;
419 struct rip_info newinfo;
420
421 memset (&newinfo, 0, sizeof (newinfo));
422 newinfo.type = ZEBRA_ROUTE_RIP;
423 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000424 newinfo.nexthop = rte->nexthop;
425 newinfo.from = from->sin_addr;
426 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000427 newinfo.metric = rte->metric;
428 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000429 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000430
431 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000432 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
433 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000434
435 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000436 {
437 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000438 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000439 inet_ntoa (p.prefix), p.prefixlen);
440 return;
441 }
hasso16705132003-05-25 14:49:19 +0000442
443 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000444 rte->nexthop = newinfo.nexthop_out;
445 rte->tag = htons (newinfo.tag_out); /* XXX */
446 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000447 }
448
paul718e3742002-12-13 20:15:29 +0000449 /* Once the entry has been validated, update the metric by
450 adding the cost of the network on wich the message
451 arrived. If the result is greater than infinity, use infinity
452 (RFC2453 Sec. 3.9.2) */
453 /* Zebra ripd can handle offset-list in. */
454 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
455
456 /* If offset-list does not modify the metric use interface's
457 metric. */
paula87552c2004-05-03 20:00:17 +0000458 if (!ret)
paul718e3742002-12-13 20:15:29 +0000459 rte->metric += ifp->metric;
460
461 if (rte->metric > RIP_METRIC_INFINITY)
462 rte->metric = RIP_METRIC_INFINITY;
463
464 /* Set nexthop pointer. */
465 if (rte->nexthop.s_addr == 0)
466 nexthop = &from->sin_addr;
467 else
468 nexthop = &rte->nexthop;
469
hasso16705132003-05-25 14:49:19 +0000470 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000471 if (rip_nexthop_check (nexthop) < 0)
472 {
473 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000474 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000475 return;
476 }
477
478 /* Get index for the prefix. */
479 rp = route_node_get (rip->table, (struct prefix *) &p);
480
481 /* Check to see whether there is already RIP route on the table. */
482 rinfo = rp->info;
483
484 if (rinfo)
485 {
486 /* Redistributed route check. */
487 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000488 && rinfo->metric != RIP_METRIC_INFINITY)
489 return;
paul718e3742002-12-13 20:15:29 +0000490
491 /* Local static route. */
492 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000493 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
494 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
495 && rinfo->metric != RIP_METRIC_INFINITY)
496 return;
paul718e3742002-12-13 20:15:29 +0000497 }
paula87552c2004-05-03 20:00:17 +0000498
499 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000500 {
501 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000502 for the destination prefix. If there is no such route, add
503 this route to the routing table, unless the metric is
504 infinity (there is no point in adding a route which
505 unusable). */
paul718e3742002-12-13 20:15:29 +0000506 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000507 {
508 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000509
paula87552c2004-05-03 20:00:17 +0000510 /* - Setting the destination prefix and length to those in
511 the RTE. */
512 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000513
paula87552c2004-05-03 20:00:17 +0000514 /* - Setting the metric to the newly calculated metric (as
515 described above). */
516 rinfo->metric = rte->metric;
517 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000518
paula87552c2004-05-03 20:00:17 +0000519 /* - Set the next hop address to be the address of the router
520 from which the datagram came or the next hop address
521 specified by a next hop RTE. */
522 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
523 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
524 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000525
paula87552c2004-05-03 20:00:17 +0000526 /* - Initialize the timeout for the route. If the
527 garbage-collection timer is running for this route, stop it
528 (see section 2.3 for a discussion of the timers). */
529 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Set the route change flag. */
532 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000533
paula87552c2004-05-03 20:00:17 +0000534 /* - Signal the output process to trigger an update (see section
535 2.5). */
536 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000537
paula87552c2004-05-03 20:00:17 +0000538 /* Finally, route goes into the kernel. */
539 rinfo->type = ZEBRA_ROUTE_RIP;
540 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000541
paula87552c2004-05-03 20:00:17 +0000542 /* Set distance value. */
543 rinfo->distance = rip_distance_apply (rinfo);
544
545 rp->info = rinfo;
546 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
547 rinfo->distance);
548 rinfo->flags |= RIP_RTF_FIB;
549 }
paul718e3742002-12-13 20:15:29 +0000550 }
551 else
552 {
553 /* Route is there but we are not sure the route is RIP or not. */
554 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000555
paul718e3742002-12-13 20:15:29 +0000556 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000557 to the address of the router from which the datagram came.
558 If this datagram is from the same router as the existing
559 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000560 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000561 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000562
563 if (same)
paula87552c2004-05-03 20:00:17 +0000564 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000565
paulb94f9db2004-05-01 20:45:38 +0000566
567 /* Fill in a minimaly temporary rip_info structure, for a future
568 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000569 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000570 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000571 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000572
573
paul718e3742002-12-13 20:15:29 +0000574 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000575 router as the existing route, and the new metric is different
576 than the old one; or, if the new metric is lower than the old
577 one, or if the tag has been changed; or if there is a route
578 with a lower administrave distance; or an update of the
579 distance on the actual route; do the following actions: */
580 if ((same && rinfo->metric != rte->metric)
581 || (rte->metric < rinfo->metric)
582 || ((same)
583 && (rinfo->metric == rte->metric)
584 && ntohs (rte->tag) != rinfo->tag)
585 || (rinfo->distance > rip_distance_apply (&rinfotmp))
586 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
587 {
588 /* - Adopt the route from the datagram. That is, put the
589 new metric in, and adjust the next hop address (if
590 necessary). */
591 oldmetric = rinfo->metric;
592 rinfo->metric = rte->metric;
593 rinfo->tag = ntohs (rte->tag);
594 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
595 rinfo->ifindex = ifp->ifindex;
596 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000597
paula87552c2004-05-03 20:00:17 +0000598 /* Should a new route to this network be established
599 while the garbage-collection timer is running, the
600 new route will replace the one that is about to be
601 deleted. In this case the garbage-collection timer
602 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000603
paula87552c2004-05-03 20:00:17 +0000604 if (oldmetric == RIP_METRIC_INFINITY &&
605 rinfo->metric < RIP_METRIC_INFINITY)
606 {
607 rinfo->type = ZEBRA_ROUTE_RIP;
608 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000609
paula87552c2004-05-03 20:00:17 +0000610 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
613 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000614
paula87552c2004-05-03 20:00:17 +0000615 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
616 rinfo->distance);
617 rinfo->flags |= RIP_RTF_FIB;
618 }
paul718e3742002-12-13 20:15:29 +0000619
paula87552c2004-05-03 20:00:17 +0000620 /* Update nexthop and/or metric value. */
621 if (oldmetric != RIP_METRIC_INFINITY)
622 {
623 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
624 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
625 rinfo->distance);
626 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000627
paula87552c2004-05-03 20:00:17 +0000628 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
629 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
630 }
paul718e3742002-12-13 20:15:29 +0000631
paula87552c2004-05-03 20:00:17 +0000632 /* - Set the route change flag and signal the output process
633 to trigger an update. */
634 rinfo->flags |= RIP_RTF_CHANGED;
635 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000636
paula87552c2004-05-03 20:00:17 +0000637 /* - If the new metric is infinity, start the deletion
638 process (described above); */
639 if (rinfo->metric == RIP_METRIC_INFINITY)
640 {
641 /* If the new metric is infinity, the deletion process
642 begins for the route, which is no longer used for
643 routing packets. Note that the deletion process is
644 started only when the metric is first set to
645 infinity. If the metric was already infinity, then a
646 new deletion process is not started. */
647 if (oldmetric != RIP_METRIC_INFINITY)
648 {
649 /* - The garbage-collection timer is set for 120 seconds. */
650 RIP_TIMER_ON (rinfo->t_garbage_collect,
651 rip_garbage_collect, rip->garbage_time);
652 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000653
paula87552c2004-05-03 20:00:17 +0000654 /* - The metric for the route is set to 16
655 (infinity). This causes the route to be removed
656 from service. */
657 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
658 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000659
paula87552c2004-05-03 20:00:17 +0000660 /* - The route change flag is to indicate that this
661 entry has been changed. */
662 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000663 response. */
paula87552c2004-05-03 20:00:17 +0000664 ; /* Above processes are already done previously. */
665 }
666 }
667 else
668 {
669 /* otherwise, re-initialize the timeout. */
670 rip_timeout_update (rinfo);
671 }
672 }
paul718e3742002-12-13 20:15:29 +0000673 /* Unlock tempolary lock of the route. */
674 route_unlock_node (rp);
675 }
676}
677
678/* Dump RIP packet */
679void
hasso8a676be2004-10-08 06:36:38 +0000680rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000681{
682 caddr_t lim;
683 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000684 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000685 char pbuf[BUFSIZ], nbuf[BUFSIZ];
686 u_char netmask = 0;
687 u_char *p;
688
689 /* Set command string. */
690 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
691 command_str = lookup (rip_msg, packet->command);
692 else
693 command_str = "unknown";
694
695 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000696 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000697 sndrcv, command_str, packet->version, size);
698
699 /* Dump each routing table entry. */
700 rte = packet->rte;
701
702 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
703 {
704 if (packet->version == RIPv2)
705 {
706 netmask = ip_masklen (rte->mask);
707
paulca5e5162004-06-06 22:06:33 +0000708 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000709 {
paulca5e5162004-06-06 22:06:33 +0000710 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000711 {
712 p = (u_char *)&rte->prefix;
713
ajs5d6c3772004-12-08 19:24:06 +0000714 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000715 ntohs (rte->family), ntohs (rte->tag), p);
716 }
paulca5e5162004-06-06 22:06:33 +0000717 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000718 {
719 struct rip_md5_info *md5;
720
721 md5 = (struct rip_md5_info *) &packet->rte;
722
ajs5d6c3772004-12-08 19:24:06 +0000723 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000724 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000725 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000726 " Auth Data len %d",
727 ntohs (md5->packet_len), md5->keyid,
728 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000729 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000730 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000731 }
paulca5e5162004-06-06 22:06:33 +0000732 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000733 {
734 p = (u_char *)&rte->prefix;
735
ajs5d6c3772004-12-08 19:24:06 +0000736 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000737 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000738 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000739 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000740 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
741 p[7], p[9], p[10], p[11], p[12], p[13],
742 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000743 }
744 else
745 {
ajs5d6c3772004-12-08 19:24:06 +0000746 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000747 ntohs (rte->family), ntohs (rte->tag));
748 }
749 }
750 else
ajs5d6c3772004-12-08 19:24:06 +0000751 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000752 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
753 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
754 BUFSIZ), ntohs (rte->family),
755 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000756 }
757 else
758 {
ajs5d6c3772004-12-08 19:24:06 +0000759 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000760 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
761 ntohs (rte->family), ntohs (rte->tag),
762 (u_long)ntohl (rte->metric));
763 }
764 }
765}
766
767/* Check if the destination address is valid (unicast; not net 0
768 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
769 check net 0 because we accept default route. */
770int
771rip_destination_check (struct in_addr addr)
772{
773 u_int32_t destination;
774
775 /* Convert to host byte order. */
776 destination = ntohl (addr.s_addr);
777
778 if (IPV4_NET127 (destination))
779 return 0;
780
781 /* Net 0 may match to the default route. */
782 if (IPV4_NET0 (destination) && destination != 0)
783 return 0;
784
785 /* Unicast address must belong to class A, B, C. */
786 if (IN_CLASSA (destination))
787 return 1;
788 if (IN_CLASSB (destination))
789 return 1;
790 if (IN_CLASSC (destination))
791 return 1;
792
793 return 0;
794}
795
796/* RIP version 2 authentication. */
797int
798rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
799 struct interface *ifp)
800{
801 struct rip_interface *ri;
802 char *auth_str;
803
804 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000805 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000806 inet_ntoa (from->sin_addr));
807
808 ri = ifp->info;
809
810 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000811 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000812 return 0;
813
814 /* Simple password authentication. */
815 if (ri->auth_str)
816 {
817 auth_str = (char *) &rte->prefix;
818
819 if (strncmp (auth_str, ri->auth_str, 16) == 0)
820 return 1;
821 }
822 if (ri->key_chain)
823 {
824 struct keychain *keychain;
825 struct key *key;
826
827 keychain = keychain_lookup (ri->key_chain);
828 if (keychain == NULL)
829 return 0;
830
831 key = key_match_for_accept (keychain, (char *) &rte->prefix);
832 if (key)
833 return 1;
834 }
835 return 0;
836}
837
838/* RIP version 2 authentication with MD5. */
839int
840rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000841 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
843 struct rip_interface *ri;
844 struct rip_md5_info *md5;
845 struct rip_md5_data *md5data;
846 struct keychain *keychain;
847 struct key *key;
848 struct md5_ctx ctx;
849 u_char pdigest[RIP_AUTH_MD5_SIZE];
850 u_char digest[RIP_AUTH_MD5_SIZE];
851 u_int16_t packet_len;
852 char *auth_str = NULL;
853
854 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000855 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000856 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000857
858 ri = ifp->info;
859 md5 = (struct rip_md5_info *) &packet->rte;
860
861 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000862 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000863 return 0;
864
paulca5e5162004-06-06 22:06:33 +0000865 /* If the authentication length is less than 16, then it must be wrong for
866 * any interpretation of rfc2082. Some implementations also interpret
867 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000868 */
paulca5e5162004-06-06 22:06:33 +0000869 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
870 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000871 {
872 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000873 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000874 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000875 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000876 }
paul718e3742002-12-13 20:15:29 +0000877
paulca5e5162004-06-06 22:06:33 +0000878 /* grab and verify check packet length */
879 packet_len = ntohs (md5->packet_len);
880
881 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
882 {
883 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000884 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000885 "greater than received length %d!",
886 md5->packet_len, length);
887 return 0;
888 }
889
890 /* retrieve authentication data */
891 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
892
paul718e3742002-12-13 20:15:29 +0000893 if (ri->key_chain)
894 {
895 keychain = keychain_lookup (ri->key_chain);
896 if (keychain == NULL)
897 return 0;
898
899 key = key_lookup_for_accept (keychain, md5->keyid);
900 if (key == NULL)
901 return 0;
902
903 auth_str = key->string;
904 }
905
906 if (ri->auth_str)
907 auth_str = ri->auth_str;
908
909 if (! auth_str)
910 return 0;
911
912 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000913
914 /* Save digest to pdigest. */
915 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
916
917 /* Overwrite digest by my secret. */
918 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000919 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000920
921 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000922 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000923 &ctx);
paul718e3742002-12-13 20:15:29 +0000924 md5_finish_ctx (&ctx, digest);
925
926 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
927 return packet_len;
928 else
929 return 0;
930}
931
paulb14ee002005-02-04 23:42:41 +0000932/* Pick correct auth string for sends, prepare auth_str buffer for use.
933 * (left justified and padded).
934 *
935 * presumes one of ri or key is valid, and that the auth strings they point
936 * to are nul terminated. If neither are present, auth_str will be fully
937 * zero padded.
938 *
939 */
940static void
941rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
942 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000943{
paulb14ee002005-02-04 23:42:41 +0000944 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000945
paulb14ee002005-02-04 23:42:41 +0000946 memset (auth_str, 0, len);
947 if (key && key->string)
948 strncpy (auth_str, key->string, len);
949 else if (ri->auth_str)
950 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000951
paulb14ee002005-02-04 23:42:41 +0000952 return;
953}
paul718e3742002-12-13 20:15:29 +0000954
paulb14ee002005-02-04 23:42:41 +0000955/* Write RIPv2 simple password authentication information
956 *
957 * auth_str is presumed to be 2 bytes and correctly prepared
958 * (left justified and zero padded).
959 */
960static void
961rip_auth_simple_write (struct stream *s, char *auth_str, int len)
962{
963 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +0000964
paulb14ee002005-02-04 23:42:41 +0000965 stream_putw (s, RIP_FAMILY_AUTH);
966 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
967 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
968
969 return;
970}
971
972/* write RIPv2 MD5 "authentication header"
973 * (uses the auth key data field)
974 *
975 * Digest offset field is set to 0.
976 *
977 * returns: offset of the digest offset field, which must be set when
978 * length to the auth-data MD5 digest is known.
979 */
980static size_t
981rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
982 struct key *key)
983{
984 size_t len = 0;
985
986 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +0000987
988 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000989 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000990 stream_putw (s, RIP_AUTH_MD5);
991
paulb14ee002005-02-04 23:42:41 +0000992 /* MD5 AH digest offset field.
993 *
994 * Set to placeholder value here, to true value when RIP-2 Packet length
995 * is known. Actual value is set in .....().
996 */
997 len = stream_get_putp(s);
998 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +0000999
1000 /* Key ID. */
1001 if (key)
1002 stream_putc (s, key->index % 256);
1003 else
1004 stream_putc (s, 1);
1005
paulca5e5162004-06-06 22:06:33 +00001006 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1007 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1008 * to be configurable.
1009 */
1010 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001011
1012 /* Sequence Number (non-decreasing). */
1013 /* RFC2080: The value used in the sequence number is
1014 arbitrary, but two suggestions are the time of the
1015 message's creation or a simple message counter. */
1016 stream_putl (s, time (NULL));
1017
1018 /* Reserved field must be zero. */
1019 stream_putl (s, 0);
1020 stream_putl (s, 0);
1021
paulb14ee002005-02-04 23:42:41 +00001022 return len;
1023}
paul718e3742002-12-13 20:15:29 +00001024
paulb14ee002005-02-04 23:42:41 +00001025/* If authentication is in used, write the appropriate header
1026 * returns stream offset to which length must later be written
1027 * or 0 if this is not required
1028 */
1029static size_t
1030rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1031 struct key *key, char *auth_str, int len)
1032{
1033 assert (ri->auth_type != RIP_NO_AUTH);
1034
1035 switch (ri->auth_type)
1036 {
1037 case RIP_AUTH_SIMPLE_PASSWORD:
1038 rip_auth_prepare_str_send (ri, key, auth_str, len);
1039 rip_auth_simple_write (s, auth_str, len);
1040 return 0;
1041 case RIP_AUTH_MD5:
1042 return rip_auth_md5_ah_write (s, ri, key);
1043 }
1044 assert (1);
1045}
1046
1047/* Write RIPv2 MD5 authentication data trailer */
1048static void
1049rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1050 char *auth_str, int authlen)
1051{
1052 unsigned long len;
1053 struct md5_ctx ctx;
1054 unsigned char digest[RIP_AUTH_MD5_SIZE];
1055
1056 /* Make it sure this interface is configured as MD5
1057 authentication. */
1058 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1059 assert (doff > 0);
1060
1061 /* Get packet length. */
1062 len = stream_get_endp(s);
1063
1064 /* Check packet length. */
1065 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1066 {
1067 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1068 return;
1069 }
1070
1071 /* Set the digest offset length in the header */
1072 stream_putw_at (s, doff, len);
1073
paul718e3742002-12-13 20:15:29 +00001074 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001075 stream_putw (s, RIP_FAMILY_AUTH);
1076 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001077
1078 /* Generate a digest for the RIP packet. */
paul718e3742002-12-13 20:15:29 +00001079 md5_init_ctx (&ctx);
1080 md5_process_bytes (s->data, s->endp, &ctx);
paulb14ee002005-02-04 23:42:41 +00001081 md5_process_bytes (auth_str, RIP_AUTH_MD5_SIZE, &ctx);
paul718e3742002-12-13 20:15:29 +00001082 md5_finish_ctx (&ctx, digest);
1083
1084 /* Copy the digest to the packet. */
1085 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1086}
1087
1088/* RIP routing information. */
1089void
1090rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001091 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001092{
1093 caddr_t lim;
1094 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001095 struct prefix_ipv4 ifaddr;
1096 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001097 int subnetted;
paul718e3742002-12-13 20:15:29 +00001098
paul727d1042002-12-13 20:50:29 +00001099 /* We don't know yet. */
1100 subnetted = -1;
1101
paul718e3742002-12-13 20:15:29 +00001102 /* The Response must be ignored if it is not from the RIP
1103 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001104 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001105 {
1106 zlog_info ("response doesn't come from RIP port: %d",
1107 from->sin_port);
1108 rip_peer_bad_packet (from);
1109 return;
1110 }
1111
1112 /* The datagram's IPv4 source address should be checked to see
1113 whether the datagram is from a valid neighbor; the source of the
1114 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001115 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001116 {
1117 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1118 inet_ntoa (from->sin_addr));
1119 rip_peer_bad_packet (from);
1120 return;
1121 }
1122
1123 /* It is also worth checking to see whether the response is from one
1124 of the router's own addresses. */
1125
1126 ; /* Alredy done in rip_read () */
1127
1128 /* Update RIP peer. */
1129 rip_peer_update (from, packet->version);
1130
1131 /* Set RTE pointer. */
1132 rte = packet->rte;
1133
1134 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1135 {
1136 /* RIPv2 authentication check. */
1137 /* If the Address Family Identifier of the first (and only the
1138 first) entry in the message is 0xFFFF, then the remainder of
1139 the entry contains the authentication. */
1140 /* If the packet gets here it means authentication enabled */
1141 /* Check is done in rip_read(). So, just skipping it */
1142 if (packet->version == RIPv2 &&
1143 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001144 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001145 continue;
1146
paulca5e5162004-06-06 22:06:33 +00001147 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001148 {
1149 /* Address family check. RIP only supports AF_INET. */
1150 zlog_info ("Unsupported family %d from %s.",
1151 ntohs (rte->family), inet_ntoa (from->sin_addr));
1152 continue;
1153 }
1154
1155 /* - is the destination address valid (e.g., unicast; not net 0
1156 or 127) */
1157 if (! rip_destination_check (rte->prefix))
1158 {
1159 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1160 rip_peer_bad_route (from);
1161 continue;
1162 }
1163
1164 /* Convert metric value to host byte order. */
1165 rte->metric = ntohl (rte->metric);
1166
1167 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1168 if (! (rte->metric >= 1 && rte->metric <= 16))
1169 {
1170 zlog_info ("Route's metric is not in the 1-16 range.");
1171 rip_peer_bad_route (from);
1172 continue;
1173 }
1174
1175 /* RIPv1 does not have nexthop value. */
1176 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1177 {
1178 zlog_info ("RIPv1 packet with nexthop value %s",
1179 inet_ntoa (rte->nexthop));
1180 rip_peer_bad_route (from);
1181 continue;
1182 }
1183
1184 /* That is, if the provided information is ignored, a possibly
1185 sub-optimal, but absolutely valid, route may be taken. If
1186 the received Next Hop is not directly reachable, it should be
1187 treated as 0.0.0.0. */
1188 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1189 {
1190 u_int32_t addrval;
1191
1192 /* Multicast address check. */
1193 addrval = ntohl (rte->nexthop.s_addr);
1194 if (IN_CLASSD (addrval))
1195 {
1196 zlog_info ("Nexthop %s is multicast address, skip this rte",
1197 inet_ntoa (rte->nexthop));
1198 continue;
1199 }
1200
1201 if (! if_lookup_address (rte->nexthop))
1202 {
1203 struct route_node *rn;
1204 struct rip_info *rinfo;
1205
1206 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1207
1208 if (rn)
1209 {
1210 rinfo = rn->info;
1211
1212 if (rinfo->type == ZEBRA_ROUTE_RIP
1213 && rinfo->sub_type == RIP_ROUTE_RTE)
1214 {
1215 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001216 zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001217 rte->nexthop = rinfo->from;
1218 }
1219 else
1220 {
1221 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001222 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001223 rte->nexthop.s_addr = 0;
1224 }
1225
1226 route_unlock_node (rn);
1227 }
1228 else
1229 {
1230 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001231 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001232 rte->nexthop.s_addr = 0;
1233 }
1234
1235 }
1236 }
1237
1238 /* For RIPv1, there won't be a valid netmask.
1239
1240 This is a best guess at the masks. If everyone was using old
1241 Ciscos before the 'ip subnet zero' option, it would be almost
1242 right too :-)
1243
1244 Cisco summarize ripv1 advertisments to the classful boundary
1245 (/16 for class B's) except when the RIP packet does to inside
1246 the classful network in question. */
1247
1248 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1249 || (packet->version == RIPv2
1250 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1251 {
1252 u_int32_t destination;
1253
paul727d1042002-12-13 20:50:29 +00001254 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001255 {
1256 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1257 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1258 apply_classful_mask_ipv4 (&ifaddrclass);
1259 subnetted = 0;
1260 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1261 subnetted = 1;
1262 }
paul727d1042002-12-13 20:50:29 +00001263
paul718e3742002-12-13 20:15:29 +00001264 destination = ntohl (rte->prefix.s_addr);
1265
paul727d1042002-12-13 20:50:29 +00001266 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001267 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001268 else if (IN_CLASSB (destination))
1269 masklen2ip (16, &rte->mask);
1270 else if (IN_CLASSC (destination))
1271 masklen2ip (24, &rte->mask);
1272
1273 if (subnetted == 1)
1274 masklen2ip (ifaddrclass.prefixlen,
1275 (struct in_addr *) &destination);
1276 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1277 ifaddrclass.prefix.s_addr))
1278 {
1279 masklen2ip (ifaddr.prefixlen, &rte->mask);
1280 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1281 masklen2ip (32, &rte->mask);
1282 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001283 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001284 }
1285 else
1286 {
1287 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1288 continue;
1289 }
1290
1291 if (IS_RIP_DEBUG_EVENT)
1292 {
ajs5d6c3772004-12-08 19:24:06 +00001293 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1294 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001295 }
1296 }
1297
1298 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1299 ignore the entry. */
1300 if ((packet->version == RIPv2)
1301 && (rte->mask.s_addr != 0)
1302 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1303 {
1304 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1305 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1306 rip_peer_bad_route (from);
1307 continue;
1308 }
1309
1310 /* Default route's netmask is ignored. */
1311 if (packet->version == RIPv2
1312 && (rte->prefix.s_addr == 0)
1313 && (rte->mask.s_addr != 0))
1314 {
1315 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001316 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001317 rte->mask.s_addr = 0;
1318 }
1319
1320 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001321 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001322 }
1323}
1324
paulc49ad8f2004-10-22 10:27:28 +00001325/* RIP packet send to destination address, on interface denoted by
1326 * by connected argument. NULL to argument denotes destination should be
1327 * should be RIP multicast group
1328 */
paul718e3742002-12-13 20:15:29 +00001329int
paulc49ad8f2004-10-22 10:27:28 +00001330rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1331 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001332{
paul931cd542004-01-23 15:31:42 +00001333 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001334 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001335
1336 assert (ifc != NULL);
1337
paul931cd542004-01-23 15:31:42 +00001338 if (IS_RIP_DEBUG_PACKET)
1339 {
1340 char dst[20];
1341 if (to)
1342 {
1343 strcpy(dst, inet_ntoa(to->sin_addr));
1344 }
1345 else
1346 {
1347 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1348 strcpy(dst, inet_ntoa(sin.sin_addr));
1349 }
ajs5d6c3772004-12-08 19:24:06 +00001350 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001351 inet_ntoa(ifc->address->u.prefix4),
1352 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001353 }
paulc49ad8f2004-10-22 10:27:28 +00001354 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001355 {
1356 /*
1357 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1358 * with multiple addresses on the same subnet: the first address
1359 * on the subnet is configured "primary", and all subsequent addresses
1360 * on that subnet are treated as "secondary" addresses.
1361 * In order to avoid routing-table bloat on other rip listeners,
1362 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1363 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1364 * flag is set, we would end up sending a packet for a "secondary"
1365 * source address on non-linux systems.
1366 */
1367 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001368 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001369 return 0;
1370 }
1371
paul718e3742002-12-13 20:15:29 +00001372 /* Make destination address. */
1373 memset (&sin, 0, sizeof (struct sockaddr_in));
1374 sin.sin_family = AF_INET;
1375#ifdef HAVE_SIN_LEN
1376 sin.sin_len = sizeof (struct sockaddr_in);
1377#endif /* HAVE_SIN_LEN */
1378
1379 /* When destination is specified, use it's port and address. */
1380 if (to)
1381 {
paul718e3742002-12-13 20:15:29 +00001382 sin.sin_port = to->sin_port;
1383 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001384 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001385 }
1386 else
1387 {
paul718e3742002-12-13 20:15:29 +00001388
1389 sin.sin_port = htons (RIP_PORT_DEFAULT);
1390 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1391
paul931cd542004-01-23 15:31:42 +00001392 /*
1393 * we have to open a new socket for each packet because this
1394 * is the most portable way to bind to a different source
1395 * ipv4 address for each packet.
1396 */
1397 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1398 if (send_sock < 0)
1399 {
1400 zlog_warn("rip_send_packet could not create socket %s",
ajs6099b3b2004-11-20 02:06:59 +00001401 safe_strerror(errno));
paul931cd542004-01-23 15:31:42 +00001402 return -1;
1403 }
1404 sockopt_broadcast (send_sock);
1405 sockopt_reuseaddr (send_sock);
1406 sockopt_reuseport (send_sock);
1407#ifdef RIP_RECVMSG
1408 setsockopt_pktinfo (send_sock);
1409#endif /* RIP_RECVMSG */
paulc49ad8f2004-10-22 10:27:28 +00001410 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001411 }
1412
paul931cd542004-01-23 15:31:42 +00001413 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001414 sizeof (struct sockaddr_in));
1415
1416 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001417 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001418 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001419
1420 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001421 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001422
paul931cd542004-01-23 15:31:42 +00001423 if (!to)
1424 close(send_sock);
1425
paul718e3742002-12-13 20:15:29 +00001426 return ret;
1427}
1428
1429/* Add redistributed route to RIP table. */
1430void
1431rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1432 unsigned int ifindex, struct in_addr *nexthop)
1433{
1434 int ret;
1435 struct route_node *rp;
1436 struct rip_info *rinfo;
1437
1438 /* Redistribute route */
1439 ret = rip_destination_check (p->prefix);
1440 if (! ret)
1441 return;
1442
1443 rp = route_node_get (rip->table, (struct prefix *) p);
1444
1445 rinfo = rp->info;
1446
1447 if (rinfo)
1448 {
1449 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1450 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1451 && rinfo->metric != RIP_METRIC_INFINITY)
1452 {
1453 route_unlock_node (rp);
1454 return;
1455 }
1456
1457 /* Manually configured RIP route check. */
1458 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001459 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1460 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001461 {
hasso16705132003-05-25 14:49:19 +00001462 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1463 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001464 {
1465 route_unlock_node (rp);
1466 return;
1467 }
1468 }
1469
1470 RIP_TIMER_OFF (rinfo->t_timeout);
1471 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1472
1473 if (rip_route_rte (rinfo))
1474 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1475 rinfo->metric);
1476 rp->info = NULL;
1477 rip_info_free (rinfo);
1478
1479 route_unlock_node (rp);
1480 }
1481
1482 rinfo = rip_info_new ();
1483
1484 rinfo->type = type;
1485 rinfo->sub_type = sub_type;
1486 rinfo->ifindex = ifindex;
1487 rinfo->metric = 1;
1488 rinfo->rp = rp;
1489
1490 if (nexthop)
1491 rinfo->nexthop = *nexthop;
1492
1493 rinfo->flags |= RIP_RTF_FIB;
1494 rp->info = rinfo;
1495
1496 rinfo->flags |= RIP_RTF_CHANGED;
1497
hasso16705132003-05-25 14:49:19 +00001498 if (IS_RIP_DEBUG_EVENT) {
1499 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001500 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001501 inet_ntoa(p->prefix), p->prefixlen,
1502 ifindex2ifname(ifindex));
1503 else
ajs5d6c3772004-12-08 19:24:06 +00001504 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001505 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1506 ifindex2ifname(ifindex));
1507 }
1508
1509
paul718e3742002-12-13 20:15:29 +00001510 rip_event (RIP_TRIGGERED_UPDATE, 0);
1511}
1512
1513/* Delete redistributed route from RIP table. */
1514void
1515rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1516 unsigned int ifindex)
1517{
1518 int ret;
1519 struct route_node *rp;
1520 struct rip_info *rinfo;
1521
1522 ret = rip_destination_check (p->prefix);
1523 if (! ret)
1524 return;
1525
1526 rp = route_node_lookup (rip->table, (struct prefix *) p);
1527 if (rp)
1528 {
1529 rinfo = rp->info;
1530
1531 if (rinfo != NULL
1532 && rinfo->type == type
1533 && rinfo->sub_type == sub_type
1534 && rinfo->ifindex == ifindex)
1535 {
1536 /* Perform poisoned reverse. */
1537 rinfo->metric = RIP_METRIC_INFINITY;
1538 RIP_TIMER_ON (rinfo->t_garbage_collect,
1539 rip_garbage_collect, rip->garbage_time);
1540 RIP_TIMER_OFF (rinfo->t_timeout);
1541 rinfo->flags |= RIP_RTF_CHANGED;
1542
hasso16705132003-05-25 14:49:19 +00001543 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001544 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001545 inet_ntoa(p->prefix), p->prefixlen,
1546 ifindex2ifname(ifindex));
1547
paul718e3742002-12-13 20:15:29 +00001548 rip_event (RIP_TRIGGERED_UPDATE, 0);
1549 }
1550 }
1551}
1552
1553/* Response to request called from rip_read ().*/
1554void
1555rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001556 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001557{
1558 caddr_t lim;
1559 struct rte *rte;
1560 struct prefix_ipv4 p;
1561 struct route_node *rp;
1562 struct rip_info *rinfo;
1563 struct rip_interface *ri;
1564
hasso16705132003-05-25 14:49:19 +00001565 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001566 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001567 return;
1568
hasso429a0f82004-02-22 23:42:22 +00001569 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001570 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001571 if (! ri->running)
1572 return;
paul718e3742002-12-13 20:15:29 +00001573
1574 /* When passive interface is specified, suppress responses */
1575 if (ri->passive)
1576 return;
paulc49ad8f2004-10-22 10:27:28 +00001577
paul718e3742002-12-13 20:15:29 +00001578 /* RIP peer update. */
1579 rip_peer_update (from, packet->version);
1580
1581 lim = ((caddr_t) packet) + size;
1582 rte = packet->rte;
1583
1584 /* The Request is processed entry by entry. If there are no
1585 entries, no response is given. */
1586 if (lim == (caddr_t) rte)
1587 return;
1588
1589 /* There is one special case. If there is exactly one entry in the
1590 request, and it has an address family identifier of zero and a
1591 metric of infinity (i.e., 16), then this is a request to send the
1592 entire routing table. */
1593 if (lim == ((caddr_t) (rte + 1)) &&
1594 ntohs (rte->family) == 0 &&
1595 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1596 {
paulcc1131a2003-10-15 23:20:17 +00001597 struct prefix_ipv4 saddr;
1598
1599 /* saddr will be used for determining which routes to split-horizon.
1600 Since the source address we'll pick will be on the same subnet as the
1601 destination, for the purpose of split-horizoning, we'll
1602 pretend that "from" is our source address. */
1603 saddr.family = AF_INET;
1604 saddr.prefixlen = IPV4_MAX_BITLEN;
1605 saddr.prefix = from->sin_addr;
1606
paul718e3742002-12-13 20:15:29 +00001607 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001608 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001609 }
1610 else
1611 {
1612 /* Examine the list of RTEs in the Request one by one. For each
1613 entry, look up the destination in the router's routing
1614 database and, if there is a route, put that route's metric in
1615 the metric field of the RTE. If there is no explicit route
1616 to the specified destination, put infinity in the metric
1617 field. Once all the entries have been filled in, change the
1618 command from Request to Response and send the datagram back
1619 to the requestor. */
1620 p.family = AF_INET;
1621
1622 for (; ((caddr_t) rte) < lim; rte++)
1623 {
1624 p.prefix = rte->prefix;
1625 p.prefixlen = ip_masklen (rte->mask);
1626 apply_mask_ipv4 (&p);
1627
1628 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1629 if (rp)
1630 {
1631 rinfo = rp->info;
1632 rte->metric = htonl (rinfo->metric);
1633 route_unlock_node (rp);
1634 }
1635 else
1636 rte->metric = htonl (RIP_METRIC_INFINITY);
1637 }
1638 packet->command = RIP_RESPONSE;
1639
paulc49ad8f2004-10-22 10:27:28 +00001640 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001641 }
1642 rip_global_queries++;
1643}
1644
1645#if RIP_RECVMSG
1646/* Set IPv6 packet info to the socket. */
1647static int
1648setsockopt_pktinfo (int sock)
1649{
1650 int ret;
1651 int val = 1;
1652
1653 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1654 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001655 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001656 return ret;
1657}
1658
1659/* Read RIP packet by recvmsg function. */
1660int
1661rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1662 int *ifindex)
1663{
1664 int ret;
1665 struct msghdr msg;
1666 struct iovec iov;
1667 struct cmsghdr *ptr;
1668 char adata[1024];
1669
1670 msg.msg_name = (void *) from;
1671 msg.msg_namelen = sizeof (struct sockaddr_in);
1672 msg.msg_iov = &iov;
1673 msg.msg_iovlen = 1;
1674 msg.msg_control = (void *) adata;
1675 msg.msg_controllen = sizeof adata;
1676 iov.iov_base = buf;
1677 iov.iov_len = size;
1678
1679 ret = recvmsg (sock, &msg, 0);
1680 if (ret < 0)
1681 return ret;
1682
ajsb99760a2005-01-04 16:24:43 +00001683 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001684 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1685 {
1686 struct in_pktinfo *pktinfo;
1687 int i;
1688
1689 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1690 i = pktinfo->ipi_ifindex;
1691 }
1692 return ret;
1693}
1694
1695/* RIP packet read function. */
1696int
1697rip_read_new (struct thread *t)
1698{
1699 int ret;
1700 int sock;
1701 char buf[RIP_PACKET_MAXSIZ];
1702 struct sockaddr_in from;
1703 unsigned int ifindex;
1704
1705 /* Fetch socket then register myself. */
1706 sock = THREAD_FD (t);
1707 rip_event (RIP_READ, sock);
1708
1709 /* Read RIP packet. */
1710 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1711 if (ret < 0)
1712 {
ajs6099b3b2004-11-20 02:06:59 +00001713 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001714 return ret;
1715 }
1716
1717 return ret;
1718}
1719#endif /* RIP_RECVMSG */
1720
1721/* First entry point of RIP packet. */
1722int
1723rip_read (struct thread *t)
1724{
1725 int sock;
1726 int ret;
1727 int rtenum;
1728 union rip_buf rip_buf;
1729 struct rip_packet *packet;
1730 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001731 int len;
1732 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001733 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001734 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001735 struct rip_interface *ri;
1736
1737 /* Fetch socket then register myself. */
1738 sock = THREAD_FD (t);
1739 rip->t_read = NULL;
1740
1741 /* Add myself to tne next event */
1742 rip_event (RIP_READ, sock);
1743
1744 /* RIPd manages only IPv4. */
1745 memset (&from, 0, sizeof (struct sockaddr_in));
1746 fromlen = sizeof (struct sockaddr_in);
1747
1748 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1749 (struct sockaddr *) &from, &fromlen);
1750 if (len < 0)
1751 {
ajs6099b3b2004-11-20 02:06:59 +00001752 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001753 return len;
1754 }
1755
1756 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001757 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001758 {
1759 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001760 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001761 return -1;
1762 }
1763
1764 /* Which interface is this packet comes from. */
1765 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001766
paul718e3742002-12-13 20:15:29 +00001767 /* RIP packet received */
1768 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001769 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001770 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1771 ifp ? ifp->name : "unknown");
1772
1773 /* If this packet come from unknown interface, ignore it. */
1774 if (ifp == NULL)
1775 {
ajs766a0ca2004-12-15 14:55:51 +00001776 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1777 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001778 return -1;
1779 }
1780
1781 ifc = connected_lookup_address (ifp, from.sin_addr);
1782
1783 if (ifc == NULL)
1784 {
ajs766a0ca2004-12-15 14:55:51 +00001785 zlog_info ("rip_read: cannot find connected address for packet from %s "
1786 "port %d on interface %s",
1787 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001788 return -1;
1789 }
1790
1791 /* Packet length check. */
1792 if (len < RIP_PACKET_MINSIZ)
1793 {
1794 zlog_warn ("packet size %d is smaller than minimum size %d",
1795 len, RIP_PACKET_MINSIZ);
1796 rip_peer_bad_packet (&from);
1797 return len;
1798 }
1799 if (len > RIP_PACKET_MAXSIZ)
1800 {
1801 zlog_warn ("packet size %d is larger than max size %d",
1802 len, RIP_PACKET_MAXSIZ);
1803 rip_peer_bad_packet (&from);
1804 return len;
1805 }
1806
1807 /* Packet alignment check. */
1808 if ((len - RIP_PACKET_MINSIZ) % 20)
1809 {
1810 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1811 rip_peer_bad_packet (&from);
1812 return len;
1813 }
1814
1815 /* Set RTE number. */
1816 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1817
1818 /* For easy to handle. */
1819 packet = &rip_buf.rip_packet;
1820
1821 /* RIP version check. */
1822 if (packet->version == 0)
1823 {
1824 zlog_info ("version 0 with command %d received.", packet->command);
1825 rip_peer_bad_packet (&from);
1826 return -1;
1827 }
1828
1829 /* Dump RIP packet. */
1830 if (IS_RIP_DEBUG_RECV)
1831 rip_packet_dump (packet, len, "RECV");
1832
1833 /* RIP version adjust. This code should rethink now. RFC1058 says
1834 that "Version 1 implementations are to ignore this extra data and
1835 process only the fields specified in this document.". So RIPv3
1836 packet should be treated as RIPv1 ignoring must be zero field. */
1837 if (packet->version > RIPv2)
1838 packet->version = RIPv2;
1839
1840 /* Is RIP running or is this RIP neighbor ?*/
1841 ri = ifp->info;
1842 if (! ri->running && ! rip_neighbor_lookup (&from))
1843 {
1844 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001845 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001846 rip_peer_bad_packet (&from);
1847 return -1;
1848 }
1849
1850 /* RIP Version check. */
1851 if (packet->command == RIP_RESPONSE)
1852 {
paulf38a4712003-06-07 01:10:00 +00001853 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1854 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001855 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001856 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001857 {
1858 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001859 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001860 packet->version);
1861 rip_peer_bad_packet (&from);
1862 return -1;
1863 }
1864 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001865 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001866 {
1867 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001868 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001869 packet->version);
1870 rip_peer_bad_packet (&from);
1871 return -1;
1872 }
paul718e3742002-12-13 20:15:29 +00001873 }
1874
1875 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1876 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1877 accepted; authenticated RIP-2 messages shall be discarded. */
1878
1879 if ((ri->auth_type == RIP_NO_AUTH)
1880 && rtenum
paulca5e5162004-06-06 22:06:33 +00001881 && (packet->version == RIPv2)
1882 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001883 {
1884 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001885 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001886 packet->version);
1887 rip_peer_bad_packet (&from);
1888 return -1;
1889 }
1890
1891 /* If the router is configured to authenticate RIP-2 messages, then
1892 RIP-1 messages and RIP-2 messages which pass authentication
1893 testing shall be accepted; unauthenticated and failed
1894 authentication RIP-2 messages shall be discarded. For maximum
1895 security, RIP-1 messages should be ignored when authentication is
1896 in use (see section 4.1); otherwise, the routing information from
1897 authenticated messages will be propagated by RIP-1 routers in an
1898 unauthenticated manner. */
1899
1900 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001901 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001902 {
1903 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001904 if (packet->version == RIPv1
1905 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001906 {
1907 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001908 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001909 ("packet RIPv%d is dropped because authentication enabled",
1910 packet->version);
paul718e3742002-12-13 20:15:29 +00001911 rip_peer_bad_packet (&from);
1912 return -1;
1913 }
1914
1915 /* Check RIPv2 authentication. */
1916 if (packet->version == RIPv2)
1917 {
paulca5e5162004-06-06 22:06:33 +00001918 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001919 {
paulca5e5162004-06-06 22:06:33 +00001920 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001921 {
1922 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1923 if (! ret)
1924 {
1925 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001926 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001927 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001928 rip_peer_bad_packet (&from);
1929 return -1;
1930 }
1931 else
1932 {
1933 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001934 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001935 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001936 }
1937 }
paulca5e5162004-06-06 22:06:33 +00001938 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001939 {
paulca5e5162004-06-06 22:06:33 +00001940 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001941 if (! ret)
1942 {
1943 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001944 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001945 rip_peer_bad_packet (&from);
1946 return -1;
1947 }
1948 else
1949 {
1950 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001951 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001952 }
1953 /* Reset RIP packet length to trim MD5 data. */
1954 len = ret;
1955 }
1956 else
1957 {
1958 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001959 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00001960 ntohs (packet->rte->tag));
1961 rip_peer_bad_packet (&from);
1962 return -1;
1963 }
1964 }
1965 else
1966 {
1967 /* There is no authentication in the packet. */
1968 if (ri->auth_str || ri->key_chain)
1969 {
1970 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001971 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001972 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001973 rip_peer_bad_packet (&from);
1974 return -1;
1975 }
1976 }
1977 }
1978 }
1979
1980 /* Process each command. */
1981 switch (packet->command)
1982 {
1983 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00001984 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001985 break;
1986 case RIP_REQUEST:
1987 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00001988 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001989 break;
1990 case RIP_TRACEON:
1991 case RIP_TRACEOFF:
1992 zlog_info ("Obsolete command %s received, please sent it to routed",
1993 lookup (rip_msg, packet->command));
1994 rip_peer_bad_packet (&from);
1995 break;
1996 case RIP_POLL_ENTRY:
1997 zlog_info ("Obsolete command %s received",
1998 lookup (rip_msg, packet->command));
1999 rip_peer_bad_packet (&from);
2000 break;
2001 default:
2002 zlog_info ("Unknown RIP command %d received", packet->command);
2003 rip_peer_bad_packet (&from);
2004 break;
2005 }
2006
2007 return len;
2008}
2009
2010/* Make socket for RIP protocol. */
2011int
2012rip_create_socket ()
2013{
2014 int ret;
2015 int sock;
2016 struct sockaddr_in addr;
2017 struct servent *sp;
2018
2019 memset (&addr, 0, sizeof (struct sockaddr_in));
2020
2021 /* Set RIP port. */
2022 sp = getservbyname ("router", "udp");
2023 if (sp)
2024 addr.sin_port = sp->s_port;
2025 else
2026 addr.sin_port = htons (RIP_PORT_DEFAULT);
2027
2028 /* Address shoud be any address. */
2029 addr.sin_family = AF_INET;
2030 addr.sin_addr.s_addr = INADDR_ANY;
2031
2032 /* Make datagram socket. */
2033 sock = socket (AF_INET, SOCK_DGRAM, 0);
2034 if (sock < 0)
2035 {
ajs6a52d0d2005-01-30 18:49:28 +00002036 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +00002037 exit (1);
2038 }
2039
2040 sockopt_broadcast (sock);
2041 sockopt_reuseaddr (sock);
2042 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00002043 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00002044#ifdef RIP_RECVMSG
2045 setsockopt_pktinfo (sock);
2046#endif /* RIP_RECVMSG */
2047
pauledd7c242003-06-04 13:59:38 +00002048 if (ripd_privs.change (ZPRIVS_RAISE))
2049 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00002050 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
2051 if (ret < 0)
2052 {
ajs79853452005-01-30 17:40:29 +00002053 int save_errno = errno;
pauld62262a2003-11-17 09:08:45 +00002054 if (ripd_privs.change (ZPRIVS_LOWER))
2055 zlog_err ("rip_create_socket: could not lower privs");
ajs79853452005-01-30 17:40:29 +00002056 zlog_err("cannot bind to port %d: %s",
2057 (int)ntohs(addr.sin_port), safe_strerror(save_errno));
paul718e3742002-12-13 20:15:29 +00002058 return ret;
2059 }
pauledd7c242003-06-04 13:59:38 +00002060 if (ripd_privs.change (ZPRIVS_LOWER))
2061 zlog_err ("rip_create_socket: could not lower privs");
2062
paul718e3742002-12-13 20:15:29 +00002063 return sock;
2064}
2065
paulb14ee002005-02-04 23:42:41 +00002066
paul718e3742002-12-13 20:15:29 +00002067/* Write routing table entry to the stream and return next index of
2068 the routing table entry in the stream. */
2069int
2070rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002071 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002072{
2073 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002074
2075 /* Write routing table entry. */
2076 if (version == RIPv1)
2077 {
2078 stream_putw (s, AF_INET);
2079 stream_putw (s, 0);
2080 stream_put_ipv4 (s, p->prefix.s_addr);
2081 stream_put_ipv4 (s, 0);
2082 stream_put_ipv4 (s, 0);
2083 stream_putl (s, rinfo->metric_out);
2084 }
2085 else
2086 {
2087 masklen2ip (p->prefixlen, &mask);
2088
2089 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002090 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002091 stream_put_ipv4 (s, p->prefix.s_addr);
2092 stream_put_ipv4 (s, mask.s_addr);
2093 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2094 stream_putl (s, rinfo->metric_out);
2095 }
2096
2097 return ++num;
2098}
2099
2100/* Send update to the ifp or spcified neighbor. */
2101void
paulc49ad8f2004-10-22 10:27:28 +00002102rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2103 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002104{
2105 int ret;
2106 struct stream *s;
2107 struct route_node *rp;
2108 struct rip_info *rinfo;
2109 struct rip_interface *ri;
2110 struct prefix_ipv4 *p;
2111 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002112 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002113 struct key *key = NULL;
2114 /* this might need to made dynamic if RIP ever supported auth methods
2115 with larger key string sizes */
2116 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2117 size_t doff; /* offset of digest offset field */
paul718e3742002-12-13 20:15:29 +00002118 int num;
2119 int rtemax;
paul01d09082003-06-08 21:22:18 +00002120 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002121
2122 /* Logging output event. */
2123 if (IS_RIP_DEBUG_EVENT)
2124 {
2125 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002126 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002127 else
ajs5d6c3772004-12-08 19:24:06 +00002128 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002129 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002130 }
2131
2132 /* Set output stream. */
2133 s = rip->obuf;
2134
2135 /* Reset stream and RTE counter. */
2136 stream_reset (s);
2137 num = 0;
2138 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2139
2140 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002141 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002142
2143 /* If output interface is in simple password authentication mode, we
2144 need space for authentication data. */
2145 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2146 rtemax -= 1;
2147
2148 /* If output interface is in MD5 authentication mode, we need space
2149 for authentication header and data. */
2150 if (ri->auth_type == RIP_AUTH_MD5)
2151 rtemax -= 2;
2152
2153 /* If output interface is in simple password authentication mode
2154 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002155 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002156 {
2157 if (ri->key_chain)
2158 {
2159 struct keychain *keychain;
2160
2161 keychain = keychain_lookup (ri->key_chain);
2162 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002163 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002164 }
paulb14ee002005-02-04 23:42:41 +00002165 /* to be passed to auth functions later */
2166 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002167 }
2168
paul727d1042002-12-13 20:50:29 +00002169 if (version == RIPv1)
2170 {
paulc49ad8f2004-10-22 10:27:28 +00002171 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002172 apply_classful_mask_ipv4 (&ifaddrclass);
2173 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002174 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002175 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002176 }
2177
paul718e3742002-12-13 20:15:29 +00002178 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2179 if ((rinfo = rp->info) != NULL)
2180 {
paul727d1042002-12-13 20:50:29 +00002181 /* For RIPv1, if we are subnetted, output subnets in our network */
2182 /* that have the same mask as the output "interface". For other */
2183 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002184
2185 if (version == RIPv1)
2186 {
paul727d1042002-12-13 20:50:29 +00002187 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002188
2189 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002190 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002191 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002192
paul727d1042002-12-13 20:50:29 +00002193 if (subnetted &&
2194 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2195 {
paulc49ad8f2004-10-22 10:27:28 +00002196 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002197 (rp->p.prefixlen != 32))
2198 continue;
2199 }
2200 else
2201 {
2202 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2203 apply_classful_mask_ipv4(&classfull);
2204 if (rp->p.u.prefix4.s_addr != 0 &&
2205 classfull.prefixlen != rp->p.prefixlen)
2206 continue;
2207 }
paul718e3742002-12-13 20:15:29 +00002208 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002209 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002210 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002211 }
2212 else
2213 p = (struct prefix_ipv4 *) &rp->p;
2214
2215 /* Apply output filters. */
2216 ret = rip_outgoing_filter (p, ri);
2217 if (ret < 0)
2218 continue;
2219
2220 /* Changed route only output. */
2221 if (route_type == rip_changed_route &&
2222 (! (rinfo->flags & RIP_RTF_CHANGED)))
2223 continue;
2224
2225 /* Split horizon. */
2226 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002227 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002228 {
paul42d14d92003-11-17 09:15:18 +00002229 /*
2230 * We perform split horizon for RIP and connected route.
2231 * For rip routes, we want to suppress the route if we would
2232 * end up sending the route back on the interface that we
2233 * learned it from, with a higher metric. For connected routes,
2234 * we suppress the route if the prefix is a subset of the
2235 * source address that we are going to use for the packet
2236 * (in order to handle the case when multiple subnets are
2237 * configured on the same interface).
2238 */
2239 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002240 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002241 continue;
2242 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002243 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002244 continue;
2245 }
2246
2247 /* Preparation for route-map. */
2248 rinfo->metric_set = 0;
2249 rinfo->nexthop_out.s_addr = 0;
2250 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002251 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002252 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002253
hasso16705132003-05-25 14:49:19 +00002254 /* In order to avoid some local loops,
2255 * if the RIP route has a nexthop via this interface, keep the nexthop,
2256 * otherwise set it to 0. The nexthop should not be propagated
2257 * beyond the local broadcast/multicast area in order
2258 * to avoid an IGP multi-level recursive look-up.
2259 * see (4.4)
2260 */
paulc49ad8f2004-10-22 10:27:28 +00002261 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002262 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002263
2264 /* Interface route-map */
2265 if (ri->routemap[RIP_FILTER_OUT])
2266 {
2267 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2268 (struct prefix *) p, RMAP_RIP,
2269 rinfo);
2270
2271 if (ret == RMAP_DENYMATCH)
2272 {
2273 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002274 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002275 inet_ntoa (p->prefix), p->prefixlen);
2276 continue;
2277 }
2278 }
paul718e3742002-12-13 20:15:29 +00002279
hasso16705132003-05-25 14:49:19 +00002280 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002281 if (rip->route_map[rinfo->type].name
2282 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2283 {
2284 ret = route_map_apply (rip->route_map[rinfo->type].map,
2285 (struct prefix *)p, RMAP_RIP, rinfo);
2286
2287 if (ret == RMAP_DENYMATCH)
2288 {
2289 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002290 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002291 inet_ntoa (p->prefix), p->prefixlen);
2292 continue;
2293 }
2294 }
2295
2296 /* When route-map does not set metric. */
2297 if (! rinfo->metric_set)
2298 {
2299 /* If redistribute metric is set. */
2300 if (rip->route_map[rinfo->type].metric_config
2301 && rinfo->metric != RIP_METRIC_INFINITY)
2302 {
2303 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2304 }
2305 else
2306 {
2307 /* If the route is not connected or localy generated
2308 one, use default-metric value*/
2309 if (rinfo->type != ZEBRA_ROUTE_RIP
2310 && rinfo->type != ZEBRA_ROUTE_CONNECT
2311 && rinfo->metric != RIP_METRIC_INFINITY)
2312 rinfo->metric_out = rip->default_metric;
2313 }
2314 }
2315
2316 /* Apply offset-list */
2317 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002318 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002319
2320 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2321 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002322
2323 /* Perform split-horizon with poisoned reverse
2324 * for RIP and connected routes.
2325 **/
2326 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002327 /*
2328 * We perform split horizon for RIP and connected route.
2329 * For rip routes, we want to suppress the route if we would
2330 * end up sending the route back on the interface that we
2331 * learned it from, with a higher metric. For connected routes,
2332 * we suppress the route if the prefix is a subset of the
2333 * source address that we are going to use for the packet
2334 * (in order to handle the case when multiple subnets are
2335 * configured on the same interface).
2336 */
2337 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002338 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002339 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002340 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002341 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002342 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002343 }
paulb14ee002005-02-04 23:42:41 +00002344
2345 /* Prepare preamble, auth headers, if needs be */
2346 if (num == 0)
2347 {
2348 stream_putc (s, RIP_RESPONSE);
2349 stream_putc (s, version);
2350 stream_putw (s, 0);
2351
2352 /* auth header for simple or v2 && MD5 */
2353 if ( (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2354 || (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) )
2355 doff = rip_auth_header_write (s, ri, key, auth_str,
2356 RIP_AUTH_SIMPLE_SIZE);
2357 }
2358
paul718e3742002-12-13 20:15:29 +00002359 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002360 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002361 if (num == rtemax)
2362 {
2363 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002364 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002365
2366 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002367 to, ifc);
paul718e3742002-12-13 20:15:29 +00002368
2369 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2370 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2371 stream_get_endp(s), "SEND");
2372 num = 0;
2373 stream_reset (s);
2374 }
2375 }
2376
2377 /* Flush unwritten RTE. */
2378 if (num != 0)
2379 {
2380 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002381 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002382
paulc49ad8f2004-10-22 10:27:28 +00002383 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002384
2385 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2386 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2387 stream_get_endp (s), "SEND");
2388 num = 0;
2389 stream_reset (s);
2390 }
2391
2392 /* Statistics updates. */
2393 ri->sent_updates++;
2394}
2395
2396/* Send RIP packet to the interface. */
2397void
paulc49ad8f2004-10-22 10:27:28 +00002398rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002399{
paul718e3742002-12-13 20:15:29 +00002400 struct sockaddr_in to;
2401
2402 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002403 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002404 {
2405 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002406 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002407
paulc49ad8f2004-10-22 10:27:28 +00002408 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002409 return;
2410 }
paulc49ad8f2004-10-22 10:27:28 +00002411
paul718e3742002-12-13 20:15:29 +00002412 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002413 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002414 {
paulc49ad8f2004-10-22 10:27:28 +00002415 if (ifc->address->family == AF_INET)
2416 {
2417 /* Destination address and port setting. */
2418 memset (&to, 0, sizeof (struct sockaddr_in));
2419 if (ifc->destination)
2420 /* use specified broadcast or point-to-point destination addr */
2421 to.sin_addr = ifc->destination->u.prefix4;
2422 else
2423 /* calculate the appropriate broadcast address */
2424 to.sin_addr.s_addr =
2425 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2426 ifc->address->prefixlen);
2427 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002428
paulc49ad8f2004-10-22 10:27:28 +00002429 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002430 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002431 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2432 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002433
paulc49ad8f2004-10-22 10:27:28 +00002434 rip_output_process (ifc, &to, route_type, version);
2435 }
paul718e3742002-12-13 20:15:29 +00002436 }
2437}
2438
2439/* Update send to all interface and neighbor. */
2440void
2441rip_update_process (int route_type)
2442{
hasso52dc7ee2004-09-23 19:18:23 +00002443 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002444 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002445 struct interface *ifp;
2446 struct rip_interface *ri;
2447 struct route_node *rp;
2448 struct sockaddr_in to;
2449 struct prefix_ipv4 *p;
2450
2451 /* Send RIP update to each interface. */
2452 for (node = listhead (iflist); node; nextnode (node))
2453 {
2454 ifp = getdata (node);
2455
2456 if (if_is_loopback (ifp))
2457 continue;
2458
paul2e3b2e42002-12-13 21:03:13 +00002459 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002460 continue;
2461
2462 /* Fetch RIP interface information. */
2463 ri = ifp->info;
2464
2465 /* When passive interface is specified, suppress announce to the
2466 interface. */
2467 if (ri->passive)
2468 continue;
2469
2470 if (ri->running)
2471 {
2472 if (IS_RIP_DEBUG_EVENT)
2473 {
2474 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002475 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002476 ifp->name, ifp->ifindex);
2477 else
ajs5d6c3772004-12-08 19:24:06 +00002478 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002479 ifp->ifindex);
2480 }
2481
paulcc1131a2003-10-15 23:20:17 +00002482 /* send update on each connected network */
2483
2484 LIST_LOOP(ifp->connected, connected, ifnode)
2485 {
2486 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002487 int done = 0;
2488 /*
2489 * If there is no version configuration in the interface,
2490 * use rip's version setting.
2491 */
paulf38a4712003-06-07 01:10:00 +00002492 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2493 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002494
2495 ifaddr = (struct prefix_ipv4 *) connected->address;
2496
2497 if (ifaddr->family != AF_INET)
2498 continue;
2499
paul931cd542004-01-23 15:31:42 +00002500 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002501 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002502 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002503 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002504 done = 1;
2505 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2506 break;
2507
paulf38a4712003-06-07 01:10:00 +00002508 }
paul718e3742002-12-13 20:15:29 +00002509 }
2510 }
2511
2512 /* RIP send updates to each neighbor. */
2513 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2514 if (rp->info != NULL)
2515 {
2516 p = (struct prefix_ipv4 *) &rp->p;
2517
2518 ifp = if_lookup_address (p->prefix);
2519 if (! ifp)
2520 {
paulc49ad8f2004-10-22 10:27:28 +00002521 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002522 inet_ntoa (p->prefix));
2523 continue;
2524 }
paulc49ad8f2004-10-22 10:27:28 +00002525
2526 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2527 {
2528 zlog_warn ("Neighbor %s doesnt have connected network",
2529 inet_ntoa (p->prefix));
2530 continue;
2531 }
2532
paul718e3742002-12-13 20:15:29 +00002533 /* Set destination address and port */
2534 memset (&to, 0, sizeof (struct sockaddr_in));
2535 to.sin_addr = p->prefix;
2536 to.sin_port = htons (RIP_PORT_DEFAULT);
2537
2538 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002539 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002540 }
2541}
2542
2543/* RIP's periodical timer. */
2544int
2545rip_update (struct thread *t)
2546{
2547 /* Clear timer pointer. */
2548 rip->t_update = NULL;
2549
2550 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002551 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002552
2553 /* Process update output. */
2554 rip_update_process (rip_all_route);
2555
2556 /* Triggered updates may be suppressed if a regular update is due by
2557 the time the triggered update would be sent. */
2558 if (rip->t_triggered_interval)
2559 {
2560 thread_cancel (rip->t_triggered_interval);
2561 rip->t_triggered_interval = NULL;
2562 }
2563 rip->trigger = 0;
2564
2565 /* Register myself. */
2566 rip_event (RIP_UPDATE_EVENT, 0);
2567
2568 return 0;
2569}
2570
2571/* Walk down the RIP routing table then clear changed flag. */
2572void
2573rip_clear_changed_flag ()
2574{
2575 struct route_node *rp;
2576 struct rip_info *rinfo;
2577
2578 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2579 if ((rinfo = rp->info) != NULL)
2580 if (rinfo->flags & RIP_RTF_CHANGED)
2581 rinfo->flags &= ~RIP_RTF_CHANGED;
2582}
2583
2584/* Triggered update interval timer. */
2585int
2586rip_triggered_interval (struct thread *t)
2587{
2588 int rip_triggered_update (struct thread *);
2589
2590 rip->t_triggered_interval = NULL;
2591
2592 if (rip->trigger)
2593 {
2594 rip->trigger = 0;
2595 rip_triggered_update (t);
2596 }
2597 return 0;
2598}
2599
2600/* Execute triggered update. */
2601int
2602rip_triggered_update (struct thread *t)
2603{
2604 int interval;
2605
2606 /* Clear thred pointer. */
2607 rip->t_triggered_update = NULL;
2608
2609 /* Cancel interval timer. */
2610 if (rip->t_triggered_interval)
2611 {
2612 thread_cancel (rip->t_triggered_interval);
2613 rip->t_triggered_interval = NULL;
2614 }
2615 rip->trigger = 0;
2616
2617 /* Logging triggered update. */
2618 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002619 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002620
2621 /* Split Horizon processing is done when generating triggered
2622 updates as well as normal updates (see section 2.6). */
2623 rip_update_process (rip_changed_route);
2624
2625 /* Once all of the triggered updates have been generated, the route
2626 change flags should be cleared. */
2627 rip_clear_changed_flag ();
2628
2629 /* After a triggered update is sent, a timer should be set for a
2630 random interval between 1 and 5 seconds. If other changes that
2631 would trigger updates occur before the timer expires, a single
2632 update is triggered when the timer expires. */
2633 interval = (random () % 5) + 1;
2634
2635 rip->t_triggered_interval =
2636 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2637
2638 return 0;
2639}
2640
2641/* Withdraw redistributed route. */
2642void
2643rip_redistribute_withdraw (int type)
2644{
2645 struct route_node *rp;
2646 struct rip_info *rinfo;
2647
2648 if (!rip)
2649 return;
2650
2651 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2652 if ((rinfo = rp->info) != NULL)
2653 {
2654 if (rinfo->type == type
2655 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2656 {
2657 /* Perform poisoned reverse. */
2658 rinfo->metric = RIP_METRIC_INFINITY;
2659 RIP_TIMER_ON (rinfo->t_garbage_collect,
2660 rip_garbage_collect, rip->garbage_time);
2661 RIP_TIMER_OFF (rinfo->t_timeout);
2662 rinfo->flags |= RIP_RTF_CHANGED;
2663
hasso16705132003-05-25 14:49:19 +00002664 if (IS_RIP_DEBUG_EVENT) {
2665 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2666
ajs5d6c3772004-12-08 19:24:06 +00002667 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002668 inet_ntoa(p->prefix), p->prefixlen,
2669 ifindex2ifname(rinfo->ifindex));
2670 }
2671
paul718e3742002-12-13 20:15:29 +00002672 rip_event (RIP_TRIGGERED_UPDATE, 0);
2673 }
2674 }
2675}
2676
2677/* Create new RIP instance and set it to global variable. */
2678int
2679rip_create ()
2680{
2681 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2682 memset (rip, 0, sizeof (struct rip));
2683
2684 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002685 rip->version_send = RI_RIP_VERSION_2;
2686 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002687 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2688 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2689 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2690 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2691
2692 /* Initialize RIP routig table. */
2693 rip->table = route_table_init ();
2694 rip->route = route_table_init ();
2695 rip->neighbor = route_table_init ();
2696
2697 /* Make output stream. */
2698 rip->obuf = stream_new (1500);
2699
2700 /* Make socket. */
2701 rip->sock = rip_create_socket ();
2702 if (rip->sock < 0)
2703 return rip->sock;
2704
2705 /* Create read and timer thread. */
2706 rip_event (RIP_READ, rip->sock);
2707 rip_event (RIP_UPDATE_EVENT, 1);
2708
2709 return 0;
2710}
2711
2712/* Sned RIP request to the destination. */
2713int
2714rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002715 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002716{
2717 struct rte *rte;
2718 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002719 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002720
2721 memset (&rip_packet, 0, sizeof (rip_packet));
2722
2723 rip_packet.command = RIP_REQUEST;
2724 rip_packet.version = version;
2725 rte = rip_packet.rte;
2726 rte->metric = htonl (RIP_METRIC_INFINITY);
2727
paul931cd542004-01-23 15:31:42 +00002728 if (connected)
2729 {
2730 /*
2731 * connected is only sent for ripv1 case, or when
2732 * interface does not support multicast. Caller loops
2733 * over each connected address for this case.
2734 */
paul11dde9c2004-05-31 14:00:00 +00002735 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002736 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002737 return -1;
2738 else
2739 return sizeof (rip_packet);
2740 }
2741
paulcc1131a2003-10-15 23:20:17 +00002742 /* send request on each connected network */
2743 LIST_LOOP(ifp->connected, connected, node)
2744 {
2745 struct prefix_ipv4 *p;
2746
2747 p = (struct prefix_ipv4 *) connected->address;
2748
2749 if (p->family != AF_INET)
2750 continue;
2751
paul11dde9c2004-05-31 14:00:00 +00002752 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002753 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002754 return -1;
2755 }
2756 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002757}
2758
2759int
2760rip_update_jitter (unsigned long time)
2761{
paul239389b2004-05-05 14:09:37 +00002762#define JITTER_BOUND 4
2763 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2764 Given that, we cannot let time be less than JITTER_BOUND seconds.
2765 The RIPv2 RFC says jitter should be small compared to
2766 update_time. We consider 1/JITTER_BOUND to be small.
2767 */
2768
2769 int jitter_input = time;
2770 int jitter;
2771
2772 if (jitter_input < JITTER_BOUND)
2773 jitter_input = JITTER_BOUND;
2774
2775 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2776
2777 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002778}
2779
2780void
2781rip_event (enum rip_event event, int sock)
2782{
2783 int jitter = 0;
2784
2785 switch (event)
2786 {
2787 case RIP_READ:
2788 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2789 break;
2790 case RIP_UPDATE_EVENT:
2791 if (rip->t_update)
2792 {
2793 thread_cancel (rip->t_update);
2794 rip->t_update = NULL;
2795 }
2796 jitter = rip_update_jitter (rip->update_time);
2797 rip->t_update =
2798 thread_add_timer (master, rip_update, NULL,
2799 sock ? 2 : rip->update_time + jitter);
2800 break;
2801 case RIP_TRIGGERED_UPDATE:
2802 if (rip->t_triggered_interval)
2803 rip->trigger = 1;
2804 else if (! rip->t_triggered_update)
2805 rip->t_triggered_update =
2806 thread_add_event (master, rip_triggered_update, NULL, 0);
2807 break;
2808 default:
2809 break;
2810 }
2811}
2812
2813DEFUN (router_rip,
2814 router_rip_cmd,
2815 "router rip",
2816 "Enable a routing process\n"
2817 "Routing Information Protocol (RIP)\n")
2818{
2819 int ret;
2820
2821 /* If rip is not enabled before. */
2822 if (! rip)
2823 {
2824 ret = rip_create ();
2825 if (ret < 0)
2826 {
2827 zlog_info ("Can't create RIP");
2828 return CMD_WARNING;
2829 }
2830 }
2831 vty->node = RIP_NODE;
2832 vty->index = rip;
2833
2834 return CMD_SUCCESS;
2835}
2836
2837DEFUN (no_router_rip,
2838 no_router_rip_cmd,
2839 "no router rip",
2840 NO_STR
2841 "Enable a routing process\n"
2842 "Routing Information Protocol (RIP)\n")
2843{
2844 if (rip)
2845 rip_clean ();
2846 return CMD_SUCCESS;
2847}
2848
2849DEFUN (rip_version,
2850 rip_version_cmd,
2851 "version <1-2>",
2852 "Set routing protocol version\n"
2853 "version\n")
2854{
2855 int version;
2856
2857 version = atoi (argv[0]);
2858 if (version != RIPv1 && version != RIPv2)
2859 {
2860 vty_out (vty, "invalid rip version %d%s", version,
2861 VTY_NEWLINE);
2862 return CMD_WARNING;
2863 }
paulf38a4712003-06-07 01:10:00 +00002864 rip->version_send = version;
2865 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002866
2867 return CMD_SUCCESS;
2868}
2869
2870DEFUN (no_rip_version,
2871 no_rip_version_cmd,
2872 "no version",
2873 NO_STR
2874 "Set routing protocol version\n")
2875{
2876 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002877 rip->version_send = RI_RIP_VERSION_2;
2878 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002879
2880 return CMD_SUCCESS;
2881}
2882
2883ALIAS (no_rip_version,
2884 no_rip_version_val_cmd,
2885 "no version <1-2>",
2886 NO_STR
2887 "Set routing protocol version\n"
2888 "version\n")
2889
2890DEFUN (rip_route,
2891 rip_route_cmd,
2892 "route A.B.C.D/M",
2893 "RIP static route configuration\n"
2894 "IP prefix <network>/<length>\n")
2895{
2896 int ret;
2897 struct prefix_ipv4 p;
2898 struct route_node *node;
2899
2900 ret = str2prefix_ipv4 (argv[0], &p);
2901 if (ret < 0)
2902 {
2903 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2904 return CMD_WARNING;
2905 }
2906 apply_mask_ipv4 (&p);
2907
2908 /* For router rip configuration. */
2909 node = route_node_get (rip->route, (struct prefix *) &p);
2910
2911 if (node->info)
2912 {
2913 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2914 route_unlock_node (node);
2915 return CMD_WARNING;
2916 }
2917
hasso8a676be2004-10-08 06:36:38 +00002918 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002919
2920 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2921
2922 return CMD_SUCCESS;
2923}
2924
2925DEFUN (no_rip_route,
2926 no_rip_route_cmd,
2927 "no route A.B.C.D/M",
2928 NO_STR
2929 "RIP static route configuration\n"
2930 "IP prefix <network>/<length>\n")
2931{
2932 int ret;
2933 struct prefix_ipv4 p;
2934 struct route_node *node;
2935
2936 ret = str2prefix_ipv4 (argv[0], &p);
2937 if (ret < 0)
2938 {
2939 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2940 return CMD_WARNING;
2941 }
2942 apply_mask_ipv4 (&p);
2943
2944 /* For router rip configuration. */
2945 node = route_node_lookup (rip->route, (struct prefix *) &p);
2946 if (! node)
2947 {
2948 vty_out (vty, "Can't find route %s.%s", argv[0],
2949 VTY_NEWLINE);
2950 return CMD_WARNING;
2951 }
2952
2953 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2954 route_unlock_node (node);
2955
2956 node->info = NULL;
2957 route_unlock_node (node);
2958
2959 return CMD_SUCCESS;
2960}
2961
2962void
2963rip_update_default_metric ()
2964{
2965 struct route_node *np;
2966 struct rip_info *rinfo;
2967
2968 for (np = route_top (rip->table); np; np = route_next (np))
2969 if ((rinfo = np->info) != NULL)
2970 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2971 rinfo->metric = rip->default_metric;
2972}
2973
2974DEFUN (rip_default_metric,
2975 rip_default_metric_cmd,
2976 "default-metric <1-16>",
2977 "Set a metric of redistribute routes\n"
2978 "Default metric\n")
2979{
2980 if (rip)
2981 {
2982 rip->default_metric = atoi (argv[0]);
2983 /* rip_update_default_metric (); */
2984 }
2985 return CMD_SUCCESS;
2986}
2987
2988DEFUN (no_rip_default_metric,
2989 no_rip_default_metric_cmd,
2990 "no default-metric",
2991 NO_STR
2992 "Set a metric of redistribute routes\n"
2993 "Default metric\n")
2994{
2995 if (rip)
2996 {
2997 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2998 /* rip_update_default_metric (); */
2999 }
3000 return CMD_SUCCESS;
3001}
3002
3003ALIAS (no_rip_default_metric,
3004 no_rip_default_metric_val_cmd,
3005 "no default-metric <1-16>",
3006 NO_STR
3007 "Set a metric of redistribute routes\n"
3008 "Default metric\n")
3009
3010DEFUN (rip_timers,
3011 rip_timers_cmd,
3012 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3013 "Adjust routing timers\n"
3014 "Basic routing protocol update timers\n"
3015 "Routing table update timer value in second. Default is 30.\n"
3016 "Routing information timeout timer. Default is 180.\n"
3017 "Garbage collection timer. Default is 120.\n")
3018{
3019 unsigned long update;
3020 unsigned long timeout;
3021 unsigned long garbage;
3022 char *endptr = NULL;
3023 unsigned long RIP_TIMER_MAX = 2147483647;
3024 unsigned long RIP_TIMER_MIN = 5;
3025
3026 update = strtoul (argv[0], &endptr, 10);
3027 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3028 {
3029 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3030 return CMD_WARNING;
3031 }
3032
3033 timeout = strtoul (argv[1], &endptr, 10);
3034 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3035 {
3036 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3037 return CMD_WARNING;
3038 }
3039
3040 garbage = strtoul (argv[2], &endptr, 10);
3041 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3042 {
3043 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3044 return CMD_WARNING;
3045 }
3046
3047 /* Set each timer value. */
3048 rip->update_time = update;
3049 rip->timeout_time = timeout;
3050 rip->garbage_time = garbage;
3051
3052 /* Reset update timer thread. */
3053 rip_event (RIP_UPDATE_EVENT, 0);
3054
3055 return CMD_SUCCESS;
3056}
3057
3058DEFUN (no_rip_timers,
3059 no_rip_timers_cmd,
3060 "no timers basic",
3061 NO_STR
3062 "Adjust routing timers\n"
3063 "Basic routing protocol update timers\n")
3064{
3065 /* Set each timer value to the default. */
3066 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3067 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3068 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3069
3070 /* Reset update timer thread. */
3071 rip_event (RIP_UPDATE_EVENT, 0);
3072
3073 return CMD_SUCCESS;
3074}
hasso16705132003-05-25 14:49:19 +00003075
3076ALIAS (no_rip_timers,
3077 no_rip_timers_val_cmd,
3078 "no timers basic <0-65535> <0-65535> <0-65535>",
3079 NO_STR
3080 "Adjust routing timers\n"
3081 "Basic routing protocol update timers\n"
3082 "Routing table update timer value in second. Default is 30.\n"
3083 "Routing information timeout timer. Default is 180.\n"
3084 "Garbage collection timer. Default is 120.\n")
3085
paul718e3742002-12-13 20:15:29 +00003086
3087struct route_table *rip_distance_table;
3088
3089struct rip_distance
3090{
3091 /* Distance value for the IP source prefix. */
3092 u_char distance;
3093
3094 /* Name of the access-list to be matched. */
3095 char *access_list;
3096};
3097
3098struct rip_distance *
3099rip_distance_new ()
3100{
3101 struct rip_distance *new;
3102 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3103 memset (new, 0, sizeof (struct rip_distance));
3104 return new;
3105}
3106
3107void
3108rip_distance_free (struct rip_distance *rdistance)
3109{
3110 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3111}
3112
3113int
hasso98b718a2004-10-11 12:57:57 +00003114rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3115 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003116{
3117 int ret;
3118 struct prefix_ipv4 p;
3119 u_char distance;
3120 struct route_node *rn;
3121 struct rip_distance *rdistance;
3122
3123 ret = str2prefix_ipv4 (ip_str, &p);
3124 if (ret == 0)
3125 {
3126 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3127 return CMD_WARNING;
3128 }
3129
3130 distance = atoi (distance_str);
3131
3132 /* Get RIP distance node. */
3133 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3134 if (rn->info)
3135 {
3136 rdistance = rn->info;
3137 route_unlock_node (rn);
3138 }
3139 else
3140 {
3141 rdistance = rip_distance_new ();
3142 rn->info = rdistance;
3143 }
3144
3145 /* Set distance value. */
3146 rdistance->distance = distance;
3147
3148 /* Reset access-list configuration. */
3149 if (rdistance->access_list)
3150 {
3151 free (rdistance->access_list);
3152 rdistance->access_list = NULL;
3153 }
3154 if (access_list_str)
3155 rdistance->access_list = strdup (access_list_str);
3156
3157 return CMD_SUCCESS;
3158}
3159
3160int
hasso98b718a2004-10-11 12:57:57 +00003161rip_distance_unset (struct vty *vty, const char *distance_str,
3162 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003163{
3164 int ret;
3165 struct prefix_ipv4 p;
3166 u_char distance;
3167 struct route_node *rn;
3168 struct rip_distance *rdistance;
3169
3170 ret = str2prefix_ipv4 (ip_str, &p);
3171 if (ret == 0)
3172 {
3173 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3174 return CMD_WARNING;
3175 }
3176
3177 distance = atoi (distance_str);
3178
3179 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3180 if (! rn)
3181 {
3182 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3183 return CMD_WARNING;
3184 }
3185
3186 rdistance = rn->info;
3187
3188 if (rdistance->access_list)
3189 free (rdistance->access_list);
3190 rip_distance_free (rdistance);
3191
3192 rn->info = NULL;
3193 route_unlock_node (rn);
3194 route_unlock_node (rn);
3195
3196 return CMD_SUCCESS;
3197}
3198
3199void
3200rip_distance_reset ()
3201{
3202 struct route_node *rn;
3203 struct rip_distance *rdistance;
3204
3205 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3206 if ((rdistance = rn->info) != NULL)
3207 {
3208 if (rdistance->access_list)
3209 free (rdistance->access_list);
3210 rip_distance_free (rdistance);
3211 rn->info = NULL;
3212 route_unlock_node (rn);
3213 }
3214}
3215
3216/* Apply RIP information to distance method. */
3217u_char
3218rip_distance_apply (struct rip_info *rinfo)
3219{
3220 struct route_node *rn;
3221 struct prefix_ipv4 p;
3222 struct rip_distance *rdistance;
3223 struct access_list *alist;
3224
3225 if (! rip)
3226 return 0;
3227
3228 memset (&p, 0, sizeof (struct prefix_ipv4));
3229 p.family = AF_INET;
3230 p.prefix = rinfo->from;
3231 p.prefixlen = IPV4_MAX_BITLEN;
3232
3233 /* Check source address. */
3234 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3235 if (rn)
3236 {
3237 rdistance = rn->info;
3238 route_unlock_node (rn);
3239
3240 if (rdistance->access_list)
3241 {
3242 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3243 if (alist == NULL)
3244 return 0;
3245 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3246 return 0;
3247
3248 return rdistance->distance;
3249 }
3250 else
3251 return rdistance->distance;
3252 }
3253
3254 if (rip->distance)
3255 return rip->distance;
3256
3257 return 0;
3258}
3259
3260void
3261rip_distance_show (struct vty *vty)
3262{
3263 struct route_node *rn;
3264 struct rip_distance *rdistance;
3265 int header = 1;
3266 char buf[BUFSIZ];
3267
3268 vty_out (vty, " Distance: (default is %d)%s",
3269 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3270 VTY_NEWLINE);
3271
3272 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3273 if ((rdistance = rn->info) != NULL)
3274 {
3275 if (header)
3276 {
3277 vty_out (vty, " Address Distance List%s",
3278 VTY_NEWLINE);
3279 header = 0;
3280 }
3281 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3282 vty_out (vty, " %-20s %4d %s%s",
3283 buf, rdistance->distance,
3284 rdistance->access_list ? rdistance->access_list : "",
3285 VTY_NEWLINE);
3286 }
3287}
3288
3289DEFUN (rip_distance,
3290 rip_distance_cmd,
3291 "distance <1-255>",
3292 "Administrative distance\n"
3293 "Distance value\n")
3294{
3295 rip->distance = atoi (argv[0]);
3296 return CMD_SUCCESS;
3297}
3298
3299DEFUN (no_rip_distance,
3300 no_rip_distance_cmd,
3301 "no distance <1-255>",
3302 NO_STR
3303 "Administrative distance\n"
3304 "Distance value\n")
3305{
3306 rip->distance = 0;
3307 return CMD_SUCCESS;
3308}
3309
3310DEFUN (rip_distance_source,
3311 rip_distance_source_cmd,
3312 "distance <1-255> A.B.C.D/M",
3313 "Administrative distance\n"
3314 "Distance value\n"
3315 "IP source prefix\n")
3316{
3317 rip_distance_set (vty, argv[0], argv[1], NULL);
3318 return CMD_SUCCESS;
3319}
3320
3321DEFUN (no_rip_distance_source,
3322 no_rip_distance_source_cmd,
3323 "no distance <1-255> A.B.C.D/M",
3324 NO_STR
3325 "Administrative distance\n"
3326 "Distance value\n"
3327 "IP source prefix\n")
3328{
3329 rip_distance_unset (vty, argv[0], argv[1], NULL);
3330 return CMD_SUCCESS;
3331}
3332
3333DEFUN (rip_distance_source_access_list,
3334 rip_distance_source_access_list_cmd,
3335 "distance <1-255> A.B.C.D/M WORD",
3336 "Administrative distance\n"
3337 "Distance value\n"
3338 "IP source prefix\n"
3339 "Access list name\n")
3340{
3341 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3342 return CMD_SUCCESS;
3343}
3344
3345DEFUN (no_rip_distance_source_access_list,
3346 no_rip_distance_source_access_list_cmd,
3347 "no distance <1-255> A.B.C.D/M WORD",
3348 NO_STR
3349 "Administrative distance\n"
3350 "Distance value\n"
3351 "IP source prefix\n"
3352 "Access list name\n")
3353{
3354 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3355 return CMD_SUCCESS;
3356}
3357
3358/* Print out routes update time. */
3359void
3360rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3361{
3362 struct timeval timer_now;
3363 time_t clock;
3364 struct tm *tm;
3365#define TIME_BUF 25
3366 char timebuf [TIME_BUF];
3367 struct thread *thread;
3368
3369 gettimeofday (&timer_now, NULL);
3370
3371 if ((thread = rinfo->t_timeout) != NULL)
3372 {
3373 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3374 tm = gmtime (&clock);
3375 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3376 vty_out (vty, "%5s", timebuf);
3377 }
3378 else if ((thread = rinfo->t_garbage_collect) != NULL)
3379 {
3380 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3381 tm = gmtime (&clock);
3382 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3383 vty_out (vty, "%5s", timebuf);
3384 }
3385}
3386
hasso8a676be2004-10-08 06:36:38 +00003387const char *
paul718e3742002-12-13 20:15:29 +00003388rip_route_type_print (int sub_type)
3389{
3390 switch (sub_type)
3391 {
3392 case RIP_ROUTE_RTE:
3393 return "n";
3394 case RIP_ROUTE_STATIC:
3395 return "s";
3396 case RIP_ROUTE_DEFAULT:
3397 return "d";
3398 case RIP_ROUTE_REDISTRIBUTE:
3399 return "r";
3400 case RIP_ROUTE_INTERFACE:
3401 return "i";
3402 default:
3403 return "?";
3404 }
3405}
3406
3407DEFUN (show_ip_rip,
3408 show_ip_rip_cmd,
3409 "show ip rip",
3410 SHOW_STR
3411 IP_STR
3412 "Show RIP routes\n")
3413{
3414 struct route_node *np;
3415 struct rip_info *rinfo;
3416
3417 if (! rip)
3418 return CMD_SUCCESS;
3419
hasso16705132003-05-25 14:49:19 +00003420 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3421 "Sub-codes:%s"
3422 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003423 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003424 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003425 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003426
3427 for (np = route_top (rip->table); np; np = route_next (np))
3428 if ((rinfo = np->info) != NULL)
3429 {
3430 int len;
3431
3432 len = vty_out (vty, "%s(%s) %s/%d",
3433 /* np->lock, For debugging. */
3434 route_info[rinfo->type].str,
3435 rip_route_type_print (rinfo->sub_type),
3436 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3437
hassoa1455d82004-03-03 19:36:24 +00003438 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003439
3440 if (len > 0)
3441 vty_out (vty, "%*s", len, " ");
3442
3443 if (rinfo->nexthop.s_addr)
3444 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3445 rinfo->metric);
3446 else
3447 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3448
3449 /* Route which exist in kernel routing table. */
3450 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3451 (rinfo->sub_type == RIP_ROUTE_RTE))
3452 {
3453 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003454 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003455 rip_vty_out_uptime (vty, rinfo);
3456 }
3457 else if (rinfo->metric == RIP_METRIC_INFINITY)
3458 {
3459 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003460 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003461 rip_vty_out_uptime (vty, rinfo);
3462 }
3463 else
hasso16705132003-05-25 14:49:19 +00003464 {
3465 vty_out (vty, "self ");
3466 vty_out (vty, "%3d", rinfo->tag);
3467 }
paul718e3742002-12-13 20:15:29 +00003468
3469 vty_out (vty, "%s", VTY_NEWLINE);
3470 }
3471 return CMD_SUCCESS;
3472}
3473
3474/* Return next event time. */
3475int
3476rip_next_thread_timer (struct thread *thread)
3477{
3478 struct timeval timer_now;
3479
3480 gettimeofday (&timer_now, NULL);
3481
3482 return thread->u.sands.tv_sec - timer_now.tv_sec;
3483}
3484
hasso16705132003-05-25 14:49:19 +00003485/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3486DEFUN (show_ip_rip_status,
3487 show_ip_rip_status_cmd,
3488 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003489 SHOW_STR
3490 IP_STR
hasso16705132003-05-25 14:49:19 +00003491 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003492 "IP routing protocol process parameters and statistics\n")
3493{
hasso52dc7ee2004-09-23 19:18:23 +00003494 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003495 struct interface *ifp;
3496 struct rip_interface *ri;
3497 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003498 const char *send_version;
3499 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003500
3501 if (! rip)
3502 return CMD_SUCCESS;
3503
3504 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3505 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3506 rip->update_time);
3507 vty_out (vty, " next due in %d seconds%s",
3508 rip_next_thread_timer (rip->t_update),
3509 VTY_NEWLINE);
3510 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3511 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3512 VTY_NEWLINE);
3513
3514 /* Filtering status show. */
3515 config_show_distribute (vty);
3516
3517 /* Default metric information. */
3518 vty_out (vty, " Default redistribution metric is %d%s",
3519 rip->default_metric, VTY_NEWLINE);
3520
3521 /* Redistribute information. */
3522 vty_out (vty, " Redistributing:");
3523 config_write_rip_redistribute (vty, 0);
3524 vty_out (vty, "%s", VTY_NEWLINE);
3525
paulf38a4712003-06-07 01:10:00 +00003526 vty_out (vty, " Default version control: send version %s,",
3527 lookup(ri_version_msg,rip->version_send));
3528 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3529 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3530 else
3531 vty_out (vty, " receive version %s %s",
3532 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003533
3534 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3535
3536 for (node = listhead (iflist); node; node = nextnode (node))
3537 {
3538 ifp = getdata (node);
3539 ri = ifp->info;
3540
3541 if (ri->enable_network || ri->enable_interface)
3542 {
3543 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003544 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003545 else
3546 send_version = lookup (ri_version_msg, ri->ri_send);
3547
3548 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003549 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003550 else
3551 receive_version = lookup (ri_version_msg, ri->ri_receive);
3552
3553 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3554 send_version,
3555 receive_version,
3556 ri->key_chain ? ri->key_chain : "",
3557 VTY_NEWLINE);
3558 }
3559 }
3560
3561 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3562 config_write_rip_network (vty, 0);
3563
paul4aaff3f2003-06-07 01:04:45 +00003564 {
3565 int found_passive = 0;
3566 for (node = listhead (iflist); node; node = nextnode (node))
3567 {
3568 ifp = getdata (node);
3569 ri = ifp->info;
3570
3571 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3572 {
3573 if (!found_passive)
3574 {
3575 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3576 found_passive = 1;
3577 }
3578 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3579 }
3580 }
3581 }
3582
paul718e3742002-12-13 20:15:29 +00003583 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3584 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3585 rip_peer_display (vty);
3586
3587 rip_distance_show (vty);
3588
3589 return CMD_SUCCESS;
3590}
3591
3592/* RIP configuration write function. */
3593int
3594config_write_rip (struct vty *vty)
3595{
3596 int write = 0;
3597 struct route_node *rn;
3598 struct rip_distance *rdistance;
3599
3600 if (rip)
3601 {
3602 /* Router RIP statement. */
3603 vty_out (vty, "router rip%s", VTY_NEWLINE);
3604 write++;
3605
3606 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003607 if (rip->version_send != RI_RIP_VERSION_2
3608 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3609 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003610 VTY_NEWLINE);
3611
3612 /* RIP timer configuration. */
3613 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3614 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3615 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3616 vty_out (vty, " timers basic %lu %lu %lu%s",
3617 rip->update_time,
3618 rip->timeout_time,
3619 rip->garbage_time,
3620 VTY_NEWLINE);
3621
3622 /* Default information configuration. */
3623 if (rip->default_information)
3624 {
3625 if (rip->default_information_route_map)
3626 vty_out (vty, " default-information originate route-map %s%s",
3627 rip->default_information_route_map, VTY_NEWLINE);
3628 else
3629 vty_out (vty, " default-information originate%s",
3630 VTY_NEWLINE);
3631 }
3632
3633 /* Redistribute configuration. */
3634 config_write_rip_redistribute (vty, 1);
3635
3636 /* RIP offset-list configuration. */
3637 config_write_rip_offset_list (vty);
3638
3639 /* RIP enabled network and interface configuration. */
3640 config_write_rip_network (vty, 1);
3641
3642 /* RIP default metric configuration */
3643 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3644 vty_out (vty, " default-metric %d%s",
3645 rip->default_metric, VTY_NEWLINE);
3646
3647 /* Distribute configuration. */
3648 write += config_write_distribute (vty);
3649
hasso16705132003-05-25 14:49:19 +00003650 /* Interface routemap configuration */
3651 write += config_write_if_rmap (vty);
3652
paul718e3742002-12-13 20:15:29 +00003653 /* Distance configuration. */
3654 if (rip->distance)
3655 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3656
3657 /* RIP source IP prefix distance configuration. */
3658 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3659 if ((rdistance = rn->info) != NULL)
3660 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3661 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3662 rdistance->access_list ? rdistance->access_list : "",
3663 VTY_NEWLINE);
3664
3665 /* RIP static route configuration. */
3666 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3667 if (rn->info)
3668 vty_out (vty, " route %s/%d%s",
3669 inet_ntoa (rn->p.u.prefix4),
3670 rn->p.prefixlen,
3671 VTY_NEWLINE);
3672
3673 }
3674 return write;
3675}
3676
3677/* RIP node structure. */
3678struct cmd_node rip_node =
3679{
3680 RIP_NODE,
3681 "%s(config-router)# ",
3682 1
3683};
3684
3685/* Distribute-list update functions. */
3686void
3687rip_distribute_update (struct distribute *dist)
3688{
3689 struct interface *ifp;
3690 struct rip_interface *ri;
3691 struct access_list *alist;
3692 struct prefix_list *plist;
3693
3694 if (! dist->ifname)
3695 return;
3696
3697 ifp = if_lookup_by_name (dist->ifname);
3698 if (ifp == NULL)
3699 return;
3700
3701 ri = ifp->info;
3702
3703 if (dist->list[DISTRIBUTE_IN])
3704 {
3705 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3706 if (alist)
3707 ri->list[RIP_FILTER_IN] = alist;
3708 else
3709 ri->list[RIP_FILTER_IN] = NULL;
3710 }
3711 else
3712 ri->list[RIP_FILTER_IN] = NULL;
3713
3714 if (dist->list[DISTRIBUTE_OUT])
3715 {
3716 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3717 if (alist)
3718 ri->list[RIP_FILTER_OUT] = alist;
3719 else
3720 ri->list[RIP_FILTER_OUT] = NULL;
3721 }
3722 else
3723 ri->list[RIP_FILTER_OUT] = NULL;
3724
3725 if (dist->prefix[DISTRIBUTE_IN])
3726 {
3727 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3728 if (plist)
3729 ri->prefix[RIP_FILTER_IN] = plist;
3730 else
3731 ri->prefix[RIP_FILTER_IN] = NULL;
3732 }
3733 else
3734 ri->prefix[RIP_FILTER_IN] = NULL;
3735
3736 if (dist->prefix[DISTRIBUTE_OUT])
3737 {
3738 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3739 if (plist)
3740 ri->prefix[RIP_FILTER_OUT] = plist;
3741 else
3742 ri->prefix[RIP_FILTER_OUT] = NULL;
3743 }
3744 else
3745 ri->prefix[RIP_FILTER_OUT] = NULL;
3746}
3747
3748void
3749rip_distribute_update_interface (struct interface *ifp)
3750{
3751 struct distribute *dist;
3752
3753 dist = distribute_lookup (ifp->name);
3754 if (dist)
3755 rip_distribute_update (dist);
3756}
3757
3758/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003759/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003760void
paul02ff83c2004-06-11 11:27:03 +00003761rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003762{
3763 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003764 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003765
3766 for (node = listhead (iflist); node; nextnode (node))
3767 {
3768 ifp = getdata (node);
3769 rip_distribute_update_interface (ifp);
3770 }
3771}
paul11dde9c2004-05-31 14:00:00 +00003772/* ARGSUSED */
3773void
3774rip_distribute_update_all_wrapper(struct access_list *notused)
3775{
paul02ff83c2004-06-11 11:27:03 +00003776 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003777}
paul718e3742002-12-13 20:15:29 +00003778
3779/* Delete all added rip route. */
3780void
3781rip_clean ()
3782{
3783 int i;
3784 struct route_node *rp;
3785 struct rip_info *rinfo;
3786
3787 if (rip)
3788 {
3789 /* Clear RIP routes */
3790 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3791 if ((rinfo = rp->info) != NULL)
3792 {
3793 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3794 rinfo->sub_type == RIP_ROUTE_RTE)
3795 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3796 &rinfo->nexthop, rinfo->metric);
3797
3798 RIP_TIMER_OFF (rinfo->t_timeout);
3799 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3800
3801 rp->info = NULL;
3802 route_unlock_node (rp);
3803
3804 rip_info_free (rinfo);
3805 }
3806
3807 /* Cancel RIP related timers. */
3808 RIP_TIMER_OFF (rip->t_update);
3809 RIP_TIMER_OFF (rip->t_triggered_update);
3810 RIP_TIMER_OFF (rip->t_triggered_interval);
3811
3812 /* Cancel read thread. */
3813 if (rip->t_read)
3814 {
3815 thread_cancel (rip->t_read);
3816 rip->t_read = NULL;
3817 }
3818
3819 /* Close RIP socket. */
3820 if (rip->sock >= 0)
3821 {
3822 close (rip->sock);
3823 rip->sock = -1;
3824 }
3825
3826 /* Static RIP route configuration. */
3827 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3828 if (rp->info)
3829 {
3830 rp->info = NULL;
3831 route_unlock_node (rp);
3832 }
3833
3834 /* RIP neighbor configuration. */
3835 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3836 if (rp->info)
3837 {
3838 rp->info = NULL;
3839 route_unlock_node (rp);
3840 }
3841
3842 /* Redistribute related clear. */
3843 if (rip->default_information_route_map)
3844 free (rip->default_information_route_map);
3845
3846 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3847 if (rip->route_map[i].name)
3848 free (rip->route_map[i].name);
3849
3850 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3851 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3852 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3853
3854 XFREE (MTYPE_RIP, rip);
3855 rip = NULL;
3856 }
3857
3858 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003859 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003860 rip_offset_clean ();
3861 rip_interface_clean ();
3862 rip_distance_reset ();
3863 rip_redistribute_clean ();
3864}
3865
3866/* Reset all values to the default settings. */
3867void
3868rip_reset ()
3869{
3870 /* Reset global counters. */
3871 rip_global_route_changes = 0;
3872 rip_global_queries = 0;
3873
3874 /* Call ripd related reset functions. */
3875 rip_debug_reset ();
3876 rip_route_map_reset ();
3877
3878 /* Call library reset functions. */
3879 vty_reset ();
3880 access_list_reset ();
3881 prefix_list_reset ();
3882
3883 distribute_list_reset ();
3884
3885 rip_interface_reset ();
3886 rip_distance_reset ();
3887
3888 rip_zclient_reset ();
3889}
3890
hasso16705132003-05-25 14:49:19 +00003891void
3892rip_if_rmap_update (struct if_rmap *if_rmap)
3893{
3894 struct interface *ifp;
3895 struct rip_interface *ri;
3896 struct route_map *rmap;
3897
3898 ifp = if_lookup_by_name (if_rmap->ifname);
3899 if (ifp == NULL)
3900 return;
3901
3902 ri = ifp->info;
3903
3904 if (if_rmap->routemap[IF_RMAP_IN])
3905 {
3906 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3907 if (rmap)
3908 ri->routemap[IF_RMAP_IN] = rmap;
3909 else
3910 ri->routemap[IF_RMAP_IN] = NULL;
3911 }
3912 else
3913 ri->routemap[RIP_FILTER_IN] = NULL;
3914
3915 if (if_rmap->routemap[IF_RMAP_OUT])
3916 {
3917 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3918 if (rmap)
3919 ri->routemap[IF_RMAP_OUT] = rmap;
3920 else
3921 ri->routemap[IF_RMAP_OUT] = NULL;
3922 }
3923 else
3924 ri->routemap[RIP_FILTER_OUT] = NULL;
3925}
3926
3927void
3928rip_if_rmap_update_interface (struct interface *ifp)
3929{
3930 struct if_rmap *if_rmap;
3931
3932 if_rmap = if_rmap_lookup (ifp->name);
3933 if (if_rmap)
3934 rip_if_rmap_update (if_rmap);
3935}
3936
3937void
3938rip_routemap_update_redistribute (void)
3939{
3940 int i;
3941
3942 if (rip)
3943 {
3944 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3945 {
3946 if (rip->route_map[i].name)
3947 rip->route_map[i].map =
3948 route_map_lookup_by_name (rip->route_map[i].name);
3949 }
3950 }
3951}
3952
paul11dde9c2004-05-31 14:00:00 +00003953/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003954void
hasso98b718a2004-10-11 12:57:57 +00003955rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003956{
3957 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003958 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003959
3960 for (node = listhead (iflist); node; nextnode (node))
3961 {
3962 ifp = getdata (node);
3963 rip_if_rmap_update_interface (ifp);
3964 }
3965
3966 rip_routemap_update_redistribute ();
3967}
3968
paul718e3742002-12-13 20:15:29 +00003969/* Allocate new rip structure and set default value. */
3970void
3971rip_init ()
3972{
3973 /* Randomize for triggered update random(). */
3974 srand (time (NULL));
3975
3976 /* Install top nodes. */
3977 install_node (&rip_node, config_write_rip);
3978
3979 /* Install rip commands. */
3980 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003981 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003982 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003983 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003984 install_element (CONFIG_NODE, &router_rip_cmd);
3985 install_element (CONFIG_NODE, &no_router_rip_cmd);
3986
3987 install_default (RIP_NODE);
3988 install_element (RIP_NODE, &rip_version_cmd);
3989 install_element (RIP_NODE, &no_rip_version_cmd);
3990 install_element (RIP_NODE, &no_rip_version_val_cmd);
3991 install_element (RIP_NODE, &rip_default_metric_cmd);
3992 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3993 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3994 install_element (RIP_NODE, &rip_timers_cmd);
3995 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003996 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003997 install_element (RIP_NODE, &rip_route_cmd);
3998 install_element (RIP_NODE, &no_rip_route_cmd);
3999 install_element (RIP_NODE, &rip_distance_cmd);
4000 install_element (RIP_NODE, &no_rip_distance_cmd);
4001 install_element (RIP_NODE, &rip_distance_source_cmd);
4002 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4003 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4004 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4005
4006 /* Debug related init. */
4007 rip_debug_init ();
4008
paul718e3742002-12-13 20:15:29 +00004009 /* SNMP init. */
4010#ifdef HAVE_SNMP
4011 rip_snmp_init ();
4012#endif /* HAVE_SNMP */
4013
4014 /* Access list install. */
4015 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004016 access_list_add_hook (rip_distribute_update_all_wrapper);
4017 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004018
4019 /* Prefix list initialize.*/
4020 prefix_list_init ();
4021 prefix_list_add_hook (rip_distribute_update_all);
4022 prefix_list_delete_hook (rip_distribute_update_all);
4023
4024 /* Distribute list install. */
4025 distribute_list_init (RIP_NODE);
4026 distribute_list_add_hook (rip_distribute_update);
4027 distribute_list_delete_hook (rip_distribute_update);
4028
hasso16705132003-05-25 14:49:19 +00004029 /* Route-map */
4030 rip_route_map_init ();
4031 rip_offset_init ();
4032
4033 route_map_add_hook (rip_routemap_update);
4034 route_map_delete_hook (rip_routemap_update);
4035
4036 if_rmap_init (RIP_NODE);
4037 if_rmap_hook_add (rip_if_rmap_update);
4038 if_rmap_hook_delete (rip_if_rmap_update);
4039
paul718e3742002-12-13 20:15:29 +00004040 /* Distance control. */
4041 rip_distance_table = route_table_init ();
4042}