blob: 3dd91dae976faf0bfce9b0abd9d3236f6ab69279 [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. */
paul1eb8ef22005-04-07 07:30:20 +0000368 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000369 {
paul1eb8ef22005-04-07 07:30:20 +0000370 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000371 {
paul718e3742002-12-13 20:15:29 +0000372 p = ifc->address;
373
374 if (p->family == AF_INET
375 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
376 return -1;
377 }
378 }
379 return 0;
380}
381
382/* RIP add route to routing table. */
383void
384rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000385 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000386{
387 int ret;
388 struct prefix_ipv4 p;
389 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000390 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000391 struct rip_interface *ri;
392 struct in_addr *nexthop;
393 u_char oldmetric;
394 int same = 0;
395
396 /* Make prefix structure. */
397 memset (&p, 0, sizeof (struct prefix_ipv4));
398 p.family = AF_INET;
399 p.prefix = rte->prefix;
400 p.prefixlen = ip_masklen (rte->mask);
401
402 /* Make sure mask is applied. */
403 apply_mask_ipv4 (&p);
404
405 /* Apply input filters. */
406 ri = ifp->info;
407
408 ret = rip_incoming_filter (&p, ri);
409 if (ret < 0)
410 return;
411
hasso16705132003-05-25 14:49:19 +0000412 /* Modify entry according to the interface routemap. */
413 if (ri->routemap[RIP_FILTER_IN])
414 {
415 int ret;
416 struct rip_info newinfo;
417
418 memset (&newinfo, 0, sizeof (newinfo));
419 newinfo.type = ZEBRA_ROUTE_RIP;
420 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000421 newinfo.nexthop = rte->nexthop;
422 newinfo.from = from->sin_addr;
423 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000424 newinfo.metric = rte->metric;
425 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000426 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000427
428 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000429 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
430 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000431
432 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000433 {
434 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000435 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000436 inet_ntoa (p.prefix), p.prefixlen);
437 return;
438 }
hasso16705132003-05-25 14:49:19 +0000439
440 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000441 rte->nexthop = newinfo.nexthop_out;
442 rte->tag = htons (newinfo.tag_out); /* XXX */
443 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000444 }
445
paul718e3742002-12-13 20:15:29 +0000446 /* Once the entry has been validated, update the metric by
447 adding the cost of the network on wich the message
448 arrived. If the result is greater than infinity, use infinity
449 (RFC2453 Sec. 3.9.2) */
450 /* Zebra ripd can handle offset-list in. */
451 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
452
453 /* If offset-list does not modify the metric use interface's
454 metric. */
paula87552c2004-05-03 20:00:17 +0000455 if (!ret)
paul718e3742002-12-13 20:15:29 +0000456 rte->metric += ifp->metric;
457
458 if (rte->metric > RIP_METRIC_INFINITY)
459 rte->metric = RIP_METRIC_INFINITY;
460
461 /* Set nexthop pointer. */
462 if (rte->nexthop.s_addr == 0)
463 nexthop = &from->sin_addr;
464 else
465 nexthop = &rte->nexthop;
466
hasso16705132003-05-25 14:49:19 +0000467 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000468 if (rip_nexthop_check (nexthop) < 0)
469 {
470 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000471 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000472 return;
473 }
474
475 /* Get index for the prefix. */
476 rp = route_node_get (rip->table, (struct prefix *) &p);
477
478 /* Check to see whether there is already RIP route on the table. */
479 rinfo = rp->info;
480
481 if (rinfo)
482 {
483 /* Redistributed route check. */
484 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000485 && rinfo->metric != RIP_METRIC_INFINITY)
486 return;
paul718e3742002-12-13 20:15:29 +0000487
488 /* Local static route. */
489 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000490 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
491 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
492 && rinfo->metric != RIP_METRIC_INFINITY)
493 return;
paul718e3742002-12-13 20:15:29 +0000494 }
paula87552c2004-05-03 20:00:17 +0000495
496 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000497 {
498 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000499 for the destination prefix. If there is no such route, add
500 this route to the routing table, unless the metric is
501 infinity (there is no point in adding a route which
502 unusable). */
paul718e3742002-12-13 20:15:29 +0000503 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000504 {
505 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000506
paula87552c2004-05-03 20:00:17 +0000507 /* - Setting the destination prefix and length to those in
508 the RTE. */
509 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000510
paula87552c2004-05-03 20:00:17 +0000511 /* - Setting the metric to the newly calculated metric (as
512 described above). */
513 rinfo->metric = rte->metric;
514 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000515
paula87552c2004-05-03 20:00:17 +0000516 /* - Set the next hop address to be the address of the router
517 from which the datagram came or the next hop address
518 specified by a next hop RTE. */
519 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
520 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
521 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000522
paula87552c2004-05-03 20:00:17 +0000523 /* - Initialize the timeout for the route. If the
524 garbage-collection timer is running for this route, stop it
525 (see section 2.3 for a discussion of the timers). */
526 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000527
paula87552c2004-05-03 20:00:17 +0000528 /* - Set the route change flag. */
529 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Signal the output process to trigger an update (see section
532 2.5). */
533 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000534
paula87552c2004-05-03 20:00:17 +0000535 /* Finally, route goes into the kernel. */
536 rinfo->type = ZEBRA_ROUTE_RIP;
537 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000538
paula87552c2004-05-03 20:00:17 +0000539 /* Set distance value. */
540 rinfo->distance = rip_distance_apply (rinfo);
541
542 rp->info = rinfo;
543 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
544 rinfo->distance);
545 rinfo->flags |= RIP_RTF_FIB;
546 }
paul718e3742002-12-13 20:15:29 +0000547 }
548 else
549 {
550 /* Route is there but we are not sure the route is RIP or not. */
551 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000552
paul718e3742002-12-13 20:15:29 +0000553 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000554 to the address of the router from which the datagram came.
555 If this datagram is from the same router as the existing
556 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000557 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000558 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000559
560 if (same)
paula87552c2004-05-03 20:00:17 +0000561 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000562
paulb94f9db2004-05-01 20:45:38 +0000563
564 /* Fill in a minimaly temporary rip_info structure, for a future
565 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000566 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000567 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000568 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000569
570
paul718e3742002-12-13 20:15:29 +0000571 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000572 router as the existing route, and the new metric is different
573 than the old one; or, if the new metric is lower than the old
574 one, or if the tag has been changed; or if there is a route
575 with a lower administrave distance; or an update of the
576 distance on the actual route; do the following actions: */
577 if ((same && rinfo->metric != rte->metric)
578 || (rte->metric < rinfo->metric)
579 || ((same)
580 && (rinfo->metric == rte->metric)
581 && ntohs (rte->tag) != rinfo->tag)
582 || (rinfo->distance > rip_distance_apply (&rinfotmp))
583 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
584 {
585 /* - Adopt the route from the datagram. That is, put the
586 new metric in, and adjust the next hop address (if
587 necessary). */
588 oldmetric = rinfo->metric;
589 rinfo->metric = rte->metric;
590 rinfo->tag = ntohs (rte->tag);
591 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
592 rinfo->ifindex = ifp->ifindex;
593 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000594
paula87552c2004-05-03 20:00:17 +0000595 /* Should a new route to this network be established
596 while the garbage-collection timer is running, the
597 new route will replace the one that is about to be
598 deleted. In this case the garbage-collection timer
599 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000600
paula87552c2004-05-03 20:00:17 +0000601 if (oldmetric == RIP_METRIC_INFINITY &&
602 rinfo->metric < RIP_METRIC_INFINITY)
603 {
604 rinfo->type = ZEBRA_ROUTE_RIP;
605 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000606
paula87552c2004-05-03 20:00:17 +0000607 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000608
paula87552c2004-05-03 20:00:17 +0000609 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
610 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
613 rinfo->distance);
614 rinfo->flags |= RIP_RTF_FIB;
615 }
paul718e3742002-12-13 20:15:29 +0000616
paula87552c2004-05-03 20:00:17 +0000617 /* Update nexthop and/or metric value. */
618 if (oldmetric != RIP_METRIC_INFINITY)
619 {
620 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
621 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
622 rinfo->distance);
623 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000624
paula87552c2004-05-03 20:00:17 +0000625 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
626 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
627 }
paul718e3742002-12-13 20:15:29 +0000628
paula87552c2004-05-03 20:00:17 +0000629 /* - Set the route change flag and signal the output process
630 to trigger an update. */
631 rinfo->flags |= RIP_RTF_CHANGED;
632 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000633
paula87552c2004-05-03 20:00:17 +0000634 /* - If the new metric is infinity, start the deletion
635 process (described above); */
636 if (rinfo->metric == RIP_METRIC_INFINITY)
637 {
638 /* If the new metric is infinity, the deletion process
639 begins for the route, which is no longer used for
640 routing packets. Note that the deletion process is
641 started only when the metric is first set to
642 infinity. If the metric was already infinity, then a
643 new deletion process is not started. */
644 if (oldmetric != RIP_METRIC_INFINITY)
645 {
646 /* - The garbage-collection timer is set for 120 seconds. */
647 RIP_TIMER_ON (rinfo->t_garbage_collect,
648 rip_garbage_collect, rip->garbage_time);
649 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000650
paula87552c2004-05-03 20:00:17 +0000651 /* - The metric for the route is set to 16
652 (infinity). This causes the route to be removed
653 from service. */
654 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
655 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000656
paula87552c2004-05-03 20:00:17 +0000657 /* - The route change flag is to indicate that this
658 entry has been changed. */
659 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000660 response. */
paula87552c2004-05-03 20:00:17 +0000661 ; /* Above processes are already done previously. */
662 }
663 }
664 else
665 {
666 /* otherwise, re-initialize the timeout. */
667 rip_timeout_update (rinfo);
668 }
669 }
paul718e3742002-12-13 20:15:29 +0000670 /* Unlock tempolary lock of the route. */
671 route_unlock_node (rp);
672 }
673}
674
675/* Dump RIP packet */
676void
hasso8a676be2004-10-08 06:36:38 +0000677rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000678{
679 caddr_t lim;
680 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000681 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000682 char pbuf[BUFSIZ], nbuf[BUFSIZ];
683 u_char netmask = 0;
684 u_char *p;
685
686 /* Set command string. */
687 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
688 command_str = lookup (rip_msg, packet->command);
689 else
690 command_str = "unknown";
691
692 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000693 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000694 sndrcv, command_str, packet->version, size);
695
696 /* Dump each routing table entry. */
697 rte = packet->rte;
698
699 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
700 {
701 if (packet->version == RIPv2)
702 {
703 netmask = ip_masklen (rte->mask);
704
paulca5e5162004-06-06 22:06:33 +0000705 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000706 {
paulca5e5162004-06-06 22:06:33 +0000707 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000708 {
709 p = (u_char *)&rte->prefix;
710
ajs5d6c3772004-12-08 19:24:06 +0000711 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000712 ntohs (rte->family), ntohs (rte->tag), p);
713 }
paulca5e5162004-06-06 22:06:33 +0000714 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000715 {
716 struct rip_md5_info *md5;
717
718 md5 = (struct rip_md5_info *) &packet->rte;
719
ajs5d6c3772004-12-08 19:24:06 +0000720 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000721 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000722 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000723 " Auth Data len %d",
724 ntohs (md5->packet_len), md5->keyid,
725 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000726 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000727 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000728 }
paulca5e5162004-06-06 22:06:33 +0000729 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000730 {
731 p = (u_char *)&rte->prefix;
732
ajs5d6c3772004-12-08 19:24:06 +0000733 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000734 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000735 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000736 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000737 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
738 p[7], p[9], p[10], p[11], p[12], p[13],
739 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000740 }
741 else
742 {
ajs5d6c3772004-12-08 19:24:06 +0000743 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000744 ntohs (rte->family), ntohs (rte->tag));
745 }
746 }
747 else
ajs5d6c3772004-12-08 19:24:06 +0000748 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000749 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
750 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
751 BUFSIZ), ntohs (rte->family),
752 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000753 }
754 else
755 {
ajs5d6c3772004-12-08 19:24:06 +0000756 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000757 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
758 ntohs (rte->family), ntohs (rte->tag),
759 (u_long)ntohl (rte->metric));
760 }
761 }
762}
763
764/* Check if the destination address is valid (unicast; not net 0
765 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
766 check net 0 because we accept default route. */
767int
768rip_destination_check (struct in_addr addr)
769{
770 u_int32_t destination;
771
772 /* Convert to host byte order. */
773 destination = ntohl (addr.s_addr);
774
775 if (IPV4_NET127 (destination))
776 return 0;
777
778 /* Net 0 may match to the default route. */
779 if (IPV4_NET0 (destination) && destination != 0)
780 return 0;
781
782 /* Unicast address must belong to class A, B, C. */
783 if (IN_CLASSA (destination))
784 return 1;
785 if (IN_CLASSB (destination))
786 return 1;
787 if (IN_CLASSC (destination))
788 return 1;
789
790 return 0;
791}
792
793/* RIP version 2 authentication. */
794int
795rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
796 struct interface *ifp)
797{
798 struct rip_interface *ri;
799 char *auth_str;
800
801 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000802 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000803 inet_ntoa (from->sin_addr));
804
805 ri = ifp->info;
806
807 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000808 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000809 return 0;
810
811 /* Simple password authentication. */
812 if (ri->auth_str)
813 {
814 auth_str = (char *) &rte->prefix;
815
816 if (strncmp (auth_str, ri->auth_str, 16) == 0)
817 return 1;
818 }
819 if (ri->key_chain)
820 {
821 struct keychain *keychain;
822 struct key *key;
823
824 keychain = keychain_lookup (ri->key_chain);
825 if (keychain == NULL)
826 return 0;
827
828 key = key_match_for_accept (keychain, (char *) &rte->prefix);
829 if (key)
830 return 1;
831 }
832 return 0;
833}
834
835/* RIP version 2 authentication with MD5. */
836int
837rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000838 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000839{
840 struct rip_interface *ri;
841 struct rip_md5_info *md5;
842 struct rip_md5_data *md5data;
843 struct keychain *keychain;
844 struct key *key;
845 struct md5_ctx ctx;
846 u_char pdigest[RIP_AUTH_MD5_SIZE];
847 u_char digest[RIP_AUTH_MD5_SIZE];
848 u_int16_t packet_len;
849 char *auth_str = NULL;
850
851 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000852 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000853 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000854
855 ri = ifp->info;
856 md5 = (struct rip_md5_info *) &packet->rte;
857
858 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000859 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000860 return 0;
861
paulca5e5162004-06-06 22:06:33 +0000862 /* If the authentication length is less than 16, then it must be wrong for
863 * any interpretation of rfc2082. Some implementations also interpret
864 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000865 */
paulca5e5162004-06-06 22:06:33 +0000866 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
867 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000868 {
869 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000870 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000871 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000872 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000873 }
paul718e3742002-12-13 20:15:29 +0000874
paulca5e5162004-06-06 22:06:33 +0000875 /* grab and verify check packet length */
876 packet_len = ntohs (md5->packet_len);
877
878 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
879 {
880 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000881 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000882 "greater than received length %d!",
883 md5->packet_len, length);
884 return 0;
885 }
886
887 /* retrieve authentication data */
888 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
889
paul718e3742002-12-13 20:15:29 +0000890 if (ri->key_chain)
891 {
892 keychain = keychain_lookup (ri->key_chain);
893 if (keychain == NULL)
894 return 0;
895
896 key = key_lookup_for_accept (keychain, md5->keyid);
897 if (key == NULL)
898 return 0;
899
900 auth_str = key->string;
901 }
902
903 if (ri->auth_str)
904 auth_str = ri->auth_str;
905
906 if (! auth_str)
907 return 0;
908
909 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000910
911 /* Save digest to pdigest. */
912 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
913
914 /* Overwrite digest by my secret. */
915 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000916 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000917
918 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000919 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000920 &ctx);
paul718e3742002-12-13 20:15:29 +0000921 md5_finish_ctx (&ctx, digest);
922
923 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
924 return packet_len;
925 else
926 return 0;
927}
928
paulb14ee002005-02-04 23:42:41 +0000929/* Pick correct auth string for sends, prepare auth_str buffer for use.
930 * (left justified and padded).
931 *
932 * presumes one of ri or key is valid, and that the auth strings they point
933 * to are nul terminated. If neither are present, auth_str will be fully
934 * zero padded.
935 *
936 */
937static void
938rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
939 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000940{
paulb14ee002005-02-04 23:42:41 +0000941 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000942
paulb14ee002005-02-04 23:42:41 +0000943 memset (auth_str, 0, len);
944 if (key && key->string)
945 strncpy (auth_str, key->string, len);
946 else if (ri->auth_str)
947 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000948
paulb14ee002005-02-04 23:42:41 +0000949 return;
950}
paul718e3742002-12-13 20:15:29 +0000951
paulb14ee002005-02-04 23:42:41 +0000952/* Write RIPv2 simple password authentication information
953 *
954 * auth_str is presumed to be 2 bytes and correctly prepared
955 * (left justified and zero padded).
956 */
957static void
958rip_auth_simple_write (struct stream *s, char *auth_str, int len)
959{
960 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +0000961
paulb14ee002005-02-04 23:42:41 +0000962 stream_putw (s, RIP_FAMILY_AUTH);
963 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
964 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
965
966 return;
967}
968
969/* write RIPv2 MD5 "authentication header"
970 * (uses the auth key data field)
971 *
972 * Digest offset field is set to 0.
973 *
974 * returns: offset of the digest offset field, which must be set when
975 * length to the auth-data MD5 digest is known.
976 */
977static size_t
978rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
979 struct key *key)
980{
981 size_t len = 0;
982
983 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +0000984
985 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000986 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000987 stream_putw (s, RIP_AUTH_MD5);
988
paulb14ee002005-02-04 23:42:41 +0000989 /* MD5 AH digest offset field.
990 *
991 * Set to placeholder value here, to true value when RIP-2 Packet length
992 * is known. Actual value is set in .....().
993 */
paul9985f832005-02-09 15:51:56 +0000994 len = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +0000995 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +0000996
997 /* Key ID. */
998 if (key)
999 stream_putc (s, key->index % 256);
1000 else
1001 stream_putc (s, 1);
1002
paulca5e5162004-06-06 22:06:33 +00001003 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1004 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1005 * to be configurable.
1006 */
1007 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001008
1009 /* Sequence Number (non-decreasing). */
1010 /* RFC2080: The value used in the sequence number is
1011 arbitrary, but two suggestions are the time of the
1012 message's creation or a simple message counter. */
1013 stream_putl (s, time (NULL));
1014
1015 /* Reserved field must be zero. */
1016 stream_putl (s, 0);
1017 stream_putl (s, 0);
1018
paulb14ee002005-02-04 23:42:41 +00001019 return len;
1020}
paul718e3742002-12-13 20:15:29 +00001021
paulb14ee002005-02-04 23:42:41 +00001022/* If authentication is in used, write the appropriate header
1023 * returns stream offset to which length must later be written
1024 * or 0 if this is not required
1025 */
1026static size_t
1027rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1028 struct key *key, char *auth_str, int len)
1029{
1030 assert (ri->auth_type != RIP_NO_AUTH);
1031
1032 switch (ri->auth_type)
1033 {
1034 case RIP_AUTH_SIMPLE_PASSWORD:
1035 rip_auth_prepare_str_send (ri, key, auth_str, len);
1036 rip_auth_simple_write (s, auth_str, len);
1037 return 0;
1038 case RIP_AUTH_MD5:
1039 return rip_auth_md5_ah_write (s, ri, key);
1040 }
1041 assert (1);
1042}
1043
1044/* Write RIPv2 MD5 authentication data trailer */
1045static void
1046rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1047 char *auth_str, int authlen)
1048{
1049 unsigned long len;
1050 struct md5_ctx ctx;
1051 unsigned char digest[RIP_AUTH_MD5_SIZE];
1052
1053 /* Make it sure this interface is configured as MD5
1054 authentication. */
1055 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1056 assert (doff > 0);
1057
1058 /* Get packet length. */
1059 len = stream_get_endp(s);
1060
1061 /* Check packet length. */
1062 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1063 {
1064 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1065 return;
1066 }
1067
1068 /* Set the digest offset length in the header */
1069 stream_putw_at (s, doff, len);
1070
paul718e3742002-12-13 20:15:29 +00001071 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001072 stream_putw (s, RIP_FAMILY_AUTH);
1073 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001074
1075 /* Generate a digest for the RIP packet. */
paul718e3742002-12-13 20:15:29 +00001076 md5_init_ctx (&ctx);
1077 md5_process_bytes (s->data, s->endp, &ctx);
paulb14ee002005-02-04 23:42:41 +00001078 md5_process_bytes (auth_str, RIP_AUTH_MD5_SIZE, &ctx);
paul718e3742002-12-13 20:15:29 +00001079 md5_finish_ctx (&ctx, digest);
1080
1081 /* Copy the digest to the packet. */
1082 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1083}
1084
1085/* RIP routing information. */
1086void
1087rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001088 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001089{
1090 caddr_t lim;
1091 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001092 struct prefix_ipv4 ifaddr;
1093 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001094 int subnetted;
paul718e3742002-12-13 20:15:29 +00001095
paul727d1042002-12-13 20:50:29 +00001096 /* We don't know yet. */
1097 subnetted = -1;
1098
paul718e3742002-12-13 20:15:29 +00001099 /* The Response must be ignored if it is not from the RIP
1100 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001101 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001102 {
1103 zlog_info ("response doesn't come from RIP port: %d",
1104 from->sin_port);
1105 rip_peer_bad_packet (from);
1106 return;
1107 }
1108
1109 /* The datagram's IPv4 source address should be checked to see
1110 whether the datagram is from a valid neighbor; the source of the
1111 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001112 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001113 {
1114 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1115 inet_ntoa (from->sin_addr));
1116 rip_peer_bad_packet (from);
1117 return;
1118 }
1119
1120 /* It is also worth checking to see whether the response is from one
1121 of the router's own addresses. */
1122
1123 ; /* Alredy done in rip_read () */
1124
1125 /* Update RIP peer. */
1126 rip_peer_update (from, packet->version);
1127
1128 /* Set RTE pointer. */
1129 rte = packet->rte;
1130
1131 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1132 {
1133 /* RIPv2 authentication check. */
1134 /* If the Address Family Identifier of the first (and only the
1135 first) entry in the message is 0xFFFF, then the remainder of
1136 the entry contains the authentication. */
1137 /* If the packet gets here it means authentication enabled */
1138 /* Check is done in rip_read(). So, just skipping it */
1139 if (packet->version == RIPv2 &&
1140 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001141 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001142 continue;
1143
paulca5e5162004-06-06 22:06:33 +00001144 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001145 {
1146 /* Address family check. RIP only supports AF_INET. */
1147 zlog_info ("Unsupported family %d from %s.",
1148 ntohs (rte->family), inet_ntoa (from->sin_addr));
1149 continue;
1150 }
1151
1152 /* - is the destination address valid (e.g., unicast; not net 0
1153 or 127) */
1154 if (! rip_destination_check (rte->prefix))
1155 {
1156 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1157 rip_peer_bad_route (from);
1158 continue;
1159 }
1160
1161 /* Convert metric value to host byte order. */
1162 rte->metric = ntohl (rte->metric);
1163
1164 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1165 if (! (rte->metric >= 1 && rte->metric <= 16))
1166 {
1167 zlog_info ("Route's metric is not in the 1-16 range.");
1168 rip_peer_bad_route (from);
1169 continue;
1170 }
1171
1172 /* RIPv1 does not have nexthop value. */
1173 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1174 {
1175 zlog_info ("RIPv1 packet with nexthop value %s",
1176 inet_ntoa (rte->nexthop));
1177 rip_peer_bad_route (from);
1178 continue;
1179 }
1180
1181 /* That is, if the provided information is ignored, a possibly
1182 sub-optimal, but absolutely valid, route may be taken. If
1183 the received Next Hop is not directly reachable, it should be
1184 treated as 0.0.0.0. */
1185 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1186 {
1187 u_int32_t addrval;
1188
1189 /* Multicast address check. */
1190 addrval = ntohl (rte->nexthop.s_addr);
1191 if (IN_CLASSD (addrval))
1192 {
1193 zlog_info ("Nexthop %s is multicast address, skip this rte",
1194 inet_ntoa (rte->nexthop));
1195 continue;
1196 }
1197
1198 if (! if_lookup_address (rte->nexthop))
1199 {
1200 struct route_node *rn;
1201 struct rip_info *rinfo;
1202
1203 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1204
1205 if (rn)
1206 {
1207 rinfo = rn->info;
1208
1209 if (rinfo->type == ZEBRA_ROUTE_RIP
1210 && rinfo->sub_type == RIP_ROUTE_RTE)
1211 {
1212 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001213 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 +00001214 rte->nexthop = rinfo->from;
1215 }
1216 else
1217 {
1218 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001219 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 +00001220 rte->nexthop.s_addr = 0;
1221 }
1222
1223 route_unlock_node (rn);
1224 }
1225 else
1226 {
1227 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001228 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 +00001229 rte->nexthop.s_addr = 0;
1230 }
1231
1232 }
1233 }
1234
1235 /* For RIPv1, there won't be a valid netmask.
1236
1237 This is a best guess at the masks. If everyone was using old
1238 Ciscos before the 'ip subnet zero' option, it would be almost
1239 right too :-)
1240
1241 Cisco summarize ripv1 advertisments to the classful boundary
1242 (/16 for class B's) except when the RIP packet does to inside
1243 the classful network in question. */
1244
1245 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1246 || (packet->version == RIPv2
1247 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1248 {
1249 u_int32_t destination;
1250
paul727d1042002-12-13 20:50:29 +00001251 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001252 {
1253 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1254 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1255 apply_classful_mask_ipv4 (&ifaddrclass);
1256 subnetted = 0;
1257 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1258 subnetted = 1;
1259 }
paul727d1042002-12-13 20:50:29 +00001260
paul718e3742002-12-13 20:15:29 +00001261 destination = ntohl (rte->prefix.s_addr);
1262
paul727d1042002-12-13 20:50:29 +00001263 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001264 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001265 else if (IN_CLASSB (destination))
1266 masklen2ip (16, &rte->mask);
1267 else if (IN_CLASSC (destination))
1268 masklen2ip (24, &rte->mask);
1269
1270 if (subnetted == 1)
1271 masklen2ip (ifaddrclass.prefixlen,
1272 (struct in_addr *) &destination);
1273 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1274 ifaddrclass.prefix.s_addr))
1275 {
1276 masklen2ip (ifaddr.prefixlen, &rte->mask);
1277 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1278 masklen2ip (32, &rte->mask);
1279 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001280 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001281 }
1282 else
1283 {
1284 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1285 continue;
1286 }
1287
1288 if (IS_RIP_DEBUG_EVENT)
1289 {
ajs5d6c3772004-12-08 19:24:06 +00001290 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1291 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001292 }
1293 }
1294
1295 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1296 ignore the entry. */
1297 if ((packet->version == RIPv2)
1298 && (rte->mask.s_addr != 0)
1299 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1300 {
1301 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1302 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1303 rip_peer_bad_route (from);
1304 continue;
1305 }
1306
1307 /* Default route's netmask is ignored. */
1308 if (packet->version == RIPv2
1309 && (rte->prefix.s_addr == 0)
1310 && (rte->mask.s_addr != 0))
1311 {
1312 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001313 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001314 rte->mask.s_addr = 0;
1315 }
1316
1317 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001318 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001319 }
1320}
1321
paulc49ad8f2004-10-22 10:27:28 +00001322/* RIP packet send to destination address, on interface denoted by
1323 * by connected argument. NULL to argument denotes destination should be
1324 * should be RIP multicast group
1325 */
paul718e3742002-12-13 20:15:29 +00001326int
paulc49ad8f2004-10-22 10:27:28 +00001327rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1328 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001329{
paul931cd542004-01-23 15:31:42 +00001330 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001331 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001332
1333 assert (ifc != NULL);
1334
paul931cd542004-01-23 15:31:42 +00001335 if (IS_RIP_DEBUG_PACKET)
1336 {
1337 char dst[20];
1338 if (to)
1339 {
1340 strcpy(dst, inet_ntoa(to->sin_addr));
1341 }
1342 else
1343 {
1344 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1345 strcpy(dst, inet_ntoa(sin.sin_addr));
1346 }
ajs5d6c3772004-12-08 19:24:06 +00001347 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001348 inet_ntoa(ifc->address->u.prefix4),
1349 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001350 }
paulc49ad8f2004-10-22 10:27:28 +00001351 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001352 {
1353 /*
1354 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1355 * with multiple addresses on the same subnet: the first address
1356 * on the subnet is configured "primary", and all subsequent addresses
1357 * on that subnet are treated as "secondary" addresses.
1358 * In order to avoid routing-table bloat on other rip listeners,
1359 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1360 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1361 * flag is set, we would end up sending a packet for a "secondary"
1362 * source address on non-linux systems.
1363 */
1364 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001365 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001366 return 0;
1367 }
1368
paul718e3742002-12-13 20:15:29 +00001369 /* Make destination address. */
1370 memset (&sin, 0, sizeof (struct sockaddr_in));
1371 sin.sin_family = AF_INET;
1372#ifdef HAVE_SIN_LEN
1373 sin.sin_len = sizeof (struct sockaddr_in);
1374#endif /* HAVE_SIN_LEN */
1375
1376 /* When destination is specified, use it's port and address. */
1377 if (to)
1378 {
paul718e3742002-12-13 20:15:29 +00001379 sin.sin_port = to->sin_port;
1380 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001381 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001382 }
1383 else
1384 {
paul718e3742002-12-13 20:15:29 +00001385
1386 sin.sin_port = htons (RIP_PORT_DEFAULT);
1387 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1388
paul931cd542004-01-23 15:31:42 +00001389 /*
1390 * we have to open a new socket for each packet because this
1391 * is the most portable way to bind to a different source
1392 * ipv4 address for each packet.
1393 */
1394 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1395 if (send_sock < 0)
1396 {
1397 zlog_warn("rip_send_packet could not create socket %s",
ajs6099b3b2004-11-20 02:06:59 +00001398 safe_strerror(errno));
paul931cd542004-01-23 15:31:42 +00001399 return -1;
1400 }
1401 sockopt_broadcast (send_sock);
1402 sockopt_reuseaddr (send_sock);
1403 sockopt_reuseport (send_sock);
1404#ifdef RIP_RECVMSG
1405 setsockopt_pktinfo (send_sock);
1406#endif /* RIP_RECVMSG */
paulc49ad8f2004-10-22 10:27:28 +00001407 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001408 }
1409
paul931cd542004-01-23 15:31:42 +00001410 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001411 sizeof (struct sockaddr_in));
1412
1413 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001414 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001415 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001416
1417 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001418 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001419
paul931cd542004-01-23 15:31:42 +00001420 if (!to)
1421 close(send_sock);
1422
paul718e3742002-12-13 20:15:29 +00001423 return ret;
1424}
1425
1426/* Add redistributed route to RIP table. */
1427void
1428rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1429 unsigned int ifindex, struct in_addr *nexthop)
1430{
1431 int ret;
1432 struct route_node *rp;
1433 struct rip_info *rinfo;
1434
1435 /* Redistribute route */
1436 ret = rip_destination_check (p->prefix);
1437 if (! ret)
1438 return;
1439
1440 rp = route_node_get (rip->table, (struct prefix *) p);
1441
1442 rinfo = rp->info;
1443
1444 if (rinfo)
1445 {
1446 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1447 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1448 && rinfo->metric != RIP_METRIC_INFINITY)
1449 {
1450 route_unlock_node (rp);
1451 return;
1452 }
1453
1454 /* Manually configured RIP route check. */
1455 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001456 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1457 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001458 {
hasso16705132003-05-25 14:49:19 +00001459 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1460 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001461 {
1462 route_unlock_node (rp);
1463 return;
1464 }
1465 }
1466
1467 RIP_TIMER_OFF (rinfo->t_timeout);
1468 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1469
1470 if (rip_route_rte (rinfo))
1471 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1472 rinfo->metric);
1473 rp->info = NULL;
1474 rip_info_free (rinfo);
1475
1476 route_unlock_node (rp);
1477 }
1478
1479 rinfo = rip_info_new ();
1480
1481 rinfo->type = type;
1482 rinfo->sub_type = sub_type;
1483 rinfo->ifindex = ifindex;
1484 rinfo->metric = 1;
1485 rinfo->rp = rp;
1486
1487 if (nexthop)
1488 rinfo->nexthop = *nexthop;
1489
1490 rinfo->flags |= RIP_RTF_FIB;
1491 rp->info = rinfo;
1492
1493 rinfo->flags |= RIP_RTF_CHANGED;
1494
hasso16705132003-05-25 14:49:19 +00001495 if (IS_RIP_DEBUG_EVENT) {
1496 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001497 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001498 inet_ntoa(p->prefix), p->prefixlen,
1499 ifindex2ifname(ifindex));
1500 else
ajs5d6c3772004-12-08 19:24:06 +00001501 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001502 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1503 ifindex2ifname(ifindex));
1504 }
1505
1506
paul718e3742002-12-13 20:15:29 +00001507 rip_event (RIP_TRIGGERED_UPDATE, 0);
1508}
1509
1510/* Delete redistributed route from RIP table. */
1511void
1512rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1513 unsigned int ifindex)
1514{
1515 int ret;
1516 struct route_node *rp;
1517 struct rip_info *rinfo;
1518
1519 ret = rip_destination_check (p->prefix);
1520 if (! ret)
1521 return;
1522
1523 rp = route_node_lookup (rip->table, (struct prefix *) p);
1524 if (rp)
1525 {
1526 rinfo = rp->info;
1527
1528 if (rinfo != NULL
1529 && rinfo->type == type
1530 && rinfo->sub_type == sub_type
1531 && rinfo->ifindex == ifindex)
1532 {
1533 /* Perform poisoned reverse. */
1534 rinfo->metric = RIP_METRIC_INFINITY;
1535 RIP_TIMER_ON (rinfo->t_garbage_collect,
1536 rip_garbage_collect, rip->garbage_time);
1537 RIP_TIMER_OFF (rinfo->t_timeout);
1538 rinfo->flags |= RIP_RTF_CHANGED;
1539
hasso16705132003-05-25 14:49:19 +00001540 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001541 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001542 inet_ntoa(p->prefix), p->prefixlen,
1543 ifindex2ifname(ifindex));
1544
paul718e3742002-12-13 20:15:29 +00001545 rip_event (RIP_TRIGGERED_UPDATE, 0);
1546 }
1547 }
1548}
1549
1550/* Response to request called from rip_read ().*/
1551void
1552rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001553 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001554{
1555 caddr_t lim;
1556 struct rte *rte;
1557 struct prefix_ipv4 p;
1558 struct route_node *rp;
1559 struct rip_info *rinfo;
1560 struct rip_interface *ri;
1561
hasso16705132003-05-25 14:49:19 +00001562 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001563 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001564 return;
1565
hasso429a0f82004-02-22 23:42:22 +00001566 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001567 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001568 if (! ri->running)
1569 return;
paul718e3742002-12-13 20:15:29 +00001570
1571 /* When passive interface is specified, suppress responses */
1572 if (ri->passive)
1573 return;
paulc49ad8f2004-10-22 10:27:28 +00001574
paul718e3742002-12-13 20:15:29 +00001575 /* RIP peer update. */
1576 rip_peer_update (from, packet->version);
1577
1578 lim = ((caddr_t) packet) + size;
1579 rte = packet->rte;
1580
1581 /* The Request is processed entry by entry. If there are no
1582 entries, no response is given. */
1583 if (lim == (caddr_t) rte)
1584 return;
1585
1586 /* There is one special case. If there is exactly one entry in the
1587 request, and it has an address family identifier of zero and a
1588 metric of infinity (i.e., 16), then this is a request to send the
1589 entire routing table. */
1590 if (lim == ((caddr_t) (rte + 1)) &&
1591 ntohs (rte->family) == 0 &&
1592 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1593 {
paulcc1131a2003-10-15 23:20:17 +00001594 struct prefix_ipv4 saddr;
1595
1596 /* saddr will be used for determining which routes to split-horizon.
1597 Since the source address we'll pick will be on the same subnet as the
1598 destination, for the purpose of split-horizoning, we'll
1599 pretend that "from" is our source address. */
1600 saddr.family = AF_INET;
1601 saddr.prefixlen = IPV4_MAX_BITLEN;
1602 saddr.prefix = from->sin_addr;
1603
paul718e3742002-12-13 20:15:29 +00001604 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001605 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001606 }
1607 else
1608 {
1609 /* Examine the list of RTEs in the Request one by one. For each
1610 entry, look up the destination in the router's routing
1611 database and, if there is a route, put that route's metric in
1612 the metric field of the RTE. If there is no explicit route
1613 to the specified destination, put infinity in the metric
1614 field. Once all the entries have been filled in, change the
1615 command from Request to Response and send the datagram back
1616 to the requestor. */
1617 p.family = AF_INET;
1618
1619 for (; ((caddr_t) rte) < lim; rte++)
1620 {
1621 p.prefix = rte->prefix;
1622 p.prefixlen = ip_masklen (rte->mask);
1623 apply_mask_ipv4 (&p);
1624
1625 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1626 if (rp)
1627 {
1628 rinfo = rp->info;
1629 rte->metric = htonl (rinfo->metric);
1630 route_unlock_node (rp);
1631 }
1632 else
1633 rte->metric = htonl (RIP_METRIC_INFINITY);
1634 }
1635 packet->command = RIP_RESPONSE;
1636
paulc49ad8f2004-10-22 10:27:28 +00001637 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001638 }
1639 rip_global_queries++;
1640}
1641
1642#if RIP_RECVMSG
1643/* Set IPv6 packet info to the socket. */
1644static int
1645setsockopt_pktinfo (int sock)
1646{
1647 int ret;
1648 int val = 1;
1649
1650 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1651 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001652 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001653 return ret;
1654}
1655
1656/* Read RIP packet by recvmsg function. */
1657int
1658rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1659 int *ifindex)
1660{
1661 int ret;
1662 struct msghdr msg;
1663 struct iovec iov;
1664 struct cmsghdr *ptr;
1665 char adata[1024];
1666
1667 msg.msg_name = (void *) from;
1668 msg.msg_namelen = sizeof (struct sockaddr_in);
1669 msg.msg_iov = &iov;
1670 msg.msg_iovlen = 1;
1671 msg.msg_control = (void *) adata;
1672 msg.msg_controllen = sizeof adata;
1673 iov.iov_base = buf;
1674 iov.iov_len = size;
1675
1676 ret = recvmsg (sock, &msg, 0);
1677 if (ret < 0)
1678 return ret;
1679
ajsb99760a2005-01-04 16:24:43 +00001680 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001681 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1682 {
1683 struct in_pktinfo *pktinfo;
1684 int i;
1685
1686 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1687 i = pktinfo->ipi_ifindex;
1688 }
1689 return ret;
1690}
1691
1692/* RIP packet read function. */
1693int
1694rip_read_new (struct thread *t)
1695{
1696 int ret;
1697 int sock;
1698 char buf[RIP_PACKET_MAXSIZ];
1699 struct sockaddr_in from;
1700 unsigned int ifindex;
1701
1702 /* Fetch socket then register myself. */
1703 sock = THREAD_FD (t);
1704 rip_event (RIP_READ, sock);
1705
1706 /* Read RIP packet. */
1707 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1708 if (ret < 0)
1709 {
ajs6099b3b2004-11-20 02:06:59 +00001710 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001711 return ret;
1712 }
1713
1714 return ret;
1715}
1716#endif /* RIP_RECVMSG */
1717
1718/* First entry point of RIP packet. */
1719int
1720rip_read (struct thread *t)
1721{
1722 int sock;
1723 int ret;
1724 int rtenum;
1725 union rip_buf rip_buf;
1726 struct rip_packet *packet;
1727 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001728 int len;
1729 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001730 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001731 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001732 struct rip_interface *ri;
1733
1734 /* Fetch socket then register myself. */
1735 sock = THREAD_FD (t);
1736 rip->t_read = NULL;
1737
1738 /* Add myself to tne next event */
1739 rip_event (RIP_READ, sock);
1740
1741 /* RIPd manages only IPv4. */
1742 memset (&from, 0, sizeof (struct sockaddr_in));
1743 fromlen = sizeof (struct sockaddr_in);
1744
1745 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1746 (struct sockaddr *) &from, &fromlen);
1747 if (len < 0)
1748 {
ajs6099b3b2004-11-20 02:06:59 +00001749 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001750 return len;
1751 }
1752
1753 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001754 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001755 {
1756 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001757 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001758 return -1;
1759 }
1760
1761 /* Which interface is this packet comes from. */
1762 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001763
paul718e3742002-12-13 20:15:29 +00001764 /* RIP packet received */
1765 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001766 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001767 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1768 ifp ? ifp->name : "unknown");
1769
1770 /* If this packet come from unknown interface, ignore it. */
1771 if (ifp == NULL)
1772 {
ajs766a0ca2004-12-15 14:55:51 +00001773 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1774 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001775 return -1;
1776 }
1777
1778 ifc = connected_lookup_address (ifp, from.sin_addr);
1779
1780 if (ifc == NULL)
1781 {
ajs766a0ca2004-12-15 14:55:51 +00001782 zlog_info ("rip_read: cannot find connected address for packet from %s "
1783 "port %d on interface %s",
1784 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001785 return -1;
1786 }
1787
1788 /* Packet length check. */
1789 if (len < RIP_PACKET_MINSIZ)
1790 {
1791 zlog_warn ("packet size %d is smaller than minimum size %d",
1792 len, RIP_PACKET_MINSIZ);
1793 rip_peer_bad_packet (&from);
1794 return len;
1795 }
1796 if (len > RIP_PACKET_MAXSIZ)
1797 {
1798 zlog_warn ("packet size %d is larger than max size %d",
1799 len, RIP_PACKET_MAXSIZ);
1800 rip_peer_bad_packet (&from);
1801 return len;
1802 }
1803
1804 /* Packet alignment check. */
1805 if ((len - RIP_PACKET_MINSIZ) % 20)
1806 {
1807 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1808 rip_peer_bad_packet (&from);
1809 return len;
1810 }
1811
1812 /* Set RTE number. */
1813 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1814
1815 /* For easy to handle. */
1816 packet = &rip_buf.rip_packet;
1817
1818 /* RIP version check. */
1819 if (packet->version == 0)
1820 {
1821 zlog_info ("version 0 with command %d received.", packet->command);
1822 rip_peer_bad_packet (&from);
1823 return -1;
1824 }
1825
1826 /* Dump RIP packet. */
1827 if (IS_RIP_DEBUG_RECV)
1828 rip_packet_dump (packet, len, "RECV");
1829
1830 /* RIP version adjust. This code should rethink now. RFC1058 says
1831 that "Version 1 implementations are to ignore this extra data and
1832 process only the fields specified in this document.". So RIPv3
1833 packet should be treated as RIPv1 ignoring must be zero field. */
1834 if (packet->version > RIPv2)
1835 packet->version = RIPv2;
1836
1837 /* Is RIP running or is this RIP neighbor ?*/
1838 ri = ifp->info;
1839 if (! ri->running && ! rip_neighbor_lookup (&from))
1840 {
1841 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001842 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001843 rip_peer_bad_packet (&from);
1844 return -1;
1845 }
1846
1847 /* RIP Version check. */
1848 if (packet->command == RIP_RESPONSE)
1849 {
paulf38a4712003-06-07 01:10:00 +00001850 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1851 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001852 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001853 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001854 {
1855 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001856 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001857 packet->version);
1858 rip_peer_bad_packet (&from);
1859 return -1;
1860 }
1861 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001862 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001863 {
1864 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001865 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001866 packet->version);
1867 rip_peer_bad_packet (&from);
1868 return -1;
1869 }
paul718e3742002-12-13 20:15:29 +00001870 }
1871
1872 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1873 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1874 accepted; authenticated RIP-2 messages shall be discarded. */
1875
1876 if ((ri->auth_type == RIP_NO_AUTH)
1877 && rtenum
paulca5e5162004-06-06 22:06:33 +00001878 && (packet->version == RIPv2)
1879 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001880 {
1881 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001882 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001883 packet->version);
1884 rip_peer_bad_packet (&from);
1885 return -1;
1886 }
1887
1888 /* If the router is configured to authenticate RIP-2 messages, then
1889 RIP-1 messages and RIP-2 messages which pass authentication
1890 testing shall be accepted; unauthenticated and failed
1891 authentication RIP-2 messages shall be discarded. For maximum
1892 security, RIP-1 messages should be ignored when authentication is
1893 in use (see section 4.1); otherwise, the routing information from
1894 authenticated messages will be propagated by RIP-1 routers in an
1895 unauthenticated manner. */
1896
1897 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001898 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001899 {
1900 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001901 if (packet->version == RIPv1
1902 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001903 {
1904 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001905 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001906 ("packet RIPv%d is dropped because authentication enabled",
1907 packet->version);
paul718e3742002-12-13 20:15:29 +00001908 rip_peer_bad_packet (&from);
1909 return -1;
1910 }
1911
1912 /* Check RIPv2 authentication. */
1913 if (packet->version == RIPv2)
1914 {
paulca5e5162004-06-06 22:06:33 +00001915 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001916 {
paulca5e5162004-06-06 22:06:33 +00001917 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001918 {
1919 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1920 if (! ret)
1921 {
1922 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001923 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001924 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001925 rip_peer_bad_packet (&from);
1926 return -1;
1927 }
1928 else
1929 {
1930 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001931 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001932 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001933 }
1934 }
paulca5e5162004-06-06 22:06:33 +00001935 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001936 {
paulca5e5162004-06-06 22:06:33 +00001937 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001938 if (! ret)
1939 {
1940 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001941 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001942 rip_peer_bad_packet (&from);
1943 return -1;
1944 }
1945 else
1946 {
1947 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001948 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001949 }
1950 /* Reset RIP packet length to trim MD5 data. */
1951 len = ret;
1952 }
1953 else
1954 {
1955 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001956 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00001957 ntohs (packet->rte->tag));
1958 rip_peer_bad_packet (&from);
1959 return -1;
1960 }
1961 }
1962 else
1963 {
1964 /* There is no authentication in the packet. */
1965 if (ri->auth_str || ri->key_chain)
1966 {
1967 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001968 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001969 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001970 rip_peer_bad_packet (&from);
1971 return -1;
1972 }
1973 }
1974 }
1975 }
1976
1977 /* Process each command. */
1978 switch (packet->command)
1979 {
1980 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00001981 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001982 break;
1983 case RIP_REQUEST:
1984 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00001985 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001986 break;
1987 case RIP_TRACEON:
1988 case RIP_TRACEOFF:
1989 zlog_info ("Obsolete command %s received, please sent it to routed",
1990 lookup (rip_msg, packet->command));
1991 rip_peer_bad_packet (&from);
1992 break;
1993 case RIP_POLL_ENTRY:
1994 zlog_info ("Obsolete command %s received",
1995 lookup (rip_msg, packet->command));
1996 rip_peer_bad_packet (&from);
1997 break;
1998 default:
1999 zlog_info ("Unknown RIP command %d received", packet->command);
2000 rip_peer_bad_packet (&from);
2001 break;
2002 }
2003
2004 return len;
2005}
2006
2007/* Make socket for RIP protocol. */
2008int
2009rip_create_socket ()
2010{
2011 int ret;
2012 int sock;
2013 struct sockaddr_in addr;
2014 struct servent *sp;
2015
2016 memset (&addr, 0, sizeof (struct sockaddr_in));
2017
2018 /* Set RIP port. */
2019 sp = getservbyname ("router", "udp");
2020 if (sp)
2021 addr.sin_port = sp->s_port;
2022 else
2023 addr.sin_port = htons (RIP_PORT_DEFAULT);
2024
2025 /* Address shoud be any address. */
2026 addr.sin_family = AF_INET;
2027 addr.sin_addr.s_addr = INADDR_ANY;
2028
2029 /* Make datagram socket. */
2030 sock = socket (AF_INET, SOCK_DGRAM, 0);
2031 if (sock < 0)
2032 {
ajs6a52d0d2005-01-30 18:49:28 +00002033 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +00002034 exit (1);
2035 }
2036
2037 sockopt_broadcast (sock);
2038 sockopt_reuseaddr (sock);
2039 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00002040 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00002041#ifdef RIP_RECVMSG
2042 setsockopt_pktinfo (sock);
2043#endif /* RIP_RECVMSG */
2044
pauledd7c242003-06-04 13:59:38 +00002045 if (ripd_privs.change (ZPRIVS_RAISE))
2046 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00002047 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
2048 if (ret < 0)
2049 {
ajs79853452005-01-30 17:40:29 +00002050 int save_errno = errno;
pauld62262a2003-11-17 09:08:45 +00002051 if (ripd_privs.change (ZPRIVS_LOWER))
2052 zlog_err ("rip_create_socket: could not lower privs");
ajs79853452005-01-30 17:40:29 +00002053 zlog_err("cannot bind to port %d: %s",
2054 (int)ntohs(addr.sin_port), safe_strerror(save_errno));
paul718e3742002-12-13 20:15:29 +00002055 return ret;
2056 }
pauledd7c242003-06-04 13:59:38 +00002057 if (ripd_privs.change (ZPRIVS_LOWER))
2058 zlog_err ("rip_create_socket: could not lower privs");
2059
paul718e3742002-12-13 20:15:29 +00002060 return sock;
2061}
2062
paulb14ee002005-02-04 23:42:41 +00002063
paul718e3742002-12-13 20:15:29 +00002064/* Write routing table entry to the stream and return next index of
2065 the routing table entry in the stream. */
2066int
2067rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002068 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002069{
2070 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002071
2072 /* Write routing table entry. */
2073 if (version == RIPv1)
2074 {
2075 stream_putw (s, AF_INET);
2076 stream_putw (s, 0);
2077 stream_put_ipv4 (s, p->prefix.s_addr);
2078 stream_put_ipv4 (s, 0);
2079 stream_put_ipv4 (s, 0);
2080 stream_putl (s, rinfo->metric_out);
2081 }
2082 else
2083 {
2084 masklen2ip (p->prefixlen, &mask);
2085
2086 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002087 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002088 stream_put_ipv4 (s, p->prefix.s_addr);
2089 stream_put_ipv4 (s, mask.s_addr);
2090 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2091 stream_putl (s, rinfo->metric_out);
2092 }
2093
2094 return ++num;
2095}
2096
2097/* Send update to the ifp or spcified neighbor. */
2098void
paulc49ad8f2004-10-22 10:27:28 +00002099rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2100 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002101{
2102 int ret;
2103 struct stream *s;
2104 struct route_node *rp;
2105 struct rip_info *rinfo;
2106 struct rip_interface *ri;
2107 struct prefix_ipv4 *p;
2108 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002109 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002110 struct key *key = NULL;
2111 /* this might need to made dynamic if RIP ever supported auth methods
2112 with larger key string sizes */
2113 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2114 size_t doff; /* offset of digest offset field */
paul718e3742002-12-13 20:15:29 +00002115 int num;
2116 int rtemax;
paul01d09082003-06-08 21:22:18 +00002117 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002118
2119 /* Logging output event. */
2120 if (IS_RIP_DEBUG_EVENT)
2121 {
2122 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002123 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002124 else
ajs5d6c3772004-12-08 19:24:06 +00002125 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002126 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002127 }
2128
2129 /* Set output stream. */
2130 s = rip->obuf;
2131
2132 /* Reset stream and RTE counter. */
2133 stream_reset (s);
2134 num = 0;
2135 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2136
2137 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002138 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002139
2140 /* If output interface is in simple password authentication mode, we
2141 need space for authentication data. */
2142 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2143 rtemax -= 1;
2144
2145 /* If output interface is in MD5 authentication mode, we need space
2146 for authentication header and data. */
2147 if (ri->auth_type == RIP_AUTH_MD5)
2148 rtemax -= 2;
2149
2150 /* If output interface is in simple password authentication mode
2151 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002152 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002153 {
2154 if (ri->key_chain)
2155 {
2156 struct keychain *keychain;
2157
2158 keychain = keychain_lookup (ri->key_chain);
2159 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002160 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002161 }
paulb14ee002005-02-04 23:42:41 +00002162 /* to be passed to auth functions later */
2163 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002164 }
2165
paul727d1042002-12-13 20:50:29 +00002166 if (version == RIPv1)
2167 {
paulc49ad8f2004-10-22 10:27:28 +00002168 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002169 apply_classful_mask_ipv4 (&ifaddrclass);
2170 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002171 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002172 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002173 }
2174
paul718e3742002-12-13 20:15:29 +00002175 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2176 if ((rinfo = rp->info) != NULL)
2177 {
paul727d1042002-12-13 20:50:29 +00002178 /* For RIPv1, if we are subnetted, output subnets in our network */
2179 /* that have the same mask as the output "interface". For other */
2180 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002181
2182 if (version == RIPv1)
2183 {
paul727d1042002-12-13 20:50:29 +00002184 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002185
2186 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002187 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002188 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002189
paul727d1042002-12-13 20:50:29 +00002190 if (subnetted &&
2191 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2192 {
paulc49ad8f2004-10-22 10:27:28 +00002193 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002194 (rp->p.prefixlen != 32))
2195 continue;
2196 }
2197 else
2198 {
2199 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2200 apply_classful_mask_ipv4(&classfull);
2201 if (rp->p.u.prefix4.s_addr != 0 &&
2202 classfull.prefixlen != rp->p.prefixlen)
2203 continue;
2204 }
paul718e3742002-12-13 20:15:29 +00002205 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002206 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002207 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002208 }
2209 else
2210 p = (struct prefix_ipv4 *) &rp->p;
2211
2212 /* Apply output filters. */
2213 ret = rip_outgoing_filter (p, ri);
2214 if (ret < 0)
2215 continue;
2216
2217 /* Changed route only output. */
2218 if (route_type == rip_changed_route &&
2219 (! (rinfo->flags & RIP_RTF_CHANGED)))
2220 continue;
2221
2222 /* Split horizon. */
2223 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002224 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002225 {
paul42d14d92003-11-17 09:15:18 +00002226 /*
2227 * We perform split horizon for RIP and connected route.
2228 * For rip routes, we want to suppress the route if we would
2229 * end up sending the route back on the interface that we
2230 * learned it from, with a higher metric. For connected routes,
2231 * we suppress the route if the prefix is a subset of the
2232 * source address that we are going to use for the packet
2233 * (in order to handle the case when multiple subnets are
2234 * configured on the same interface).
2235 */
2236 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002237 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002238 continue;
2239 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002240 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002241 continue;
2242 }
2243
2244 /* Preparation for route-map. */
2245 rinfo->metric_set = 0;
2246 rinfo->nexthop_out.s_addr = 0;
2247 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002248 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002249 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002250
hasso16705132003-05-25 14:49:19 +00002251 /* In order to avoid some local loops,
2252 * if the RIP route has a nexthop via this interface, keep the nexthop,
2253 * otherwise set it to 0. The nexthop should not be propagated
2254 * beyond the local broadcast/multicast area in order
2255 * to avoid an IGP multi-level recursive look-up.
2256 * see (4.4)
2257 */
paulc49ad8f2004-10-22 10:27:28 +00002258 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002259 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002260
2261 /* Interface route-map */
2262 if (ri->routemap[RIP_FILTER_OUT])
2263 {
2264 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2265 (struct prefix *) p, RMAP_RIP,
2266 rinfo);
2267
2268 if (ret == RMAP_DENYMATCH)
2269 {
2270 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002271 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002272 inet_ntoa (p->prefix), p->prefixlen);
2273 continue;
2274 }
2275 }
paul718e3742002-12-13 20:15:29 +00002276
hasso16705132003-05-25 14:49:19 +00002277 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002278 if (rip->route_map[rinfo->type].name
2279 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2280 {
2281 ret = route_map_apply (rip->route_map[rinfo->type].map,
2282 (struct prefix *)p, RMAP_RIP, rinfo);
2283
2284 if (ret == RMAP_DENYMATCH)
2285 {
2286 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002287 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002288 inet_ntoa (p->prefix), p->prefixlen);
2289 continue;
2290 }
2291 }
2292
2293 /* When route-map does not set metric. */
2294 if (! rinfo->metric_set)
2295 {
2296 /* If redistribute metric is set. */
2297 if (rip->route_map[rinfo->type].metric_config
2298 && rinfo->metric != RIP_METRIC_INFINITY)
2299 {
2300 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2301 }
2302 else
2303 {
2304 /* If the route is not connected or localy generated
2305 one, use default-metric value*/
2306 if (rinfo->type != ZEBRA_ROUTE_RIP
2307 && rinfo->type != ZEBRA_ROUTE_CONNECT
2308 && rinfo->metric != RIP_METRIC_INFINITY)
2309 rinfo->metric_out = rip->default_metric;
2310 }
2311 }
2312
2313 /* Apply offset-list */
2314 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002315 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002316
2317 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2318 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002319
2320 /* Perform split-horizon with poisoned reverse
2321 * for RIP and connected routes.
2322 **/
2323 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002324 /*
2325 * We perform split horizon for RIP and connected route.
2326 * For rip routes, we want to suppress the route if we would
2327 * end up sending the route back on the interface that we
2328 * learned it from, with a higher metric. For connected routes,
2329 * we suppress the route if the prefix is a subset of the
2330 * source address that we are going to use for the packet
2331 * (in order to handle the case when multiple subnets are
2332 * configured on the same interface).
2333 */
2334 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002335 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002336 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002337 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002338 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002339 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002340 }
paulb14ee002005-02-04 23:42:41 +00002341
2342 /* Prepare preamble, auth headers, if needs be */
2343 if (num == 0)
2344 {
2345 stream_putc (s, RIP_RESPONSE);
2346 stream_putc (s, version);
2347 stream_putw (s, 0);
2348
2349 /* auth header for simple or v2 && MD5 */
2350 if ( (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2351 || (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) )
2352 doff = rip_auth_header_write (s, ri, key, auth_str,
2353 RIP_AUTH_SIMPLE_SIZE);
2354 }
2355
paul718e3742002-12-13 20:15:29 +00002356 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002357 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002358 if (num == rtemax)
2359 {
2360 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002361 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002362
2363 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002364 to, ifc);
paul718e3742002-12-13 20:15:29 +00002365
2366 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2367 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2368 stream_get_endp(s), "SEND");
2369 num = 0;
2370 stream_reset (s);
2371 }
2372 }
2373
2374 /* Flush unwritten RTE. */
2375 if (num != 0)
2376 {
2377 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002378 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002379
paulc49ad8f2004-10-22 10:27:28 +00002380 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002381
2382 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2383 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2384 stream_get_endp (s), "SEND");
2385 num = 0;
2386 stream_reset (s);
2387 }
2388
2389 /* Statistics updates. */
2390 ri->sent_updates++;
2391}
2392
2393/* Send RIP packet to the interface. */
2394void
paulc49ad8f2004-10-22 10:27:28 +00002395rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002396{
paul718e3742002-12-13 20:15:29 +00002397 struct sockaddr_in to;
2398
2399 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002400 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002401 {
2402 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002403 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002404
paulc49ad8f2004-10-22 10:27:28 +00002405 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002406 return;
2407 }
paulc49ad8f2004-10-22 10:27:28 +00002408
paul718e3742002-12-13 20:15:29 +00002409 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002410 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002411 {
paulc49ad8f2004-10-22 10:27:28 +00002412 if (ifc->address->family == AF_INET)
2413 {
2414 /* Destination address and port setting. */
2415 memset (&to, 0, sizeof (struct sockaddr_in));
2416 if (ifc->destination)
2417 /* use specified broadcast or point-to-point destination addr */
2418 to.sin_addr = ifc->destination->u.prefix4;
2419 else
2420 /* calculate the appropriate broadcast address */
2421 to.sin_addr.s_addr =
2422 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2423 ifc->address->prefixlen);
2424 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002425
paulc49ad8f2004-10-22 10:27:28 +00002426 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002427 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002428 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2429 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002430
paulc49ad8f2004-10-22 10:27:28 +00002431 rip_output_process (ifc, &to, route_type, version);
2432 }
paul718e3742002-12-13 20:15:29 +00002433 }
2434}
2435
2436/* Update send to all interface and neighbor. */
2437void
2438rip_update_process (int route_type)
2439{
paul1eb8ef22005-04-07 07:30:20 +00002440 struct listnode *node;
2441 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002442 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002443 struct interface *ifp;
2444 struct rip_interface *ri;
2445 struct route_node *rp;
2446 struct sockaddr_in to;
2447 struct prefix_ipv4 *p;
2448
2449 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002450 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002451 {
paul718e3742002-12-13 20:15:29 +00002452 if (if_is_loopback (ifp))
2453 continue;
2454
paul2e3b2e42002-12-13 21:03:13 +00002455 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002456 continue;
2457
2458 /* Fetch RIP interface information. */
2459 ri = ifp->info;
2460
2461 /* When passive interface is specified, suppress announce to the
2462 interface. */
2463 if (ri->passive)
2464 continue;
2465
2466 if (ri->running)
2467 {
2468 if (IS_RIP_DEBUG_EVENT)
2469 {
2470 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002471 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002472 ifp->name, ifp->ifindex);
2473 else
ajs5d6c3772004-12-08 19:24:06 +00002474 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002475 ifp->ifindex);
2476 }
2477
paulcc1131a2003-10-15 23:20:17 +00002478 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002479 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002480 {
2481 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002482 int done = 0;
2483 /*
2484 * If there is no version configuration in the interface,
2485 * use rip's version setting.
2486 */
paulf38a4712003-06-07 01:10:00 +00002487 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2488 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002489
2490 ifaddr = (struct prefix_ipv4 *) connected->address;
2491
2492 if (ifaddr->family != AF_INET)
2493 continue;
2494
paul931cd542004-01-23 15:31:42 +00002495 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002496 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002497 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002498 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002499 done = 1;
2500 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2501 break;
2502
paulf38a4712003-06-07 01:10:00 +00002503 }
paul718e3742002-12-13 20:15:29 +00002504 }
2505 }
2506
2507 /* RIP send updates to each neighbor. */
2508 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2509 if (rp->info != NULL)
2510 {
2511 p = (struct prefix_ipv4 *) &rp->p;
2512
2513 ifp = if_lookup_address (p->prefix);
2514 if (! ifp)
2515 {
paulc49ad8f2004-10-22 10:27:28 +00002516 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002517 inet_ntoa (p->prefix));
2518 continue;
2519 }
paulc49ad8f2004-10-22 10:27:28 +00002520
2521 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2522 {
2523 zlog_warn ("Neighbor %s doesnt have connected network",
2524 inet_ntoa (p->prefix));
2525 continue;
2526 }
2527
paul718e3742002-12-13 20:15:29 +00002528 /* Set destination address and port */
2529 memset (&to, 0, sizeof (struct sockaddr_in));
2530 to.sin_addr = p->prefix;
2531 to.sin_port = htons (RIP_PORT_DEFAULT);
2532
2533 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002534 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002535 }
2536}
2537
2538/* RIP's periodical timer. */
2539int
2540rip_update (struct thread *t)
2541{
2542 /* Clear timer pointer. */
2543 rip->t_update = NULL;
2544
2545 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002546 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002547
2548 /* Process update output. */
2549 rip_update_process (rip_all_route);
2550
2551 /* Triggered updates may be suppressed if a regular update is due by
2552 the time the triggered update would be sent. */
2553 if (rip->t_triggered_interval)
2554 {
2555 thread_cancel (rip->t_triggered_interval);
2556 rip->t_triggered_interval = NULL;
2557 }
2558 rip->trigger = 0;
2559
2560 /* Register myself. */
2561 rip_event (RIP_UPDATE_EVENT, 0);
2562
2563 return 0;
2564}
2565
2566/* Walk down the RIP routing table then clear changed flag. */
2567void
2568rip_clear_changed_flag ()
2569{
2570 struct route_node *rp;
2571 struct rip_info *rinfo;
2572
2573 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2574 if ((rinfo = rp->info) != NULL)
2575 if (rinfo->flags & RIP_RTF_CHANGED)
2576 rinfo->flags &= ~RIP_RTF_CHANGED;
2577}
2578
2579/* Triggered update interval timer. */
2580int
2581rip_triggered_interval (struct thread *t)
2582{
2583 int rip_triggered_update (struct thread *);
2584
2585 rip->t_triggered_interval = NULL;
2586
2587 if (rip->trigger)
2588 {
2589 rip->trigger = 0;
2590 rip_triggered_update (t);
2591 }
2592 return 0;
2593}
2594
2595/* Execute triggered update. */
2596int
2597rip_triggered_update (struct thread *t)
2598{
2599 int interval;
2600
2601 /* Clear thred pointer. */
2602 rip->t_triggered_update = NULL;
2603
2604 /* Cancel interval timer. */
2605 if (rip->t_triggered_interval)
2606 {
2607 thread_cancel (rip->t_triggered_interval);
2608 rip->t_triggered_interval = NULL;
2609 }
2610 rip->trigger = 0;
2611
2612 /* Logging triggered update. */
2613 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002614 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002615
2616 /* Split Horizon processing is done when generating triggered
2617 updates as well as normal updates (see section 2.6). */
2618 rip_update_process (rip_changed_route);
2619
2620 /* Once all of the triggered updates have been generated, the route
2621 change flags should be cleared. */
2622 rip_clear_changed_flag ();
2623
2624 /* After a triggered update is sent, a timer should be set for a
2625 random interval between 1 and 5 seconds. If other changes that
2626 would trigger updates occur before the timer expires, a single
2627 update is triggered when the timer expires. */
2628 interval = (random () % 5) + 1;
2629
2630 rip->t_triggered_interval =
2631 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2632
2633 return 0;
2634}
2635
2636/* Withdraw redistributed route. */
2637void
2638rip_redistribute_withdraw (int type)
2639{
2640 struct route_node *rp;
2641 struct rip_info *rinfo;
2642
2643 if (!rip)
2644 return;
2645
2646 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2647 if ((rinfo = rp->info) != NULL)
2648 {
2649 if (rinfo->type == type
2650 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2651 {
2652 /* Perform poisoned reverse. */
2653 rinfo->metric = RIP_METRIC_INFINITY;
2654 RIP_TIMER_ON (rinfo->t_garbage_collect,
2655 rip_garbage_collect, rip->garbage_time);
2656 RIP_TIMER_OFF (rinfo->t_timeout);
2657 rinfo->flags |= RIP_RTF_CHANGED;
2658
hasso16705132003-05-25 14:49:19 +00002659 if (IS_RIP_DEBUG_EVENT) {
2660 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2661
ajs5d6c3772004-12-08 19:24:06 +00002662 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002663 inet_ntoa(p->prefix), p->prefixlen,
2664 ifindex2ifname(rinfo->ifindex));
2665 }
2666
paul718e3742002-12-13 20:15:29 +00002667 rip_event (RIP_TRIGGERED_UPDATE, 0);
2668 }
2669 }
2670}
2671
2672/* Create new RIP instance and set it to global variable. */
2673int
2674rip_create ()
2675{
2676 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2677 memset (rip, 0, sizeof (struct rip));
2678
2679 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002680 rip->version_send = RI_RIP_VERSION_2;
2681 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002682 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2683 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2684 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2685 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2686
2687 /* Initialize RIP routig table. */
2688 rip->table = route_table_init ();
2689 rip->route = route_table_init ();
2690 rip->neighbor = route_table_init ();
2691
2692 /* Make output stream. */
2693 rip->obuf = stream_new (1500);
2694
2695 /* Make socket. */
2696 rip->sock = rip_create_socket ();
2697 if (rip->sock < 0)
2698 return rip->sock;
2699
2700 /* Create read and timer thread. */
2701 rip_event (RIP_READ, rip->sock);
2702 rip_event (RIP_UPDATE_EVENT, 1);
2703
2704 return 0;
2705}
2706
2707/* Sned RIP request to the destination. */
2708int
2709rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002710 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002711{
2712 struct rte *rte;
2713 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002714 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002715
2716 memset (&rip_packet, 0, sizeof (rip_packet));
2717
2718 rip_packet.command = RIP_REQUEST;
2719 rip_packet.version = version;
2720 rte = rip_packet.rte;
2721 rte->metric = htonl (RIP_METRIC_INFINITY);
2722
paul931cd542004-01-23 15:31:42 +00002723 if (connected)
2724 {
2725 /*
2726 * connected is only sent for ripv1 case, or when
2727 * interface does not support multicast. Caller loops
2728 * over each connected address for this case.
2729 */
paul11dde9c2004-05-31 14:00:00 +00002730 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002731 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002732 return -1;
2733 else
2734 return sizeof (rip_packet);
2735 }
2736
paulcc1131a2003-10-15 23:20:17 +00002737 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002738 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002739 {
2740 struct prefix_ipv4 *p;
2741
2742 p = (struct prefix_ipv4 *) connected->address;
2743
2744 if (p->family != AF_INET)
2745 continue;
2746
paul11dde9c2004-05-31 14:00:00 +00002747 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002748 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002749 return -1;
2750 }
2751 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002752}
2753
2754int
2755rip_update_jitter (unsigned long time)
2756{
paul239389b2004-05-05 14:09:37 +00002757#define JITTER_BOUND 4
2758 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2759 Given that, we cannot let time be less than JITTER_BOUND seconds.
2760 The RIPv2 RFC says jitter should be small compared to
2761 update_time. We consider 1/JITTER_BOUND to be small.
2762 */
2763
2764 int jitter_input = time;
2765 int jitter;
2766
2767 if (jitter_input < JITTER_BOUND)
2768 jitter_input = JITTER_BOUND;
2769
2770 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2771
2772 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002773}
2774
2775void
2776rip_event (enum rip_event event, int sock)
2777{
2778 int jitter = 0;
2779
2780 switch (event)
2781 {
2782 case RIP_READ:
2783 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2784 break;
2785 case RIP_UPDATE_EVENT:
2786 if (rip->t_update)
2787 {
2788 thread_cancel (rip->t_update);
2789 rip->t_update = NULL;
2790 }
2791 jitter = rip_update_jitter (rip->update_time);
2792 rip->t_update =
2793 thread_add_timer (master, rip_update, NULL,
2794 sock ? 2 : rip->update_time + jitter);
2795 break;
2796 case RIP_TRIGGERED_UPDATE:
2797 if (rip->t_triggered_interval)
2798 rip->trigger = 1;
2799 else if (! rip->t_triggered_update)
2800 rip->t_triggered_update =
2801 thread_add_event (master, rip_triggered_update, NULL, 0);
2802 break;
2803 default:
2804 break;
2805 }
2806}
2807
2808DEFUN (router_rip,
2809 router_rip_cmd,
2810 "router rip",
2811 "Enable a routing process\n"
2812 "Routing Information Protocol (RIP)\n")
2813{
2814 int ret;
2815
2816 /* If rip is not enabled before. */
2817 if (! rip)
2818 {
2819 ret = rip_create ();
2820 if (ret < 0)
2821 {
2822 zlog_info ("Can't create RIP");
2823 return CMD_WARNING;
2824 }
2825 }
2826 vty->node = RIP_NODE;
2827 vty->index = rip;
2828
2829 return CMD_SUCCESS;
2830}
2831
2832DEFUN (no_router_rip,
2833 no_router_rip_cmd,
2834 "no router rip",
2835 NO_STR
2836 "Enable a routing process\n"
2837 "Routing Information Protocol (RIP)\n")
2838{
2839 if (rip)
2840 rip_clean ();
2841 return CMD_SUCCESS;
2842}
2843
2844DEFUN (rip_version,
2845 rip_version_cmd,
2846 "version <1-2>",
2847 "Set routing protocol version\n"
2848 "version\n")
2849{
2850 int version;
2851
2852 version = atoi (argv[0]);
2853 if (version != RIPv1 && version != RIPv2)
2854 {
2855 vty_out (vty, "invalid rip version %d%s", version,
2856 VTY_NEWLINE);
2857 return CMD_WARNING;
2858 }
paulf38a4712003-06-07 01:10:00 +00002859 rip->version_send = version;
2860 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002861
2862 return CMD_SUCCESS;
2863}
2864
2865DEFUN (no_rip_version,
2866 no_rip_version_cmd,
2867 "no version",
2868 NO_STR
2869 "Set routing protocol version\n")
2870{
2871 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002872 rip->version_send = RI_RIP_VERSION_2;
2873 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002874
2875 return CMD_SUCCESS;
2876}
2877
2878ALIAS (no_rip_version,
2879 no_rip_version_val_cmd,
2880 "no version <1-2>",
2881 NO_STR
2882 "Set routing protocol version\n"
2883 "version\n")
2884
2885DEFUN (rip_route,
2886 rip_route_cmd,
2887 "route A.B.C.D/M",
2888 "RIP static route configuration\n"
2889 "IP prefix <network>/<length>\n")
2890{
2891 int ret;
2892 struct prefix_ipv4 p;
2893 struct route_node *node;
2894
2895 ret = str2prefix_ipv4 (argv[0], &p);
2896 if (ret < 0)
2897 {
2898 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2899 return CMD_WARNING;
2900 }
2901 apply_mask_ipv4 (&p);
2902
2903 /* For router rip configuration. */
2904 node = route_node_get (rip->route, (struct prefix *) &p);
2905
2906 if (node->info)
2907 {
2908 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2909 route_unlock_node (node);
2910 return CMD_WARNING;
2911 }
2912
hasso8a676be2004-10-08 06:36:38 +00002913 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002914
2915 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2916
2917 return CMD_SUCCESS;
2918}
2919
2920DEFUN (no_rip_route,
2921 no_rip_route_cmd,
2922 "no route A.B.C.D/M",
2923 NO_STR
2924 "RIP static route configuration\n"
2925 "IP prefix <network>/<length>\n")
2926{
2927 int ret;
2928 struct prefix_ipv4 p;
2929 struct route_node *node;
2930
2931 ret = str2prefix_ipv4 (argv[0], &p);
2932 if (ret < 0)
2933 {
2934 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2935 return CMD_WARNING;
2936 }
2937 apply_mask_ipv4 (&p);
2938
2939 /* For router rip configuration. */
2940 node = route_node_lookup (rip->route, (struct prefix *) &p);
2941 if (! node)
2942 {
2943 vty_out (vty, "Can't find route %s.%s", argv[0],
2944 VTY_NEWLINE);
2945 return CMD_WARNING;
2946 }
2947
2948 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2949 route_unlock_node (node);
2950
2951 node->info = NULL;
2952 route_unlock_node (node);
2953
2954 return CMD_SUCCESS;
2955}
2956
2957void
2958rip_update_default_metric ()
2959{
2960 struct route_node *np;
2961 struct rip_info *rinfo;
2962
2963 for (np = route_top (rip->table); np; np = route_next (np))
2964 if ((rinfo = np->info) != NULL)
2965 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2966 rinfo->metric = rip->default_metric;
2967}
2968
2969DEFUN (rip_default_metric,
2970 rip_default_metric_cmd,
2971 "default-metric <1-16>",
2972 "Set a metric of redistribute routes\n"
2973 "Default metric\n")
2974{
2975 if (rip)
2976 {
2977 rip->default_metric = atoi (argv[0]);
2978 /* rip_update_default_metric (); */
2979 }
2980 return CMD_SUCCESS;
2981}
2982
2983DEFUN (no_rip_default_metric,
2984 no_rip_default_metric_cmd,
2985 "no default-metric",
2986 NO_STR
2987 "Set a metric of redistribute routes\n"
2988 "Default metric\n")
2989{
2990 if (rip)
2991 {
2992 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2993 /* rip_update_default_metric (); */
2994 }
2995 return CMD_SUCCESS;
2996}
2997
2998ALIAS (no_rip_default_metric,
2999 no_rip_default_metric_val_cmd,
3000 "no default-metric <1-16>",
3001 NO_STR
3002 "Set a metric of redistribute routes\n"
3003 "Default metric\n")
3004
3005DEFUN (rip_timers,
3006 rip_timers_cmd,
3007 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3008 "Adjust routing timers\n"
3009 "Basic routing protocol update timers\n"
3010 "Routing table update timer value in second. Default is 30.\n"
3011 "Routing information timeout timer. Default is 180.\n"
3012 "Garbage collection timer. Default is 120.\n")
3013{
3014 unsigned long update;
3015 unsigned long timeout;
3016 unsigned long garbage;
3017 char *endptr = NULL;
3018 unsigned long RIP_TIMER_MAX = 2147483647;
3019 unsigned long RIP_TIMER_MIN = 5;
3020
3021 update = strtoul (argv[0], &endptr, 10);
3022 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3023 {
3024 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3025 return CMD_WARNING;
3026 }
3027
3028 timeout = strtoul (argv[1], &endptr, 10);
3029 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3030 {
3031 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3032 return CMD_WARNING;
3033 }
3034
3035 garbage = strtoul (argv[2], &endptr, 10);
3036 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3037 {
3038 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3039 return CMD_WARNING;
3040 }
3041
3042 /* Set each timer value. */
3043 rip->update_time = update;
3044 rip->timeout_time = timeout;
3045 rip->garbage_time = garbage;
3046
3047 /* Reset update timer thread. */
3048 rip_event (RIP_UPDATE_EVENT, 0);
3049
3050 return CMD_SUCCESS;
3051}
3052
3053DEFUN (no_rip_timers,
3054 no_rip_timers_cmd,
3055 "no timers basic",
3056 NO_STR
3057 "Adjust routing timers\n"
3058 "Basic routing protocol update timers\n")
3059{
3060 /* Set each timer value to the default. */
3061 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3062 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3063 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3064
3065 /* Reset update timer thread. */
3066 rip_event (RIP_UPDATE_EVENT, 0);
3067
3068 return CMD_SUCCESS;
3069}
hasso16705132003-05-25 14:49:19 +00003070
3071ALIAS (no_rip_timers,
3072 no_rip_timers_val_cmd,
3073 "no timers basic <0-65535> <0-65535> <0-65535>",
3074 NO_STR
3075 "Adjust routing timers\n"
3076 "Basic routing protocol update timers\n"
3077 "Routing table update timer value in second. Default is 30.\n"
3078 "Routing information timeout timer. Default is 180.\n"
3079 "Garbage collection timer. Default is 120.\n")
3080
paul718e3742002-12-13 20:15:29 +00003081
3082struct route_table *rip_distance_table;
3083
3084struct rip_distance
3085{
3086 /* Distance value for the IP source prefix. */
3087 u_char distance;
3088
3089 /* Name of the access-list to be matched. */
3090 char *access_list;
3091};
3092
3093struct rip_distance *
3094rip_distance_new ()
3095{
3096 struct rip_distance *new;
3097 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3098 memset (new, 0, sizeof (struct rip_distance));
3099 return new;
3100}
3101
3102void
3103rip_distance_free (struct rip_distance *rdistance)
3104{
3105 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3106}
3107
3108int
hasso98b718a2004-10-11 12:57:57 +00003109rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3110 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003111{
3112 int ret;
3113 struct prefix_ipv4 p;
3114 u_char distance;
3115 struct route_node *rn;
3116 struct rip_distance *rdistance;
3117
3118 ret = str2prefix_ipv4 (ip_str, &p);
3119 if (ret == 0)
3120 {
3121 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3122 return CMD_WARNING;
3123 }
3124
3125 distance = atoi (distance_str);
3126
3127 /* Get RIP distance node. */
3128 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3129 if (rn->info)
3130 {
3131 rdistance = rn->info;
3132 route_unlock_node (rn);
3133 }
3134 else
3135 {
3136 rdistance = rip_distance_new ();
3137 rn->info = rdistance;
3138 }
3139
3140 /* Set distance value. */
3141 rdistance->distance = distance;
3142
3143 /* Reset access-list configuration. */
3144 if (rdistance->access_list)
3145 {
3146 free (rdistance->access_list);
3147 rdistance->access_list = NULL;
3148 }
3149 if (access_list_str)
3150 rdistance->access_list = strdup (access_list_str);
3151
3152 return CMD_SUCCESS;
3153}
3154
3155int
hasso98b718a2004-10-11 12:57:57 +00003156rip_distance_unset (struct vty *vty, const char *distance_str,
3157 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003158{
3159 int ret;
3160 struct prefix_ipv4 p;
3161 u_char distance;
3162 struct route_node *rn;
3163 struct rip_distance *rdistance;
3164
3165 ret = str2prefix_ipv4 (ip_str, &p);
3166 if (ret == 0)
3167 {
3168 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3169 return CMD_WARNING;
3170 }
3171
3172 distance = atoi (distance_str);
3173
3174 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3175 if (! rn)
3176 {
3177 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3178 return CMD_WARNING;
3179 }
3180
3181 rdistance = rn->info;
3182
3183 if (rdistance->access_list)
3184 free (rdistance->access_list);
3185 rip_distance_free (rdistance);
3186
3187 rn->info = NULL;
3188 route_unlock_node (rn);
3189 route_unlock_node (rn);
3190
3191 return CMD_SUCCESS;
3192}
3193
3194void
3195rip_distance_reset ()
3196{
3197 struct route_node *rn;
3198 struct rip_distance *rdistance;
3199
3200 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3201 if ((rdistance = rn->info) != NULL)
3202 {
3203 if (rdistance->access_list)
3204 free (rdistance->access_list);
3205 rip_distance_free (rdistance);
3206 rn->info = NULL;
3207 route_unlock_node (rn);
3208 }
3209}
3210
3211/* Apply RIP information to distance method. */
3212u_char
3213rip_distance_apply (struct rip_info *rinfo)
3214{
3215 struct route_node *rn;
3216 struct prefix_ipv4 p;
3217 struct rip_distance *rdistance;
3218 struct access_list *alist;
3219
3220 if (! rip)
3221 return 0;
3222
3223 memset (&p, 0, sizeof (struct prefix_ipv4));
3224 p.family = AF_INET;
3225 p.prefix = rinfo->from;
3226 p.prefixlen = IPV4_MAX_BITLEN;
3227
3228 /* Check source address. */
3229 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3230 if (rn)
3231 {
3232 rdistance = rn->info;
3233 route_unlock_node (rn);
3234
3235 if (rdistance->access_list)
3236 {
3237 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3238 if (alist == NULL)
3239 return 0;
3240 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3241 return 0;
3242
3243 return rdistance->distance;
3244 }
3245 else
3246 return rdistance->distance;
3247 }
3248
3249 if (rip->distance)
3250 return rip->distance;
3251
3252 return 0;
3253}
3254
3255void
3256rip_distance_show (struct vty *vty)
3257{
3258 struct route_node *rn;
3259 struct rip_distance *rdistance;
3260 int header = 1;
3261 char buf[BUFSIZ];
3262
3263 vty_out (vty, " Distance: (default is %d)%s",
3264 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3265 VTY_NEWLINE);
3266
3267 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3268 if ((rdistance = rn->info) != NULL)
3269 {
3270 if (header)
3271 {
3272 vty_out (vty, " Address Distance List%s",
3273 VTY_NEWLINE);
3274 header = 0;
3275 }
3276 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3277 vty_out (vty, " %-20s %4d %s%s",
3278 buf, rdistance->distance,
3279 rdistance->access_list ? rdistance->access_list : "",
3280 VTY_NEWLINE);
3281 }
3282}
3283
3284DEFUN (rip_distance,
3285 rip_distance_cmd,
3286 "distance <1-255>",
3287 "Administrative distance\n"
3288 "Distance value\n")
3289{
3290 rip->distance = atoi (argv[0]);
3291 return CMD_SUCCESS;
3292}
3293
3294DEFUN (no_rip_distance,
3295 no_rip_distance_cmd,
3296 "no distance <1-255>",
3297 NO_STR
3298 "Administrative distance\n"
3299 "Distance value\n")
3300{
3301 rip->distance = 0;
3302 return CMD_SUCCESS;
3303}
3304
3305DEFUN (rip_distance_source,
3306 rip_distance_source_cmd,
3307 "distance <1-255> A.B.C.D/M",
3308 "Administrative distance\n"
3309 "Distance value\n"
3310 "IP source prefix\n")
3311{
3312 rip_distance_set (vty, argv[0], argv[1], NULL);
3313 return CMD_SUCCESS;
3314}
3315
3316DEFUN (no_rip_distance_source,
3317 no_rip_distance_source_cmd,
3318 "no distance <1-255> A.B.C.D/M",
3319 NO_STR
3320 "Administrative distance\n"
3321 "Distance value\n"
3322 "IP source prefix\n")
3323{
3324 rip_distance_unset (vty, argv[0], argv[1], NULL);
3325 return CMD_SUCCESS;
3326}
3327
3328DEFUN (rip_distance_source_access_list,
3329 rip_distance_source_access_list_cmd,
3330 "distance <1-255> A.B.C.D/M WORD",
3331 "Administrative distance\n"
3332 "Distance value\n"
3333 "IP source prefix\n"
3334 "Access list name\n")
3335{
3336 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3337 return CMD_SUCCESS;
3338}
3339
3340DEFUN (no_rip_distance_source_access_list,
3341 no_rip_distance_source_access_list_cmd,
3342 "no distance <1-255> A.B.C.D/M WORD",
3343 NO_STR
3344 "Administrative distance\n"
3345 "Distance value\n"
3346 "IP source prefix\n"
3347 "Access list name\n")
3348{
3349 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3350 return CMD_SUCCESS;
3351}
3352
3353/* Print out routes update time. */
3354void
3355rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3356{
3357 struct timeval timer_now;
3358 time_t clock;
3359 struct tm *tm;
3360#define TIME_BUF 25
3361 char timebuf [TIME_BUF];
3362 struct thread *thread;
3363
3364 gettimeofday (&timer_now, NULL);
3365
3366 if ((thread = rinfo->t_timeout) != NULL)
3367 {
3368 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3369 tm = gmtime (&clock);
3370 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3371 vty_out (vty, "%5s", timebuf);
3372 }
3373 else if ((thread = rinfo->t_garbage_collect) != NULL)
3374 {
3375 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3376 tm = gmtime (&clock);
3377 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3378 vty_out (vty, "%5s", timebuf);
3379 }
3380}
3381
hasso8a676be2004-10-08 06:36:38 +00003382const char *
paul718e3742002-12-13 20:15:29 +00003383rip_route_type_print (int sub_type)
3384{
3385 switch (sub_type)
3386 {
3387 case RIP_ROUTE_RTE:
3388 return "n";
3389 case RIP_ROUTE_STATIC:
3390 return "s";
3391 case RIP_ROUTE_DEFAULT:
3392 return "d";
3393 case RIP_ROUTE_REDISTRIBUTE:
3394 return "r";
3395 case RIP_ROUTE_INTERFACE:
3396 return "i";
3397 default:
3398 return "?";
3399 }
3400}
3401
3402DEFUN (show_ip_rip,
3403 show_ip_rip_cmd,
3404 "show ip rip",
3405 SHOW_STR
3406 IP_STR
3407 "Show RIP routes\n")
3408{
3409 struct route_node *np;
3410 struct rip_info *rinfo;
3411
3412 if (! rip)
3413 return CMD_SUCCESS;
3414
hasso16705132003-05-25 14:49:19 +00003415 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3416 "Sub-codes:%s"
3417 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003418 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003419 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003420 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003421
3422 for (np = route_top (rip->table); np; np = route_next (np))
3423 if ((rinfo = np->info) != NULL)
3424 {
3425 int len;
3426
3427 len = vty_out (vty, "%s(%s) %s/%d",
3428 /* np->lock, For debugging. */
3429 route_info[rinfo->type].str,
3430 rip_route_type_print (rinfo->sub_type),
3431 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3432
hassoa1455d82004-03-03 19:36:24 +00003433 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003434
3435 if (len > 0)
3436 vty_out (vty, "%*s", len, " ");
3437
3438 if (rinfo->nexthop.s_addr)
3439 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3440 rinfo->metric);
3441 else
3442 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3443
3444 /* Route which exist in kernel routing table. */
3445 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3446 (rinfo->sub_type == RIP_ROUTE_RTE))
3447 {
3448 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003449 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003450 rip_vty_out_uptime (vty, rinfo);
3451 }
3452 else if (rinfo->metric == RIP_METRIC_INFINITY)
3453 {
3454 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003455 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003456 rip_vty_out_uptime (vty, rinfo);
3457 }
3458 else
hasso16705132003-05-25 14:49:19 +00003459 {
3460 vty_out (vty, "self ");
3461 vty_out (vty, "%3d", rinfo->tag);
3462 }
paul718e3742002-12-13 20:15:29 +00003463
3464 vty_out (vty, "%s", VTY_NEWLINE);
3465 }
3466 return CMD_SUCCESS;
3467}
3468
3469/* Return next event time. */
3470int
3471rip_next_thread_timer (struct thread *thread)
3472{
3473 struct timeval timer_now;
3474
3475 gettimeofday (&timer_now, NULL);
3476
3477 return thread->u.sands.tv_sec - timer_now.tv_sec;
3478}
3479
hasso16705132003-05-25 14:49:19 +00003480/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3481DEFUN (show_ip_rip_status,
3482 show_ip_rip_status_cmd,
3483 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003484 SHOW_STR
3485 IP_STR
hasso16705132003-05-25 14:49:19 +00003486 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003487 "IP routing protocol process parameters and statistics\n")
3488{
hasso52dc7ee2004-09-23 19:18:23 +00003489 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003490 struct interface *ifp;
3491 struct rip_interface *ri;
3492 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003493 const char *send_version;
3494 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003495
3496 if (! rip)
3497 return CMD_SUCCESS;
3498
3499 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3500 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3501 rip->update_time);
3502 vty_out (vty, " next due in %d seconds%s",
3503 rip_next_thread_timer (rip->t_update),
3504 VTY_NEWLINE);
3505 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3506 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3507 VTY_NEWLINE);
3508
3509 /* Filtering status show. */
3510 config_show_distribute (vty);
3511
3512 /* Default metric information. */
3513 vty_out (vty, " Default redistribution metric is %d%s",
3514 rip->default_metric, VTY_NEWLINE);
3515
3516 /* Redistribute information. */
3517 vty_out (vty, " Redistributing:");
3518 config_write_rip_redistribute (vty, 0);
3519 vty_out (vty, "%s", VTY_NEWLINE);
3520
paulf38a4712003-06-07 01:10:00 +00003521 vty_out (vty, " Default version control: send version %s,",
3522 lookup(ri_version_msg,rip->version_send));
3523 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3524 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3525 else
3526 vty_out (vty, " receive version %s %s",
3527 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003528
3529 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3530
paul1eb8ef22005-04-07 07:30:20 +00003531 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003532 {
paul718e3742002-12-13 20:15:29 +00003533 ri = ifp->info;
3534
3535 if (ri->enable_network || ri->enable_interface)
3536 {
3537 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003538 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003539 else
3540 send_version = lookup (ri_version_msg, ri->ri_send);
3541
3542 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003543 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003544 else
3545 receive_version = lookup (ri_version_msg, ri->ri_receive);
3546
3547 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3548 send_version,
3549 receive_version,
3550 ri->key_chain ? ri->key_chain : "",
3551 VTY_NEWLINE);
3552 }
3553 }
3554
3555 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3556 config_write_rip_network (vty, 0);
3557
paul4aaff3f2003-06-07 01:04:45 +00003558 {
3559 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003560 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003561 {
paul4aaff3f2003-06-07 01:04:45 +00003562 ri = ifp->info;
3563
3564 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3565 {
3566 if (!found_passive)
3567 {
3568 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3569 found_passive = 1;
3570 }
3571 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3572 }
3573 }
3574 }
3575
paul718e3742002-12-13 20:15:29 +00003576 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3577 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3578 rip_peer_display (vty);
3579
3580 rip_distance_show (vty);
3581
3582 return CMD_SUCCESS;
3583}
3584
3585/* RIP configuration write function. */
3586int
3587config_write_rip (struct vty *vty)
3588{
3589 int write = 0;
3590 struct route_node *rn;
3591 struct rip_distance *rdistance;
3592
3593 if (rip)
3594 {
3595 /* Router RIP statement. */
3596 vty_out (vty, "router rip%s", VTY_NEWLINE);
3597 write++;
3598
3599 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003600 if (rip->version_send != RI_RIP_VERSION_2
3601 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3602 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003603 VTY_NEWLINE);
3604
3605 /* RIP timer configuration. */
3606 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3607 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3608 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3609 vty_out (vty, " timers basic %lu %lu %lu%s",
3610 rip->update_time,
3611 rip->timeout_time,
3612 rip->garbage_time,
3613 VTY_NEWLINE);
3614
3615 /* Default information configuration. */
3616 if (rip->default_information)
3617 {
3618 if (rip->default_information_route_map)
3619 vty_out (vty, " default-information originate route-map %s%s",
3620 rip->default_information_route_map, VTY_NEWLINE);
3621 else
3622 vty_out (vty, " default-information originate%s",
3623 VTY_NEWLINE);
3624 }
3625
3626 /* Redistribute configuration. */
3627 config_write_rip_redistribute (vty, 1);
3628
3629 /* RIP offset-list configuration. */
3630 config_write_rip_offset_list (vty);
3631
3632 /* RIP enabled network and interface configuration. */
3633 config_write_rip_network (vty, 1);
3634
3635 /* RIP default metric configuration */
3636 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3637 vty_out (vty, " default-metric %d%s",
3638 rip->default_metric, VTY_NEWLINE);
3639
3640 /* Distribute configuration. */
3641 write += config_write_distribute (vty);
3642
hasso16705132003-05-25 14:49:19 +00003643 /* Interface routemap configuration */
3644 write += config_write_if_rmap (vty);
3645
paul718e3742002-12-13 20:15:29 +00003646 /* Distance configuration. */
3647 if (rip->distance)
3648 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3649
3650 /* RIP source IP prefix distance configuration. */
3651 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3652 if ((rdistance = rn->info) != NULL)
3653 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3654 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3655 rdistance->access_list ? rdistance->access_list : "",
3656 VTY_NEWLINE);
3657
3658 /* RIP static route configuration. */
3659 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3660 if (rn->info)
3661 vty_out (vty, " route %s/%d%s",
3662 inet_ntoa (rn->p.u.prefix4),
3663 rn->p.prefixlen,
3664 VTY_NEWLINE);
3665
3666 }
3667 return write;
3668}
3669
3670/* RIP node structure. */
3671struct cmd_node rip_node =
3672{
3673 RIP_NODE,
3674 "%s(config-router)# ",
3675 1
3676};
3677
3678/* Distribute-list update functions. */
3679void
3680rip_distribute_update (struct distribute *dist)
3681{
3682 struct interface *ifp;
3683 struct rip_interface *ri;
3684 struct access_list *alist;
3685 struct prefix_list *plist;
3686
3687 if (! dist->ifname)
3688 return;
3689
3690 ifp = if_lookup_by_name (dist->ifname);
3691 if (ifp == NULL)
3692 return;
3693
3694 ri = ifp->info;
3695
3696 if (dist->list[DISTRIBUTE_IN])
3697 {
3698 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3699 if (alist)
3700 ri->list[RIP_FILTER_IN] = alist;
3701 else
3702 ri->list[RIP_FILTER_IN] = NULL;
3703 }
3704 else
3705 ri->list[RIP_FILTER_IN] = NULL;
3706
3707 if (dist->list[DISTRIBUTE_OUT])
3708 {
3709 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3710 if (alist)
3711 ri->list[RIP_FILTER_OUT] = alist;
3712 else
3713 ri->list[RIP_FILTER_OUT] = NULL;
3714 }
3715 else
3716 ri->list[RIP_FILTER_OUT] = NULL;
3717
3718 if (dist->prefix[DISTRIBUTE_IN])
3719 {
3720 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3721 if (plist)
3722 ri->prefix[RIP_FILTER_IN] = plist;
3723 else
3724 ri->prefix[RIP_FILTER_IN] = NULL;
3725 }
3726 else
3727 ri->prefix[RIP_FILTER_IN] = NULL;
3728
3729 if (dist->prefix[DISTRIBUTE_OUT])
3730 {
3731 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3732 if (plist)
3733 ri->prefix[RIP_FILTER_OUT] = plist;
3734 else
3735 ri->prefix[RIP_FILTER_OUT] = NULL;
3736 }
3737 else
3738 ri->prefix[RIP_FILTER_OUT] = NULL;
3739}
3740
3741void
3742rip_distribute_update_interface (struct interface *ifp)
3743{
3744 struct distribute *dist;
3745
3746 dist = distribute_lookup (ifp->name);
3747 if (dist)
3748 rip_distribute_update (dist);
3749}
3750
3751/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003752/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003753void
paul02ff83c2004-06-11 11:27:03 +00003754rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003755{
3756 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003757 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003758
paul1eb8ef22005-04-07 07:30:20 +00003759 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3760 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003761}
paul11dde9c2004-05-31 14:00:00 +00003762/* ARGSUSED */
3763void
3764rip_distribute_update_all_wrapper(struct access_list *notused)
3765{
paul02ff83c2004-06-11 11:27:03 +00003766 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003767}
paul718e3742002-12-13 20:15:29 +00003768
3769/* Delete all added rip route. */
3770void
3771rip_clean ()
3772{
3773 int i;
3774 struct route_node *rp;
3775 struct rip_info *rinfo;
3776
3777 if (rip)
3778 {
3779 /* Clear RIP routes */
3780 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3781 if ((rinfo = rp->info) != NULL)
3782 {
3783 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3784 rinfo->sub_type == RIP_ROUTE_RTE)
3785 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3786 &rinfo->nexthop, rinfo->metric);
3787
3788 RIP_TIMER_OFF (rinfo->t_timeout);
3789 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3790
3791 rp->info = NULL;
3792 route_unlock_node (rp);
3793
3794 rip_info_free (rinfo);
3795 }
3796
3797 /* Cancel RIP related timers. */
3798 RIP_TIMER_OFF (rip->t_update);
3799 RIP_TIMER_OFF (rip->t_triggered_update);
3800 RIP_TIMER_OFF (rip->t_triggered_interval);
3801
3802 /* Cancel read thread. */
3803 if (rip->t_read)
3804 {
3805 thread_cancel (rip->t_read);
3806 rip->t_read = NULL;
3807 }
3808
3809 /* Close RIP socket. */
3810 if (rip->sock >= 0)
3811 {
3812 close (rip->sock);
3813 rip->sock = -1;
3814 }
3815
3816 /* Static RIP route configuration. */
3817 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3818 if (rp->info)
3819 {
3820 rp->info = NULL;
3821 route_unlock_node (rp);
3822 }
3823
3824 /* RIP neighbor configuration. */
3825 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3826 if (rp->info)
3827 {
3828 rp->info = NULL;
3829 route_unlock_node (rp);
3830 }
3831
3832 /* Redistribute related clear. */
3833 if (rip->default_information_route_map)
3834 free (rip->default_information_route_map);
3835
3836 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3837 if (rip->route_map[i].name)
3838 free (rip->route_map[i].name);
3839
3840 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3841 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3842 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3843
3844 XFREE (MTYPE_RIP, rip);
3845 rip = NULL;
3846 }
3847
3848 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003849 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003850 rip_offset_clean ();
3851 rip_interface_clean ();
3852 rip_distance_reset ();
3853 rip_redistribute_clean ();
3854}
3855
3856/* Reset all values to the default settings. */
3857void
3858rip_reset ()
3859{
3860 /* Reset global counters. */
3861 rip_global_route_changes = 0;
3862 rip_global_queries = 0;
3863
3864 /* Call ripd related reset functions. */
3865 rip_debug_reset ();
3866 rip_route_map_reset ();
3867
3868 /* Call library reset functions. */
3869 vty_reset ();
3870 access_list_reset ();
3871 prefix_list_reset ();
3872
3873 distribute_list_reset ();
3874
3875 rip_interface_reset ();
3876 rip_distance_reset ();
3877
3878 rip_zclient_reset ();
3879}
3880
hasso16705132003-05-25 14:49:19 +00003881void
3882rip_if_rmap_update (struct if_rmap *if_rmap)
3883{
3884 struct interface *ifp;
3885 struct rip_interface *ri;
3886 struct route_map *rmap;
3887
3888 ifp = if_lookup_by_name (if_rmap->ifname);
3889 if (ifp == NULL)
3890 return;
3891
3892 ri = ifp->info;
3893
3894 if (if_rmap->routemap[IF_RMAP_IN])
3895 {
3896 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3897 if (rmap)
3898 ri->routemap[IF_RMAP_IN] = rmap;
3899 else
3900 ri->routemap[IF_RMAP_IN] = NULL;
3901 }
3902 else
3903 ri->routemap[RIP_FILTER_IN] = NULL;
3904
3905 if (if_rmap->routemap[IF_RMAP_OUT])
3906 {
3907 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3908 if (rmap)
3909 ri->routemap[IF_RMAP_OUT] = rmap;
3910 else
3911 ri->routemap[IF_RMAP_OUT] = NULL;
3912 }
3913 else
3914 ri->routemap[RIP_FILTER_OUT] = NULL;
3915}
3916
3917void
3918rip_if_rmap_update_interface (struct interface *ifp)
3919{
3920 struct if_rmap *if_rmap;
3921
3922 if_rmap = if_rmap_lookup (ifp->name);
3923 if (if_rmap)
3924 rip_if_rmap_update (if_rmap);
3925}
3926
3927void
3928rip_routemap_update_redistribute (void)
3929{
3930 int i;
3931
3932 if (rip)
3933 {
3934 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3935 {
3936 if (rip->route_map[i].name)
3937 rip->route_map[i].map =
3938 route_map_lookup_by_name (rip->route_map[i].name);
3939 }
3940 }
3941}
3942
paul11dde9c2004-05-31 14:00:00 +00003943/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003944void
hasso98b718a2004-10-11 12:57:57 +00003945rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003946{
3947 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003948 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003949
paul1eb8ef22005-04-07 07:30:20 +00003950 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3951 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003952
3953 rip_routemap_update_redistribute ();
3954}
3955
paul718e3742002-12-13 20:15:29 +00003956/* Allocate new rip structure and set default value. */
3957void
3958rip_init ()
3959{
3960 /* Randomize for triggered update random(). */
3961 srand (time (NULL));
3962
3963 /* Install top nodes. */
3964 install_node (&rip_node, config_write_rip);
3965
3966 /* Install rip commands. */
3967 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003968 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003969 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003970 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003971 install_element (CONFIG_NODE, &router_rip_cmd);
3972 install_element (CONFIG_NODE, &no_router_rip_cmd);
3973
3974 install_default (RIP_NODE);
3975 install_element (RIP_NODE, &rip_version_cmd);
3976 install_element (RIP_NODE, &no_rip_version_cmd);
3977 install_element (RIP_NODE, &no_rip_version_val_cmd);
3978 install_element (RIP_NODE, &rip_default_metric_cmd);
3979 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3980 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3981 install_element (RIP_NODE, &rip_timers_cmd);
3982 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003983 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003984 install_element (RIP_NODE, &rip_route_cmd);
3985 install_element (RIP_NODE, &no_rip_route_cmd);
3986 install_element (RIP_NODE, &rip_distance_cmd);
3987 install_element (RIP_NODE, &no_rip_distance_cmd);
3988 install_element (RIP_NODE, &rip_distance_source_cmd);
3989 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3990 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3991 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3992
3993 /* Debug related init. */
3994 rip_debug_init ();
3995
paul718e3742002-12-13 20:15:29 +00003996 /* SNMP init. */
3997#ifdef HAVE_SNMP
3998 rip_snmp_init ();
3999#endif /* HAVE_SNMP */
4000
4001 /* Access list install. */
4002 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004003 access_list_add_hook (rip_distribute_update_all_wrapper);
4004 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004005
4006 /* Prefix list initialize.*/
4007 prefix_list_init ();
4008 prefix_list_add_hook (rip_distribute_update_all);
4009 prefix_list_delete_hook (rip_distribute_update_all);
4010
4011 /* Distribute list install. */
4012 distribute_list_init (RIP_NODE);
4013 distribute_list_add_hook (rip_distribute_update);
4014 distribute_list_delete_hook (rip_distribute_update);
4015
hasso16705132003-05-25 14:49:19 +00004016 /* Route-map */
4017 rip_route_map_init ();
4018 rip_offset_init ();
4019
4020 route_map_add_hook (rip_routemap_update);
4021 route_map_delete_hook (rip_routemap_update);
4022
4023 if_rmap_init (RIP_NODE);
4024 if_rmap_hook_add (rip_if_rmap_update);
4025 if_rmap_hook_delete (rip_if_rmap_update);
4026
paul718e3742002-12-13 20:15:29 +00004027 /* Distance control. */
4028 rip_distance_table = route_table_init ();
4029}