blob: 4723ebe03a575489d982597386ff96fb161513ce [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
paul0cb8a012005-05-29 11:27:24 +00002349 /* auth header for !v1 && !no_auth */
2350 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002351 doff = rip_auth_header_write (s, ri, key, auth_str,
2352 RIP_AUTH_SIMPLE_SIZE);
2353 }
2354
paul718e3742002-12-13 20:15:29 +00002355 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002356 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002357 if (num == rtemax)
2358 {
2359 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002360 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002361
2362 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002363 to, ifc);
paul718e3742002-12-13 20:15:29 +00002364
2365 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2366 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2367 stream_get_endp(s), "SEND");
2368 num = 0;
2369 stream_reset (s);
2370 }
2371 }
2372
2373 /* Flush unwritten RTE. */
2374 if (num != 0)
2375 {
2376 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002377 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002378
paulc49ad8f2004-10-22 10:27:28 +00002379 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002380
2381 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2382 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2383 stream_get_endp (s), "SEND");
2384 num = 0;
2385 stream_reset (s);
2386 }
2387
2388 /* Statistics updates. */
2389 ri->sent_updates++;
2390}
2391
2392/* Send RIP packet to the interface. */
2393void
paulc49ad8f2004-10-22 10:27:28 +00002394rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002395{
paul718e3742002-12-13 20:15:29 +00002396 struct sockaddr_in to;
2397
2398 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002399 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002400 {
2401 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002402 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002403
paulc49ad8f2004-10-22 10:27:28 +00002404 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002405 return;
2406 }
paulc49ad8f2004-10-22 10:27:28 +00002407
paul718e3742002-12-13 20:15:29 +00002408 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002409 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002410 {
paulc49ad8f2004-10-22 10:27:28 +00002411 if (ifc->address->family == AF_INET)
2412 {
2413 /* Destination address and port setting. */
2414 memset (&to, 0, sizeof (struct sockaddr_in));
2415 if (ifc->destination)
2416 /* use specified broadcast or point-to-point destination addr */
2417 to.sin_addr = ifc->destination->u.prefix4;
2418 else
2419 /* calculate the appropriate broadcast address */
2420 to.sin_addr.s_addr =
2421 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2422 ifc->address->prefixlen);
2423 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002424
paulc49ad8f2004-10-22 10:27:28 +00002425 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002426 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002427 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2428 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002429
paulc49ad8f2004-10-22 10:27:28 +00002430 rip_output_process (ifc, &to, route_type, version);
2431 }
paul718e3742002-12-13 20:15:29 +00002432 }
2433}
2434
2435/* Update send to all interface and neighbor. */
2436void
2437rip_update_process (int route_type)
2438{
paul1eb8ef22005-04-07 07:30:20 +00002439 struct listnode *node;
2440 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002441 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002442 struct interface *ifp;
2443 struct rip_interface *ri;
2444 struct route_node *rp;
2445 struct sockaddr_in to;
2446 struct prefix_ipv4 *p;
2447
2448 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002449 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002450 {
paul718e3742002-12-13 20:15:29 +00002451 if (if_is_loopback (ifp))
2452 continue;
2453
paul2e3b2e42002-12-13 21:03:13 +00002454 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002455 continue;
2456
2457 /* Fetch RIP interface information. */
2458 ri = ifp->info;
2459
2460 /* When passive interface is specified, suppress announce to the
2461 interface. */
2462 if (ri->passive)
2463 continue;
2464
2465 if (ri->running)
2466 {
2467 if (IS_RIP_DEBUG_EVENT)
2468 {
2469 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002470 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002471 ifp->name, ifp->ifindex);
2472 else
ajs5d6c3772004-12-08 19:24:06 +00002473 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002474 ifp->ifindex);
2475 }
2476
paulcc1131a2003-10-15 23:20:17 +00002477 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002478 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002479 {
2480 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002481 int done = 0;
2482 /*
2483 * If there is no version configuration in the interface,
2484 * use rip's version setting.
2485 */
paulf38a4712003-06-07 01:10:00 +00002486 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2487 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002488
2489 ifaddr = (struct prefix_ipv4 *) connected->address;
2490
2491 if (ifaddr->family != AF_INET)
2492 continue;
2493
paul931cd542004-01-23 15:31:42 +00002494 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002495 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002496 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002497 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002498 done = 1;
2499 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2500 break;
2501
paulf38a4712003-06-07 01:10:00 +00002502 }
paul718e3742002-12-13 20:15:29 +00002503 }
2504 }
2505
2506 /* RIP send updates to each neighbor. */
2507 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2508 if (rp->info != NULL)
2509 {
2510 p = (struct prefix_ipv4 *) &rp->p;
2511
2512 ifp = if_lookup_address (p->prefix);
2513 if (! ifp)
2514 {
paulc49ad8f2004-10-22 10:27:28 +00002515 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002516 inet_ntoa (p->prefix));
2517 continue;
2518 }
paulc49ad8f2004-10-22 10:27:28 +00002519
2520 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2521 {
2522 zlog_warn ("Neighbor %s doesnt have connected network",
2523 inet_ntoa (p->prefix));
2524 continue;
2525 }
2526
paul718e3742002-12-13 20:15:29 +00002527 /* Set destination address and port */
2528 memset (&to, 0, sizeof (struct sockaddr_in));
2529 to.sin_addr = p->prefix;
2530 to.sin_port = htons (RIP_PORT_DEFAULT);
2531
2532 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002533 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002534 }
2535}
2536
2537/* RIP's periodical timer. */
2538int
2539rip_update (struct thread *t)
2540{
2541 /* Clear timer pointer. */
2542 rip->t_update = NULL;
2543
2544 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002545 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002546
2547 /* Process update output. */
2548 rip_update_process (rip_all_route);
2549
2550 /* Triggered updates may be suppressed if a regular update is due by
2551 the time the triggered update would be sent. */
2552 if (rip->t_triggered_interval)
2553 {
2554 thread_cancel (rip->t_triggered_interval);
2555 rip->t_triggered_interval = NULL;
2556 }
2557 rip->trigger = 0;
2558
2559 /* Register myself. */
2560 rip_event (RIP_UPDATE_EVENT, 0);
2561
2562 return 0;
2563}
2564
2565/* Walk down the RIP routing table then clear changed flag. */
2566void
2567rip_clear_changed_flag ()
2568{
2569 struct route_node *rp;
2570 struct rip_info *rinfo;
2571
2572 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2573 if ((rinfo = rp->info) != NULL)
2574 if (rinfo->flags & RIP_RTF_CHANGED)
2575 rinfo->flags &= ~RIP_RTF_CHANGED;
2576}
2577
2578/* Triggered update interval timer. */
2579int
2580rip_triggered_interval (struct thread *t)
2581{
2582 int rip_triggered_update (struct thread *);
2583
2584 rip->t_triggered_interval = NULL;
2585
2586 if (rip->trigger)
2587 {
2588 rip->trigger = 0;
2589 rip_triggered_update (t);
2590 }
2591 return 0;
2592}
2593
2594/* Execute triggered update. */
2595int
2596rip_triggered_update (struct thread *t)
2597{
2598 int interval;
2599
2600 /* Clear thred pointer. */
2601 rip->t_triggered_update = NULL;
2602
2603 /* Cancel interval timer. */
2604 if (rip->t_triggered_interval)
2605 {
2606 thread_cancel (rip->t_triggered_interval);
2607 rip->t_triggered_interval = NULL;
2608 }
2609 rip->trigger = 0;
2610
2611 /* Logging triggered update. */
2612 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002613 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002614
2615 /* Split Horizon processing is done when generating triggered
2616 updates as well as normal updates (see section 2.6). */
2617 rip_update_process (rip_changed_route);
2618
2619 /* Once all of the triggered updates have been generated, the route
2620 change flags should be cleared. */
2621 rip_clear_changed_flag ();
2622
2623 /* After a triggered update is sent, a timer should be set for a
2624 random interval between 1 and 5 seconds. If other changes that
2625 would trigger updates occur before the timer expires, a single
2626 update is triggered when the timer expires. */
2627 interval = (random () % 5) + 1;
2628
2629 rip->t_triggered_interval =
2630 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2631
2632 return 0;
2633}
2634
2635/* Withdraw redistributed route. */
2636void
2637rip_redistribute_withdraw (int type)
2638{
2639 struct route_node *rp;
2640 struct rip_info *rinfo;
2641
2642 if (!rip)
2643 return;
2644
2645 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2646 if ((rinfo = rp->info) != NULL)
2647 {
2648 if (rinfo->type == type
2649 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2650 {
2651 /* Perform poisoned reverse. */
2652 rinfo->metric = RIP_METRIC_INFINITY;
2653 RIP_TIMER_ON (rinfo->t_garbage_collect,
2654 rip_garbage_collect, rip->garbage_time);
2655 RIP_TIMER_OFF (rinfo->t_timeout);
2656 rinfo->flags |= RIP_RTF_CHANGED;
2657
hasso16705132003-05-25 14:49:19 +00002658 if (IS_RIP_DEBUG_EVENT) {
2659 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2660
ajs5d6c3772004-12-08 19:24:06 +00002661 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002662 inet_ntoa(p->prefix), p->prefixlen,
2663 ifindex2ifname(rinfo->ifindex));
2664 }
2665
paul718e3742002-12-13 20:15:29 +00002666 rip_event (RIP_TRIGGERED_UPDATE, 0);
2667 }
2668 }
2669}
2670
2671/* Create new RIP instance and set it to global variable. */
2672int
2673rip_create ()
2674{
2675 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2676 memset (rip, 0, sizeof (struct rip));
2677
2678 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002679 rip->version_send = RI_RIP_VERSION_2;
2680 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002681 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2682 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2683 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2684 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2685
2686 /* Initialize RIP routig table. */
2687 rip->table = route_table_init ();
2688 rip->route = route_table_init ();
2689 rip->neighbor = route_table_init ();
2690
2691 /* Make output stream. */
2692 rip->obuf = stream_new (1500);
2693
2694 /* Make socket. */
2695 rip->sock = rip_create_socket ();
2696 if (rip->sock < 0)
2697 return rip->sock;
2698
2699 /* Create read and timer thread. */
2700 rip_event (RIP_READ, rip->sock);
2701 rip_event (RIP_UPDATE_EVENT, 1);
2702
2703 return 0;
2704}
2705
2706/* Sned RIP request to the destination. */
2707int
2708rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002709 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002710{
2711 struct rte *rte;
2712 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002713 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002714
2715 memset (&rip_packet, 0, sizeof (rip_packet));
2716
2717 rip_packet.command = RIP_REQUEST;
2718 rip_packet.version = version;
2719 rte = rip_packet.rte;
2720 rte->metric = htonl (RIP_METRIC_INFINITY);
2721
paul931cd542004-01-23 15:31:42 +00002722 if (connected)
2723 {
2724 /*
2725 * connected is only sent for ripv1 case, or when
2726 * interface does not support multicast. Caller loops
2727 * over each connected address for this case.
2728 */
paul11dde9c2004-05-31 14:00:00 +00002729 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002730 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002731 return -1;
2732 else
2733 return sizeof (rip_packet);
2734 }
2735
paulcc1131a2003-10-15 23:20:17 +00002736 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002737 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002738 {
2739 struct prefix_ipv4 *p;
2740
2741 p = (struct prefix_ipv4 *) connected->address;
2742
2743 if (p->family != AF_INET)
2744 continue;
2745
paul11dde9c2004-05-31 14:00:00 +00002746 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002747 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002748 return -1;
2749 }
2750 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002751}
2752
2753int
2754rip_update_jitter (unsigned long time)
2755{
paul239389b2004-05-05 14:09:37 +00002756#define JITTER_BOUND 4
2757 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2758 Given that, we cannot let time be less than JITTER_BOUND seconds.
2759 The RIPv2 RFC says jitter should be small compared to
2760 update_time. We consider 1/JITTER_BOUND to be small.
2761 */
2762
2763 int jitter_input = time;
2764 int jitter;
2765
2766 if (jitter_input < JITTER_BOUND)
2767 jitter_input = JITTER_BOUND;
2768
2769 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2770
2771 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002772}
2773
2774void
2775rip_event (enum rip_event event, int sock)
2776{
2777 int jitter = 0;
2778
2779 switch (event)
2780 {
2781 case RIP_READ:
2782 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2783 break;
2784 case RIP_UPDATE_EVENT:
2785 if (rip->t_update)
2786 {
2787 thread_cancel (rip->t_update);
2788 rip->t_update = NULL;
2789 }
2790 jitter = rip_update_jitter (rip->update_time);
2791 rip->t_update =
2792 thread_add_timer (master, rip_update, NULL,
2793 sock ? 2 : rip->update_time + jitter);
2794 break;
2795 case RIP_TRIGGERED_UPDATE:
2796 if (rip->t_triggered_interval)
2797 rip->trigger = 1;
2798 else if (! rip->t_triggered_update)
2799 rip->t_triggered_update =
2800 thread_add_event (master, rip_triggered_update, NULL, 0);
2801 break;
2802 default:
2803 break;
2804 }
2805}
2806
2807DEFUN (router_rip,
2808 router_rip_cmd,
2809 "router rip",
2810 "Enable a routing process\n"
2811 "Routing Information Protocol (RIP)\n")
2812{
2813 int ret;
2814
2815 /* If rip is not enabled before. */
2816 if (! rip)
2817 {
2818 ret = rip_create ();
2819 if (ret < 0)
2820 {
2821 zlog_info ("Can't create RIP");
2822 return CMD_WARNING;
2823 }
2824 }
2825 vty->node = RIP_NODE;
2826 vty->index = rip;
2827
2828 return CMD_SUCCESS;
2829}
2830
2831DEFUN (no_router_rip,
2832 no_router_rip_cmd,
2833 "no router rip",
2834 NO_STR
2835 "Enable a routing process\n"
2836 "Routing Information Protocol (RIP)\n")
2837{
2838 if (rip)
2839 rip_clean ();
2840 return CMD_SUCCESS;
2841}
2842
2843DEFUN (rip_version,
2844 rip_version_cmd,
2845 "version <1-2>",
2846 "Set routing protocol version\n"
2847 "version\n")
2848{
2849 int version;
2850
2851 version = atoi (argv[0]);
2852 if (version != RIPv1 && version != RIPv2)
2853 {
2854 vty_out (vty, "invalid rip version %d%s", version,
2855 VTY_NEWLINE);
2856 return CMD_WARNING;
2857 }
paulf38a4712003-06-07 01:10:00 +00002858 rip->version_send = version;
2859 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002860
2861 return CMD_SUCCESS;
2862}
2863
2864DEFUN (no_rip_version,
2865 no_rip_version_cmd,
2866 "no version",
2867 NO_STR
2868 "Set routing protocol version\n")
2869{
2870 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002871 rip->version_send = RI_RIP_VERSION_2;
2872 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002873
2874 return CMD_SUCCESS;
2875}
2876
2877ALIAS (no_rip_version,
2878 no_rip_version_val_cmd,
2879 "no version <1-2>",
2880 NO_STR
2881 "Set routing protocol version\n"
2882 "version\n")
2883
2884DEFUN (rip_route,
2885 rip_route_cmd,
2886 "route A.B.C.D/M",
2887 "RIP static route configuration\n"
2888 "IP prefix <network>/<length>\n")
2889{
2890 int ret;
2891 struct prefix_ipv4 p;
2892 struct route_node *node;
2893
2894 ret = str2prefix_ipv4 (argv[0], &p);
2895 if (ret < 0)
2896 {
2897 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2898 return CMD_WARNING;
2899 }
2900 apply_mask_ipv4 (&p);
2901
2902 /* For router rip configuration. */
2903 node = route_node_get (rip->route, (struct prefix *) &p);
2904
2905 if (node->info)
2906 {
2907 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2908 route_unlock_node (node);
2909 return CMD_WARNING;
2910 }
2911
hasso8a676be2004-10-08 06:36:38 +00002912 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002913
2914 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2915
2916 return CMD_SUCCESS;
2917}
2918
2919DEFUN (no_rip_route,
2920 no_rip_route_cmd,
2921 "no route A.B.C.D/M",
2922 NO_STR
2923 "RIP static route configuration\n"
2924 "IP prefix <network>/<length>\n")
2925{
2926 int ret;
2927 struct prefix_ipv4 p;
2928 struct route_node *node;
2929
2930 ret = str2prefix_ipv4 (argv[0], &p);
2931 if (ret < 0)
2932 {
2933 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2934 return CMD_WARNING;
2935 }
2936 apply_mask_ipv4 (&p);
2937
2938 /* For router rip configuration. */
2939 node = route_node_lookup (rip->route, (struct prefix *) &p);
2940 if (! node)
2941 {
2942 vty_out (vty, "Can't find route %s.%s", argv[0],
2943 VTY_NEWLINE);
2944 return CMD_WARNING;
2945 }
2946
2947 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2948 route_unlock_node (node);
2949
2950 node->info = NULL;
2951 route_unlock_node (node);
2952
2953 return CMD_SUCCESS;
2954}
2955
2956void
2957rip_update_default_metric ()
2958{
2959 struct route_node *np;
2960 struct rip_info *rinfo;
2961
2962 for (np = route_top (rip->table); np; np = route_next (np))
2963 if ((rinfo = np->info) != NULL)
2964 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2965 rinfo->metric = rip->default_metric;
2966}
2967
2968DEFUN (rip_default_metric,
2969 rip_default_metric_cmd,
2970 "default-metric <1-16>",
2971 "Set a metric of redistribute routes\n"
2972 "Default metric\n")
2973{
2974 if (rip)
2975 {
2976 rip->default_metric = atoi (argv[0]);
2977 /* rip_update_default_metric (); */
2978 }
2979 return CMD_SUCCESS;
2980}
2981
2982DEFUN (no_rip_default_metric,
2983 no_rip_default_metric_cmd,
2984 "no default-metric",
2985 NO_STR
2986 "Set a metric of redistribute routes\n"
2987 "Default metric\n")
2988{
2989 if (rip)
2990 {
2991 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2992 /* rip_update_default_metric (); */
2993 }
2994 return CMD_SUCCESS;
2995}
2996
2997ALIAS (no_rip_default_metric,
2998 no_rip_default_metric_val_cmd,
2999 "no default-metric <1-16>",
3000 NO_STR
3001 "Set a metric of redistribute routes\n"
3002 "Default metric\n")
3003
3004DEFUN (rip_timers,
3005 rip_timers_cmd,
3006 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3007 "Adjust routing timers\n"
3008 "Basic routing protocol update timers\n"
3009 "Routing table update timer value in second. Default is 30.\n"
3010 "Routing information timeout timer. Default is 180.\n"
3011 "Garbage collection timer. Default is 120.\n")
3012{
3013 unsigned long update;
3014 unsigned long timeout;
3015 unsigned long garbage;
3016 char *endptr = NULL;
3017 unsigned long RIP_TIMER_MAX = 2147483647;
3018 unsigned long RIP_TIMER_MIN = 5;
3019
3020 update = strtoul (argv[0], &endptr, 10);
3021 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3022 {
3023 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3024 return CMD_WARNING;
3025 }
3026
3027 timeout = strtoul (argv[1], &endptr, 10);
3028 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3029 {
3030 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033
3034 garbage = strtoul (argv[2], &endptr, 10);
3035 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3036 {
3037 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3038 return CMD_WARNING;
3039 }
3040
3041 /* Set each timer value. */
3042 rip->update_time = update;
3043 rip->timeout_time = timeout;
3044 rip->garbage_time = garbage;
3045
3046 /* Reset update timer thread. */
3047 rip_event (RIP_UPDATE_EVENT, 0);
3048
3049 return CMD_SUCCESS;
3050}
3051
3052DEFUN (no_rip_timers,
3053 no_rip_timers_cmd,
3054 "no timers basic",
3055 NO_STR
3056 "Adjust routing timers\n"
3057 "Basic routing protocol update timers\n")
3058{
3059 /* Set each timer value to the default. */
3060 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3061 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3062 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3063
3064 /* Reset update timer thread. */
3065 rip_event (RIP_UPDATE_EVENT, 0);
3066
3067 return CMD_SUCCESS;
3068}
hasso16705132003-05-25 14:49:19 +00003069
3070ALIAS (no_rip_timers,
3071 no_rip_timers_val_cmd,
3072 "no timers basic <0-65535> <0-65535> <0-65535>",
3073 NO_STR
3074 "Adjust routing timers\n"
3075 "Basic routing protocol update timers\n"
3076 "Routing table update timer value in second. Default is 30.\n"
3077 "Routing information timeout timer. Default is 180.\n"
3078 "Garbage collection timer. Default is 120.\n")
3079
paul718e3742002-12-13 20:15:29 +00003080
3081struct route_table *rip_distance_table;
3082
3083struct rip_distance
3084{
3085 /* Distance value for the IP source prefix. */
3086 u_char distance;
3087
3088 /* Name of the access-list to be matched. */
3089 char *access_list;
3090};
3091
3092struct rip_distance *
3093rip_distance_new ()
3094{
3095 struct rip_distance *new;
3096 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3097 memset (new, 0, sizeof (struct rip_distance));
3098 return new;
3099}
3100
3101void
3102rip_distance_free (struct rip_distance *rdistance)
3103{
3104 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3105}
3106
3107int
hasso98b718a2004-10-11 12:57:57 +00003108rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3109 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003110{
3111 int ret;
3112 struct prefix_ipv4 p;
3113 u_char distance;
3114 struct route_node *rn;
3115 struct rip_distance *rdistance;
3116
3117 ret = str2prefix_ipv4 (ip_str, &p);
3118 if (ret == 0)
3119 {
3120 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3121 return CMD_WARNING;
3122 }
3123
3124 distance = atoi (distance_str);
3125
3126 /* Get RIP distance node. */
3127 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3128 if (rn->info)
3129 {
3130 rdistance = rn->info;
3131 route_unlock_node (rn);
3132 }
3133 else
3134 {
3135 rdistance = rip_distance_new ();
3136 rn->info = rdistance;
3137 }
3138
3139 /* Set distance value. */
3140 rdistance->distance = distance;
3141
3142 /* Reset access-list configuration. */
3143 if (rdistance->access_list)
3144 {
3145 free (rdistance->access_list);
3146 rdistance->access_list = NULL;
3147 }
3148 if (access_list_str)
3149 rdistance->access_list = strdup (access_list_str);
3150
3151 return CMD_SUCCESS;
3152}
3153
3154int
hasso98b718a2004-10-11 12:57:57 +00003155rip_distance_unset (struct vty *vty, const char *distance_str,
3156 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003157{
3158 int ret;
3159 struct prefix_ipv4 p;
3160 u_char distance;
3161 struct route_node *rn;
3162 struct rip_distance *rdistance;
3163
3164 ret = str2prefix_ipv4 (ip_str, &p);
3165 if (ret == 0)
3166 {
3167 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3168 return CMD_WARNING;
3169 }
3170
3171 distance = atoi (distance_str);
3172
3173 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3174 if (! rn)
3175 {
3176 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3177 return CMD_WARNING;
3178 }
3179
3180 rdistance = rn->info;
3181
3182 if (rdistance->access_list)
3183 free (rdistance->access_list);
3184 rip_distance_free (rdistance);
3185
3186 rn->info = NULL;
3187 route_unlock_node (rn);
3188 route_unlock_node (rn);
3189
3190 return CMD_SUCCESS;
3191}
3192
3193void
3194rip_distance_reset ()
3195{
3196 struct route_node *rn;
3197 struct rip_distance *rdistance;
3198
3199 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3200 if ((rdistance = rn->info) != NULL)
3201 {
3202 if (rdistance->access_list)
3203 free (rdistance->access_list);
3204 rip_distance_free (rdistance);
3205 rn->info = NULL;
3206 route_unlock_node (rn);
3207 }
3208}
3209
3210/* Apply RIP information to distance method. */
3211u_char
3212rip_distance_apply (struct rip_info *rinfo)
3213{
3214 struct route_node *rn;
3215 struct prefix_ipv4 p;
3216 struct rip_distance *rdistance;
3217 struct access_list *alist;
3218
3219 if (! rip)
3220 return 0;
3221
3222 memset (&p, 0, sizeof (struct prefix_ipv4));
3223 p.family = AF_INET;
3224 p.prefix = rinfo->from;
3225 p.prefixlen = IPV4_MAX_BITLEN;
3226
3227 /* Check source address. */
3228 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3229 if (rn)
3230 {
3231 rdistance = rn->info;
3232 route_unlock_node (rn);
3233
3234 if (rdistance->access_list)
3235 {
3236 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3237 if (alist == NULL)
3238 return 0;
3239 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3240 return 0;
3241
3242 return rdistance->distance;
3243 }
3244 else
3245 return rdistance->distance;
3246 }
3247
3248 if (rip->distance)
3249 return rip->distance;
3250
3251 return 0;
3252}
3253
3254void
3255rip_distance_show (struct vty *vty)
3256{
3257 struct route_node *rn;
3258 struct rip_distance *rdistance;
3259 int header = 1;
3260 char buf[BUFSIZ];
3261
3262 vty_out (vty, " Distance: (default is %d)%s",
3263 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3264 VTY_NEWLINE);
3265
3266 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3267 if ((rdistance = rn->info) != NULL)
3268 {
3269 if (header)
3270 {
3271 vty_out (vty, " Address Distance List%s",
3272 VTY_NEWLINE);
3273 header = 0;
3274 }
3275 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3276 vty_out (vty, " %-20s %4d %s%s",
3277 buf, rdistance->distance,
3278 rdistance->access_list ? rdistance->access_list : "",
3279 VTY_NEWLINE);
3280 }
3281}
3282
3283DEFUN (rip_distance,
3284 rip_distance_cmd,
3285 "distance <1-255>",
3286 "Administrative distance\n"
3287 "Distance value\n")
3288{
3289 rip->distance = atoi (argv[0]);
3290 return CMD_SUCCESS;
3291}
3292
3293DEFUN (no_rip_distance,
3294 no_rip_distance_cmd,
3295 "no distance <1-255>",
3296 NO_STR
3297 "Administrative distance\n"
3298 "Distance value\n")
3299{
3300 rip->distance = 0;
3301 return CMD_SUCCESS;
3302}
3303
3304DEFUN (rip_distance_source,
3305 rip_distance_source_cmd,
3306 "distance <1-255> A.B.C.D/M",
3307 "Administrative distance\n"
3308 "Distance value\n"
3309 "IP source prefix\n")
3310{
3311 rip_distance_set (vty, argv[0], argv[1], NULL);
3312 return CMD_SUCCESS;
3313}
3314
3315DEFUN (no_rip_distance_source,
3316 no_rip_distance_source_cmd,
3317 "no distance <1-255> A.B.C.D/M",
3318 NO_STR
3319 "Administrative distance\n"
3320 "Distance value\n"
3321 "IP source prefix\n")
3322{
3323 rip_distance_unset (vty, argv[0], argv[1], NULL);
3324 return CMD_SUCCESS;
3325}
3326
3327DEFUN (rip_distance_source_access_list,
3328 rip_distance_source_access_list_cmd,
3329 "distance <1-255> A.B.C.D/M WORD",
3330 "Administrative distance\n"
3331 "Distance value\n"
3332 "IP source prefix\n"
3333 "Access list name\n")
3334{
3335 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3336 return CMD_SUCCESS;
3337}
3338
3339DEFUN (no_rip_distance_source_access_list,
3340 no_rip_distance_source_access_list_cmd,
3341 "no distance <1-255> A.B.C.D/M WORD",
3342 NO_STR
3343 "Administrative distance\n"
3344 "Distance value\n"
3345 "IP source prefix\n"
3346 "Access list name\n")
3347{
3348 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3349 return CMD_SUCCESS;
3350}
3351
3352/* Print out routes update time. */
3353void
3354rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3355{
3356 struct timeval timer_now;
3357 time_t clock;
3358 struct tm *tm;
3359#define TIME_BUF 25
3360 char timebuf [TIME_BUF];
3361 struct thread *thread;
3362
3363 gettimeofday (&timer_now, NULL);
3364
3365 if ((thread = rinfo->t_timeout) != NULL)
3366 {
3367 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3368 tm = gmtime (&clock);
3369 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3370 vty_out (vty, "%5s", timebuf);
3371 }
3372 else if ((thread = rinfo->t_garbage_collect) != NULL)
3373 {
3374 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3375 tm = gmtime (&clock);
3376 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3377 vty_out (vty, "%5s", timebuf);
3378 }
3379}
3380
hasso8a676be2004-10-08 06:36:38 +00003381const char *
paul718e3742002-12-13 20:15:29 +00003382rip_route_type_print (int sub_type)
3383{
3384 switch (sub_type)
3385 {
3386 case RIP_ROUTE_RTE:
3387 return "n";
3388 case RIP_ROUTE_STATIC:
3389 return "s";
3390 case RIP_ROUTE_DEFAULT:
3391 return "d";
3392 case RIP_ROUTE_REDISTRIBUTE:
3393 return "r";
3394 case RIP_ROUTE_INTERFACE:
3395 return "i";
3396 default:
3397 return "?";
3398 }
3399}
3400
3401DEFUN (show_ip_rip,
3402 show_ip_rip_cmd,
3403 "show ip rip",
3404 SHOW_STR
3405 IP_STR
3406 "Show RIP routes\n")
3407{
3408 struct route_node *np;
3409 struct rip_info *rinfo;
3410
3411 if (! rip)
3412 return CMD_SUCCESS;
3413
hasso16705132003-05-25 14:49:19 +00003414 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3415 "Sub-codes:%s"
3416 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003417 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003418 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003419 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003420
3421 for (np = route_top (rip->table); np; np = route_next (np))
3422 if ((rinfo = np->info) != NULL)
3423 {
3424 int len;
3425
3426 len = vty_out (vty, "%s(%s) %s/%d",
3427 /* np->lock, For debugging. */
3428 route_info[rinfo->type].str,
3429 rip_route_type_print (rinfo->sub_type),
3430 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3431
hassoa1455d82004-03-03 19:36:24 +00003432 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003433
3434 if (len > 0)
3435 vty_out (vty, "%*s", len, " ");
3436
3437 if (rinfo->nexthop.s_addr)
3438 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3439 rinfo->metric);
3440 else
3441 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3442
3443 /* Route which exist in kernel routing table. */
3444 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3445 (rinfo->sub_type == RIP_ROUTE_RTE))
3446 {
3447 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003448 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003449 rip_vty_out_uptime (vty, rinfo);
3450 }
3451 else if (rinfo->metric == RIP_METRIC_INFINITY)
3452 {
3453 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003454 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003455 rip_vty_out_uptime (vty, rinfo);
3456 }
3457 else
hasso16705132003-05-25 14:49:19 +00003458 {
3459 vty_out (vty, "self ");
3460 vty_out (vty, "%3d", rinfo->tag);
3461 }
paul718e3742002-12-13 20:15:29 +00003462
3463 vty_out (vty, "%s", VTY_NEWLINE);
3464 }
3465 return CMD_SUCCESS;
3466}
3467
3468/* Return next event time. */
3469int
3470rip_next_thread_timer (struct thread *thread)
3471{
3472 struct timeval timer_now;
3473
3474 gettimeofday (&timer_now, NULL);
3475
3476 return thread->u.sands.tv_sec - timer_now.tv_sec;
3477}
3478
hasso16705132003-05-25 14:49:19 +00003479/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3480DEFUN (show_ip_rip_status,
3481 show_ip_rip_status_cmd,
3482 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003483 SHOW_STR
3484 IP_STR
hasso16705132003-05-25 14:49:19 +00003485 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003486 "IP routing protocol process parameters and statistics\n")
3487{
hasso52dc7ee2004-09-23 19:18:23 +00003488 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003489 struct interface *ifp;
3490 struct rip_interface *ri;
3491 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003492 const char *send_version;
3493 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003494
3495 if (! rip)
3496 return CMD_SUCCESS;
3497
3498 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3499 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3500 rip->update_time);
3501 vty_out (vty, " next due in %d seconds%s",
3502 rip_next_thread_timer (rip->t_update),
3503 VTY_NEWLINE);
3504 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3505 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3506 VTY_NEWLINE);
3507
3508 /* Filtering status show. */
3509 config_show_distribute (vty);
3510
3511 /* Default metric information. */
3512 vty_out (vty, " Default redistribution metric is %d%s",
3513 rip->default_metric, VTY_NEWLINE);
3514
3515 /* Redistribute information. */
3516 vty_out (vty, " Redistributing:");
3517 config_write_rip_redistribute (vty, 0);
3518 vty_out (vty, "%s", VTY_NEWLINE);
3519
paulf38a4712003-06-07 01:10:00 +00003520 vty_out (vty, " Default version control: send version %s,",
3521 lookup(ri_version_msg,rip->version_send));
3522 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3523 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3524 else
3525 vty_out (vty, " receive version %s %s",
3526 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003527
3528 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3529
paul1eb8ef22005-04-07 07:30:20 +00003530 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003531 {
paul718e3742002-12-13 20:15:29 +00003532 ri = ifp->info;
3533
3534 if (ri->enable_network || ri->enable_interface)
3535 {
3536 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003537 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003538 else
3539 send_version = lookup (ri_version_msg, ri->ri_send);
3540
3541 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003542 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003543 else
3544 receive_version = lookup (ri_version_msg, ri->ri_receive);
3545
3546 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3547 send_version,
3548 receive_version,
3549 ri->key_chain ? ri->key_chain : "",
3550 VTY_NEWLINE);
3551 }
3552 }
3553
3554 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3555 config_write_rip_network (vty, 0);
3556
paul4aaff3f2003-06-07 01:04:45 +00003557 {
3558 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003559 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003560 {
paul4aaff3f2003-06-07 01:04:45 +00003561 ri = ifp->info;
3562
3563 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3564 {
3565 if (!found_passive)
3566 {
3567 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3568 found_passive = 1;
3569 }
3570 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3571 }
3572 }
3573 }
3574
paul718e3742002-12-13 20:15:29 +00003575 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3576 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3577 rip_peer_display (vty);
3578
3579 rip_distance_show (vty);
3580
3581 return CMD_SUCCESS;
3582}
3583
3584/* RIP configuration write function. */
3585int
3586config_write_rip (struct vty *vty)
3587{
3588 int write = 0;
3589 struct route_node *rn;
3590 struct rip_distance *rdistance;
3591
3592 if (rip)
3593 {
3594 /* Router RIP statement. */
3595 vty_out (vty, "router rip%s", VTY_NEWLINE);
3596 write++;
3597
3598 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003599 if (rip->version_send != RI_RIP_VERSION_2
3600 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3601 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003602 VTY_NEWLINE);
3603
3604 /* RIP timer configuration. */
3605 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3606 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3607 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3608 vty_out (vty, " timers basic %lu %lu %lu%s",
3609 rip->update_time,
3610 rip->timeout_time,
3611 rip->garbage_time,
3612 VTY_NEWLINE);
3613
3614 /* Default information configuration. */
3615 if (rip->default_information)
3616 {
3617 if (rip->default_information_route_map)
3618 vty_out (vty, " default-information originate route-map %s%s",
3619 rip->default_information_route_map, VTY_NEWLINE);
3620 else
3621 vty_out (vty, " default-information originate%s",
3622 VTY_NEWLINE);
3623 }
3624
3625 /* Redistribute configuration. */
3626 config_write_rip_redistribute (vty, 1);
3627
3628 /* RIP offset-list configuration. */
3629 config_write_rip_offset_list (vty);
3630
3631 /* RIP enabled network and interface configuration. */
3632 config_write_rip_network (vty, 1);
3633
3634 /* RIP default metric configuration */
3635 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3636 vty_out (vty, " default-metric %d%s",
3637 rip->default_metric, VTY_NEWLINE);
3638
3639 /* Distribute configuration. */
3640 write += config_write_distribute (vty);
3641
hasso16705132003-05-25 14:49:19 +00003642 /* Interface routemap configuration */
3643 write += config_write_if_rmap (vty);
3644
paul718e3742002-12-13 20:15:29 +00003645 /* Distance configuration. */
3646 if (rip->distance)
3647 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3648
3649 /* RIP source IP prefix distance configuration. */
3650 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3651 if ((rdistance = rn->info) != NULL)
3652 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3653 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3654 rdistance->access_list ? rdistance->access_list : "",
3655 VTY_NEWLINE);
3656
3657 /* RIP static route configuration. */
3658 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3659 if (rn->info)
3660 vty_out (vty, " route %s/%d%s",
3661 inet_ntoa (rn->p.u.prefix4),
3662 rn->p.prefixlen,
3663 VTY_NEWLINE);
3664
3665 }
3666 return write;
3667}
3668
3669/* RIP node structure. */
3670struct cmd_node rip_node =
3671{
3672 RIP_NODE,
3673 "%s(config-router)# ",
3674 1
3675};
3676
3677/* Distribute-list update functions. */
3678void
3679rip_distribute_update (struct distribute *dist)
3680{
3681 struct interface *ifp;
3682 struct rip_interface *ri;
3683 struct access_list *alist;
3684 struct prefix_list *plist;
3685
3686 if (! dist->ifname)
3687 return;
3688
3689 ifp = if_lookup_by_name (dist->ifname);
3690 if (ifp == NULL)
3691 return;
3692
3693 ri = ifp->info;
3694
3695 if (dist->list[DISTRIBUTE_IN])
3696 {
3697 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3698 if (alist)
3699 ri->list[RIP_FILTER_IN] = alist;
3700 else
3701 ri->list[RIP_FILTER_IN] = NULL;
3702 }
3703 else
3704 ri->list[RIP_FILTER_IN] = NULL;
3705
3706 if (dist->list[DISTRIBUTE_OUT])
3707 {
3708 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3709 if (alist)
3710 ri->list[RIP_FILTER_OUT] = alist;
3711 else
3712 ri->list[RIP_FILTER_OUT] = NULL;
3713 }
3714 else
3715 ri->list[RIP_FILTER_OUT] = NULL;
3716
3717 if (dist->prefix[DISTRIBUTE_IN])
3718 {
3719 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3720 if (plist)
3721 ri->prefix[RIP_FILTER_IN] = plist;
3722 else
3723 ri->prefix[RIP_FILTER_IN] = NULL;
3724 }
3725 else
3726 ri->prefix[RIP_FILTER_IN] = NULL;
3727
3728 if (dist->prefix[DISTRIBUTE_OUT])
3729 {
3730 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3731 if (plist)
3732 ri->prefix[RIP_FILTER_OUT] = plist;
3733 else
3734 ri->prefix[RIP_FILTER_OUT] = NULL;
3735 }
3736 else
3737 ri->prefix[RIP_FILTER_OUT] = NULL;
3738}
3739
3740void
3741rip_distribute_update_interface (struct interface *ifp)
3742{
3743 struct distribute *dist;
3744
3745 dist = distribute_lookup (ifp->name);
3746 if (dist)
3747 rip_distribute_update (dist);
3748}
3749
3750/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003751/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003752void
paul02ff83c2004-06-11 11:27:03 +00003753rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003754{
3755 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003756 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003757
paul1eb8ef22005-04-07 07:30:20 +00003758 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3759 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003760}
paul11dde9c2004-05-31 14:00:00 +00003761/* ARGSUSED */
3762void
3763rip_distribute_update_all_wrapper(struct access_list *notused)
3764{
paul02ff83c2004-06-11 11:27:03 +00003765 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003766}
paul718e3742002-12-13 20:15:29 +00003767
3768/* Delete all added rip route. */
3769void
3770rip_clean ()
3771{
3772 int i;
3773 struct route_node *rp;
3774 struct rip_info *rinfo;
3775
3776 if (rip)
3777 {
3778 /* Clear RIP routes */
3779 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3780 if ((rinfo = rp->info) != NULL)
3781 {
3782 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3783 rinfo->sub_type == RIP_ROUTE_RTE)
3784 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3785 &rinfo->nexthop, rinfo->metric);
3786
3787 RIP_TIMER_OFF (rinfo->t_timeout);
3788 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3789
3790 rp->info = NULL;
3791 route_unlock_node (rp);
3792
3793 rip_info_free (rinfo);
3794 }
3795
3796 /* Cancel RIP related timers. */
3797 RIP_TIMER_OFF (rip->t_update);
3798 RIP_TIMER_OFF (rip->t_triggered_update);
3799 RIP_TIMER_OFF (rip->t_triggered_interval);
3800
3801 /* Cancel read thread. */
3802 if (rip->t_read)
3803 {
3804 thread_cancel (rip->t_read);
3805 rip->t_read = NULL;
3806 }
3807
3808 /* Close RIP socket. */
3809 if (rip->sock >= 0)
3810 {
3811 close (rip->sock);
3812 rip->sock = -1;
3813 }
3814
3815 /* Static RIP route configuration. */
3816 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3817 if (rp->info)
3818 {
3819 rp->info = NULL;
3820 route_unlock_node (rp);
3821 }
3822
3823 /* RIP neighbor configuration. */
3824 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3825 if (rp->info)
3826 {
3827 rp->info = NULL;
3828 route_unlock_node (rp);
3829 }
3830
3831 /* Redistribute related clear. */
3832 if (rip->default_information_route_map)
3833 free (rip->default_information_route_map);
3834
3835 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3836 if (rip->route_map[i].name)
3837 free (rip->route_map[i].name);
3838
3839 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3840 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3841 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3842
3843 XFREE (MTYPE_RIP, rip);
3844 rip = NULL;
3845 }
3846
3847 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003848 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003849 rip_offset_clean ();
3850 rip_interface_clean ();
3851 rip_distance_reset ();
3852 rip_redistribute_clean ();
3853}
3854
3855/* Reset all values to the default settings. */
3856void
3857rip_reset ()
3858{
3859 /* Reset global counters. */
3860 rip_global_route_changes = 0;
3861 rip_global_queries = 0;
3862
3863 /* Call ripd related reset functions. */
3864 rip_debug_reset ();
3865 rip_route_map_reset ();
3866
3867 /* Call library reset functions. */
3868 vty_reset ();
3869 access_list_reset ();
3870 prefix_list_reset ();
3871
3872 distribute_list_reset ();
3873
3874 rip_interface_reset ();
3875 rip_distance_reset ();
3876
3877 rip_zclient_reset ();
3878}
3879
hasso16705132003-05-25 14:49:19 +00003880void
3881rip_if_rmap_update (struct if_rmap *if_rmap)
3882{
3883 struct interface *ifp;
3884 struct rip_interface *ri;
3885 struct route_map *rmap;
3886
3887 ifp = if_lookup_by_name (if_rmap->ifname);
3888 if (ifp == NULL)
3889 return;
3890
3891 ri = ifp->info;
3892
3893 if (if_rmap->routemap[IF_RMAP_IN])
3894 {
3895 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3896 if (rmap)
3897 ri->routemap[IF_RMAP_IN] = rmap;
3898 else
3899 ri->routemap[IF_RMAP_IN] = NULL;
3900 }
3901 else
3902 ri->routemap[RIP_FILTER_IN] = NULL;
3903
3904 if (if_rmap->routemap[IF_RMAP_OUT])
3905 {
3906 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3907 if (rmap)
3908 ri->routemap[IF_RMAP_OUT] = rmap;
3909 else
3910 ri->routemap[IF_RMAP_OUT] = NULL;
3911 }
3912 else
3913 ri->routemap[RIP_FILTER_OUT] = NULL;
3914}
3915
3916void
3917rip_if_rmap_update_interface (struct interface *ifp)
3918{
3919 struct if_rmap *if_rmap;
3920
3921 if_rmap = if_rmap_lookup (ifp->name);
3922 if (if_rmap)
3923 rip_if_rmap_update (if_rmap);
3924}
3925
3926void
3927rip_routemap_update_redistribute (void)
3928{
3929 int i;
3930
3931 if (rip)
3932 {
3933 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3934 {
3935 if (rip->route_map[i].name)
3936 rip->route_map[i].map =
3937 route_map_lookup_by_name (rip->route_map[i].name);
3938 }
3939 }
3940}
3941
paul11dde9c2004-05-31 14:00:00 +00003942/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003943void
hasso98b718a2004-10-11 12:57:57 +00003944rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003945{
3946 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003947 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003948
paul1eb8ef22005-04-07 07:30:20 +00003949 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3950 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003951
3952 rip_routemap_update_redistribute ();
3953}
3954
paul718e3742002-12-13 20:15:29 +00003955/* Allocate new rip structure and set default value. */
3956void
3957rip_init ()
3958{
3959 /* Randomize for triggered update random(). */
3960 srand (time (NULL));
3961
3962 /* Install top nodes. */
3963 install_node (&rip_node, config_write_rip);
3964
3965 /* Install rip commands. */
3966 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003967 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003968 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003969 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003970 install_element (CONFIG_NODE, &router_rip_cmd);
3971 install_element (CONFIG_NODE, &no_router_rip_cmd);
3972
3973 install_default (RIP_NODE);
3974 install_element (RIP_NODE, &rip_version_cmd);
3975 install_element (RIP_NODE, &no_rip_version_cmd);
3976 install_element (RIP_NODE, &no_rip_version_val_cmd);
3977 install_element (RIP_NODE, &rip_default_metric_cmd);
3978 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3979 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3980 install_element (RIP_NODE, &rip_timers_cmd);
3981 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003982 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003983 install_element (RIP_NODE, &rip_route_cmd);
3984 install_element (RIP_NODE, &no_rip_route_cmd);
3985 install_element (RIP_NODE, &rip_distance_cmd);
3986 install_element (RIP_NODE, &no_rip_distance_cmd);
3987 install_element (RIP_NODE, &rip_distance_source_cmd);
3988 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3989 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3990 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3991
3992 /* Debug related init. */
3993 rip_debug_init ();
3994
paul718e3742002-12-13 20:15:29 +00003995 /* SNMP init. */
3996#ifdef HAVE_SNMP
3997 rip_snmp_init ();
3998#endif /* HAVE_SNMP */
3999
4000 /* Access list install. */
4001 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004002 access_list_add_hook (rip_distribute_update_all_wrapper);
4003 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004004
4005 /* Prefix list initialize.*/
4006 prefix_list_init ();
4007 prefix_list_add_hook (rip_distribute_update_all);
4008 prefix_list_delete_hook (rip_distribute_update_all);
4009
4010 /* Distribute list install. */
4011 distribute_list_init (RIP_NODE);
4012 distribute_list_add_hook (rip_distribute_update);
4013 distribute_list_delete_hook (rip_distribute_update);
4014
hasso16705132003-05-25 14:49:19 +00004015 /* Route-map */
4016 rip_route_map_init ();
4017 rip_offset_init ();
4018
4019 route_map_add_hook (rip_routemap_update);
4020 route_map_delete_hook (rip_routemap_update);
4021
4022 if_rmap_init (RIP_NODE);
4023 if_rmap_hook_add (rip_if_rmap_update);
4024 if_rmap_hook_delete (rip_if_rmap_update);
4025
paul718e3742002-12-13 20:15:29 +00004026 /* Distance control. */
4027 rip_distance_table = route_table_init ();
4028}