blob: fdb26446bdee19c3e0ad7bb001b7c7932a713db3 [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
paula4e987e2005-06-03 17:46:49 +00001322/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001323static int
1324rip_create_socket (struct sockaddr_in *to)
paula4e987e2005-06-03 17:46:49 +00001325{
1326 int ret;
1327 int sock;
1328 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001329
1330 if (!to)
1331 {
1332 memset (&addr, 0, sizeof (struct sockaddr_in));
1333 addr.sin_family = AF_INET;
1334 addr.sin_port = htons (RIP_PORT_DEFAULT);
1335 addr.sin_family = AF_INET;
1336 addr.sin_addr.s_addr = INADDR_ANY;
1337 }
1338
paula4e987e2005-06-03 17:46:49 +00001339 /* Make datagram socket. */
1340 sock = socket (AF_INET, SOCK_DGRAM, 0);
1341 if (sock < 0)
1342 {
1343 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1344 exit (1);
1345 }
1346
1347 sockopt_broadcast (sock);
1348 sockopt_reuseaddr (sock);
1349 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001350#ifdef RIP_RECVMSG
1351 setsockopt_pktinfo (sock);
1352#endif /* RIP_RECVMSG */
1353
1354 if (ripd_privs.change (ZPRIVS_RAISE))
1355 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001356 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1357 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1358
paula4e987e2005-06-03 17:46:49 +00001359 {
1360 int save_errno = errno;
1361 if (ripd_privs.change (ZPRIVS_LOWER))
1362 zlog_err ("rip_create_socket: could not lower privs");
1363 zlog_err("cannot bind to port %d: %s",
1364 (int)ntohs(addr.sin_port), safe_strerror(save_errno));
paulf69bd9d2005-06-03 18:01:50 +00001365 close (sock);
paula4e987e2005-06-03 17:46:49 +00001366 return ret;
1367 }
paulf69bd9d2005-06-03 18:01:50 +00001368
paula4e987e2005-06-03 17:46:49 +00001369 if (ripd_privs.change (ZPRIVS_LOWER))
1370 zlog_err ("rip_create_socket: could not lower privs");
1371
1372 return sock;
1373}
1374
paulc49ad8f2004-10-22 10:27:28 +00001375/* RIP packet send to destination address, on interface denoted by
1376 * by connected argument. NULL to argument denotes destination should be
1377 * should be RIP multicast group
1378 */
paul718e3742002-12-13 20:15:29 +00001379int
paulc49ad8f2004-10-22 10:27:28 +00001380rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1381 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001382{
paul931cd542004-01-23 15:31:42 +00001383 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001384 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001385
1386 assert (ifc != NULL);
1387
paul931cd542004-01-23 15:31:42 +00001388 if (IS_RIP_DEBUG_PACKET)
1389 {
paulf69bd9d2005-06-03 18:01:50 +00001390#define ADDRESS_SIZE 20
1391 char dst[ADDRESS_SIZE];
1392 dst[ADDRESS_SIZE - 1] = '\0';
1393
paul931cd542004-01-23 15:31:42 +00001394 if (to)
1395 {
paulf69bd9d2005-06-03 18:01:50 +00001396 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001397 }
1398 else
1399 {
1400 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001401 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001402 }
paulf69bd9d2005-06-03 18:01:50 +00001403#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001404 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001405 inet_ntoa(ifc->address->u.prefix4),
1406 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001407 }
paulf69bd9d2005-06-03 18:01:50 +00001408
paulc49ad8f2004-10-22 10:27:28 +00001409 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001410 {
1411 /*
1412 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1413 * with multiple addresses on the same subnet: the first address
1414 * on the subnet is configured "primary", and all subsequent addresses
1415 * on that subnet are treated as "secondary" addresses.
1416 * In order to avoid routing-table bloat on other rip listeners,
1417 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1418 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1419 * flag is set, we would end up sending a packet for a "secondary"
1420 * source address on non-linux systems.
1421 */
1422 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001423 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001424 return 0;
1425 }
1426
paul718e3742002-12-13 20:15:29 +00001427 /* Make destination address. */
1428 memset (&sin, 0, sizeof (struct sockaddr_in));
1429 sin.sin_family = AF_INET;
1430#ifdef HAVE_SIN_LEN
1431 sin.sin_len = sizeof (struct sockaddr_in);
1432#endif /* HAVE_SIN_LEN */
1433
1434 /* When destination is specified, use it's port and address. */
1435 if (to)
1436 {
paul718e3742002-12-13 20:15:29 +00001437 sin.sin_port = to->sin_port;
1438 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001439 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001440 }
1441 else
1442 {
paul718e3742002-12-13 20:15:29 +00001443
1444 sin.sin_port = htons (RIP_PORT_DEFAULT);
1445 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1446
paul931cd542004-01-23 15:31:42 +00001447 /*
1448 * we have to open a new socket for each packet because this
1449 * is the most portable way to bind to a different source
1450 * ipv4 address for each packet.
1451 */
paulf69bd9d2005-06-03 18:01:50 +00001452 if ( (send_sock = rip_create_socket (&sin)) < 0)
paul931cd542004-01-23 15:31:42 +00001453 {
paulf69bd9d2005-06-03 18:01:50 +00001454 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001455 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001456 }
paulc49ad8f2004-10-22 10:27:28 +00001457 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001458 }
1459
paul931cd542004-01-23 15:31:42 +00001460 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001461 sizeof (struct sockaddr_in));
1462
1463 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001464 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001465 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001466
1467 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001468 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001469
paul931cd542004-01-23 15:31:42 +00001470 if (!to)
1471 close(send_sock);
1472
paul718e3742002-12-13 20:15:29 +00001473 return ret;
1474}
1475
1476/* Add redistributed route to RIP table. */
1477void
1478rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1479 unsigned int ifindex, struct in_addr *nexthop)
1480{
1481 int ret;
1482 struct route_node *rp;
1483 struct rip_info *rinfo;
1484
1485 /* Redistribute route */
1486 ret = rip_destination_check (p->prefix);
1487 if (! ret)
1488 return;
1489
1490 rp = route_node_get (rip->table, (struct prefix *) p);
1491
1492 rinfo = rp->info;
1493
1494 if (rinfo)
1495 {
1496 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1497 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1498 && rinfo->metric != RIP_METRIC_INFINITY)
1499 {
1500 route_unlock_node (rp);
1501 return;
1502 }
1503
1504 /* Manually configured RIP route check. */
1505 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001506 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1507 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001508 {
hasso16705132003-05-25 14:49:19 +00001509 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1510 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001511 {
1512 route_unlock_node (rp);
1513 return;
1514 }
1515 }
1516
1517 RIP_TIMER_OFF (rinfo->t_timeout);
1518 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1519
1520 if (rip_route_rte (rinfo))
1521 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1522 rinfo->metric);
1523 rp->info = NULL;
1524 rip_info_free (rinfo);
1525
1526 route_unlock_node (rp);
1527 }
1528
1529 rinfo = rip_info_new ();
1530
1531 rinfo->type = type;
1532 rinfo->sub_type = sub_type;
1533 rinfo->ifindex = ifindex;
1534 rinfo->metric = 1;
1535 rinfo->rp = rp;
1536
1537 if (nexthop)
1538 rinfo->nexthop = *nexthop;
1539
1540 rinfo->flags |= RIP_RTF_FIB;
1541 rp->info = rinfo;
1542
1543 rinfo->flags |= RIP_RTF_CHANGED;
1544
hasso16705132003-05-25 14:49:19 +00001545 if (IS_RIP_DEBUG_EVENT) {
1546 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001547 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001548 inet_ntoa(p->prefix), p->prefixlen,
1549 ifindex2ifname(ifindex));
1550 else
ajs5d6c3772004-12-08 19:24:06 +00001551 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001552 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1553 ifindex2ifname(ifindex));
1554 }
1555
1556
paul718e3742002-12-13 20:15:29 +00001557 rip_event (RIP_TRIGGERED_UPDATE, 0);
1558}
1559
1560/* Delete redistributed route from RIP table. */
1561void
1562rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1563 unsigned int ifindex)
1564{
1565 int ret;
1566 struct route_node *rp;
1567 struct rip_info *rinfo;
1568
1569 ret = rip_destination_check (p->prefix);
1570 if (! ret)
1571 return;
1572
1573 rp = route_node_lookup (rip->table, (struct prefix *) p);
1574 if (rp)
1575 {
1576 rinfo = rp->info;
1577
1578 if (rinfo != NULL
1579 && rinfo->type == type
1580 && rinfo->sub_type == sub_type
1581 && rinfo->ifindex == ifindex)
1582 {
1583 /* Perform poisoned reverse. */
1584 rinfo->metric = RIP_METRIC_INFINITY;
1585 RIP_TIMER_ON (rinfo->t_garbage_collect,
1586 rip_garbage_collect, rip->garbage_time);
1587 RIP_TIMER_OFF (rinfo->t_timeout);
1588 rinfo->flags |= RIP_RTF_CHANGED;
1589
hasso16705132003-05-25 14:49:19 +00001590 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001591 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001592 inet_ntoa(p->prefix), p->prefixlen,
1593 ifindex2ifname(ifindex));
1594
paul718e3742002-12-13 20:15:29 +00001595 rip_event (RIP_TRIGGERED_UPDATE, 0);
1596 }
1597 }
1598}
1599
1600/* Response to request called from rip_read ().*/
1601void
1602rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001603 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001604{
1605 caddr_t lim;
1606 struct rte *rte;
1607 struct prefix_ipv4 p;
1608 struct route_node *rp;
1609 struct rip_info *rinfo;
1610 struct rip_interface *ri;
1611
hasso16705132003-05-25 14:49:19 +00001612 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001613 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001614 return;
1615
hasso429a0f82004-02-22 23:42:22 +00001616 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001617 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001618 if (! ri->running)
1619 return;
paul718e3742002-12-13 20:15:29 +00001620
1621 /* When passive interface is specified, suppress responses */
1622 if (ri->passive)
1623 return;
paulc49ad8f2004-10-22 10:27:28 +00001624
paul718e3742002-12-13 20:15:29 +00001625 /* RIP peer update. */
1626 rip_peer_update (from, packet->version);
1627
1628 lim = ((caddr_t) packet) + size;
1629 rte = packet->rte;
1630
1631 /* The Request is processed entry by entry. If there are no
1632 entries, no response is given. */
1633 if (lim == (caddr_t) rte)
1634 return;
1635
1636 /* There is one special case. If there is exactly one entry in the
1637 request, and it has an address family identifier of zero and a
1638 metric of infinity (i.e., 16), then this is a request to send the
1639 entire routing table. */
1640 if (lim == ((caddr_t) (rte + 1)) &&
1641 ntohs (rte->family) == 0 &&
1642 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1643 {
paulcc1131a2003-10-15 23:20:17 +00001644 struct prefix_ipv4 saddr;
1645
1646 /* saddr will be used for determining which routes to split-horizon.
1647 Since the source address we'll pick will be on the same subnet as the
1648 destination, for the purpose of split-horizoning, we'll
1649 pretend that "from" is our source address. */
1650 saddr.family = AF_INET;
1651 saddr.prefixlen = IPV4_MAX_BITLEN;
1652 saddr.prefix = from->sin_addr;
1653
paul718e3742002-12-13 20:15:29 +00001654 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001655 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001656 }
1657 else
1658 {
1659 /* Examine the list of RTEs in the Request one by one. For each
1660 entry, look up the destination in the router's routing
1661 database and, if there is a route, put that route's metric in
1662 the metric field of the RTE. If there is no explicit route
1663 to the specified destination, put infinity in the metric
1664 field. Once all the entries have been filled in, change the
1665 command from Request to Response and send the datagram back
1666 to the requestor. */
1667 p.family = AF_INET;
1668
1669 for (; ((caddr_t) rte) < lim; rte++)
1670 {
1671 p.prefix = rte->prefix;
1672 p.prefixlen = ip_masklen (rte->mask);
1673 apply_mask_ipv4 (&p);
1674
1675 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1676 if (rp)
1677 {
1678 rinfo = rp->info;
1679 rte->metric = htonl (rinfo->metric);
1680 route_unlock_node (rp);
1681 }
1682 else
1683 rte->metric = htonl (RIP_METRIC_INFINITY);
1684 }
1685 packet->command = RIP_RESPONSE;
1686
paulc49ad8f2004-10-22 10:27:28 +00001687 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001688 }
1689 rip_global_queries++;
1690}
1691
1692#if RIP_RECVMSG
1693/* Set IPv6 packet info to the socket. */
1694static int
1695setsockopt_pktinfo (int sock)
1696{
1697 int ret;
1698 int val = 1;
1699
1700 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1701 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001702 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001703 return ret;
1704}
1705
1706/* Read RIP packet by recvmsg function. */
1707int
1708rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1709 int *ifindex)
1710{
1711 int ret;
1712 struct msghdr msg;
1713 struct iovec iov;
1714 struct cmsghdr *ptr;
1715 char adata[1024];
1716
1717 msg.msg_name = (void *) from;
1718 msg.msg_namelen = sizeof (struct sockaddr_in);
1719 msg.msg_iov = &iov;
1720 msg.msg_iovlen = 1;
1721 msg.msg_control = (void *) adata;
1722 msg.msg_controllen = sizeof adata;
1723 iov.iov_base = buf;
1724 iov.iov_len = size;
1725
1726 ret = recvmsg (sock, &msg, 0);
1727 if (ret < 0)
1728 return ret;
1729
ajsb99760a2005-01-04 16:24:43 +00001730 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001731 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1732 {
1733 struct in_pktinfo *pktinfo;
1734 int i;
1735
1736 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1737 i = pktinfo->ipi_ifindex;
1738 }
1739 return ret;
1740}
1741
1742/* RIP packet read function. */
1743int
1744rip_read_new (struct thread *t)
1745{
1746 int ret;
1747 int sock;
1748 char buf[RIP_PACKET_MAXSIZ];
1749 struct sockaddr_in from;
1750 unsigned int ifindex;
1751
1752 /* Fetch socket then register myself. */
1753 sock = THREAD_FD (t);
1754 rip_event (RIP_READ, sock);
1755
1756 /* Read RIP packet. */
1757 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1758 if (ret < 0)
1759 {
ajs6099b3b2004-11-20 02:06:59 +00001760 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001761 return ret;
1762 }
1763
1764 return ret;
1765}
1766#endif /* RIP_RECVMSG */
1767
1768/* First entry point of RIP packet. */
1769int
1770rip_read (struct thread *t)
1771{
1772 int sock;
1773 int ret;
1774 int rtenum;
1775 union rip_buf rip_buf;
1776 struct rip_packet *packet;
1777 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001778 int len;
1779 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001780 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001781 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001782 struct rip_interface *ri;
1783
1784 /* Fetch socket then register myself. */
1785 sock = THREAD_FD (t);
1786 rip->t_read = NULL;
1787
1788 /* Add myself to tne next event */
1789 rip_event (RIP_READ, sock);
1790
1791 /* RIPd manages only IPv4. */
1792 memset (&from, 0, sizeof (struct sockaddr_in));
1793 fromlen = sizeof (struct sockaddr_in);
1794
1795 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1796 (struct sockaddr *) &from, &fromlen);
1797 if (len < 0)
1798 {
ajs6099b3b2004-11-20 02:06:59 +00001799 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001800 return len;
1801 }
1802
1803 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001804 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001805 {
1806 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001807 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001808 return -1;
1809 }
1810
1811 /* Which interface is this packet comes from. */
1812 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001813
paul718e3742002-12-13 20:15:29 +00001814 /* RIP packet received */
1815 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001816 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001817 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1818 ifp ? ifp->name : "unknown");
1819
1820 /* If this packet come from unknown interface, ignore it. */
1821 if (ifp == NULL)
1822 {
ajs766a0ca2004-12-15 14:55:51 +00001823 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1824 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001825 return -1;
1826 }
1827
1828 ifc = connected_lookup_address (ifp, from.sin_addr);
1829
1830 if (ifc == NULL)
1831 {
ajs766a0ca2004-12-15 14:55:51 +00001832 zlog_info ("rip_read: cannot find connected address for packet from %s "
1833 "port %d on interface %s",
1834 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001835 return -1;
1836 }
1837
1838 /* Packet length check. */
1839 if (len < RIP_PACKET_MINSIZ)
1840 {
1841 zlog_warn ("packet size %d is smaller than minimum size %d",
1842 len, RIP_PACKET_MINSIZ);
1843 rip_peer_bad_packet (&from);
1844 return len;
1845 }
1846 if (len > RIP_PACKET_MAXSIZ)
1847 {
1848 zlog_warn ("packet size %d is larger than max size %d",
1849 len, RIP_PACKET_MAXSIZ);
1850 rip_peer_bad_packet (&from);
1851 return len;
1852 }
1853
1854 /* Packet alignment check. */
1855 if ((len - RIP_PACKET_MINSIZ) % 20)
1856 {
1857 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1858 rip_peer_bad_packet (&from);
1859 return len;
1860 }
1861
1862 /* Set RTE number. */
1863 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1864
1865 /* For easy to handle. */
1866 packet = &rip_buf.rip_packet;
1867
1868 /* RIP version check. */
1869 if (packet->version == 0)
1870 {
1871 zlog_info ("version 0 with command %d received.", packet->command);
1872 rip_peer_bad_packet (&from);
1873 return -1;
1874 }
1875
1876 /* Dump RIP packet. */
1877 if (IS_RIP_DEBUG_RECV)
1878 rip_packet_dump (packet, len, "RECV");
1879
1880 /* RIP version adjust. This code should rethink now. RFC1058 says
1881 that "Version 1 implementations are to ignore this extra data and
1882 process only the fields specified in this document.". So RIPv3
1883 packet should be treated as RIPv1 ignoring must be zero field. */
1884 if (packet->version > RIPv2)
1885 packet->version = RIPv2;
1886
1887 /* Is RIP running or is this RIP neighbor ?*/
1888 ri = ifp->info;
1889 if (! ri->running && ! rip_neighbor_lookup (&from))
1890 {
1891 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001892 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001893 rip_peer_bad_packet (&from);
1894 return -1;
1895 }
1896
1897 /* RIP Version check. */
1898 if (packet->command == RIP_RESPONSE)
1899 {
paulf38a4712003-06-07 01:10:00 +00001900 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1901 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001902 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001903 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001904 {
1905 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001906 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001907 packet->version);
1908 rip_peer_bad_packet (&from);
1909 return -1;
1910 }
1911 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001912 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001913 {
1914 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001915 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001916 packet->version);
1917 rip_peer_bad_packet (&from);
1918 return -1;
1919 }
paul718e3742002-12-13 20:15:29 +00001920 }
1921
1922 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1923 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1924 accepted; authenticated RIP-2 messages shall be discarded. */
1925
1926 if ((ri->auth_type == RIP_NO_AUTH)
1927 && rtenum
paulca5e5162004-06-06 22:06:33 +00001928 && (packet->version == RIPv2)
1929 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001930 {
1931 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001932 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001933 packet->version);
1934 rip_peer_bad_packet (&from);
1935 return -1;
1936 }
1937
1938 /* If the router is configured to authenticate RIP-2 messages, then
1939 RIP-1 messages and RIP-2 messages which pass authentication
1940 testing shall be accepted; unauthenticated and failed
1941 authentication RIP-2 messages shall be discarded. For maximum
1942 security, RIP-1 messages should be ignored when authentication is
1943 in use (see section 4.1); otherwise, the routing information from
1944 authenticated messages will be propagated by RIP-1 routers in an
1945 unauthenticated manner. */
1946
1947 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001948 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001949 {
1950 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001951 if (packet->version == RIPv1
1952 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001953 {
1954 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001955 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001956 ("packet RIPv%d is dropped because authentication enabled",
1957 packet->version);
paul718e3742002-12-13 20:15:29 +00001958 rip_peer_bad_packet (&from);
1959 return -1;
1960 }
1961
1962 /* Check RIPv2 authentication. */
1963 if (packet->version == RIPv2)
1964 {
paulca5e5162004-06-06 22:06:33 +00001965 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001966 {
paulca5e5162004-06-06 22:06:33 +00001967 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001968 {
1969 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1970 if (! ret)
1971 {
1972 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001973 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001974 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001975 rip_peer_bad_packet (&from);
1976 return -1;
1977 }
1978 else
1979 {
1980 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001981 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001982 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001983 }
1984 }
paulca5e5162004-06-06 22:06:33 +00001985 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001986 {
paulca5e5162004-06-06 22:06:33 +00001987 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001988 if (! ret)
1989 {
1990 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001991 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001992 rip_peer_bad_packet (&from);
1993 return -1;
1994 }
1995 else
1996 {
1997 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001998 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001999 }
2000 /* Reset RIP packet length to trim MD5 data. */
2001 len = ret;
2002 }
2003 else
2004 {
2005 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002006 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002007 ntohs (packet->rte->tag));
2008 rip_peer_bad_packet (&from);
2009 return -1;
2010 }
2011 }
2012 else
2013 {
2014 /* There is no authentication in the packet. */
2015 if (ri->auth_str || ri->key_chain)
2016 {
2017 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002018 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002019 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002020 rip_peer_bad_packet (&from);
2021 return -1;
2022 }
2023 }
2024 }
2025 }
2026
2027 /* Process each command. */
2028 switch (packet->command)
2029 {
2030 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002031 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002032 break;
2033 case RIP_REQUEST:
2034 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002035 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002036 break;
2037 case RIP_TRACEON:
2038 case RIP_TRACEOFF:
2039 zlog_info ("Obsolete command %s received, please sent it to routed",
2040 lookup (rip_msg, packet->command));
2041 rip_peer_bad_packet (&from);
2042 break;
2043 case RIP_POLL_ENTRY:
2044 zlog_info ("Obsolete command %s received",
2045 lookup (rip_msg, packet->command));
2046 rip_peer_bad_packet (&from);
2047 break;
2048 default:
2049 zlog_info ("Unknown RIP command %d received", packet->command);
2050 rip_peer_bad_packet (&from);
2051 break;
2052 }
2053
2054 return len;
2055}
2056
paul718e3742002-12-13 20:15:29 +00002057/* Write routing table entry to the stream and return next index of
2058 the routing table entry in the stream. */
2059int
2060rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002061 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002062{
2063 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002064
2065 /* Write routing table entry. */
2066 if (version == RIPv1)
2067 {
2068 stream_putw (s, AF_INET);
2069 stream_putw (s, 0);
2070 stream_put_ipv4 (s, p->prefix.s_addr);
2071 stream_put_ipv4 (s, 0);
2072 stream_put_ipv4 (s, 0);
2073 stream_putl (s, rinfo->metric_out);
2074 }
2075 else
2076 {
2077 masklen2ip (p->prefixlen, &mask);
2078
2079 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002080 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002081 stream_put_ipv4 (s, p->prefix.s_addr);
2082 stream_put_ipv4 (s, mask.s_addr);
2083 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2084 stream_putl (s, rinfo->metric_out);
2085 }
2086
2087 return ++num;
2088}
2089
2090/* Send update to the ifp or spcified neighbor. */
2091void
paulc49ad8f2004-10-22 10:27:28 +00002092rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2093 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002094{
2095 int ret;
2096 struct stream *s;
2097 struct route_node *rp;
2098 struct rip_info *rinfo;
2099 struct rip_interface *ri;
2100 struct prefix_ipv4 *p;
2101 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002102 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002103 struct key *key = NULL;
2104 /* this might need to made dynamic if RIP ever supported auth methods
2105 with larger key string sizes */
2106 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2107 size_t doff; /* offset of digest offset field */
paul718e3742002-12-13 20:15:29 +00002108 int num;
2109 int rtemax;
paul01d09082003-06-08 21:22:18 +00002110 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002111
2112 /* Logging output event. */
2113 if (IS_RIP_DEBUG_EVENT)
2114 {
2115 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002116 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002117 else
ajs5d6c3772004-12-08 19:24:06 +00002118 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002119 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002120 }
2121
2122 /* Set output stream. */
2123 s = rip->obuf;
2124
2125 /* Reset stream and RTE counter. */
2126 stream_reset (s);
2127 num = 0;
2128 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2129
2130 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002131 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002132
2133 /* If output interface is in simple password authentication mode, we
2134 need space for authentication data. */
2135 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2136 rtemax -= 1;
2137
2138 /* If output interface is in MD5 authentication mode, we need space
2139 for authentication header and data. */
2140 if (ri->auth_type == RIP_AUTH_MD5)
2141 rtemax -= 2;
2142
2143 /* If output interface is in simple password authentication mode
2144 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002145 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002146 {
2147 if (ri->key_chain)
2148 {
2149 struct keychain *keychain;
2150
2151 keychain = keychain_lookup (ri->key_chain);
2152 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002153 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002154 }
paulb14ee002005-02-04 23:42:41 +00002155 /* to be passed to auth functions later */
2156 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002157 }
2158
paul727d1042002-12-13 20:50:29 +00002159 if (version == RIPv1)
2160 {
paulc49ad8f2004-10-22 10:27:28 +00002161 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002162 apply_classful_mask_ipv4 (&ifaddrclass);
2163 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002164 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002165 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002166 }
2167
paul718e3742002-12-13 20:15:29 +00002168 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2169 if ((rinfo = rp->info) != NULL)
2170 {
paul727d1042002-12-13 20:50:29 +00002171 /* For RIPv1, if we are subnetted, output subnets in our network */
2172 /* that have the same mask as the output "interface". For other */
2173 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002174
2175 if (version == RIPv1)
2176 {
paul727d1042002-12-13 20:50:29 +00002177 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002178
2179 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002180 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002181 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002182
paul727d1042002-12-13 20:50:29 +00002183 if (subnetted &&
2184 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2185 {
paulc49ad8f2004-10-22 10:27:28 +00002186 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002187 (rp->p.prefixlen != 32))
2188 continue;
2189 }
2190 else
2191 {
2192 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2193 apply_classful_mask_ipv4(&classfull);
2194 if (rp->p.u.prefix4.s_addr != 0 &&
2195 classfull.prefixlen != rp->p.prefixlen)
2196 continue;
2197 }
paul718e3742002-12-13 20:15:29 +00002198 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002199 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002200 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002201 }
2202 else
2203 p = (struct prefix_ipv4 *) &rp->p;
2204
2205 /* Apply output filters. */
2206 ret = rip_outgoing_filter (p, ri);
2207 if (ret < 0)
2208 continue;
2209
2210 /* Changed route only output. */
2211 if (route_type == rip_changed_route &&
2212 (! (rinfo->flags & RIP_RTF_CHANGED)))
2213 continue;
2214
2215 /* Split horizon. */
2216 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002217 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002218 {
paul42d14d92003-11-17 09:15:18 +00002219 /*
2220 * We perform split horizon for RIP and connected route.
2221 * For rip routes, we want to suppress the route if we would
2222 * end up sending the route back on the interface that we
2223 * learned it from, with a higher metric. For connected routes,
2224 * we suppress the route if the prefix is a subset of the
2225 * source address that we are going to use for the packet
2226 * (in order to handle the case when multiple subnets are
2227 * configured on the same interface).
2228 */
2229 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002230 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002231 continue;
2232 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002233 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002234 continue;
2235 }
2236
2237 /* Preparation for route-map. */
2238 rinfo->metric_set = 0;
2239 rinfo->nexthop_out.s_addr = 0;
2240 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002241 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002242 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002243
hasso16705132003-05-25 14:49:19 +00002244 /* In order to avoid some local loops,
2245 * if the RIP route has a nexthop via this interface, keep the nexthop,
2246 * otherwise set it to 0. The nexthop should not be propagated
2247 * beyond the local broadcast/multicast area in order
2248 * to avoid an IGP multi-level recursive look-up.
2249 * see (4.4)
2250 */
paulc49ad8f2004-10-22 10:27:28 +00002251 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002252 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002253
2254 /* Interface route-map */
2255 if (ri->routemap[RIP_FILTER_OUT])
2256 {
2257 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2258 (struct prefix *) p, RMAP_RIP,
2259 rinfo);
2260
2261 if (ret == RMAP_DENYMATCH)
2262 {
2263 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002264 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002265 inet_ntoa (p->prefix), p->prefixlen);
2266 continue;
2267 }
2268 }
paul718e3742002-12-13 20:15:29 +00002269
hasso16705132003-05-25 14:49:19 +00002270 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002271 if (rip->route_map[rinfo->type].name
2272 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2273 {
2274 ret = route_map_apply (rip->route_map[rinfo->type].map,
2275 (struct prefix *)p, RMAP_RIP, rinfo);
2276
2277 if (ret == RMAP_DENYMATCH)
2278 {
2279 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002280 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002281 inet_ntoa (p->prefix), p->prefixlen);
2282 continue;
2283 }
2284 }
2285
2286 /* When route-map does not set metric. */
2287 if (! rinfo->metric_set)
2288 {
2289 /* If redistribute metric is set. */
2290 if (rip->route_map[rinfo->type].metric_config
2291 && rinfo->metric != RIP_METRIC_INFINITY)
2292 {
2293 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2294 }
2295 else
2296 {
2297 /* If the route is not connected or localy generated
2298 one, use default-metric value*/
2299 if (rinfo->type != ZEBRA_ROUTE_RIP
2300 && rinfo->type != ZEBRA_ROUTE_CONNECT
2301 && rinfo->metric != RIP_METRIC_INFINITY)
2302 rinfo->metric_out = rip->default_metric;
2303 }
2304 }
2305
2306 /* Apply offset-list */
2307 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002308 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002309
2310 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2311 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002312
2313 /* Perform split-horizon with poisoned reverse
2314 * for RIP and connected routes.
2315 **/
2316 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002317 /*
2318 * We perform split horizon for RIP and connected route.
2319 * For rip routes, we want to suppress the route if we would
2320 * end up sending the route back on the interface that we
2321 * learned it from, with a higher metric. For connected routes,
2322 * we suppress the route if the prefix is a subset of the
2323 * source address that we are going to use for the packet
2324 * (in order to handle the case when multiple subnets are
2325 * configured on the same interface).
2326 */
2327 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002328 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002329 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002330 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002331 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002332 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002333 }
paulb14ee002005-02-04 23:42:41 +00002334
2335 /* Prepare preamble, auth headers, if needs be */
2336 if (num == 0)
2337 {
2338 stream_putc (s, RIP_RESPONSE);
2339 stream_putc (s, version);
2340 stream_putw (s, 0);
2341
paul0cb8a012005-05-29 11:27:24 +00002342 /* auth header for !v1 && !no_auth */
2343 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002344 doff = rip_auth_header_write (s, ri, key, auth_str,
2345 RIP_AUTH_SIMPLE_SIZE);
2346 }
2347
paul718e3742002-12-13 20:15:29 +00002348 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002349 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002350 if (num == rtemax)
2351 {
2352 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002353 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002354
2355 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002356 to, ifc);
paul718e3742002-12-13 20:15:29 +00002357
2358 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2359 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2360 stream_get_endp(s), "SEND");
2361 num = 0;
2362 stream_reset (s);
2363 }
2364 }
2365
2366 /* Flush unwritten RTE. */
2367 if (num != 0)
2368 {
2369 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002370 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002371
paulc49ad8f2004-10-22 10:27:28 +00002372 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002373
2374 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2375 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2376 stream_get_endp (s), "SEND");
2377 num = 0;
2378 stream_reset (s);
2379 }
2380
2381 /* Statistics updates. */
2382 ri->sent_updates++;
2383}
2384
2385/* Send RIP packet to the interface. */
2386void
paulc49ad8f2004-10-22 10:27:28 +00002387rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002388{
paul718e3742002-12-13 20:15:29 +00002389 struct sockaddr_in to;
2390
2391 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002392 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002393 {
2394 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002395 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002396
paulc49ad8f2004-10-22 10:27:28 +00002397 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002398 return;
2399 }
paulc49ad8f2004-10-22 10:27:28 +00002400
paul718e3742002-12-13 20:15:29 +00002401 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002402 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002403 {
paulc49ad8f2004-10-22 10:27:28 +00002404 if (ifc->address->family == AF_INET)
2405 {
2406 /* Destination address and port setting. */
2407 memset (&to, 0, sizeof (struct sockaddr_in));
2408 if (ifc->destination)
2409 /* use specified broadcast or point-to-point destination addr */
2410 to.sin_addr = ifc->destination->u.prefix4;
2411 else
2412 /* calculate the appropriate broadcast address */
2413 to.sin_addr.s_addr =
2414 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2415 ifc->address->prefixlen);
2416 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002417
paulc49ad8f2004-10-22 10:27:28 +00002418 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002419 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002420 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2421 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002422
paulc49ad8f2004-10-22 10:27:28 +00002423 rip_output_process (ifc, &to, route_type, version);
2424 }
paul718e3742002-12-13 20:15:29 +00002425 }
2426}
2427
2428/* Update send to all interface and neighbor. */
2429void
2430rip_update_process (int route_type)
2431{
paul1eb8ef22005-04-07 07:30:20 +00002432 struct listnode *node;
2433 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002434 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002435 struct interface *ifp;
2436 struct rip_interface *ri;
2437 struct route_node *rp;
2438 struct sockaddr_in to;
2439 struct prefix_ipv4 *p;
2440
2441 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002442 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002443 {
paul718e3742002-12-13 20:15:29 +00002444 if (if_is_loopback (ifp))
2445 continue;
2446
paul2e3b2e42002-12-13 21:03:13 +00002447 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002448 continue;
2449
2450 /* Fetch RIP interface information. */
2451 ri = ifp->info;
2452
2453 /* When passive interface is specified, suppress announce to the
2454 interface. */
2455 if (ri->passive)
2456 continue;
2457
2458 if (ri->running)
2459 {
2460 if (IS_RIP_DEBUG_EVENT)
2461 {
2462 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002463 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002464 ifp->name, ifp->ifindex);
2465 else
ajs5d6c3772004-12-08 19:24:06 +00002466 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002467 ifp->ifindex);
2468 }
2469
paulcc1131a2003-10-15 23:20:17 +00002470 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002471 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002472 {
2473 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002474 int done = 0;
2475 /*
2476 * If there is no version configuration in the interface,
2477 * use rip's version setting.
2478 */
paulf38a4712003-06-07 01:10:00 +00002479 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2480 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002481
2482 ifaddr = (struct prefix_ipv4 *) connected->address;
2483
2484 if (ifaddr->family != AF_INET)
2485 continue;
2486
paul931cd542004-01-23 15:31:42 +00002487 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002488 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002489 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002490 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002491 done = 1;
2492 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2493 break;
2494
paulf38a4712003-06-07 01:10:00 +00002495 }
paul718e3742002-12-13 20:15:29 +00002496 }
2497 }
2498
2499 /* RIP send updates to each neighbor. */
2500 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2501 if (rp->info != NULL)
2502 {
2503 p = (struct prefix_ipv4 *) &rp->p;
2504
2505 ifp = if_lookup_address (p->prefix);
2506 if (! ifp)
2507 {
paulc49ad8f2004-10-22 10:27:28 +00002508 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002509 inet_ntoa (p->prefix));
2510 continue;
2511 }
paulc49ad8f2004-10-22 10:27:28 +00002512
2513 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2514 {
2515 zlog_warn ("Neighbor %s doesnt have connected network",
2516 inet_ntoa (p->prefix));
2517 continue;
2518 }
2519
paul718e3742002-12-13 20:15:29 +00002520 /* Set destination address and port */
2521 memset (&to, 0, sizeof (struct sockaddr_in));
2522 to.sin_addr = p->prefix;
2523 to.sin_port = htons (RIP_PORT_DEFAULT);
2524
2525 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002526 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002527 }
2528}
2529
2530/* RIP's periodical timer. */
2531int
2532rip_update (struct thread *t)
2533{
2534 /* Clear timer pointer. */
2535 rip->t_update = NULL;
2536
2537 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002538 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002539
2540 /* Process update output. */
2541 rip_update_process (rip_all_route);
2542
2543 /* Triggered updates may be suppressed if a regular update is due by
2544 the time the triggered update would be sent. */
2545 if (rip->t_triggered_interval)
2546 {
2547 thread_cancel (rip->t_triggered_interval);
2548 rip->t_triggered_interval = NULL;
2549 }
2550 rip->trigger = 0;
2551
2552 /* Register myself. */
2553 rip_event (RIP_UPDATE_EVENT, 0);
2554
2555 return 0;
2556}
2557
2558/* Walk down the RIP routing table then clear changed flag. */
2559void
2560rip_clear_changed_flag ()
2561{
2562 struct route_node *rp;
2563 struct rip_info *rinfo;
2564
2565 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2566 if ((rinfo = rp->info) != NULL)
2567 if (rinfo->flags & RIP_RTF_CHANGED)
2568 rinfo->flags &= ~RIP_RTF_CHANGED;
2569}
2570
2571/* Triggered update interval timer. */
2572int
2573rip_triggered_interval (struct thread *t)
2574{
2575 int rip_triggered_update (struct thread *);
2576
2577 rip->t_triggered_interval = NULL;
2578
2579 if (rip->trigger)
2580 {
2581 rip->trigger = 0;
2582 rip_triggered_update (t);
2583 }
2584 return 0;
2585}
2586
2587/* Execute triggered update. */
2588int
2589rip_triggered_update (struct thread *t)
2590{
2591 int interval;
2592
2593 /* Clear thred pointer. */
2594 rip->t_triggered_update = NULL;
2595
2596 /* Cancel interval timer. */
2597 if (rip->t_triggered_interval)
2598 {
2599 thread_cancel (rip->t_triggered_interval);
2600 rip->t_triggered_interval = NULL;
2601 }
2602 rip->trigger = 0;
2603
2604 /* Logging triggered update. */
2605 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002606 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002607
2608 /* Split Horizon processing is done when generating triggered
2609 updates as well as normal updates (see section 2.6). */
2610 rip_update_process (rip_changed_route);
2611
2612 /* Once all of the triggered updates have been generated, the route
2613 change flags should be cleared. */
2614 rip_clear_changed_flag ();
2615
2616 /* After a triggered update is sent, a timer should be set for a
2617 random interval between 1 and 5 seconds. If other changes that
2618 would trigger updates occur before the timer expires, a single
2619 update is triggered when the timer expires. */
2620 interval = (random () % 5) + 1;
2621
2622 rip->t_triggered_interval =
2623 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2624
2625 return 0;
2626}
2627
2628/* Withdraw redistributed route. */
2629void
2630rip_redistribute_withdraw (int type)
2631{
2632 struct route_node *rp;
2633 struct rip_info *rinfo;
2634
2635 if (!rip)
2636 return;
2637
2638 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2639 if ((rinfo = rp->info) != NULL)
2640 {
2641 if (rinfo->type == type
2642 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2643 {
2644 /* Perform poisoned reverse. */
2645 rinfo->metric = RIP_METRIC_INFINITY;
2646 RIP_TIMER_ON (rinfo->t_garbage_collect,
2647 rip_garbage_collect, rip->garbage_time);
2648 RIP_TIMER_OFF (rinfo->t_timeout);
2649 rinfo->flags |= RIP_RTF_CHANGED;
2650
hasso16705132003-05-25 14:49:19 +00002651 if (IS_RIP_DEBUG_EVENT) {
2652 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2653
ajs5d6c3772004-12-08 19:24:06 +00002654 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002655 inet_ntoa(p->prefix), p->prefixlen,
2656 ifindex2ifname(rinfo->ifindex));
2657 }
2658
paul718e3742002-12-13 20:15:29 +00002659 rip_event (RIP_TRIGGERED_UPDATE, 0);
2660 }
2661 }
2662}
2663
2664/* Create new RIP instance and set it to global variable. */
2665int
2666rip_create ()
2667{
2668 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2669 memset (rip, 0, sizeof (struct rip));
2670
2671 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002672 rip->version_send = RI_RIP_VERSION_2;
2673 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002674 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2675 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2676 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2677 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2678
2679 /* Initialize RIP routig table. */
2680 rip->table = route_table_init ();
2681 rip->route = route_table_init ();
2682 rip->neighbor = route_table_init ();
2683
2684 /* Make output stream. */
2685 rip->obuf = stream_new (1500);
2686
2687 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002688 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002689 if (rip->sock < 0)
2690 return rip->sock;
2691
2692 /* Create read and timer thread. */
2693 rip_event (RIP_READ, rip->sock);
2694 rip_event (RIP_UPDATE_EVENT, 1);
2695
2696 return 0;
2697}
2698
2699/* Sned RIP request to the destination. */
2700int
2701rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002702 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002703{
2704 struct rte *rte;
2705 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002706 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002707
2708 memset (&rip_packet, 0, sizeof (rip_packet));
2709
2710 rip_packet.command = RIP_REQUEST;
2711 rip_packet.version = version;
2712 rte = rip_packet.rte;
2713 rte->metric = htonl (RIP_METRIC_INFINITY);
2714
paul931cd542004-01-23 15:31:42 +00002715 if (connected)
2716 {
2717 /*
2718 * connected is only sent for ripv1 case, or when
2719 * interface does not support multicast. Caller loops
2720 * over each connected address for this case.
2721 */
paul11dde9c2004-05-31 14:00:00 +00002722 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002723 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002724 return -1;
2725 else
2726 return sizeof (rip_packet);
2727 }
2728
paulcc1131a2003-10-15 23:20:17 +00002729 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002730 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002731 {
2732 struct prefix_ipv4 *p;
2733
2734 p = (struct prefix_ipv4 *) connected->address;
2735
2736 if (p->family != AF_INET)
2737 continue;
2738
paul11dde9c2004-05-31 14:00:00 +00002739 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002740 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002741 return -1;
2742 }
2743 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002744}
2745
2746int
2747rip_update_jitter (unsigned long time)
2748{
paul239389b2004-05-05 14:09:37 +00002749#define JITTER_BOUND 4
2750 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2751 Given that, we cannot let time be less than JITTER_BOUND seconds.
2752 The RIPv2 RFC says jitter should be small compared to
2753 update_time. We consider 1/JITTER_BOUND to be small.
2754 */
2755
2756 int jitter_input = time;
2757 int jitter;
2758
2759 if (jitter_input < JITTER_BOUND)
2760 jitter_input = JITTER_BOUND;
2761
2762 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2763
2764 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002765}
2766
2767void
2768rip_event (enum rip_event event, int sock)
2769{
2770 int jitter = 0;
2771
2772 switch (event)
2773 {
2774 case RIP_READ:
2775 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2776 break;
2777 case RIP_UPDATE_EVENT:
2778 if (rip->t_update)
2779 {
2780 thread_cancel (rip->t_update);
2781 rip->t_update = NULL;
2782 }
2783 jitter = rip_update_jitter (rip->update_time);
2784 rip->t_update =
2785 thread_add_timer (master, rip_update, NULL,
2786 sock ? 2 : rip->update_time + jitter);
2787 break;
2788 case RIP_TRIGGERED_UPDATE:
2789 if (rip->t_triggered_interval)
2790 rip->trigger = 1;
2791 else if (! rip->t_triggered_update)
2792 rip->t_triggered_update =
2793 thread_add_event (master, rip_triggered_update, NULL, 0);
2794 break;
2795 default:
2796 break;
2797 }
2798}
2799
2800DEFUN (router_rip,
2801 router_rip_cmd,
2802 "router rip",
2803 "Enable a routing process\n"
2804 "Routing Information Protocol (RIP)\n")
2805{
2806 int ret;
2807
2808 /* If rip is not enabled before. */
2809 if (! rip)
2810 {
2811 ret = rip_create ();
2812 if (ret < 0)
2813 {
2814 zlog_info ("Can't create RIP");
2815 return CMD_WARNING;
2816 }
2817 }
2818 vty->node = RIP_NODE;
2819 vty->index = rip;
2820
2821 return CMD_SUCCESS;
2822}
2823
2824DEFUN (no_router_rip,
2825 no_router_rip_cmd,
2826 "no router rip",
2827 NO_STR
2828 "Enable a routing process\n"
2829 "Routing Information Protocol (RIP)\n")
2830{
2831 if (rip)
2832 rip_clean ();
2833 return CMD_SUCCESS;
2834}
2835
2836DEFUN (rip_version,
2837 rip_version_cmd,
2838 "version <1-2>",
2839 "Set routing protocol version\n"
2840 "version\n")
2841{
2842 int version;
2843
2844 version = atoi (argv[0]);
2845 if (version != RIPv1 && version != RIPv2)
2846 {
2847 vty_out (vty, "invalid rip version %d%s", version,
2848 VTY_NEWLINE);
2849 return CMD_WARNING;
2850 }
paulf38a4712003-06-07 01:10:00 +00002851 rip->version_send = version;
2852 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002853
2854 return CMD_SUCCESS;
2855}
2856
2857DEFUN (no_rip_version,
2858 no_rip_version_cmd,
2859 "no version",
2860 NO_STR
2861 "Set routing protocol version\n")
2862{
2863 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002864 rip->version_send = RI_RIP_VERSION_2;
2865 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002866
2867 return CMD_SUCCESS;
2868}
2869
2870ALIAS (no_rip_version,
2871 no_rip_version_val_cmd,
2872 "no version <1-2>",
2873 NO_STR
2874 "Set routing protocol version\n"
2875 "version\n")
2876
2877DEFUN (rip_route,
2878 rip_route_cmd,
2879 "route A.B.C.D/M",
2880 "RIP static route configuration\n"
2881 "IP prefix <network>/<length>\n")
2882{
2883 int ret;
2884 struct prefix_ipv4 p;
2885 struct route_node *node;
2886
2887 ret = str2prefix_ipv4 (argv[0], &p);
2888 if (ret < 0)
2889 {
2890 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2891 return CMD_WARNING;
2892 }
2893 apply_mask_ipv4 (&p);
2894
2895 /* For router rip configuration. */
2896 node = route_node_get (rip->route, (struct prefix *) &p);
2897
2898 if (node->info)
2899 {
2900 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2901 route_unlock_node (node);
2902 return CMD_WARNING;
2903 }
2904
hasso8a676be2004-10-08 06:36:38 +00002905 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002906
2907 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2908
2909 return CMD_SUCCESS;
2910}
2911
2912DEFUN (no_rip_route,
2913 no_rip_route_cmd,
2914 "no route A.B.C.D/M",
2915 NO_STR
2916 "RIP static route configuration\n"
2917 "IP prefix <network>/<length>\n")
2918{
2919 int ret;
2920 struct prefix_ipv4 p;
2921 struct route_node *node;
2922
2923 ret = str2prefix_ipv4 (argv[0], &p);
2924 if (ret < 0)
2925 {
2926 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2927 return CMD_WARNING;
2928 }
2929 apply_mask_ipv4 (&p);
2930
2931 /* For router rip configuration. */
2932 node = route_node_lookup (rip->route, (struct prefix *) &p);
2933 if (! node)
2934 {
2935 vty_out (vty, "Can't find route %s.%s", argv[0],
2936 VTY_NEWLINE);
2937 return CMD_WARNING;
2938 }
2939
2940 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2941 route_unlock_node (node);
2942
2943 node->info = NULL;
2944 route_unlock_node (node);
2945
2946 return CMD_SUCCESS;
2947}
2948
2949void
2950rip_update_default_metric ()
2951{
2952 struct route_node *np;
2953 struct rip_info *rinfo;
2954
2955 for (np = route_top (rip->table); np; np = route_next (np))
2956 if ((rinfo = np->info) != NULL)
2957 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2958 rinfo->metric = rip->default_metric;
2959}
2960
2961DEFUN (rip_default_metric,
2962 rip_default_metric_cmd,
2963 "default-metric <1-16>",
2964 "Set a metric of redistribute routes\n"
2965 "Default metric\n")
2966{
2967 if (rip)
2968 {
2969 rip->default_metric = atoi (argv[0]);
2970 /* rip_update_default_metric (); */
2971 }
2972 return CMD_SUCCESS;
2973}
2974
2975DEFUN (no_rip_default_metric,
2976 no_rip_default_metric_cmd,
2977 "no default-metric",
2978 NO_STR
2979 "Set a metric of redistribute routes\n"
2980 "Default metric\n")
2981{
2982 if (rip)
2983 {
2984 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2985 /* rip_update_default_metric (); */
2986 }
2987 return CMD_SUCCESS;
2988}
2989
2990ALIAS (no_rip_default_metric,
2991 no_rip_default_metric_val_cmd,
2992 "no default-metric <1-16>",
2993 NO_STR
2994 "Set a metric of redistribute routes\n"
2995 "Default metric\n")
2996
2997DEFUN (rip_timers,
2998 rip_timers_cmd,
2999 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3000 "Adjust routing timers\n"
3001 "Basic routing protocol update timers\n"
3002 "Routing table update timer value in second. Default is 30.\n"
3003 "Routing information timeout timer. Default is 180.\n"
3004 "Garbage collection timer. Default is 120.\n")
3005{
3006 unsigned long update;
3007 unsigned long timeout;
3008 unsigned long garbage;
3009 char *endptr = NULL;
3010 unsigned long RIP_TIMER_MAX = 2147483647;
3011 unsigned long RIP_TIMER_MIN = 5;
3012
3013 update = strtoul (argv[0], &endptr, 10);
3014 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3015 {
3016 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3017 return CMD_WARNING;
3018 }
3019
3020 timeout = strtoul (argv[1], &endptr, 10);
3021 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3022 {
3023 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3024 return CMD_WARNING;
3025 }
3026
3027 garbage = strtoul (argv[2], &endptr, 10);
3028 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3029 {
3030 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033
3034 /* Set each timer value. */
3035 rip->update_time = update;
3036 rip->timeout_time = timeout;
3037 rip->garbage_time = garbage;
3038
3039 /* Reset update timer thread. */
3040 rip_event (RIP_UPDATE_EVENT, 0);
3041
3042 return CMD_SUCCESS;
3043}
3044
3045DEFUN (no_rip_timers,
3046 no_rip_timers_cmd,
3047 "no timers basic",
3048 NO_STR
3049 "Adjust routing timers\n"
3050 "Basic routing protocol update timers\n")
3051{
3052 /* Set each timer value to the default. */
3053 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3054 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3055 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3056
3057 /* Reset update timer thread. */
3058 rip_event (RIP_UPDATE_EVENT, 0);
3059
3060 return CMD_SUCCESS;
3061}
hasso16705132003-05-25 14:49:19 +00003062
3063ALIAS (no_rip_timers,
3064 no_rip_timers_val_cmd,
3065 "no timers basic <0-65535> <0-65535> <0-65535>",
3066 NO_STR
3067 "Adjust routing timers\n"
3068 "Basic routing protocol update timers\n"
3069 "Routing table update timer value in second. Default is 30.\n"
3070 "Routing information timeout timer. Default is 180.\n"
3071 "Garbage collection timer. Default is 120.\n")
3072
paul718e3742002-12-13 20:15:29 +00003073
3074struct route_table *rip_distance_table;
3075
3076struct rip_distance
3077{
3078 /* Distance value for the IP source prefix. */
3079 u_char distance;
3080
3081 /* Name of the access-list to be matched. */
3082 char *access_list;
3083};
3084
3085struct rip_distance *
3086rip_distance_new ()
3087{
3088 struct rip_distance *new;
3089 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3090 memset (new, 0, sizeof (struct rip_distance));
3091 return new;
3092}
3093
3094void
3095rip_distance_free (struct rip_distance *rdistance)
3096{
3097 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3098}
3099
3100int
hasso98b718a2004-10-11 12:57:57 +00003101rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3102 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003103{
3104 int ret;
3105 struct prefix_ipv4 p;
3106 u_char distance;
3107 struct route_node *rn;
3108 struct rip_distance *rdistance;
3109
3110 ret = str2prefix_ipv4 (ip_str, &p);
3111 if (ret == 0)
3112 {
3113 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3114 return CMD_WARNING;
3115 }
3116
3117 distance = atoi (distance_str);
3118
3119 /* Get RIP distance node. */
3120 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3121 if (rn->info)
3122 {
3123 rdistance = rn->info;
3124 route_unlock_node (rn);
3125 }
3126 else
3127 {
3128 rdistance = rip_distance_new ();
3129 rn->info = rdistance;
3130 }
3131
3132 /* Set distance value. */
3133 rdistance->distance = distance;
3134
3135 /* Reset access-list configuration. */
3136 if (rdistance->access_list)
3137 {
3138 free (rdistance->access_list);
3139 rdistance->access_list = NULL;
3140 }
3141 if (access_list_str)
3142 rdistance->access_list = strdup (access_list_str);
3143
3144 return CMD_SUCCESS;
3145}
3146
3147int
hasso98b718a2004-10-11 12:57:57 +00003148rip_distance_unset (struct vty *vty, const char *distance_str,
3149 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003150{
3151 int ret;
3152 struct prefix_ipv4 p;
3153 u_char distance;
3154 struct route_node *rn;
3155 struct rip_distance *rdistance;
3156
3157 ret = str2prefix_ipv4 (ip_str, &p);
3158 if (ret == 0)
3159 {
3160 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3161 return CMD_WARNING;
3162 }
3163
3164 distance = atoi (distance_str);
3165
3166 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3167 if (! rn)
3168 {
3169 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3170 return CMD_WARNING;
3171 }
3172
3173 rdistance = rn->info;
3174
3175 if (rdistance->access_list)
3176 free (rdistance->access_list);
3177 rip_distance_free (rdistance);
3178
3179 rn->info = NULL;
3180 route_unlock_node (rn);
3181 route_unlock_node (rn);
3182
3183 return CMD_SUCCESS;
3184}
3185
3186void
3187rip_distance_reset ()
3188{
3189 struct route_node *rn;
3190 struct rip_distance *rdistance;
3191
3192 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3193 if ((rdistance = rn->info) != NULL)
3194 {
3195 if (rdistance->access_list)
3196 free (rdistance->access_list);
3197 rip_distance_free (rdistance);
3198 rn->info = NULL;
3199 route_unlock_node (rn);
3200 }
3201}
3202
3203/* Apply RIP information to distance method. */
3204u_char
3205rip_distance_apply (struct rip_info *rinfo)
3206{
3207 struct route_node *rn;
3208 struct prefix_ipv4 p;
3209 struct rip_distance *rdistance;
3210 struct access_list *alist;
3211
3212 if (! rip)
3213 return 0;
3214
3215 memset (&p, 0, sizeof (struct prefix_ipv4));
3216 p.family = AF_INET;
3217 p.prefix = rinfo->from;
3218 p.prefixlen = IPV4_MAX_BITLEN;
3219
3220 /* Check source address. */
3221 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3222 if (rn)
3223 {
3224 rdistance = rn->info;
3225 route_unlock_node (rn);
3226
3227 if (rdistance->access_list)
3228 {
3229 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3230 if (alist == NULL)
3231 return 0;
3232 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3233 return 0;
3234
3235 return rdistance->distance;
3236 }
3237 else
3238 return rdistance->distance;
3239 }
3240
3241 if (rip->distance)
3242 return rip->distance;
3243
3244 return 0;
3245}
3246
3247void
3248rip_distance_show (struct vty *vty)
3249{
3250 struct route_node *rn;
3251 struct rip_distance *rdistance;
3252 int header = 1;
3253 char buf[BUFSIZ];
3254
3255 vty_out (vty, " Distance: (default is %d)%s",
3256 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3257 VTY_NEWLINE);
3258
3259 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3260 if ((rdistance = rn->info) != NULL)
3261 {
3262 if (header)
3263 {
3264 vty_out (vty, " Address Distance List%s",
3265 VTY_NEWLINE);
3266 header = 0;
3267 }
3268 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3269 vty_out (vty, " %-20s %4d %s%s",
3270 buf, rdistance->distance,
3271 rdistance->access_list ? rdistance->access_list : "",
3272 VTY_NEWLINE);
3273 }
3274}
3275
3276DEFUN (rip_distance,
3277 rip_distance_cmd,
3278 "distance <1-255>",
3279 "Administrative distance\n"
3280 "Distance value\n")
3281{
3282 rip->distance = atoi (argv[0]);
3283 return CMD_SUCCESS;
3284}
3285
3286DEFUN (no_rip_distance,
3287 no_rip_distance_cmd,
3288 "no distance <1-255>",
3289 NO_STR
3290 "Administrative distance\n"
3291 "Distance value\n")
3292{
3293 rip->distance = 0;
3294 return CMD_SUCCESS;
3295}
3296
3297DEFUN (rip_distance_source,
3298 rip_distance_source_cmd,
3299 "distance <1-255> A.B.C.D/M",
3300 "Administrative distance\n"
3301 "Distance value\n"
3302 "IP source prefix\n")
3303{
3304 rip_distance_set (vty, argv[0], argv[1], NULL);
3305 return CMD_SUCCESS;
3306}
3307
3308DEFUN (no_rip_distance_source,
3309 no_rip_distance_source_cmd,
3310 "no distance <1-255> A.B.C.D/M",
3311 NO_STR
3312 "Administrative distance\n"
3313 "Distance value\n"
3314 "IP source prefix\n")
3315{
3316 rip_distance_unset (vty, argv[0], argv[1], NULL);
3317 return CMD_SUCCESS;
3318}
3319
3320DEFUN (rip_distance_source_access_list,
3321 rip_distance_source_access_list_cmd,
3322 "distance <1-255> A.B.C.D/M WORD",
3323 "Administrative distance\n"
3324 "Distance value\n"
3325 "IP source prefix\n"
3326 "Access list name\n")
3327{
3328 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3329 return CMD_SUCCESS;
3330}
3331
3332DEFUN (no_rip_distance_source_access_list,
3333 no_rip_distance_source_access_list_cmd,
3334 "no distance <1-255> A.B.C.D/M WORD",
3335 NO_STR
3336 "Administrative distance\n"
3337 "Distance value\n"
3338 "IP source prefix\n"
3339 "Access list name\n")
3340{
3341 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3342 return CMD_SUCCESS;
3343}
3344
3345/* Print out routes update time. */
3346void
3347rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3348{
3349 struct timeval timer_now;
3350 time_t clock;
3351 struct tm *tm;
3352#define TIME_BUF 25
3353 char timebuf [TIME_BUF];
3354 struct thread *thread;
3355
3356 gettimeofday (&timer_now, NULL);
3357
3358 if ((thread = rinfo->t_timeout) != NULL)
3359 {
3360 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3361 tm = gmtime (&clock);
3362 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3363 vty_out (vty, "%5s", timebuf);
3364 }
3365 else if ((thread = rinfo->t_garbage_collect) != 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}
3373
hasso8a676be2004-10-08 06:36:38 +00003374const char *
paul718e3742002-12-13 20:15:29 +00003375rip_route_type_print (int sub_type)
3376{
3377 switch (sub_type)
3378 {
3379 case RIP_ROUTE_RTE:
3380 return "n";
3381 case RIP_ROUTE_STATIC:
3382 return "s";
3383 case RIP_ROUTE_DEFAULT:
3384 return "d";
3385 case RIP_ROUTE_REDISTRIBUTE:
3386 return "r";
3387 case RIP_ROUTE_INTERFACE:
3388 return "i";
3389 default:
3390 return "?";
3391 }
3392}
3393
3394DEFUN (show_ip_rip,
3395 show_ip_rip_cmd,
3396 "show ip rip",
3397 SHOW_STR
3398 IP_STR
3399 "Show RIP routes\n")
3400{
3401 struct route_node *np;
3402 struct rip_info *rinfo;
3403
3404 if (! rip)
3405 return CMD_SUCCESS;
3406
hasso16705132003-05-25 14:49:19 +00003407 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3408 "Sub-codes:%s"
3409 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003410 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003411 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003412 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003413
3414 for (np = route_top (rip->table); np; np = route_next (np))
3415 if ((rinfo = np->info) != NULL)
3416 {
3417 int len;
3418
3419 len = vty_out (vty, "%s(%s) %s/%d",
3420 /* np->lock, For debugging. */
3421 route_info[rinfo->type].str,
3422 rip_route_type_print (rinfo->sub_type),
3423 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3424
hassoa1455d82004-03-03 19:36:24 +00003425 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003426
3427 if (len > 0)
3428 vty_out (vty, "%*s", len, " ");
3429
3430 if (rinfo->nexthop.s_addr)
3431 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3432 rinfo->metric);
3433 else
3434 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3435
3436 /* Route which exist in kernel routing table. */
3437 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3438 (rinfo->sub_type == RIP_ROUTE_RTE))
3439 {
3440 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003441 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003442 rip_vty_out_uptime (vty, rinfo);
3443 }
3444 else if (rinfo->metric == RIP_METRIC_INFINITY)
3445 {
3446 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003447 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003448 rip_vty_out_uptime (vty, rinfo);
3449 }
3450 else
hasso16705132003-05-25 14:49:19 +00003451 {
3452 vty_out (vty, "self ");
3453 vty_out (vty, "%3d", rinfo->tag);
3454 }
paul718e3742002-12-13 20:15:29 +00003455
3456 vty_out (vty, "%s", VTY_NEWLINE);
3457 }
3458 return CMD_SUCCESS;
3459}
3460
3461/* Return next event time. */
3462int
3463rip_next_thread_timer (struct thread *thread)
3464{
3465 struct timeval timer_now;
3466
3467 gettimeofday (&timer_now, NULL);
3468
3469 return thread->u.sands.tv_sec - timer_now.tv_sec;
3470}
3471
hasso16705132003-05-25 14:49:19 +00003472/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3473DEFUN (show_ip_rip_status,
3474 show_ip_rip_status_cmd,
3475 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003476 SHOW_STR
3477 IP_STR
hasso16705132003-05-25 14:49:19 +00003478 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003479 "IP routing protocol process parameters and statistics\n")
3480{
hasso52dc7ee2004-09-23 19:18:23 +00003481 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003482 struct interface *ifp;
3483 struct rip_interface *ri;
3484 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003485 const char *send_version;
3486 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003487
3488 if (! rip)
3489 return CMD_SUCCESS;
3490
3491 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3492 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3493 rip->update_time);
3494 vty_out (vty, " next due in %d seconds%s",
3495 rip_next_thread_timer (rip->t_update),
3496 VTY_NEWLINE);
3497 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3498 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3499 VTY_NEWLINE);
3500
3501 /* Filtering status show. */
3502 config_show_distribute (vty);
3503
3504 /* Default metric information. */
3505 vty_out (vty, " Default redistribution metric is %d%s",
3506 rip->default_metric, VTY_NEWLINE);
3507
3508 /* Redistribute information. */
3509 vty_out (vty, " Redistributing:");
3510 config_write_rip_redistribute (vty, 0);
3511 vty_out (vty, "%s", VTY_NEWLINE);
3512
paulf38a4712003-06-07 01:10:00 +00003513 vty_out (vty, " Default version control: send version %s,",
3514 lookup(ri_version_msg,rip->version_send));
3515 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3516 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3517 else
3518 vty_out (vty, " receive version %s %s",
3519 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003520
3521 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3522
paul1eb8ef22005-04-07 07:30:20 +00003523 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003524 {
paul718e3742002-12-13 20:15:29 +00003525 ri = ifp->info;
3526
3527 if (ri->enable_network || ri->enable_interface)
3528 {
3529 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003530 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003531 else
3532 send_version = lookup (ri_version_msg, ri->ri_send);
3533
3534 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003535 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003536 else
3537 receive_version = lookup (ri_version_msg, ri->ri_receive);
3538
3539 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3540 send_version,
3541 receive_version,
3542 ri->key_chain ? ri->key_chain : "",
3543 VTY_NEWLINE);
3544 }
3545 }
3546
3547 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3548 config_write_rip_network (vty, 0);
3549
paul4aaff3f2003-06-07 01:04:45 +00003550 {
3551 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003552 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003553 {
paul4aaff3f2003-06-07 01:04:45 +00003554 ri = ifp->info;
3555
3556 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3557 {
3558 if (!found_passive)
3559 {
3560 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3561 found_passive = 1;
3562 }
3563 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3564 }
3565 }
3566 }
3567
paul718e3742002-12-13 20:15:29 +00003568 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3569 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3570 rip_peer_display (vty);
3571
3572 rip_distance_show (vty);
3573
3574 return CMD_SUCCESS;
3575}
3576
3577/* RIP configuration write function. */
3578int
3579config_write_rip (struct vty *vty)
3580{
3581 int write = 0;
3582 struct route_node *rn;
3583 struct rip_distance *rdistance;
3584
3585 if (rip)
3586 {
3587 /* Router RIP statement. */
3588 vty_out (vty, "router rip%s", VTY_NEWLINE);
3589 write++;
3590
3591 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003592 if (rip->version_send != RI_RIP_VERSION_2
3593 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3594 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003595 VTY_NEWLINE);
3596
3597 /* RIP timer configuration. */
3598 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3599 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3600 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3601 vty_out (vty, " timers basic %lu %lu %lu%s",
3602 rip->update_time,
3603 rip->timeout_time,
3604 rip->garbage_time,
3605 VTY_NEWLINE);
3606
3607 /* Default information configuration. */
3608 if (rip->default_information)
3609 {
3610 if (rip->default_information_route_map)
3611 vty_out (vty, " default-information originate route-map %s%s",
3612 rip->default_information_route_map, VTY_NEWLINE);
3613 else
3614 vty_out (vty, " default-information originate%s",
3615 VTY_NEWLINE);
3616 }
3617
3618 /* Redistribute configuration. */
3619 config_write_rip_redistribute (vty, 1);
3620
3621 /* RIP offset-list configuration. */
3622 config_write_rip_offset_list (vty);
3623
3624 /* RIP enabled network and interface configuration. */
3625 config_write_rip_network (vty, 1);
3626
3627 /* RIP default metric configuration */
3628 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3629 vty_out (vty, " default-metric %d%s",
3630 rip->default_metric, VTY_NEWLINE);
3631
3632 /* Distribute configuration. */
3633 write += config_write_distribute (vty);
3634
hasso16705132003-05-25 14:49:19 +00003635 /* Interface routemap configuration */
3636 write += config_write_if_rmap (vty);
3637
paul718e3742002-12-13 20:15:29 +00003638 /* Distance configuration. */
3639 if (rip->distance)
3640 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3641
3642 /* RIP source IP prefix distance configuration. */
3643 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3644 if ((rdistance = rn->info) != NULL)
3645 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3646 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3647 rdistance->access_list ? rdistance->access_list : "",
3648 VTY_NEWLINE);
3649
3650 /* RIP static route configuration. */
3651 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3652 if (rn->info)
3653 vty_out (vty, " route %s/%d%s",
3654 inet_ntoa (rn->p.u.prefix4),
3655 rn->p.prefixlen,
3656 VTY_NEWLINE);
3657
3658 }
3659 return write;
3660}
3661
3662/* RIP node structure. */
3663struct cmd_node rip_node =
3664{
3665 RIP_NODE,
3666 "%s(config-router)# ",
3667 1
3668};
3669
3670/* Distribute-list update functions. */
3671void
3672rip_distribute_update (struct distribute *dist)
3673{
3674 struct interface *ifp;
3675 struct rip_interface *ri;
3676 struct access_list *alist;
3677 struct prefix_list *plist;
3678
3679 if (! dist->ifname)
3680 return;
3681
3682 ifp = if_lookup_by_name (dist->ifname);
3683 if (ifp == NULL)
3684 return;
3685
3686 ri = ifp->info;
3687
3688 if (dist->list[DISTRIBUTE_IN])
3689 {
3690 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3691 if (alist)
3692 ri->list[RIP_FILTER_IN] = alist;
3693 else
3694 ri->list[RIP_FILTER_IN] = NULL;
3695 }
3696 else
3697 ri->list[RIP_FILTER_IN] = NULL;
3698
3699 if (dist->list[DISTRIBUTE_OUT])
3700 {
3701 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3702 if (alist)
3703 ri->list[RIP_FILTER_OUT] = alist;
3704 else
3705 ri->list[RIP_FILTER_OUT] = NULL;
3706 }
3707 else
3708 ri->list[RIP_FILTER_OUT] = NULL;
3709
3710 if (dist->prefix[DISTRIBUTE_IN])
3711 {
3712 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3713 if (plist)
3714 ri->prefix[RIP_FILTER_IN] = plist;
3715 else
3716 ri->prefix[RIP_FILTER_IN] = NULL;
3717 }
3718 else
3719 ri->prefix[RIP_FILTER_IN] = NULL;
3720
3721 if (dist->prefix[DISTRIBUTE_OUT])
3722 {
3723 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3724 if (plist)
3725 ri->prefix[RIP_FILTER_OUT] = plist;
3726 else
3727 ri->prefix[RIP_FILTER_OUT] = NULL;
3728 }
3729 else
3730 ri->prefix[RIP_FILTER_OUT] = NULL;
3731}
3732
3733void
3734rip_distribute_update_interface (struct interface *ifp)
3735{
3736 struct distribute *dist;
3737
3738 dist = distribute_lookup (ifp->name);
3739 if (dist)
3740 rip_distribute_update (dist);
3741}
3742
3743/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003744/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003745void
paul02ff83c2004-06-11 11:27:03 +00003746rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003747{
3748 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003749 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003750
paul1eb8ef22005-04-07 07:30:20 +00003751 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3752 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003753}
paul11dde9c2004-05-31 14:00:00 +00003754/* ARGSUSED */
3755void
3756rip_distribute_update_all_wrapper(struct access_list *notused)
3757{
paul02ff83c2004-06-11 11:27:03 +00003758 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003759}
paul718e3742002-12-13 20:15:29 +00003760
3761/* Delete all added rip route. */
3762void
3763rip_clean ()
3764{
3765 int i;
3766 struct route_node *rp;
3767 struct rip_info *rinfo;
3768
3769 if (rip)
3770 {
3771 /* Clear RIP routes */
3772 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3773 if ((rinfo = rp->info) != NULL)
3774 {
3775 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3776 rinfo->sub_type == RIP_ROUTE_RTE)
3777 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3778 &rinfo->nexthop, rinfo->metric);
3779
3780 RIP_TIMER_OFF (rinfo->t_timeout);
3781 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3782
3783 rp->info = NULL;
3784 route_unlock_node (rp);
3785
3786 rip_info_free (rinfo);
3787 }
3788
3789 /* Cancel RIP related timers. */
3790 RIP_TIMER_OFF (rip->t_update);
3791 RIP_TIMER_OFF (rip->t_triggered_update);
3792 RIP_TIMER_OFF (rip->t_triggered_interval);
3793
3794 /* Cancel read thread. */
3795 if (rip->t_read)
3796 {
3797 thread_cancel (rip->t_read);
3798 rip->t_read = NULL;
3799 }
3800
3801 /* Close RIP socket. */
3802 if (rip->sock >= 0)
3803 {
3804 close (rip->sock);
3805 rip->sock = -1;
3806 }
3807
3808 /* Static RIP route configuration. */
3809 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3810 if (rp->info)
3811 {
3812 rp->info = NULL;
3813 route_unlock_node (rp);
3814 }
3815
3816 /* RIP neighbor configuration. */
3817 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3818 if (rp->info)
3819 {
3820 rp->info = NULL;
3821 route_unlock_node (rp);
3822 }
3823
3824 /* Redistribute related clear. */
3825 if (rip->default_information_route_map)
3826 free (rip->default_information_route_map);
3827
3828 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3829 if (rip->route_map[i].name)
3830 free (rip->route_map[i].name);
3831
3832 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3833 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3834 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3835
3836 XFREE (MTYPE_RIP, rip);
3837 rip = NULL;
3838 }
3839
3840 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003841 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003842 rip_offset_clean ();
3843 rip_interface_clean ();
3844 rip_distance_reset ();
3845 rip_redistribute_clean ();
3846}
3847
3848/* Reset all values to the default settings. */
3849void
3850rip_reset ()
3851{
3852 /* Reset global counters. */
3853 rip_global_route_changes = 0;
3854 rip_global_queries = 0;
3855
3856 /* Call ripd related reset functions. */
3857 rip_debug_reset ();
3858 rip_route_map_reset ();
3859
3860 /* Call library reset functions. */
3861 vty_reset ();
3862 access_list_reset ();
3863 prefix_list_reset ();
3864
3865 distribute_list_reset ();
3866
3867 rip_interface_reset ();
3868 rip_distance_reset ();
3869
3870 rip_zclient_reset ();
3871}
3872
hasso16705132003-05-25 14:49:19 +00003873void
3874rip_if_rmap_update (struct if_rmap *if_rmap)
3875{
3876 struct interface *ifp;
3877 struct rip_interface *ri;
3878 struct route_map *rmap;
3879
3880 ifp = if_lookup_by_name (if_rmap->ifname);
3881 if (ifp == NULL)
3882 return;
3883
3884 ri = ifp->info;
3885
3886 if (if_rmap->routemap[IF_RMAP_IN])
3887 {
3888 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3889 if (rmap)
3890 ri->routemap[IF_RMAP_IN] = rmap;
3891 else
3892 ri->routemap[IF_RMAP_IN] = NULL;
3893 }
3894 else
3895 ri->routemap[RIP_FILTER_IN] = NULL;
3896
3897 if (if_rmap->routemap[IF_RMAP_OUT])
3898 {
3899 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3900 if (rmap)
3901 ri->routemap[IF_RMAP_OUT] = rmap;
3902 else
3903 ri->routemap[IF_RMAP_OUT] = NULL;
3904 }
3905 else
3906 ri->routemap[RIP_FILTER_OUT] = NULL;
3907}
3908
3909void
3910rip_if_rmap_update_interface (struct interface *ifp)
3911{
3912 struct if_rmap *if_rmap;
3913
3914 if_rmap = if_rmap_lookup (ifp->name);
3915 if (if_rmap)
3916 rip_if_rmap_update (if_rmap);
3917}
3918
3919void
3920rip_routemap_update_redistribute (void)
3921{
3922 int i;
3923
3924 if (rip)
3925 {
3926 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3927 {
3928 if (rip->route_map[i].name)
3929 rip->route_map[i].map =
3930 route_map_lookup_by_name (rip->route_map[i].name);
3931 }
3932 }
3933}
3934
paul11dde9c2004-05-31 14:00:00 +00003935/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003936void
hasso98b718a2004-10-11 12:57:57 +00003937rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003938{
3939 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003940 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003941
paul1eb8ef22005-04-07 07:30:20 +00003942 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3943 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003944
3945 rip_routemap_update_redistribute ();
3946}
3947
paul718e3742002-12-13 20:15:29 +00003948/* Allocate new rip structure and set default value. */
3949void
3950rip_init ()
3951{
3952 /* Randomize for triggered update random(). */
3953 srand (time (NULL));
3954
3955 /* Install top nodes. */
3956 install_node (&rip_node, config_write_rip);
3957
3958 /* Install rip commands. */
3959 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003960 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003961 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003962 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003963 install_element (CONFIG_NODE, &router_rip_cmd);
3964 install_element (CONFIG_NODE, &no_router_rip_cmd);
3965
3966 install_default (RIP_NODE);
3967 install_element (RIP_NODE, &rip_version_cmd);
3968 install_element (RIP_NODE, &no_rip_version_cmd);
3969 install_element (RIP_NODE, &no_rip_version_val_cmd);
3970 install_element (RIP_NODE, &rip_default_metric_cmd);
3971 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3972 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3973 install_element (RIP_NODE, &rip_timers_cmd);
3974 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003975 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003976 install_element (RIP_NODE, &rip_route_cmd);
3977 install_element (RIP_NODE, &no_rip_route_cmd);
3978 install_element (RIP_NODE, &rip_distance_cmd);
3979 install_element (RIP_NODE, &no_rip_distance_cmd);
3980 install_element (RIP_NODE, &rip_distance_source_cmd);
3981 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3982 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3983 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3984
3985 /* Debug related init. */
3986 rip_debug_init ();
3987
paul718e3742002-12-13 20:15:29 +00003988 /* SNMP init. */
3989#ifdef HAVE_SNMP
3990 rip_snmp_init ();
3991#endif /* HAVE_SNMP */
3992
3993 /* Access list install. */
3994 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00003995 access_list_add_hook (rip_distribute_update_all_wrapper);
3996 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00003997
3998 /* Prefix list initialize.*/
3999 prefix_list_init ();
4000 prefix_list_add_hook (rip_distribute_update_all);
4001 prefix_list_delete_hook (rip_distribute_update_all);
4002
4003 /* Distribute list install. */
4004 distribute_list_init (RIP_NODE);
4005 distribute_list_add_hook (rip_distribute_update);
4006 distribute_list_delete_hook (rip_distribute_update);
4007
hasso16705132003-05-25 14:49:19 +00004008 /* Route-map */
4009 rip_route_map_init ();
4010 rip_offset_init ();
4011
4012 route_map_add_hook (rip_routemap_update);
4013 route_map_delete_hook (rip_routemap_update);
4014
4015 if_rmap_init (RIP_NODE);
4016 if_rmap_hook_add (rip_if_rmap_update);
4017 if_rmap_hook_delete (rip_if_rmap_update);
4018
paul718e3742002-12-13 20:15:29 +00004019 /* Distance control. */
4020 rip_distance_table = route_table_init ();
4021}