blob: c40e2acebe2fa98d89468c86f2f3df71f0848be7 [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. */
1323int
1324rip_create_socket ()
1325{
1326 int ret;
1327 int sock;
1328 struct sockaddr_in addr;
1329 struct servent *sp;
1330
1331 memset (&addr, 0, sizeof (struct sockaddr_in));
1332
1333 /* Set RIP port. */
1334 sp = getservbyname ("router", "udp");
1335 if (sp)
1336 addr.sin_port = sp->s_port;
1337 else
1338 addr.sin_port = htons (RIP_PORT_DEFAULT);
1339
1340 /* Address shoud be any address. */
1341 addr.sin_family = AF_INET;
1342 addr.sin_addr.s_addr = INADDR_ANY;
1343
1344 /* Make datagram socket. */
1345 sock = socket (AF_INET, SOCK_DGRAM, 0);
1346 if (sock < 0)
1347 {
1348 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1349 exit (1);
1350 }
1351
1352 sockopt_broadcast (sock);
1353 sockopt_reuseaddr (sock);
1354 sockopt_reuseport (sock);
1355 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1356#ifdef RIP_RECVMSG
1357 setsockopt_pktinfo (sock);
1358#endif /* RIP_RECVMSG */
1359
1360 if (ripd_privs.change (ZPRIVS_RAISE))
1361 zlog_err ("rip_create_socket: could not raise privs");
1362 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1363 if (ret < 0)
1364 {
1365 int save_errno = errno;
1366 if (ripd_privs.change (ZPRIVS_LOWER))
1367 zlog_err ("rip_create_socket: could not lower privs");
1368 zlog_err("cannot bind to port %d: %s",
1369 (int)ntohs(addr.sin_port), safe_strerror(save_errno));
1370 return ret;
1371 }
1372 if (ripd_privs.change (ZPRIVS_LOWER))
1373 zlog_err ("rip_create_socket: could not lower privs");
1374
1375 return sock;
1376}
1377
paulc49ad8f2004-10-22 10:27:28 +00001378/* RIP packet send to destination address, on interface denoted by
1379 * by connected argument. NULL to argument denotes destination should be
1380 * should be RIP multicast group
1381 */
paul718e3742002-12-13 20:15:29 +00001382int
paulc49ad8f2004-10-22 10:27:28 +00001383rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1384 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001385{
paul931cd542004-01-23 15:31:42 +00001386 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001387 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001388
1389 assert (ifc != NULL);
1390
paul931cd542004-01-23 15:31:42 +00001391 if (IS_RIP_DEBUG_PACKET)
1392 {
1393 char dst[20];
1394 if (to)
1395 {
1396 strcpy(dst, inet_ntoa(to->sin_addr));
1397 }
1398 else
1399 {
1400 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1401 strcpy(dst, inet_ntoa(sin.sin_addr));
1402 }
ajs5d6c3772004-12-08 19:24:06 +00001403 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001404 inet_ntoa(ifc->address->u.prefix4),
1405 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001406 }
paulc49ad8f2004-10-22 10:27:28 +00001407 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001408 {
1409 /*
1410 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1411 * with multiple addresses on the same subnet: the first address
1412 * on the subnet is configured "primary", and all subsequent addresses
1413 * on that subnet are treated as "secondary" addresses.
1414 * In order to avoid routing-table bloat on other rip listeners,
1415 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1416 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1417 * flag is set, we would end up sending a packet for a "secondary"
1418 * source address on non-linux systems.
1419 */
1420 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001421 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001422 return 0;
1423 }
1424
paul718e3742002-12-13 20:15:29 +00001425 /* Make destination address. */
1426 memset (&sin, 0, sizeof (struct sockaddr_in));
1427 sin.sin_family = AF_INET;
1428#ifdef HAVE_SIN_LEN
1429 sin.sin_len = sizeof (struct sockaddr_in);
1430#endif /* HAVE_SIN_LEN */
1431
1432 /* When destination is specified, use it's port and address. */
1433 if (to)
1434 {
paul718e3742002-12-13 20:15:29 +00001435 sin.sin_port = to->sin_port;
1436 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001437 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001438 }
1439 else
1440 {
paul718e3742002-12-13 20:15:29 +00001441
1442 sin.sin_port = htons (RIP_PORT_DEFAULT);
1443 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1444
paul931cd542004-01-23 15:31:42 +00001445 /*
1446 * we have to open a new socket for each packet because this
1447 * is the most portable way to bind to a different source
1448 * ipv4 address for each packet.
1449 */
1450 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1451 if (send_sock < 0)
1452 {
1453 zlog_warn("rip_send_packet could not create socket %s",
ajs6099b3b2004-11-20 02:06:59 +00001454 safe_strerror(errno));
paul931cd542004-01-23 15:31:42 +00001455 return -1;
1456 }
1457 sockopt_broadcast (send_sock);
1458 sockopt_reuseaddr (send_sock);
1459 sockopt_reuseport (send_sock);
1460#ifdef RIP_RECVMSG
1461 setsockopt_pktinfo (send_sock);
1462#endif /* RIP_RECVMSG */
paulc49ad8f2004-10-22 10:27:28 +00001463 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001464 }
1465
paul931cd542004-01-23 15:31:42 +00001466 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001467 sizeof (struct sockaddr_in));
1468
1469 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001470 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001471 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001472
1473 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001474 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001475
paul931cd542004-01-23 15:31:42 +00001476 if (!to)
1477 close(send_sock);
1478
paul718e3742002-12-13 20:15:29 +00001479 return ret;
1480}
1481
1482/* Add redistributed route to RIP table. */
1483void
1484rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1485 unsigned int ifindex, struct in_addr *nexthop)
1486{
1487 int ret;
1488 struct route_node *rp;
1489 struct rip_info *rinfo;
1490
1491 /* Redistribute route */
1492 ret = rip_destination_check (p->prefix);
1493 if (! ret)
1494 return;
1495
1496 rp = route_node_get (rip->table, (struct prefix *) p);
1497
1498 rinfo = rp->info;
1499
1500 if (rinfo)
1501 {
1502 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1503 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1504 && rinfo->metric != RIP_METRIC_INFINITY)
1505 {
1506 route_unlock_node (rp);
1507 return;
1508 }
1509
1510 /* Manually configured RIP route check. */
1511 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001512 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1513 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001514 {
hasso16705132003-05-25 14:49:19 +00001515 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1516 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001517 {
1518 route_unlock_node (rp);
1519 return;
1520 }
1521 }
1522
1523 RIP_TIMER_OFF (rinfo->t_timeout);
1524 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1525
1526 if (rip_route_rte (rinfo))
1527 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1528 rinfo->metric);
1529 rp->info = NULL;
1530 rip_info_free (rinfo);
1531
1532 route_unlock_node (rp);
1533 }
1534
1535 rinfo = rip_info_new ();
1536
1537 rinfo->type = type;
1538 rinfo->sub_type = sub_type;
1539 rinfo->ifindex = ifindex;
1540 rinfo->metric = 1;
1541 rinfo->rp = rp;
1542
1543 if (nexthop)
1544 rinfo->nexthop = *nexthop;
1545
1546 rinfo->flags |= RIP_RTF_FIB;
1547 rp->info = rinfo;
1548
1549 rinfo->flags |= RIP_RTF_CHANGED;
1550
hasso16705132003-05-25 14:49:19 +00001551 if (IS_RIP_DEBUG_EVENT) {
1552 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001553 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001554 inet_ntoa(p->prefix), p->prefixlen,
1555 ifindex2ifname(ifindex));
1556 else
ajs5d6c3772004-12-08 19:24:06 +00001557 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001558 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1559 ifindex2ifname(ifindex));
1560 }
1561
1562
paul718e3742002-12-13 20:15:29 +00001563 rip_event (RIP_TRIGGERED_UPDATE, 0);
1564}
1565
1566/* Delete redistributed route from RIP table. */
1567void
1568rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1569 unsigned int ifindex)
1570{
1571 int ret;
1572 struct route_node *rp;
1573 struct rip_info *rinfo;
1574
1575 ret = rip_destination_check (p->prefix);
1576 if (! ret)
1577 return;
1578
1579 rp = route_node_lookup (rip->table, (struct prefix *) p);
1580 if (rp)
1581 {
1582 rinfo = rp->info;
1583
1584 if (rinfo != NULL
1585 && rinfo->type == type
1586 && rinfo->sub_type == sub_type
1587 && rinfo->ifindex == ifindex)
1588 {
1589 /* Perform poisoned reverse. */
1590 rinfo->metric = RIP_METRIC_INFINITY;
1591 RIP_TIMER_ON (rinfo->t_garbage_collect,
1592 rip_garbage_collect, rip->garbage_time);
1593 RIP_TIMER_OFF (rinfo->t_timeout);
1594 rinfo->flags |= RIP_RTF_CHANGED;
1595
hasso16705132003-05-25 14:49:19 +00001596 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001597 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001598 inet_ntoa(p->prefix), p->prefixlen,
1599 ifindex2ifname(ifindex));
1600
paul718e3742002-12-13 20:15:29 +00001601 rip_event (RIP_TRIGGERED_UPDATE, 0);
1602 }
1603 }
1604}
1605
1606/* Response to request called from rip_read ().*/
1607void
1608rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001609 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001610{
1611 caddr_t lim;
1612 struct rte *rte;
1613 struct prefix_ipv4 p;
1614 struct route_node *rp;
1615 struct rip_info *rinfo;
1616 struct rip_interface *ri;
1617
hasso16705132003-05-25 14:49:19 +00001618 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001619 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001620 return;
1621
hasso429a0f82004-02-22 23:42:22 +00001622 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001623 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001624 if (! ri->running)
1625 return;
paul718e3742002-12-13 20:15:29 +00001626
1627 /* When passive interface is specified, suppress responses */
1628 if (ri->passive)
1629 return;
paulc49ad8f2004-10-22 10:27:28 +00001630
paul718e3742002-12-13 20:15:29 +00001631 /* RIP peer update. */
1632 rip_peer_update (from, packet->version);
1633
1634 lim = ((caddr_t) packet) + size;
1635 rte = packet->rte;
1636
1637 /* The Request is processed entry by entry. If there are no
1638 entries, no response is given. */
1639 if (lim == (caddr_t) rte)
1640 return;
1641
1642 /* There is one special case. If there is exactly one entry in the
1643 request, and it has an address family identifier of zero and a
1644 metric of infinity (i.e., 16), then this is a request to send the
1645 entire routing table. */
1646 if (lim == ((caddr_t) (rte + 1)) &&
1647 ntohs (rte->family) == 0 &&
1648 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1649 {
paulcc1131a2003-10-15 23:20:17 +00001650 struct prefix_ipv4 saddr;
1651
1652 /* saddr will be used for determining which routes to split-horizon.
1653 Since the source address we'll pick will be on the same subnet as the
1654 destination, for the purpose of split-horizoning, we'll
1655 pretend that "from" is our source address. */
1656 saddr.family = AF_INET;
1657 saddr.prefixlen = IPV4_MAX_BITLEN;
1658 saddr.prefix = from->sin_addr;
1659
paul718e3742002-12-13 20:15:29 +00001660 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001661 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001662 }
1663 else
1664 {
1665 /* Examine the list of RTEs in the Request one by one. For each
1666 entry, look up the destination in the router's routing
1667 database and, if there is a route, put that route's metric in
1668 the metric field of the RTE. If there is no explicit route
1669 to the specified destination, put infinity in the metric
1670 field. Once all the entries have been filled in, change the
1671 command from Request to Response and send the datagram back
1672 to the requestor. */
1673 p.family = AF_INET;
1674
1675 for (; ((caddr_t) rte) < lim; rte++)
1676 {
1677 p.prefix = rte->prefix;
1678 p.prefixlen = ip_masklen (rte->mask);
1679 apply_mask_ipv4 (&p);
1680
1681 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1682 if (rp)
1683 {
1684 rinfo = rp->info;
1685 rte->metric = htonl (rinfo->metric);
1686 route_unlock_node (rp);
1687 }
1688 else
1689 rte->metric = htonl (RIP_METRIC_INFINITY);
1690 }
1691 packet->command = RIP_RESPONSE;
1692
paulc49ad8f2004-10-22 10:27:28 +00001693 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001694 }
1695 rip_global_queries++;
1696}
1697
1698#if RIP_RECVMSG
1699/* Set IPv6 packet info to the socket. */
1700static int
1701setsockopt_pktinfo (int sock)
1702{
1703 int ret;
1704 int val = 1;
1705
1706 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1707 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001708 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001709 return ret;
1710}
1711
1712/* Read RIP packet by recvmsg function. */
1713int
1714rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1715 int *ifindex)
1716{
1717 int ret;
1718 struct msghdr msg;
1719 struct iovec iov;
1720 struct cmsghdr *ptr;
1721 char adata[1024];
1722
1723 msg.msg_name = (void *) from;
1724 msg.msg_namelen = sizeof (struct sockaddr_in);
1725 msg.msg_iov = &iov;
1726 msg.msg_iovlen = 1;
1727 msg.msg_control = (void *) adata;
1728 msg.msg_controllen = sizeof adata;
1729 iov.iov_base = buf;
1730 iov.iov_len = size;
1731
1732 ret = recvmsg (sock, &msg, 0);
1733 if (ret < 0)
1734 return ret;
1735
ajsb99760a2005-01-04 16:24:43 +00001736 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001737 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1738 {
1739 struct in_pktinfo *pktinfo;
1740 int i;
1741
1742 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1743 i = pktinfo->ipi_ifindex;
1744 }
1745 return ret;
1746}
1747
1748/* RIP packet read function. */
1749int
1750rip_read_new (struct thread *t)
1751{
1752 int ret;
1753 int sock;
1754 char buf[RIP_PACKET_MAXSIZ];
1755 struct sockaddr_in from;
1756 unsigned int ifindex;
1757
1758 /* Fetch socket then register myself. */
1759 sock = THREAD_FD (t);
1760 rip_event (RIP_READ, sock);
1761
1762 /* Read RIP packet. */
1763 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1764 if (ret < 0)
1765 {
ajs6099b3b2004-11-20 02:06:59 +00001766 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001767 return ret;
1768 }
1769
1770 return ret;
1771}
1772#endif /* RIP_RECVMSG */
1773
1774/* First entry point of RIP packet. */
1775int
1776rip_read (struct thread *t)
1777{
1778 int sock;
1779 int ret;
1780 int rtenum;
1781 union rip_buf rip_buf;
1782 struct rip_packet *packet;
1783 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001784 int len;
1785 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001786 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001787 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001788 struct rip_interface *ri;
1789
1790 /* Fetch socket then register myself. */
1791 sock = THREAD_FD (t);
1792 rip->t_read = NULL;
1793
1794 /* Add myself to tne next event */
1795 rip_event (RIP_READ, sock);
1796
1797 /* RIPd manages only IPv4. */
1798 memset (&from, 0, sizeof (struct sockaddr_in));
1799 fromlen = sizeof (struct sockaddr_in);
1800
1801 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1802 (struct sockaddr *) &from, &fromlen);
1803 if (len < 0)
1804 {
ajs6099b3b2004-11-20 02:06:59 +00001805 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001806 return len;
1807 }
1808
1809 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001810 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001811 {
1812 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001813 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001814 return -1;
1815 }
1816
1817 /* Which interface is this packet comes from. */
1818 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001819
paul718e3742002-12-13 20:15:29 +00001820 /* RIP packet received */
1821 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001822 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001823 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1824 ifp ? ifp->name : "unknown");
1825
1826 /* If this packet come from unknown interface, ignore it. */
1827 if (ifp == NULL)
1828 {
ajs766a0ca2004-12-15 14:55:51 +00001829 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1830 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001831 return -1;
1832 }
1833
1834 ifc = connected_lookup_address (ifp, from.sin_addr);
1835
1836 if (ifc == NULL)
1837 {
ajs766a0ca2004-12-15 14:55:51 +00001838 zlog_info ("rip_read: cannot find connected address for packet from %s "
1839 "port %d on interface %s",
1840 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001841 return -1;
1842 }
1843
1844 /* Packet length check. */
1845 if (len < RIP_PACKET_MINSIZ)
1846 {
1847 zlog_warn ("packet size %d is smaller than minimum size %d",
1848 len, RIP_PACKET_MINSIZ);
1849 rip_peer_bad_packet (&from);
1850 return len;
1851 }
1852 if (len > RIP_PACKET_MAXSIZ)
1853 {
1854 zlog_warn ("packet size %d is larger than max size %d",
1855 len, RIP_PACKET_MAXSIZ);
1856 rip_peer_bad_packet (&from);
1857 return len;
1858 }
1859
1860 /* Packet alignment check. */
1861 if ((len - RIP_PACKET_MINSIZ) % 20)
1862 {
1863 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1864 rip_peer_bad_packet (&from);
1865 return len;
1866 }
1867
1868 /* Set RTE number. */
1869 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1870
1871 /* For easy to handle. */
1872 packet = &rip_buf.rip_packet;
1873
1874 /* RIP version check. */
1875 if (packet->version == 0)
1876 {
1877 zlog_info ("version 0 with command %d received.", packet->command);
1878 rip_peer_bad_packet (&from);
1879 return -1;
1880 }
1881
1882 /* Dump RIP packet. */
1883 if (IS_RIP_DEBUG_RECV)
1884 rip_packet_dump (packet, len, "RECV");
1885
1886 /* RIP version adjust. This code should rethink now. RFC1058 says
1887 that "Version 1 implementations are to ignore this extra data and
1888 process only the fields specified in this document.". So RIPv3
1889 packet should be treated as RIPv1 ignoring must be zero field. */
1890 if (packet->version > RIPv2)
1891 packet->version = RIPv2;
1892
1893 /* Is RIP running or is this RIP neighbor ?*/
1894 ri = ifp->info;
1895 if (! ri->running && ! rip_neighbor_lookup (&from))
1896 {
1897 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001898 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001899 rip_peer_bad_packet (&from);
1900 return -1;
1901 }
1902
1903 /* RIP Version check. */
1904 if (packet->command == RIP_RESPONSE)
1905 {
paulf38a4712003-06-07 01:10:00 +00001906 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1907 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001908 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001909 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001910 {
1911 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001912 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001913 packet->version);
1914 rip_peer_bad_packet (&from);
1915 return -1;
1916 }
1917 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001918 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001919 {
1920 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001921 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001922 packet->version);
1923 rip_peer_bad_packet (&from);
1924 return -1;
1925 }
paul718e3742002-12-13 20:15:29 +00001926 }
1927
1928 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1929 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1930 accepted; authenticated RIP-2 messages shall be discarded. */
1931
1932 if ((ri->auth_type == RIP_NO_AUTH)
1933 && rtenum
paulca5e5162004-06-06 22:06:33 +00001934 && (packet->version == RIPv2)
1935 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001936 {
1937 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001938 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001939 packet->version);
1940 rip_peer_bad_packet (&from);
1941 return -1;
1942 }
1943
1944 /* If the router is configured to authenticate RIP-2 messages, then
1945 RIP-1 messages and RIP-2 messages which pass authentication
1946 testing shall be accepted; unauthenticated and failed
1947 authentication RIP-2 messages shall be discarded. For maximum
1948 security, RIP-1 messages should be ignored when authentication is
1949 in use (see section 4.1); otherwise, the routing information from
1950 authenticated messages will be propagated by RIP-1 routers in an
1951 unauthenticated manner. */
1952
1953 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001954 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001955 {
1956 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001957 if (packet->version == RIPv1
1958 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001959 {
1960 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001961 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001962 ("packet RIPv%d is dropped because authentication enabled",
1963 packet->version);
paul718e3742002-12-13 20:15:29 +00001964 rip_peer_bad_packet (&from);
1965 return -1;
1966 }
1967
1968 /* Check RIPv2 authentication. */
1969 if (packet->version == RIPv2)
1970 {
paulca5e5162004-06-06 22:06:33 +00001971 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001972 {
paulca5e5162004-06-06 22:06:33 +00001973 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001974 {
1975 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1976 if (! ret)
1977 {
1978 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001979 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001980 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001981 rip_peer_bad_packet (&from);
1982 return -1;
1983 }
1984 else
1985 {
1986 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001987 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001988 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001989 }
1990 }
paulca5e5162004-06-06 22:06:33 +00001991 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001992 {
paulca5e5162004-06-06 22:06:33 +00001993 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001994 if (! ret)
1995 {
1996 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001997 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001998 rip_peer_bad_packet (&from);
1999 return -1;
2000 }
2001 else
2002 {
2003 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002004 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002005 }
2006 /* Reset RIP packet length to trim MD5 data. */
2007 len = ret;
2008 }
2009 else
2010 {
2011 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002012 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002013 ntohs (packet->rte->tag));
2014 rip_peer_bad_packet (&from);
2015 return -1;
2016 }
2017 }
2018 else
2019 {
2020 /* There is no authentication in the packet. */
2021 if (ri->auth_str || ri->key_chain)
2022 {
2023 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002024 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002025 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002026 rip_peer_bad_packet (&from);
2027 return -1;
2028 }
2029 }
2030 }
2031 }
2032
2033 /* Process each command. */
2034 switch (packet->command)
2035 {
2036 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002037 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002038 break;
2039 case RIP_REQUEST:
2040 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002041 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002042 break;
2043 case RIP_TRACEON:
2044 case RIP_TRACEOFF:
2045 zlog_info ("Obsolete command %s received, please sent it to routed",
2046 lookup (rip_msg, packet->command));
2047 rip_peer_bad_packet (&from);
2048 break;
2049 case RIP_POLL_ENTRY:
2050 zlog_info ("Obsolete command %s received",
2051 lookup (rip_msg, packet->command));
2052 rip_peer_bad_packet (&from);
2053 break;
2054 default:
2055 zlog_info ("Unknown RIP command %d received", packet->command);
2056 rip_peer_bad_packet (&from);
2057 break;
2058 }
2059
2060 return len;
2061}
2062
paul718e3742002-12-13 20:15:29 +00002063/* Write routing table entry to the stream and return next index of
2064 the routing table entry in the stream. */
2065int
2066rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002067 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002068{
2069 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002070
2071 /* Write routing table entry. */
2072 if (version == RIPv1)
2073 {
2074 stream_putw (s, AF_INET);
2075 stream_putw (s, 0);
2076 stream_put_ipv4 (s, p->prefix.s_addr);
2077 stream_put_ipv4 (s, 0);
2078 stream_put_ipv4 (s, 0);
2079 stream_putl (s, rinfo->metric_out);
2080 }
2081 else
2082 {
2083 masklen2ip (p->prefixlen, &mask);
2084
2085 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002086 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002087 stream_put_ipv4 (s, p->prefix.s_addr);
2088 stream_put_ipv4 (s, mask.s_addr);
2089 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2090 stream_putl (s, rinfo->metric_out);
2091 }
2092
2093 return ++num;
2094}
2095
2096/* Send update to the ifp or spcified neighbor. */
2097void
paulc49ad8f2004-10-22 10:27:28 +00002098rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2099 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002100{
2101 int ret;
2102 struct stream *s;
2103 struct route_node *rp;
2104 struct rip_info *rinfo;
2105 struct rip_interface *ri;
2106 struct prefix_ipv4 *p;
2107 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002108 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002109 struct key *key = NULL;
2110 /* this might need to made dynamic if RIP ever supported auth methods
2111 with larger key string sizes */
2112 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2113 size_t doff; /* offset of digest offset field */
paul718e3742002-12-13 20:15:29 +00002114 int num;
2115 int rtemax;
paul01d09082003-06-08 21:22:18 +00002116 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002117
2118 /* Logging output event. */
2119 if (IS_RIP_DEBUG_EVENT)
2120 {
2121 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002122 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002123 else
ajs5d6c3772004-12-08 19:24:06 +00002124 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002125 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002126 }
2127
2128 /* Set output stream. */
2129 s = rip->obuf;
2130
2131 /* Reset stream and RTE counter. */
2132 stream_reset (s);
2133 num = 0;
2134 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2135
2136 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002137 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002138
2139 /* If output interface is in simple password authentication mode, we
2140 need space for authentication data. */
2141 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2142 rtemax -= 1;
2143
2144 /* If output interface is in MD5 authentication mode, we need space
2145 for authentication header and data. */
2146 if (ri->auth_type == RIP_AUTH_MD5)
2147 rtemax -= 2;
2148
2149 /* If output interface is in simple password authentication mode
2150 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002151 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002152 {
2153 if (ri->key_chain)
2154 {
2155 struct keychain *keychain;
2156
2157 keychain = keychain_lookup (ri->key_chain);
2158 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002159 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002160 }
paulb14ee002005-02-04 23:42:41 +00002161 /* to be passed to auth functions later */
2162 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002163 }
2164
paul727d1042002-12-13 20:50:29 +00002165 if (version == RIPv1)
2166 {
paulc49ad8f2004-10-22 10:27:28 +00002167 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002168 apply_classful_mask_ipv4 (&ifaddrclass);
2169 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002170 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002171 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002172 }
2173
paul718e3742002-12-13 20:15:29 +00002174 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2175 if ((rinfo = rp->info) != NULL)
2176 {
paul727d1042002-12-13 20:50:29 +00002177 /* For RIPv1, if we are subnetted, output subnets in our network */
2178 /* that have the same mask as the output "interface". For other */
2179 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002180
2181 if (version == RIPv1)
2182 {
paul727d1042002-12-13 20:50:29 +00002183 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002184
2185 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002186 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002187 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002188
paul727d1042002-12-13 20:50:29 +00002189 if (subnetted &&
2190 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2191 {
paulc49ad8f2004-10-22 10:27:28 +00002192 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002193 (rp->p.prefixlen != 32))
2194 continue;
2195 }
2196 else
2197 {
2198 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2199 apply_classful_mask_ipv4(&classfull);
2200 if (rp->p.u.prefix4.s_addr != 0 &&
2201 classfull.prefixlen != rp->p.prefixlen)
2202 continue;
2203 }
paul718e3742002-12-13 20:15:29 +00002204 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002205 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002206 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002207 }
2208 else
2209 p = (struct prefix_ipv4 *) &rp->p;
2210
2211 /* Apply output filters. */
2212 ret = rip_outgoing_filter (p, ri);
2213 if (ret < 0)
2214 continue;
2215
2216 /* Changed route only output. */
2217 if (route_type == rip_changed_route &&
2218 (! (rinfo->flags & RIP_RTF_CHANGED)))
2219 continue;
2220
2221 /* Split horizon. */
2222 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002223 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002224 {
paul42d14d92003-11-17 09:15:18 +00002225 /*
2226 * We perform split horizon for RIP and connected route.
2227 * For rip routes, we want to suppress the route if we would
2228 * end up sending the route back on the interface that we
2229 * learned it from, with a higher metric. For connected routes,
2230 * we suppress the route if the prefix is a subset of the
2231 * source address that we are going to use for the packet
2232 * (in order to handle the case when multiple subnets are
2233 * configured on the same interface).
2234 */
2235 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002236 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002237 continue;
2238 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002239 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002240 continue;
2241 }
2242
2243 /* Preparation for route-map. */
2244 rinfo->metric_set = 0;
2245 rinfo->nexthop_out.s_addr = 0;
2246 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002247 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002248 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002249
hasso16705132003-05-25 14:49:19 +00002250 /* In order to avoid some local loops,
2251 * if the RIP route has a nexthop via this interface, keep the nexthop,
2252 * otherwise set it to 0. The nexthop should not be propagated
2253 * beyond the local broadcast/multicast area in order
2254 * to avoid an IGP multi-level recursive look-up.
2255 * see (4.4)
2256 */
paulc49ad8f2004-10-22 10:27:28 +00002257 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002258 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002259
2260 /* Interface route-map */
2261 if (ri->routemap[RIP_FILTER_OUT])
2262 {
2263 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2264 (struct prefix *) p, RMAP_RIP,
2265 rinfo);
2266
2267 if (ret == RMAP_DENYMATCH)
2268 {
2269 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002270 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002271 inet_ntoa (p->prefix), p->prefixlen);
2272 continue;
2273 }
2274 }
paul718e3742002-12-13 20:15:29 +00002275
hasso16705132003-05-25 14:49:19 +00002276 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002277 if (rip->route_map[rinfo->type].name
2278 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2279 {
2280 ret = route_map_apply (rip->route_map[rinfo->type].map,
2281 (struct prefix *)p, RMAP_RIP, rinfo);
2282
2283 if (ret == RMAP_DENYMATCH)
2284 {
2285 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002286 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002287 inet_ntoa (p->prefix), p->prefixlen);
2288 continue;
2289 }
2290 }
2291
2292 /* When route-map does not set metric. */
2293 if (! rinfo->metric_set)
2294 {
2295 /* If redistribute metric is set. */
2296 if (rip->route_map[rinfo->type].metric_config
2297 && rinfo->metric != RIP_METRIC_INFINITY)
2298 {
2299 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2300 }
2301 else
2302 {
2303 /* If the route is not connected or localy generated
2304 one, use default-metric value*/
2305 if (rinfo->type != ZEBRA_ROUTE_RIP
2306 && rinfo->type != ZEBRA_ROUTE_CONNECT
2307 && rinfo->metric != RIP_METRIC_INFINITY)
2308 rinfo->metric_out = rip->default_metric;
2309 }
2310 }
2311
2312 /* Apply offset-list */
2313 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002314 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002315
2316 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2317 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002318
2319 /* Perform split-horizon with poisoned reverse
2320 * for RIP and connected routes.
2321 **/
2322 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002323 /*
2324 * We perform split horizon for RIP and connected route.
2325 * For rip routes, we want to suppress the route if we would
2326 * end up sending the route back on the interface that we
2327 * learned it from, with a higher metric. For connected routes,
2328 * we suppress the route if the prefix is a subset of the
2329 * source address that we are going to use for the packet
2330 * (in order to handle the case when multiple subnets are
2331 * configured on the same interface).
2332 */
2333 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002334 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002335 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002336 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002337 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002338 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002339 }
paulb14ee002005-02-04 23:42:41 +00002340
2341 /* Prepare preamble, auth headers, if needs be */
2342 if (num == 0)
2343 {
2344 stream_putc (s, RIP_RESPONSE);
2345 stream_putc (s, version);
2346 stream_putw (s, 0);
2347
paul0cb8a012005-05-29 11:27:24 +00002348 /* auth header for !v1 && !no_auth */
2349 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002350 doff = rip_auth_header_write (s, ri, key, auth_str,
2351 RIP_AUTH_SIMPLE_SIZE);
2352 }
2353
paul718e3742002-12-13 20:15:29 +00002354 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002355 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002356 if (num == rtemax)
2357 {
2358 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002359 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002360
2361 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002362 to, ifc);
paul718e3742002-12-13 20:15:29 +00002363
2364 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2365 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2366 stream_get_endp(s), "SEND");
2367 num = 0;
2368 stream_reset (s);
2369 }
2370 }
2371
2372 /* Flush unwritten RTE. */
2373 if (num != 0)
2374 {
2375 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002376 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002377
paulc49ad8f2004-10-22 10:27:28 +00002378 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002379
2380 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2381 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2382 stream_get_endp (s), "SEND");
2383 num = 0;
2384 stream_reset (s);
2385 }
2386
2387 /* Statistics updates. */
2388 ri->sent_updates++;
2389}
2390
2391/* Send RIP packet to the interface. */
2392void
paulc49ad8f2004-10-22 10:27:28 +00002393rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002394{
paul718e3742002-12-13 20:15:29 +00002395 struct sockaddr_in to;
2396
2397 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002398 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002399 {
2400 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002401 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002402
paulc49ad8f2004-10-22 10:27:28 +00002403 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002404 return;
2405 }
paulc49ad8f2004-10-22 10:27:28 +00002406
paul718e3742002-12-13 20:15:29 +00002407 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002408 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002409 {
paulc49ad8f2004-10-22 10:27:28 +00002410 if (ifc->address->family == AF_INET)
2411 {
2412 /* Destination address and port setting. */
2413 memset (&to, 0, sizeof (struct sockaddr_in));
2414 if (ifc->destination)
2415 /* use specified broadcast or point-to-point destination addr */
2416 to.sin_addr = ifc->destination->u.prefix4;
2417 else
2418 /* calculate the appropriate broadcast address */
2419 to.sin_addr.s_addr =
2420 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2421 ifc->address->prefixlen);
2422 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002423
paulc49ad8f2004-10-22 10:27:28 +00002424 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002425 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002426 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2427 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002428
paulc49ad8f2004-10-22 10:27:28 +00002429 rip_output_process (ifc, &to, route_type, version);
2430 }
paul718e3742002-12-13 20:15:29 +00002431 }
2432}
2433
2434/* Update send to all interface and neighbor. */
2435void
2436rip_update_process (int route_type)
2437{
paul1eb8ef22005-04-07 07:30:20 +00002438 struct listnode *node;
2439 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002440 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002441 struct interface *ifp;
2442 struct rip_interface *ri;
2443 struct route_node *rp;
2444 struct sockaddr_in to;
2445 struct prefix_ipv4 *p;
2446
2447 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002448 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002449 {
paul718e3742002-12-13 20:15:29 +00002450 if (if_is_loopback (ifp))
2451 continue;
2452
paul2e3b2e42002-12-13 21:03:13 +00002453 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002454 continue;
2455
2456 /* Fetch RIP interface information. */
2457 ri = ifp->info;
2458
2459 /* When passive interface is specified, suppress announce to the
2460 interface. */
2461 if (ri->passive)
2462 continue;
2463
2464 if (ri->running)
2465 {
2466 if (IS_RIP_DEBUG_EVENT)
2467 {
2468 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002469 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002470 ifp->name, ifp->ifindex);
2471 else
ajs5d6c3772004-12-08 19:24:06 +00002472 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002473 ifp->ifindex);
2474 }
2475
paulcc1131a2003-10-15 23:20:17 +00002476 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002477 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002478 {
2479 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002480 int done = 0;
2481 /*
2482 * If there is no version configuration in the interface,
2483 * use rip's version setting.
2484 */
paulf38a4712003-06-07 01:10:00 +00002485 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2486 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002487
2488 ifaddr = (struct prefix_ipv4 *) connected->address;
2489
2490 if (ifaddr->family != AF_INET)
2491 continue;
2492
paul931cd542004-01-23 15:31:42 +00002493 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002494 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002495 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002496 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002497 done = 1;
2498 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2499 break;
2500
paulf38a4712003-06-07 01:10:00 +00002501 }
paul718e3742002-12-13 20:15:29 +00002502 }
2503 }
2504
2505 /* RIP send updates to each neighbor. */
2506 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2507 if (rp->info != NULL)
2508 {
2509 p = (struct prefix_ipv4 *) &rp->p;
2510
2511 ifp = if_lookup_address (p->prefix);
2512 if (! ifp)
2513 {
paulc49ad8f2004-10-22 10:27:28 +00002514 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002515 inet_ntoa (p->prefix));
2516 continue;
2517 }
paulc49ad8f2004-10-22 10:27:28 +00002518
2519 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2520 {
2521 zlog_warn ("Neighbor %s doesnt have connected network",
2522 inet_ntoa (p->prefix));
2523 continue;
2524 }
2525
paul718e3742002-12-13 20:15:29 +00002526 /* Set destination address and port */
2527 memset (&to, 0, sizeof (struct sockaddr_in));
2528 to.sin_addr = p->prefix;
2529 to.sin_port = htons (RIP_PORT_DEFAULT);
2530
2531 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002532 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002533 }
2534}
2535
2536/* RIP's periodical timer. */
2537int
2538rip_update (struct thread *t)
2539{
2540 /* Clear timer pointer. */
2541 rip->t_update = NULL;
2542
2543 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002544 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002545
2546 /* Process update output. */
2547 rip_update_process (rip_all_route);
2548
2549 /* Triggered updates may be suppressed if a regular update is due by
2550 the time the triggered update would be sent. */
2551 if (rip->t_triggered_interval)
2552 {
2553 thread_cancel (rip->t_triggered_interval);
2554 rip->t_triggered_interval = NULL;
2555 }
2556 rip->trigger = 0;
2557
2558 /* Register myself. */
2559 rip_event (RIP_UPDATE_EVENT, 0);
2560
2561 return 0;
2562}
2563
2564/* Walk down the RIP routing table then clear changed flag. */
2565void
2566rip_clear_changed_flag ()
2567{
2568 struct route_node *rp;
2569 struct rip_info *rinfo;
2570
2571 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2572 if ((rinfo = rp->info) != NULL)
2573 if (rinfo->flags & RIP_RTF_CHANGED)
2574 rinfo->flags &= ~RIP_RTF_CHANGED;
2575}
2576
2577/* Triggered update interval timer. */
2578int
2579rip_triggered_interval (struct thread *t)
2580{
2581 int rip_triggered_update (struct thread *);
2582
2583 rip->t_triggered_interval = NULL;
2584
2585 if (rip->trigger)
2586 {
2587 rip->trigger = 0;
2588 rip_triggered_update (t);
2589 }
2590 return 0;
2591}
2592
2593/* Execute triggered update. */
2594int
2595rip_triggered_update (struct thread *t)
2596{
2597 int interval;
2598
2599 /* Clear thred pointer. */
2600 rip->t_triggered_update = NULL;
2601
2602 /* Cancel interval timer. */
2603 if (rip->t_triggered_interval)
2604 {
2605 thread_cancel (rip->t_triggered_interval);
2606 rip->t_triggered_interval = NULL;
2607 }
2608 rip->trigger = 0;
2609
2610 /* Logging triggered update. */
2611 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002612 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002613
2614 /* Split Horizon processing is done when generating triggered
2615 updates as well as normal updates (see section 2.6). */
2616 rip_update_process (rip_changed_route);
2617
2618 /* Once all of the triggered updates have been generated, the route
2619 change flags should be cleared. */
2620 rip_clear_changed_flag ();
2621
2622 /* After a triggered update is sent, a timer should be set for a
2623 random interval between 1 and 5 seconds. If other changes that
2624 would trigger updates occur before the timer expires, a single
2625 update is triggered when the timer expires. */
2626 interval = (random () % 5) + 1;
2627
2628 rip->t_triggered_interval =
2629 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2630
2631 return 0;
2632}
2633
2634/* Withdraw redistributed route. */
2635void
2636rip_redistribute_withdraw (int type)
2637{
2638 struct route_node *rp;
2639 struct rip_info *rinfo;
2640
2641 if (!rip)
2642 return;
2643
2644 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2645 if ((rinfo = rp->info) != NULL)
2646 {
2647 if (rinfo->type == type
2648 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2649 {
2650 /* Perform poisoned reverse. */
2651 rinfo->metric = RIP_METRIC_INFINITY;
2652 RIP_TIMER_ON (rinfo->t_garbage_collect,
2653 rip_garbage_collect, rip->garbage_time);
2654 RIP_TIMER_OFF (rinfo->t_timeout);
2655 rinfo->flags |= RIP_RTF_CHANGED;
2656
hasso16705132003-05-25 14:49:19 +00002657 if (IS_RIP_DEBUG_EVENT) {
2658 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2659
ajs5d6c3772004-12-08 19:24:06 +00002660 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002661 inet_ntoa(p->prefix), p->prefixlen,
2662 ifindex2ifname(rinfo->ifindex));
2663 }
2664
paul718e3742002-12-13 20:15:29 +00002665 rip_event (RIP_TRIGGERED_UPDATE, 0);
2666 }
2667 }
2668}
2669
2670/* Create new RIP instance and set it to global variable. */
2671int
2672rip_create ()
2673{
2674 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2675 memset (rip, 0, sizeof (struct rip));
2676
2677 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002678 rip->version_send = RI_RIP_VERSION_2;
2679 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002680 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2681 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2682 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2683 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2684
2685 /* Initialize RIP routig table. */
2686 rip->table = route_table_init ();
2687 rip->route = route_table_init ();
2688 rip->neighbor = route_table_init ();
2689
2690 /* Make output stream. */
2691 rip->obuf = stream_new (1500);
2692
2693 /* Make socket. */
2694 rip->sock = rip_create_socket ();
2695 if (rip->sock < 0)
2696 return rip->sock;
2697
2698 /* Create read and timer thread. */
2699 rip_event (RIP_READ, rip->sock);
2700 rip_event (RIP_UPDATE_EVENT, 1);
2701
2702 return 0;
2703}
2704
2705/* Sned RIP request to the destination. */
2706int
2707rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002708 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002709{
2710 struct rte *rte;
2711 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002712 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002713
2714 memset (&rip_packet, 0, sizeof (rip_packet));
2715
2716 rip_packet.command = RIP_REQUEST;
2717 rip_packet.version = version;
2718 rte = rip_packet.rte;
2719 rte->metric = htonl (RIP_METRIC_INFINITY);
2720
paul931cd542004-01-23 15:31:42 +00002721 if (connected)
2722 {
2723 /*
2724 * connected is only sent for ripv1 case, or when
2725 * interface does not support multicast. Caller loops
2726 * over each connected address for this case.
2727 */
paul11dde9c2004-05-31 14:00:00 +00002728 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002729 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002730 return -1;
2731 else
2732 return sizeof (rip_packet);
2733 }
2734
paulcc1131a2003-10-15 23:20:17 +00002735 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002736 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002737 {
2738 struct prefix_ipv4 *p;
2739
2740 p = (struct prefix_ipv4 *) connected->address;
2741
2742 if (p->family != AF_INET)
2743 continue;
2744
paul11dde9c2004-05-31 14:00:00 +00002745 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002746 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002747 return -1;
2748 }
2749 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002750}
2751
2752int
2753rip_update_jitter (unsigned long time)
2754{
paul239389b2004-05-05 14:09:37 +00002755#define JITTER_BOUND 4
2756 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2757 Given that, we cannot let time be less than JITTER_BOUND seconds.
2758 The RIPv2 RFC says jitter should be small compared to
2759 update_time. We consider 1/JITTER_BOUND to be small.
2760 */
2761
2762 int jitter_input = time;
2763 int jitter;
2764
2765 if (jitter_input < JITTER_BOUND)
2766 jitter_input = JITTER_BOUND;
2767
2768 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2769
2770 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002771}
2772
2773void
2774rip_event (enum rip_event event, int sock)
2775{
2776 int jitter = 0;
2777
2778 switch (event)
2779 {
2780 case RIP_READ:
2781 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2782 break;
2783 case RIP_UPDATE_EVENT:
2784 if (rip->t_update)
2785 {
2786 thread_cancel (rip->t_update);
2787 rip->t_update = NULL;
2788 }
2789 jitter = rip_update_jitter (rip->update_time);
2790 rip->t_update =
2791 thread_add_timer (master, rip_update, NULL,
2792 sock ? 2 : rip->update_time + jitter);
2793 break;
2794 case RIP_TRIGGERED_UPDATE:
2795 if (rip->t_triggered_interval)
2796 rip->trigger = 1;
2797 else if (! rip->t_triggered_update)
2798 rip->t_triggered_update =
2799 thread_add_event (master, rip_triggered_update, NULL, 0);
2800 break;
2801 default:
2802 break;
2803 }
2804}
2805
2806DEFUN (router_rip,
2807 router_rip_cmd,
2808 "router rip",
2809 "Enable a routing process\n"
2810 "Routing Information Protocol (RIP)\n")
2811{
2812 int ret;
2813
2814 /* If rip is not enabled before. */
2815 if (! rip)
2816 {
2817 ret = rip_create ();
2818 if (ret < 0)
2819 {
2820 zlog_info ("Can't create RIP");
2821 return CMD_WARNING;
2822 }
2823 }
2824 vty->node = RIP_NODE;
2825 vty->index = rip;
2826
2827 return CMD_SUCCESS;
2828}
2829
2830DEFUN (no_router_rip,
2831 no_router_rip_cmd,
2832 "no router rip",
2833 NO_STR
2834 "Enable a routing process\n"
2835 "Routing Information Protocol (RIP)\n")
2836{
2837 if (rip)
2838 rip_clean ();
2839 return CMD_SUCCESS;
2840}
2841
2842DEFUN (rip_version,
2843 rip_version_cmd,
2844 "version <1-2>",
2845 "Set routing protocol version\n"
2846 "version\n")
2847{
2848 int version;
2849
2850 version = atoi (argv[0]);
2851 if (version != RIPv1 && version != RIPv2)
2852 {
2853 vty_out (vty, "invalid rip version %d%s", version,
2854 VTY_NEWLINE);
2855 return CMD_WARNING;
2856 }
paulf38a4712003-06-07 01:10:00 +00002857 rip->version_send = version;
2858 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002859
2860 return CMD_SUCCESS;
2861}
2862
2863DEFUN (no_rip_version,
2864 no_rip_version_cmd,
2865 "no version",
2866 NO_STR
2867 "Set routing protocol version\n")
2868{
2869 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002870 rip->version_send = RI_RIP_VERSION_2;
2871 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002872
2873 return CMD_SUCCESS;
2874}
2875
2876ALIAS (no_rip_version,
2877 no_rip_version_val_cmd,
2878 "no version <1-2>",
2879 NO_STR
2880 "Set routing protocol version\n"
2881 "version\n")
2882
2883DEFUN (rip_route,
2884 rip_route_cmd,
2885 "route A.B.C.D/M",
2886 "RIP static route configuration\n"
2887 "IP prefix <network>/<length>\n")
2888{
2889 int ret;
2890 struct prefix_ipv4 p;
2891 struct route_node *node;
2892
2893 ret = str2prefix_ipv4 (argv[0], &p);
2894 if (ret < 0)
2895 {
2896 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2897 return CMD_WARNING;
2898 }
2899 apply_mask_ipv4 (&p);
2900
2901 /* For router rip configuration. */
2902 node = route_node_get (rip->route, (struct prefix *) &p);
2903
2904 if (node->info)
2905 {
2906 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2907 route_unlock_node (node);
2908 return CMD_WARNING;
2909 }
2910
hasso8a676be2004-10-08 06:36:38 +00002911 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002912
2913 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2914
2915 return CMD_SUCCESS;
2916}
2917
2918DEFUN (no_rip_route,
2919 no_rip_route_cmd,
2920 "no route A.B.C.D/M",
2921 NO_STR
2922 "RIP static route configuration\n"
2923 "IP prefix <network>/<length>\n")
2924{
2925 int ret;
2926 struct prefix_ipv4 p;
2927 struct route_node *node;
2928
2929 ret = str2prefix_ipv4 (argv[0], &p);
2930 if (ret < 0)
2931 {
2932 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2933 return CMD_WARNING;
2934 }
2935 apply_mask_ipv4 (&p);
2936
2937 /* For router rip configuration. */
2938 node = route_node_lookup (rip->route, (struct prefix *) &p);
2939 if (! node)
2940 {
2941 vty_out (vty, "Can't find route %s.%s", argv[0],
2942 VTY_NEWLINE);
2943 return CMD_WARNING;
2944 }
2945
2946 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2947 route_unlock_node (node);
2948
2949 node->info = NULL;
2950 route_unlock_node (node);
2951
2952 return CMD_SUCCESS;
2953}
2954
2955void
2956rip_update_default_metric ()
2957{
2958 struct route_node *np;
2959 struct rip_info *rinfo;
2960
2961 for (np = route_top (rip->table); np; np = route_next (np))
2962 if ((rinfo = np->info) != NULL)
2963 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2964 rinfo->metric = rip->default_metric;
2965}
2966
2967DEFUN (rip_default_metric,
2968 rip_default_metric_cmd,
2969 "default-metric <1-16>",
2970 "Set a metric of redistribute routes\n"
2971 "Default metric\n")
2972{
2973 if (rip)
2974 {
2975 rip->default_metric = atoi (argv[0]);
2976 /* rip_update_default_metric (); */
2977 }
2978 return CMD_SUCCESS;
2979}
2980
2981DEFUN (no_rip_default_metric,
2982 no_rip_default_metric_cmd,
2983 "no default-metric",
2984 NO_STR
2985 "Set a metric of redistribute routes\n"
2986 "Default metric\n")
2987{
2988 if (rip)
2989 {
2990 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2991 /* rip_update_default_metric (); */
2992 }
2993 return CMD_SUCCESS;
2994}
2995
2996ALIAS (no_rip_default_metric,
2997 no_rip_default_metric_val_cmd,
2998 "no default-metric <1-16>",
2999 NO_STR
3000 "Set a metric of redistribute routes\n"
3001 "Default metric\n")
3002
3003DEFUN (rip_timers,
3004 rip_timers_cmd,
3005 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3006 "Adjust routing timers\n"
3007 "Basic routing protocol update timers\n"
3008 "Routing table update timer value in second. Default is 30.\n"
3009 "Routing information timeout timer. Default is 180.\n"
3010 "Garbage collection timer. Default is 120.\n")
3011{
3012 unsigned long update;
3013 unsigned long timeout;
3014 unsigned long garbage;
3015 char *endptr = NULL;
3016 unsigned long RIP_TIMER_MAX = 2147483647;
3017 unsigned long RIP_TIMER_MIN = 5;
3018
3019 update = strtoul (argv[0], &endptr, 10);
3020 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3021 {
3022 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3023 return CMD_WARNING;
3024 }
3025
3026 timeout = strtoul (argv[1], &endptr, 10);
3027 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3028 {
3029 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3030 return CMD_WARNING;
3031 }
3032
3033 garbage = strtoul (argv[2], &endptr, 10);
3034 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3035 {
3036 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3037 return CMD_WARNING;
3038 }
3039
3040 /* Set each timer value. */
3041 rip->update_time = update;
3042 rip->timeout_time = timeout;
3043 rip->garbage_time = garbage;
3044
3045 /* Reset update timer thread. */
3046 rip_event (RIP_UPDATE_EVENT, 0);
3047
3048 return CMD_SUCCESS;
3049}
3050
3051DEFUN (no_rip_timers,
3052 no_rip_timers_cmd,
3053 "no timers basic",
3054 NO_STR
3055 "Adjust routing timers\n"
3056 "Basic routing protocol update timers\n")
3057{
3058 /* Set each timer value to the default. */
3059 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3060 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3061 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3062
3063 /* Reset update timer thread. */
3064 rip_event (RIP_UPDATE_EVENT, 0);
3065
3066 return CMD_SUCCESS;
3067}
hasso16705132003-05-25 14:49:19 +00003068
3069ALIAS (no_rip_timers,
3070 no_rip_timers_val_cmd,
3071 "no timers basic <0-65535> <0-65535> <0-65535>",
3072 NO_STR
3073 "Adjust routing timers\n"
3074 "Basic routing protocol update timers\n"
3075 "Routing table update timer value in second. Default is 30.\n"
3076 "Routing information timeout timer. Default is 180.\n"
3077 "Garbage collection timer. Default is 120.\n")
3078
paul718e3742002-12-13 20:15:29 +00003079
3080struct route_table *rip_distance_table;
3081
3082struct rip_distance
3083{
3084 /* Distance value for the IP source prefix. */
3085 u_char distance;
3086
3087 /* Name of the access-list to be matched. */
3088 char *access_list;
3089};
3090
3091struct rip_distance *
3092rip_distance_new ()
3093{
3094 struct rip_distance *new;
3095 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3096 memset (new, 0, sizeof (struct rip_distance));
3097 return new;
3098}
3099
3100void
3101rip_distance_free (struct rip_distance *rdistance)
3102{
3103 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3104}
3105
3106int
hasso98b718a2004-10-11 12:57:57 +00003107rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3108 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003109{
3110 int ret;
3111 struct prefix_ipv4 p;
3112 u_char distance;
3113 struct route_node *rn;
3114 struct rip_distance *rdistance;
3115
3116 ret = str2prefix_ipv4 (ip_str, &p);
3117 if (ret == 0)
3118 {
3119 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3120 return CMD_WARNING;
3121 }
3122
3123 distance = atoi (distance_str);
3124
3125 /* Get RIP distance node. */
3126 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3127 if (rn->info)
3128 {
3129 rdistance = rn->info;
3130 route_unlock_node (rn);
3131 }
3132 else
3133 {
3134 rdistance = rip_distance_new ();
3135 rn->info = rdistance;
3136 }
3137
3138 /* Set distance value. */
3139 rdistance->distance = distance;
3140
3141 /* Reset access-list configuration. */
3142 if (rdistance->access_list)
3143 {
3144 free (rdistance->access_list);
3145 rdistance->access_list = NULL;
3146 }
3147 if (access_list_str)
3148 rdistance->access_list = strdup (access_list_str);
3149
3150 return CMD_SUCCESS;
3151}
3152
3153int
hasso98b718a2004-10-11 12:57:57 +00003154rip_distance_unset (struct vty *vty, const char *distance_str,
3155 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003156{
3157 int ret;
3158 struct prefix_ipv4 p;
3159 u_char distance;
3160 struct route_node *rn;
3161 struct rip_distance *rdistance;
3162
3163 ret = str2prefix_ipv4 (ip_str, &p);
3164 if (ret == 0)
3165 {
3166 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3167 return CMD_WARNING;
3168 }
3169
3170 distance = atoi (distance_str);
3171
3172 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3173 if (! rn)
3174 {
3175 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3176 return CMD_WARNING;
3177 }
3178
3179 rdistance = rn->info;
3180
3181 if (rdistance->access_list)
3182 free (rdistance->access_list);
3183 rip_distance_free (rdistance);
3184
3185 rn->info = NULL;
3186 route_unlock_node (rn);
3187 route_unlock_node (rn);
3188
3189 return CMD_SUCCESS;
3190}
3191
3192void
3193rip_distance_reset ()
3194{
3195 struct route_node *rn;
3196 struct rip_distance *rdistance;
3197
3198 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3199 if ((rdistance = rn->info) != NULL)
3200 {
3201 if (rdistance->access_list)
3202 free (rdistance->access_list);
3203 rip_distance_free (rdistance);
3204 rn->info = NULL;
3205 route_unlock_node (rn);
3206 }
3207}
3208
3209/* Apply RIP information to distance method. */
3210u_char
3211rip_distance_apply (struct rip_info *rinfo)
3212{
3213 struct route_node *rn;
3214 struct prefix_ipv4 p;
3215 struct rip_distance *rdistance;
3216 struct access_list *alist;
3217
3218 if (! rip)
3219 return 0;
3220
3221 memset (&p, 0, sizeof (struct prefix_ipv4));
3222 p.family = AF_INET;
3223 p.prefix = rinfo->from;
3224 p.prefixlen = IPV4_MAX_BITLEN;
3225
3226 /* Check source address. */
3227 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3228 if (rn)
3229 {
3230 rdistance = rn->info;
3231 route_unlock_node (rn);
3232
3233 if (rdistance->access_list)
3234 {
3235 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3236 if (alist == NULL)
3237 return 0;
3238 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3239 return 0;
3240
3241 return rdistance->distance;
3242 }
3243 else
3244 return rdistance->distance;
3245 }
3246
3247 if (rip->distance)
3248 return rip->distance;
3249
3250 return 0;
3251}
3252
3253void
3254rip_distance_show (struct vty *vty)
3255{
3256 struct route_node *rn;
3257 struct rip_distance *rdistance;
3258 int header = 1;
3259 char buf[BUFSIZ];
3260
3261 vty_out (vty, " Distance: (default is %d)%s",
3262 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3263 VTY_NEWLINE);
3264
3265 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3266 if ((rdistance = rn->info) != NULL)
3267 {
3268 if (header)
3269 {
3270 vty_out (vty, " Address Distance List%s",
3271 VTY_NEWLINE);
3272 header = 0;
3273 }
3274 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3275 vty_out (vty, " %-20s %4d %s%s",
3276 buf, rdistance->distance,
3277 rdistance->access_list ? rdistance->access_list : "",
3278 VTY_NEWLINE);
3279 }
3280}
3281
3282DEFUN (rip_distance,
3283 rip_distance_cmd,
3284 "distance <1-255>",
3285 "Administrative distance\n"
3286 "Distance value\n")
3287{
3288 rip->distance = atoi (argv[0]);
3289 return CMD_SUCCESS;
3290}
3291
3292DEFUN (no_rip_distance,
3293 no_rip_distance_cmd,
3294 "no distance <1-255>",
3295 NO_STR
3296 "Administrative distance\n"
3297 "Distance value\n")
3298{
3299 rip->distance = 0;
3300 return CMD_SUCCESS;
3301}
3302
3303DEFUN (rip_distance_source,
3304 rip_distance_source_cmd,
3305 "distance <1-255> A.B.C.D/M",
3306 "Administrative distance\n"
3307 "Distance value\n"
3308 "IP source prefix\n")
3309{
3310 rip_distance_set (vty, argv[0], argv[1], NULL);
3311 return CMD_SUCCESS;
3312}
3313
3314DEFUN (no_rip_distance_source,
3315 no_rip_distance_source_cmd,
3316 "no distance <1-255> A.B.C.D/M",
3317 NO_STR
3318 "Administrative distance\n"
3319 "Distance value\n"
3320 "IP source prefix\n")
3321{
3322 rip_distance_unset (vty, argv[0], argv[1], NULL);
3323 return CMD_SUCCESS;
3324}
3325
3326DEFUN (rip_distance_source_access_list,
3327 rip_distance_source_access_list_cmd,
3328 "distance <1-255> A.B.C.D/M WORD",
3329 "Administrative distance\n"
3330 "Distance value\n"
3331 "IP source prefix\n"
3332 "Access list name\n")
3333{
3334 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3335 return CMD_SUCCESS;
3336}
3337
3338DEFUN (no_rip_distance_source_access_list,
3339 no_rip_distance_source_access_list_cmd,
3340 "no distance <1-255> A.B.C.D/M WORD",
3341 NO_STR
3342 "Administrative distance\n"
3343 "Distance value\n"
3344 "IP source prefix\n"
3345 "Access list name\n")
3346{
3347 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3348 return CMD_SUCCESS;
3349}
3350
3351/* Print out routes update time. */
3352void
3353rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3354{
3355 struct timeval timer_now;
3356 time_t clock;
3357 struct tm *tm;
3358#define TIME_BUF 25
3359 char timebuf [TIME_BUF];
3360 struct thread *thread;
3361
3362 gettimeofday (&timer_now, NULL);
3363
3364 if ((thread = rinfo->t_timeout) != NULL)
3365 {
3366 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3367 tm = gmtime (&clock);
3368 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3369 vty_out (vty, "%5s", timebuf);
3370 }
3371 else if ((thread = rinfo->t_garbage_collect) != NULL)
3372 {
3373 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3374 tm = gmtime (&clock);
3375 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3376 vty_out (vty, "%5s", timebuf);
3377 }
3378}
3379
hasso8a676be2004-10-08 06:36:38 +00003380const char *
paul718e3742002-12-13 20:15:29 +00003381rip_route_type_print (int sub_type)
3382{
3383 switch (sub_type)
3384 {
3385 case RIP_ROUTE_RTE:
3386 return "n";
3387 case RIP_ROUTE_STATIC:
3388 return "s";
3389 case RIP_ROUTE_DEFAULT:
3390 return "d";
3391 case RIP_ROUTE_REDISTRIBUTE:
3392 return "r";
3393 case RIP_ROUTE_INTERFACE:
3394 return "i";
3395 default:
3396 return "?";
3397 }
3398}
3399
3400DEFUN (show_ip_rip,
3401 show_ip_rip_cmd,
3402 "show ip rip",
3403 SHOW_STR
3404 IP_STR
3405 "Show RIP routes\n")
3406{
3407 struct route_node *np;
3408 struct rip_info *rinfo;
3409
3410 if (! rip)
3411 return CMD_SUCCESS;
3412
hasso16705132003-05-25 14:49:19 +00003413 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3414 "Sub-codes:%s"
3415 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003416 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003417 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003418 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003419
3420 for (np = route_top (rip->table); np; np = route_next (np))
3421 if ((rinfo = np->info) != NULL)
3422 {
3423 int len;
3424
3425 len = vty_out (vty, "%s(%s) %s/%d",
3426 /* np->lock, For debugging. */
3427 route_info[rinfo->type].str,
3428 rip_route_type_print (rinfo->sub_type),
3429 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3430
hassoa1455d82004-03-03 19:36:24 +00003431 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003432
3433 if (len > 0)
3434 vty_out (vty, "%*s", len, " ");
3435
3436 if (rinfo->nexthop.s_addr)
3437 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3438 rinfo->metric);
3439 else
3440 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3441
3442 /* Route which exist in kernel routing table. */
3443 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3444 (rinfo->sub_type == RIP_ROUTE_RTE))
3445 {
3446 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
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 if (rinfo->metric == RIP_METRIC_INFINITY)
3451 {
3452 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003453 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003454 rip_vty_out_uptime (vty, rinfo);
3455 }
3456 else
hasso16705132003-05-25 14:49:19 +00003457 {
3458 vty_out (vty, "self ");
3459 vty_out (vty, "%3d", rinfo->tag);
3460 }
paul718e3742002-12-13 20:15:29 +00003461
3462 vty_out (vty, "%s", VTY_NEWLINE);
3463 }
3464 return CMD_SUCCESS;
3465}
3466
3467/* Return next event time. */
3468int
3469rip_next_thread_timer (struct thread *thread)
3470{
3471 struct timeval timer_now;
3472
3473 gettimeofday (&timer_now, NULL);
3474
3475 return thread->u.sands.tv_sec - timer_now.tv_sec;
3476}
3477
hasso16705132003-05-25 14:49:19 +00003478/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3479DEFUN (show_ip_rip_status,
3480 show_ip_rip_status_cmd,
3481 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003482 SHOW_STR
3483 IP_STR
hasso16705132003-05-25 14:49:19 +00003484 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003485 "IP routing protocol process parameters and statistics\n")
3486{
hasso52dc7ee2004-09-23 19:18:23 +00003487 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003488 struct interface *ifp;
3489 struct rip_interface *ri;
3490 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003491 const char *send_version;
3492 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003493
3494 if (! rip)
3495 return CMD_SUCCESS;
3496
3497 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3498 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3499 rip->update_time);
3500 vty_out (vty, " next due in %d seconds%s",
3501 rip_next_thread_timer (rip->t_update),
3502 VTY_NEWLINE);
3503 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3504 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3505 VTY_NEWLINE);
3506
3507 /* Filtering status show. */
3508 config_show_distribute (vty);
3509
3510 /* Default metric information. */
3511 vty_out (vty, " Default redistribution metric is %d%s",
3512 rip->default_metric, VTY_NEWLINE);
3513
3514 /* Redistribute information. */
3515 vty_out (vty, " Redistributing:");
3516 config_write_rip_redistribute (vty, 0);
3517 vty_out (vty, "%s", VTY_NEWLINE);
3518
paulf38a4712003-06-07 01:10:00 +00003519 vty_out (vty, " Default version control: send version %s,",
3520 lookup(ri_version_msg,rip->version_send));
3521 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3522 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3523 else
3524 vty_out (vty, " receive version %s %s",
3525 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003526
3527 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3528
paul1eb8ef22005-04-07 07:30:20 +00003529 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003530 {
paul718e3742002-12-13 20:15:29 +00003531 ri = ifp->info;
3532
3533 if (ri->enable_network || ri->enable_interface)
3534 {
3535 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003536 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003537 else
3538 send_version = lookup (ri_version_msg, ri->ri_send);
3539
3540 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003541 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003542 else
3543 receive_version = lookup (ri_version_msg, ri->ri_receive);
3544
3545 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3546 send_version,
3547 receive_version,
3548 ri->key_chain ? ri->key_chain : "",
3549 VTY_NEWLINE);
3550 }
3551 }
3552
3553 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3554 config_write_rip_network (vty, 0);
3555
paul4aaff3f2003-06-07 01:04:45 +00003556 {
3557 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003558 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003559 {
paul4aaff3f2003-06-07 01:04:45 +00003560 ri = ifp->info;
3561
3562 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3563 {
3564 if (!found_passive)
3565 {
3566 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3567 found_passive = 1;
3568 }
3569 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3570 }
3571 }
3572 }
3573
paul718e3742002-12-13 20:15:29 +00003574 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3575 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3576 rip_peer_display (vty);
3577
3578 rip_distance_show (vty);
3579
3580 return CMD_SUCCESS;
3581}
3582
3583/* RIP configuration write function. */
3584int
3585config_write_rip (struct vty *vty)
3586{
3587 int write = 0;
3588 struct route_node *rn;
3589 struct rip_distance *rdistance;
3590
3591 if (rip)
3592 {
3593 /* Router RIP statement. */
3594 vty_out (vty, "router rip%s", VTY_NEWLINE);
3595 write++;
3596
3597 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003598 if (rip->version_send != RI_RIP_VERSION_2
3599 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3600 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003601 VTY_NEWLINE);
3602
3603 /* RIP timer configuration. */
3604 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3605 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3606 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3607 vty_out (vty, " timers basic %lu %lu %lu%s",
3608 rip->update_time,
3609 rip->timeout_time,
3610 rip->garbage_time,
3611 VTY_NEWLINE);
3612
3613 /* Default information configuration. */
3614 if (rip->default_information)
3615 {
3616 if (rip->default_information_route_map)
3617 vty_out (vty, " default-information originate route-map %s%s",
3618 rip->default_information_route_map, VTY_NEWLINE);
3619 else
3620 vty_out (vty, " default-information originate%s",
3621 VTY_NEWLINE);
3622 }
3623
3624 /* Redistribute configuration. */
3625 config_write_rip_redistribute (vty, 1);
3626
3627 /* RIP offset-list configuration. */
3628 config_write_rip_offset_list (vty);
3629
3630 /* RIP enabled network and interface configuration. */
3631 config_write_rip_network (vty, 1);
3632
3633 /* RIP default metric configuration */
3634 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3635 vty_out (vty, " default-metric %d%s",
3636 rip->default_metric, VTY_NEWLINE);
3637
3638 /* Distribute configuration. */
3639 write += config_write_distribute (vty);
3640
hasso16705132003-05-25 14:49:19 +00003641 /* Interface routemap configuration */
3642 write += config_write_if_rmap (vty);
3643
paul718e3742002-12-13 20:15:29 +00003644 /* Distance configuration. */
3645 if (rip->distance)
3646 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3647
3648 /* RIP source IP prefix distance configuration. */
3649 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3650 if ((rdistance = rn->info) != NULL)
3651 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3652 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3653 rdistance->access_list ? rdistance->access_list : "",
3654 VTY_NEWLINE);
3655
3656 /* RIP static route configuration. */
3657 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3658 if (rn->info)
3659 vty_out (vty, " route %s/%d%s",
3660 inet_ntoa (rn->p.u.prefix4),
3661 rn->p.prefixlen,
3662 VTY_NEWLINE);
3663
3664 }
3665 return write;
3666}
3667
3668/* RIP node structure. */
3669struct cmd_node rip_node =
3670{
3671 RIP_NODE,
3672 "%s(config-router)# ",
3673 1
3674};
3675
3676/* Distribute-list update functions. */
3677void
3678rip_distribute_update (struct distribute *dist)
3679{
3680 struct interface *ifp;
3681 struct rip_interface *ri;
3682 struct access_list *alist;
3683 struct prefix_list *plist;
3684
3685 if (! dist->ifname)
3686 return;
3687
3688 ifp = if_lookup_by_name (dist->ifname);
3689 if (ifp == NULL)
3690 return;
3691
3692 ri = ifp->info;
3693
3694 if (dist->list[DISTRIBUTE_IN])
3695 {
3696 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3697 if (alist)
3698 ri->list[RIP_FILTER_IN] = alist;
3699 else
3700 ri->list[RIP_FILTER_IN] = NULL;
3701 }
3702 else
3703 ri->list[RIP_FILTER_IN] = NULL;
3704
3705 if (dist->list[DISTRIBUTE_OUT])
3706 {
3707 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3708 if (alist)
3709 ri->list[RIP_FILTER_OUT] = alist;
3710 else
3711 ri->list[RIP_FILTER_OUT] = NULL;
3712 }
3713 else
3714 ri->list[RIP_FILTER_OUT] = NULL;
3715
3716 if (dist->prefix[DISTRIBUTE_IN])
3717 {
3718 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3719 if (plist)
3720 ri->prefix[RIP_FILTER_IN] = plist;
3721 else
3722 ri->prefix[RIP_FILTER_IN] = NULL;
3723 }
3724 else
3725 ri->prefix[RIP_FILTER_IN] = NULL;
3726
3727 if (dist->prefix[DISTRIBUTE_OUT])
3728 {
3729 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3730 if (plist)
3731 ri->prefix[RIP_FILTER_OUT] = plist;
3732 else
3733 ri->prefix[RIP_FILTER_OUT] = NULL;
3734 }
3735 else
3736 ri->prefix[RIP_FILTER_OUT] = NULL;
3737}
3738
3739void
3740rip_distribute_update_interface (struct interface *ifp)
3741{
3742 struct distribute *dist;
3743
3744 dist = distribute_lookup (ifp->name);
3745 if (dist)
3746 rip_distribute_update (dist);
3747}
3748
3749/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003750/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003751void
paul02ff83c2004-06-11 11:27:03 +00003752rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003753{
3754 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003755 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003756
paul1eb8ef22005-04-07 07:30:20 +00003757 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3758 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003759}
paul11dde9c2004-05-31 14:00:00 +00003760/* ARGSUSED */
3761void
3762rip_distribute_update_all_wrapper(struct access_list *notused)
3763{
paul02ff83c2004-06-11 11:27:03 +00003764 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003765}
paul718e3742002-12-13 20:15:29 +00003766
3767/* Delete all added rip route. */
3768void
3769rip_clean ()
3770{
3771 int i;
3772 struct route_node *rp;
3773 struct rip_info *rinfo;
3774
3775 if (rip)
3776 {
3777 /* Clear RIP routes */
3778 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3779 if ((rinfo = rp->info) != NULL)
3780 {
3781 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3782 rinfo->sub_type == RIP_ROUTE_RTE)
3783 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3784 &rinfo->nexthop, rinfo->metric);
3785
3786 RIP_TIMER_OFF (rinfo->t_timeout);
3787 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3788
3789 rp->info = NULL;
3790 route_unlock_node (rp);
3791
3792 rip_info_free (rinfo);
3793 }
3794
3795 /* Cancel RIP related timers. */
3796 RIP_TIMER_OFF (rip->t_update);
3797 RIP_TIMER_OFF (rip->t_triggered_update);
3798 RIP_TIMER_OFF (rip->t_triggered_interval);
3799
3800 /* Cancel read thread. */
3801 if (rip->t_read)
3802 {
3803 thread_cancel (rip->t_read);
3804 rip->t_read = NULL;
3805 }
3806
3807 /* Close RIP socket. */
3808 if (rip->sock >= 0)
3809 {
3810 close (rip->sock);
3811 rip->sock = -1;
3812 }
3813
3814 /* Static RIP route configuration. */
3815 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3816 if (rp->info)
3817 {
3818 rp->info = NULL;
3819 route_unlock_node (rp);
3820 }
3821
3822 /* RIP neighbor configuration. */
3823 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3824 if (rp->info)
3825 {
3826 rp->info = NULL;
3827 route_unlock_node (rp);
3828 }
3829
3830 /* Redistribute related clear. */
3831 if (rip->default_information_route_map)
3832 free (rip->default_information_route_map);
3833
3834 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3835 if (rip->route_map[i].name)
3836 free (rip->route_map[i].name);
3837
3838 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3839 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3840 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3841
3842 XFREE (MTYPE_RIP, rip);
3843 rip = NULL;
3844 }
3845
3846 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003847 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003848 rip_offset_clean ();
3849 rip_interface_clean ();
3850 rip_distance_reset ();
3851 rip_redistribute_clean ();
3852}
3853
3854/* Reset all values to the default settings. */
3855void
3856rip_reset ()
3857{
3858 /* Reset global counters. */
3859 rip_global_route_changes = 0;
3860 rip_global_queries = 0;
3861
3862 /* Call ripd related reset functions. */
3863 rip_debug_reset ();
3864 rip_route_map_reset ();
3865
3866 /* Call library reset functions. */
3867 vty_reset ();
3868 access_list_reset ();
3869 prefix_list_reset ();
3870
3871 distribute_list_reset ();
3872
3873 rip_interface_reset ();
3874 rip_distance_reset ();
3875
3876 rip_zclient_reset ();
3877}
3878
hasso16705132003-05-25 14:49:19 +00003879void
3880rip_if_rmap_update (struct if_rmap *if_rmap)
3881{
3882 struct interface *ifp;
3883 struct rip_interface *ri;
3884 struct route_map *rmap;
3885
3886 ifp = if_lookup_by_name (if_rmap->ifname);
3887 if (ifp == NULL)
3888 return;
3889
3890 ri = ifp->info;
3891
3892 if (if_rmap->routemap[IF_RMAP_IN])
3893 {
3894 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3895 if (rmap)
3896 ri->routemap[IF_RMAP_IN] = rmap;
3897 else
3898 ri->routemap[IF_RMAP_IN] = NULL;
3899 }
3900 else
3901 ri->routemap[RIP_FILTER_IN] = NULL;
3902
3903 if (if_rmap->routemap[IF_RMAP_OUT])
3904 {
3905 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3906 if (rmap)
3907 ri->routemap[IF_RMAP_OUT] = rmap;
3908 else
3909 ri->routemap[IF_RMAP_OUT] = NULL;
3910 }
3911 else
3912 ri->routemap[RIP_FILTER_OUT] = NULL;
3913}
3914
3915void
3916rip_if_rmap_update_interface (struct interface *ifp)
3917{
3918 struct if_rmap *if_rmap;
3919
3920 if_rmap = if_rmap_lookup (ifp->name);
3921 if (if_rmap)
3922 rip_if_rmap_update (if_rmap);
3923}
3924
3925void
3926rip_routemap_update_redistribute (void)
3927{
3928 int i;
3929
3930 if (rip)
3931 {
3932 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3933 {
3934 if (rip->route_map[i].name)
3935 rip->route_map[i].map =
3936 route_map_lookup_by_name (rip->route_map[i].name);
3937 }
3938 }
3939}
3940
paul11dde9c2004-05-31 14:00:00 +00003941/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003942void
hasso98b718a2004-10-11 12:57:57 +00003943rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003944{
3945 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003946 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003947
paul1eb8ef22005-04-07 07:30:20 +00003948 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3949 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003950
3951 rip_routemap_update_redistribute ();
3952}
3953
paul718e3742002-12-13 20:15:29 +00003954/* Allocate new rip structure and set default value. */
3955void
3956rip_init ()
3957{
3958 /* Randomize for triggered update random(). */
3959 srand (time (NULL));
3960
3961 /* Install top nodes. */
3962 install_node (&rip_node, config_write_rip);
3963
3964 /* Install rip commands. */
3965 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003966 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003967 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003968 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003969 install_element (CONFIG_NODE, &router_rip_cmd);
3970 install_element (CONFIG_NODE, &no_router_rip_cmd);
3971
3972 install_default (RIP_NODE);
3973 install_element (RIP_NODE, &rip_version_cmd);
3974 install_element (RIP_NODE, &no_rip_version_cmd);
3975 install_element (RIP_NODE, &no_rip_version_val_cmd);
3976 install_element (RIP_NODE, &rip_default_metric_cmd);
3977 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3978 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3979 install_element (RIP_NODE, &rip_timers_cmd);
3980 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003981 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003982 install_element (RIP_NODE, &rip_route_cmd);
3983 install_element (RIP_NODE, &no_rip_route_cmd);
3984 install_element (RIP_NODE, &rip_distance_cmd);
3985 install_element (RIP_NODE, &no_rip_distance_cmd);
3986 install_element (RIP_NODE, &rip_distance_source_cmd);
3987 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3988 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3989 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3990
3991 /* Debug related init. */
3992 rip_debug_init ();
3993
paul718e3742002-12-13 20:15:29 +00003994 /* SNMP init. */
3995#ifdef HAVE_SNMP
3996 rip_snmp_init ();
3997#endif /* HAVE_SNMP */
3998
3999 /* Access list install. */
4000 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004001 access_list_add_hook (rip_distribute_update_all_wrapper);
4002 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004003
4004 /* Prefix list initialize.*/
4005 prefix_list_init ();
4006 prefix_list_add_hook (rip_distribute_update_all);
4007 prefix_list_delete_hook (rip_distribute_update_all);
4008
4009 /* Distribute list install. */
4010 distribute_list_init (RIP_NODE);
4011 distribute_list_add_hook (rip_distribute_update);
4012 distribute_list_delete_hook (rip_distribute_update);
4013
hasso16705132003-05-25 14:49:19 +00004014 /* Route-map */
4015 rip_route_map_init ();
4016 rip_offset_init ();
4017
4018 route_map_add_hook (rip_routemap_update);
4019 route_map_delete_hook (rip_routemap_update);
4020
4021 if_rmap_init (RIP_NODE);
4022 if_rmap_hook_add (rip_if_rmap_update);
4023 if_rmap_hook_delete (rip_if_rmap_update);
4024
paul718e3742002-12-13 20:15:29 +00004025 /* Distance control. */
4026 rip_distance_table = route_table_init ();
4027}