blob: b75e018b81614af1c3f24754d1c93f53e2f39ae7 [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"
vincentc1a03d42005-09-28 15:47:44 +000039#include "md5.h"
paul718e3742002-12-13 20:15:29 +000040#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;
vincentc1a03d42005-09-28 15:47:44 +0000845 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000846 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
vincentc1a03d42005-09-28 15:47:44 +0000918 memset (&ctx, 0, sizeof(ctx));
919 MD5Init(&ctx);
920 MD5Update(&ctx, packet, packet_len + md5->auth_len);
921 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000922
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;
vincentc1a03d42005-09-28 15:47:44 +00001050 MD5_CTX ctx;
paulb14ee002005-02-04 23:42:41 +00001051 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. */
vincentc1a03d42005-09-28 15:47:44 +00001076 memset(&ctx, 0, sizeof(ctx));
1077 MD5Init(&ctx);
1078 MD5Update(&ctx, s->data, s->endp);
1079 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1080 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +00001081
1082 /* Copy the digest to the packet. */
1083 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1084}
1085
1086/* RIP routing information. */
1087void
1088rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001089 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001090{
1091 caddr_t lim;
1092 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001093 struct prefix_ipv4 ifaddr;
1094 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001095 int subnetted;
paul718e3742002-12-13 20:15:29 +00001096
paul727d1042002-12-13 20:50:29 +00001097 /* We don't know yet. */
1098 subnetted = -1;
1099
paul718e3742002-12-13 20:15:29 +00001100 /* The Response must be ignored if it is not from the RIP
1101 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001102 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001103 {
1104 zlog_info ("response doesn't come from RIP port: %d",
1105 from->sin_port);
1106 rip_peer_bad_packet (from);
1107 return;
1108 }
1109
1110 /* The datagram's IPv4 source address should be checked to see
1111 whether the datagram is from a valid neighbor; the source of the
1112 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001113 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001114 {
1115 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1116 inet_ntoa (from->sin_addr));
1117 rip_peer_bad_packet (from);
1118 return;
1119 }
1120
1121 /* It is also worth checking to see whether the response is from one
1122 of the router's own addresses. */
1123
1124 ; /* Alredy done in rip_read () */
1125
1126 /* Update RIP peer. */
1127 rip_peer_update (from, packet->version);
1128
1129 /* Set RTE pointer. */
1130 rte = packet->rte;
1131
1132 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1133 {
1134 /* RIPv2 authentication check. */
1135 /* If the Address Family Identifier of the first (and only the
1136 first) entry in the message is 0xFFFF, then the remainder of
1137 the entry contains the authentication. */
1138 /* If the packet gets here it means authentication enabled */
1139 /* Check is done in rip_read(). So, just skipping it */
1140 if (packet->version == RIPv2 &&
1141 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001142 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001143 continue;
1144
paulca5e5162004-06-06 22:06:33 +00001145 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001146 {
1147 /* Address family check. RIP only supports AF_INET. */
1148 zlog_info ("Unsupported family %d from %s.",
1149 ntohs (rte->family), inet_ntoa (from->sin_addr));
1150 continue;
1151 }
1152
1153 /* - is the destination address valid (e.g., unicast; not net 0
1154 or 127) */
1155 if (! rip_destination_check (rte->prefix))
1156 {
1157 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1158 rip_peer_bad_route (from);
1159 continue;
1160 }
1161
1162 /* Convert metric value to host byte order. */
1163 rte->metric = ntohl (rte->metric);
1164
1165 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1166 if (! (rte->metric >= 1 && rte->metric <= 16))
1167 {
1168 zlog_info ("Route's metric is not in the 1-16 range.");
1169 rip_peer_bad_route (from);
1170 continue;
1171 }
1172
1173 /* RIPv1 does not have nexthop value. */
1174 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1175 {
1176 zlog_info ("RIPv1 packet with nexthop value %s",
1177 inet_ntoa (rte->nexthop));
1178 rip_peer_bad_route (from);
1179 continue;
1180 }
1181
1182 /* That is, if the provided information is ignored, a possibly
1183 sub-optimal, but absolutely valid, route may be taken. If
1184 the received Next Hop is not directly reachable, it should be
1185 treated as 0.0.0.0. */
1186 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1187 {
1188 u_int32_t addrval;
1189
1190 /* Multicast address check. */
1191 addrval = ntohl (rte->nexthop.s_addr);
1192 if (IN_CLASSD (addrval))
1193 {
1194 zlog_info ("Nexthop %s is multicast address, skip this rte",
1195 inet_ntoa (rte->nexthop));
1196 continue;
1197 }
1198
1199 if (! if_lookup_address (rte->nexthop))
1200 {
1201 struct route_node *rn;
1202 struct rip_info *rinfo;
1203
1204 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1205
1206 if (rn)
1207 {
1208 rinfo = rn->info;
1209
1210 if (rinfo->type == ZEBRA_ROUTE_RIP
1211 && rinfo->sub_type == RIP_ROUTE_RTE)
1212 {
1213 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001214 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 +00001215 rte->nexthop = rinfo->from;
1216 }
1217 else
1218 {
1219 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001220 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 +00001221 rte->nexthop.s_addr = 0;
1222 }
1223
1224 route_unlock_node (rn);
1225 }
1226 else
1227 {
1228 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001229 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 +00001230 rte->nexthop.s_addr = 0;
1231 }
1232
1233 }
1234 }
1235
1236 /* For RIPv1, there won't be a valid netmask.
1237
1238 This is a best guess at the masks. If everyone was using old
1239 Ciscos before the 'ip subnet zero' option, it would be almost
1240 right too :-)
1241
1242 Cisco summarize ripv1 advertisments to the classful boundary
1243 (/16 for class B's) except when the RIP packet does to inside
1244 the classful network in question. */
1245
1246 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1247 || (packet->version == RIPv2
1248 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1249 {
1250 u_int32_t destination;
1251
paul727d1042002-12-13 20:50:29 +00001252 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001253 {
1254 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1255 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1256 apply_classful_mask_ipv4 (&ifaddrclass);
1257 subnetted = 0;
1258 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1259 subnetted = 1;
1260 }
paul727d1042002-12-13 20:50:29 +00001261
paul718e3742002-12-13 20:15:29 +00001262 destination = ntohl (rte->prefix.s_addr);
1263
paul727d1042002-12-13 20:50:29 +00001264 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001265 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001266 else if (IN_CLASSB (destination))
1267 masklen2ip (16, &rte->mask);
1268 else if (IN_CLASSC (destination))
1269 masklen2ip (24, &rte->mask);
1270
1271 if (subnetted == 1)
1272 masklen2ip (ifaddrclass.prefixlen,
1273 (struct in_addr *) &destination);
1274 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1275 ifaddrclass.prefix.s_addr))
1276 {
1277 masklen2ip (ifaddr.prefixlen, &rte->mask);
1278 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1279 masklen2ip (32, &rte->mask);
1280 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001281 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001282 }
1283 else
1284 {
1285 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1286 continue;
1287 }
1288
1289 if (IS_RIP_DEBUG_EVENT)
1290 {
ajs5d6c3772004-12-08 19:24:06 +00001291 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1292 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001293 }
1294 }
1295
1296 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1297 ignore the entry. */
1298 if ((packet->version == RIPv2)
1299 && (rte->mask.s_addr != 0)
1300 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1301 {
1302 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1303 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1304 rip_peer_bad_route (from);
1305 continue;
1306 }
1307
1308 /* Default route's netmask is ignored. */
1309 if (packet->version == RIPv2
1310 && (rte->prefix.s_addr == 0)
1311 && (rte->mask.s_addr != 0))
1312 {
1313 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001314 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001315 rte->mask.s_addr = 0;
1316 }
1317
1318 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001319 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001320 }
1321}
1322
paula4e987e2005-06-03 17:46:49 +00001323/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001324static int
paul2c61ae32005-08-16 15:22:14 +00001325rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001326{
1327 int ret;
1328 int sock;
1329 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001330
paul2c61ae32005-08-16 15:22:14 +00001331 memset (&addr, 0, sizeof (struct sockaddr_in));
1332
1333 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001334 {
paulf69bd9d2005-06-03 18:01:50 +00001335 addr.sin_family = AF_INET;
1336 addr.sin_addr.s_addr = INADDR_ANY;
paul2c61ae32005-08-16 15:22:14 +00001337#ifdef HAVE_SINLEN
1338 addr.sin_len = sizeof (struct sockaddr_in);
1339#endif /* HAVE_SINLEN */
paulf69bd9d2005-06-03 18:01:50 +00001340 }
1341
paul2c61ae32005-08-16 15:22:14 +00001342 /* sending port must always be the RIP port */
1343 addr.sin_port = htons (RIP_PORT_DEFAULT);
1344
paula4e987e2005-06-03 17:46:49 +00001345 /* Make datagram socket. */
1346 sock = socket (AF_INET, SOCK_DGRAM, 0);
1347 if (sock < 0)
1348 {
1349 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1350 exit (1);
1351 }
1352
1353 sockopt_broadcast (sock);
1354 sockopt_reuseaddr (sock);
1355 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001356#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");
paulf69bd9d2005-06-03 18:01:50 +00001362 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1363 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1364
paula4e987e2005-06-03 17:46:49 +00001365 {
1366 int save_errno = errno;
1367 if (ripd_privs.change (ZPRIVS_LOWER))
1368 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001369
1370 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1371 sock, inet_ntoa(addr.sin_addr),
1372 (int) ntohs(addr.sin_port),
1373 safe_strerror(save_errno));
1374
paulf69bd9d2005-06-03 18:01:50 +00001375 close (sock);
paula4e987e2005-06-03 17:46:49 +00001376 return ret;
1377 }
paulf69bd9d2005-06-03 18:01:50 +00001378
paula4e987e2005-06-03 17:46:49 +00001379 if (ripd_privs.change (ZPRIVS_LOWER))
1380 zlog_err ("rip_create_socket: could not lower privs");
1381
1382 return sock;
1383}
1384
paulc49ad8f2004-10-22 10:27:28 +00001385/* RIP packet send to destination address, on interface denoted by
1386 * by connected argument. NULL to argument denotes destination should be
1387 * should be RIP multicast group
1388 */
paul718e3742002-12-13 20:15:29 +00001389int
paulc49ad8f2004-10-22 10:27:28 +00001390rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1391 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001392{
paul931cd542004-01-23 15:31:42 +00001393 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001394 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001395
1396 assert (ifc != NULL);
1397
paul931cd542004-01-23 15:31:42 +00001398 if (IS_RIP_DEBUG_PACKET)
1399 {
paulf69bd9d2005-06-03 18:01:50 +00001400#define ADDRESS_SIZE 20
1401 char dst[ADDRESS_SIZE];
1402 dst[ADDRESS_SIZE - 1] = '\0';
1403
paul931cd542004-01-23 15:31:42 +00001404 if (to)
1405 {
paulf69bd9d2005-06-03 18:01:50 +00001406 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001407 }
1408 else
1409 {
1410 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001411 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001412 }
paulf69bd9d2005-06-03 18:01:50 +00001413#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001414 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001415 inet_ntoa(ifc->address->u.prefix4),
1416 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001417 }
paulf69bd9d2005-06-03 18:01:50 +00001418
paulc49ad8f2004-10-22 10:27:28 +00001419 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001420 {
1421 /*
1422 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1423 * with multiple addresses on the same subnet: the first address
1424 * on the subnet is configured "primary", and all subsequent addresses
1425 * on that subnet are treated as "secondary" addresses.
1426 * In order to avoid routing-table bloat on other rip listeners,
1427 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1428 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1429 * flag is set, we would end up sending a packet for a "secondary"
1430 * source address on non-linux systems.
1431 */
1432 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001433 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001434 return 0;
1435 }
1436
paul718e3742002-12-13 20:15:29 +00001437 /* Make destination address. */
1438 memset (&sin, 0, sizeof (struct sockaddr_in));
1439 sin.sin_family = AF_INET;
1440#ifdef HAVE_SIN_LEN
1441 sin.sin_len = sizeof (struct sockaddr_in);
1442#endif /* HAVE_SIN_LEN */
1443
1444 /* When destination is specified, use it's port and address. */
1445 if (to)
1446 {
paul718e3742002-12-13 20:15:29 +00001447 sin.sin_port = to->sin_port;
1448 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001449 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001450 }
1451 else
1452 {
paul2c61ae32005-08-16 15:22:14 +00001453 struct sockaddr_in from;
1454
paul718e3742002-12-13 20:15:29 +00001455 sin.sin_port = htons (RIP_PORT_DEFAULT);
1456 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001457
1458 /* multicast send should bind to local interface address */
1459 from.sin_family = AF_INET;
1460 from.sin_port = htons (RIP_PORT_DEFAULT);
1461 from.sin_addr = ifc->address->u.prefix4;
1462#ifdef HAVE_SIN_LEN
1463 from.sin_len = sizeof (struct sockaddr_in);
1464#endif /* HAVE_SIN_LEN */
1465
paul931cd542004-01-23 15:31:42 +00001466 /*
1467 * we have to open a new socket for each packet because this
1468 * is the most portable way to bind to a different source
1469 * ipv4 address for each packet.
1470 */
paul2c61ae32005-08-16 15:22:14 +00001471 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001472 {
paulf69bd9d2005-06-03 18:01:50 +00001473 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001474 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001475 }
paulc49ad8f2004-10-22 10:27:28 +00001476 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001477 }
1478
paul931cd542004-01-23 15:31:42 +00001479 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001480 sizeof (struct sockaddr_in));
1481
1482 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001483 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001484 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001485
1486 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001487 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001488
paul931cd542004-01-23 15:31:42 +00001489 if (!to)
1490 close(send_sock);
1491
paul718e3742002-12-13 20:15:29 +00001492 return ret;
1493}
1494
1495/* Add redistributed route to RIP table. */
1496void
1497rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1498 unsigned int ifindex, struct in_addr *nexthop)
1499{
1500 int ret;
1501 struct route_node *rp;
1502 struct rip_info *rinfo;
1503
1504 /* Redistribute route */
1505 ret = rip_destination_check (p->prefix);
1506 if (! ret)
1507 return;
1508
1509 rp = route_node_get (rip->table, (struct prefix *) p);
1510
1511 rinfo = rp->info;
1512
1513 if (rinfo)
1514 {
1515 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1516 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1517 && rinfo->metric != RIP_METRIC_INFINITY)
1518 {
1519 route_unlock_node (rp);
1520 return;
1521 }
1522
1523 /* Manually configured RIP route check. */
1524 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001525 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1526 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001527 {
hasso16705132003-05-25 14:49:19 +00001528 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1529 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001530 {
1531 route_unlock_node (rp);
1532 return;
1533 }
1534 }
1535
1536 RIP_TIMER_OFF (rinfo->t_timeout);
1537 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1538
1539 if (rip_route_rte (rinfo))
1540 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1541 rinfo->metric);
1542 rp->info = NULL;
1543 rip_info_free (rinfo);
1544
1545 route_unlock_node (rp);
1546 }
1547
1548 rinfo = rip_info_new ();
1549
1550 rinfo->type = type;
1551 rinfo->sub_type = sub_type;
1552 rinfo->ifindex = ifindex;
1553 rinfo->metric = 1;
1554 rinfo->rp = rp;
1555
1556 if (nexthop)
1557 rinfo->nexthop = *nexthop;
1558
1559 rinfo->flags |= RIP_RTF_FIB;
1560 rp->info = rinfo;
1561
1562 rinfo->flags |= RIP_RTF_CHANGED;
1563
hasso16705132003-05-25 14:49:19 +00001564 if (IS_RIP_DEBUG_EVENT) {
1565 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001566 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001567 inet_ntoa(p->prefix), p->prefixlen,
1568 ifindex2ifname(ifindex));
1569 else
ajs5d6c3772004-12-08 19:24:06 +00001570 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001571 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1572 ifindex2ifname(ifindex));
1573 }
1574
1575
paul718e3742002-12-13 20:15:29 +00001576 rip_event (RIP_TRIGGERED_UPDATE, 0);
1577}
1578
1579/* Delete redistributed route from RIP table. */
1580void
1581rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1582 unsigned int ifindex)
1583{
1584 int ret;
1585 struct route_node *rp;
1586 struct rip_info *rinfo;
1587
1588 ret = rip_destination_check (p->prefix);
1589 if (! ret)
1590 return;
1591
1592 rp = route_node_lookup (rip->table, (struct prefix *) p);
1593 if (rp)
1594 {
1595 rinfo = rp->info;
1596
1597 if (rinfo != NULL
1598 && rinfo->type == type
1599 && rinfo->sub_type == sub_type
1600 && rinfo->ifindex == ifindex)
1601 {
1602 /* Perform poisoned reverse. */
1603 rinfo->metric = RIP_METRIC_INFINITY;
1604 RIP_TIMER_ON (rinfo->t_garbage_collect,
1605 rip_garbage_collect, rip->garbage_time);
1606 RIP_TIMER_OFF (rinfo->t_timeout);
1607 rinfo->flags |= RIP_RTF_CHANGED;
1608
hasso16705132003-05-25 14:49:19 +00001609 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001610 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001611 inet_ntoa(p->prefix), p->prefixlen,
1612 ifindex2ifname(ifindex));
1613
paul718e3742002-12-13 20:15:29 +00001614 rip_event (RIP_TRIGGERED_UPDATE, 0);
1615 }
1616 }
1617}
1618
1619/* Response to request called from rip_read ().*/
1620void
1621rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001622 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001623{
1624 caddr_t lim;
1625 struct rte *rte;
1626 struct prefix_ipv4 p;
1627 struct route_node *rp;
1628 struct rip_info *rinfo;
1629 struct rip_interface *ri;
1630
hasso16705132003-05-25 14:49:19 +00001631 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001632 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001633 return;
1634
hasso429a0f82004-02-22 23:42:22 +00001635 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001636 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001637 if (! ri->running)
1638 return;
paul718e3742002-12-13 20:15:29 +00001639
1640 /* When passive interface is specified, suppress responses */
1641 if (ri->passive)
1642 return;
paulc49ad8f2004-10-22 10:27:28 +00001643
paul718e3742002-12-13 20:15:29 +00001644 /* RIP peer update. */
1645 rip_peer_update (from, packet->version);
1646
1647 lim = ((caddr_t) packet) + size;
1648 rte = packet->rte;
1649
1650 /* The Request is processed entry by entry. If there are no
1651 entries, no response is given. */
1652 if (lim == (caddr_t) rte)
1653 return;
1654
1655 /* There is one special case. If there is exactly one entry in the
1656 request, and it has an address family identifier of zero and a
1657 metric of infinity (i.e., 16), then this is a request to send the
1658 entire routing table. */
1659 if (lim == ((caddr_t) (rte + 1)) &&
1660 ntohs (rte->family) == 0 &&
1661 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1662 {
paulcc1131a2003-10-15 23:20:17 +00001663 struct prefix_ipv4 saddr;
1664
1665 /* saddr will be used for determining which routes to split-horizon.
1666 Since the source address we'll pick will be on the same subnet as the
1667 destination, for the purpose of split-horizoning, we'll
1668 pretend that "from" is our source address. */
1669 saddr.family = AF_INET;
1670 saddr.prefixlen = IPV4_MAX_BITLEN;
1671 saddr.prefix = from->sin_addr;
1672
paul718e3742002-12-13 20:15:29 +00001673 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001674 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001675 }
1676 else
1677 {
1678 /* Examine the list of RTEs in the Request one by one. For each
1679 entry, look up the destination in the router's routing
1680 database and, if there is a route, put that route's metric in
1681 the metric field of the RTE. If there is no explicit route
1682 to the specified destination, put infinity in the metric
1683 field. Once all the entries have been filled in, change the
1684 command from Request to Response and send the datagram back
1685 to the requestor. */
1686 p.family = AF_INET;
1687
1688 for (; ((caddr_t) rte) < lim; rte++)
1689 {
1690 p.prefix = rte->prefix;
1691 p.prefixlen = ip_masklen (rte->mask);
1692 apply_mask_ipv4 (&p);
1693
1694 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1695 if (rp)
1696 {
1697 rinfo = rp->info;
1698 rte->metric = htonl (rinfo->metric);
1699 route_unlock_node (rp);
1700 }
1701 else
1702 rte->metric = htonl (RIP_METRIC_INFINITY);
1703 }
1704 packet->command = RIP_RESPONSE;
1705
paulc49ad8f2004-10-22 10:27:28 +00001706 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001707 }
1708 rip_global_queries++;
1709}
1710
1711#if RIP_RECVMSG
1712/* Set IPv6 packet info to the socket. */
1713static int
1714setsockopt_pktinfo (int sock)
1715{
1716 int ret;
1717 int val = 1;
1718
1719 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1720 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001721 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001722 return ret;
1723}
1724
1725/* Read RIP packet by recvmsg function. */
1726int
1727rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1728 int *ifindex)
1729{
1730 int ret;
1731 struct msghdr msg;
1732 struct iovec iov;
1733 struct cmsghdr *ptr;
1734 char adata[1024];
1735
1736 msg.msg_name = (void *) from;
1737 msg.msg_namelen = sizeof (struct sockaddr_in);
1738 msg.msg_iov = &iov;
1739 msg.msg_iovlen = 1;
1740 msg.msg_control = (void *) adata;
1741 msg.msg_controllen = sizeof adata;
1742 iov.iov_base = buf;
1743 iov.iov_len = size;
1744
1745 ret = recvmsg (sock, &msg, 0);
1746 if (ret < 0)
1747 return ret;
1748
ajsb99760a2005-01-04 16:24:43 +00001749 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001750 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1751 {
1752 struct in_pktinfo *pktinfo;
1753 int i;
1754
1755 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1756 i = pktinfo->ipi_ifindex;
1757 }
1758 return ret;
1759}
1760
1761/* RIP packet read function. */
1762int
1763rip_read_new (struct thread *t)
1764{
1765 int ret;
1766 int sock;
1767 char buf[RIP_PACKET_MAXSIZ];
1768 struct sockaddr_in from;
1769 unsigned int ifindex;
1770
1771 /* Fetch socket then register myself. */
1772 sock = THREAD_FD (t);
1773 rip_event (RIP_READ, sock);
1774
1775 /* Read RIP packet. */
1776 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1777 if (ret < 0)
1778 {
ajs6099b3b2004-11-20 02:06:59 +00001779 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001780 return ret;
1781 }
1782
1783 return ret;
1784}
1785#endif /* RIP_RECVMSG */
1786
1787/* First entry point of RIP packet. */
1788int
1789rip_read (struct thread *t)
1790{
1791 int sock;
1792 int ret;
1793 int rtenum;
1794 union rip_buf rip_buf;
1795 struct rip_packet *packet;
1796 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001797 int len;
1798 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001799 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001800 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001801 struct rip_interface *ri;
1802
1803 /* Fetch socket then register myself. */
1804 sock = THREAD_FD (t);
1805 rip->t_read = NULL;
1806
1807 /* Add myself to tne next event */
1808 rip_event (RIP_READ, sock);
1809
1810 /* RIPd manages only IPv4. */
1811 memset (&from, 0, sizeof (struct sockaddr_in));
1812 fromlen = sizeof (struct sockaddr_in);
1813
1814 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1815 (struct sockaddr *) &from, &fromlen);
1816 if (len < 0)
1817 {
ajs6099b3b2004-11-20 02:06:59 +00001818 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001819 return len;
1820 }
1821
1822 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001823 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001824 {
1825 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001826 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001827 return -1;
1828 }
1829
1830 /* Which interface is this packet comes from. */
1831 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001832
paul718e3742002-12-13 20:15:29 +00001833 /* RIP packet received */
1834 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001835 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001836 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1837 ifp ? ifp->name : "unknown");
1838
1839 /* If this packet come from unknown interface, ignore it. */
1840 if (ifp == NULL)
1841 {
ajs766a0ca2004-12-15 14:55:51 +00001842 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1843 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001844 return -1;
1845 }
1846
1847 ifc = connected_lookup_address (ifp, from.sin_addr);
1848
1849 if (ifc == NULL)
1850 {
ajs766a0ca2004-12-15 14:55:51 +00001851 zlog_info ("rip_read: cannot find connected address for packet from %s "
1852 "port %d on interface %s",
1853 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001854 return -1;
1855 }
1856
1857 /* Packet length check. */
1858 if (len < RIP_PACKET_MINSIZ)
1859 {
1860 zlog_warn ("packet size %d is smaller than minimum size %d",
1861 len, RIP_PACKET_MINSIZ);
1862 rip_peer_bad_packet (&from);
1863 return len;
1864 }
1865 if (len > RIP_PACKET_MAXSIZ)
1866 {
1867 zlog_warn ("packet size %d is larger than max size %d",
1868 len, RIP_PACKET_MAXSIZ);
1869 rip_peer_bad_packet (&from);
1870 return len;
1871 }
1872
1873 /* Packet alignment check. */
1874 if ((len - RIP_PACKET_MINSIZ) % 20)
1875 {
1876 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1877 rip_peer_bad_packet (&from);
1878 return len;
1879 }
1880
1881 /* Set RTE number. */
1882 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1883
1884 /* For easy to handle. */
1885 packet = &rip_buf.rip_packet;
1886
1887 /* RIP version check. */
1888 if (packet->version == 0)
1889 {
1890 zlog_info ("version 0 with command %d received.", packet->command);
1891 rip_peer_bad_packet (&from);
1892 return -1;
1893 }
1894
1895 /* Dump RIP packet. */
1896 if (IS_RIP_DEBUG_RECV)
1897 rip_packet_dump (packet, len, "RECV");
1898
1899 /* RIP version adjust. This code should rethink now. RFC1058 says
1900 that "Version 1 implementations are to ignore this extra data and
1901 process only the fields specified in this document.". So RIPv3
1902 packet should be treated as RIPv1 ignoring must be zero field. */
1903 if (packet->version > RIPv2)
1904 packet->version = RIPv2;
1905
1906 /* Is RIP running or is this RIP neighbor ?*/
1907 ri = ifp->info;
1908 if (! ri->running && ! rip_neighbor_lookup (&from))
1909 {
1910 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001911 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001912 rip_peer_bad_packet (&from);
1913 return -1;
1914 }
1915
1916 /* RIP Version check. */
1917 if (packet->command == RIP_RESPONSE)
1918 {
paulf38a4712003-06-07 01:10:00 +00001919 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1920 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001921 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001922 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001923 {
1924 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001925 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001926 packet->version);
1927 rip_peer_bad_packet (&from);
1928 return -1;
1929 }
1930 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001931 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001932 {
1933 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001934 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001935 packet->version);
1936 rip_peer_bad_packet (&from);
1937 return -1;
1938 }
paul718e3742002-12-13 20:15:29 +00001939 }
1940
1941 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1942 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1943 accepted; authenticated RIP-2 messages shall be discarded. */
1944
1945 if ((ri->auth_type == RIP_NO_AUTH)
1946 && rtenum
paulca5e5162004-06-06 22:06:33 +00001947 && (packet->version == RIPv2)
1948 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001949 {
1950 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001951 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001952 packet->version);
1953 rip_peer_bad_packet (&from);
1954 return -1;
1955 }
1956
1957 /* If the router is configured to authenticate RIP-2 messages, then
1958 RIP-1 messages and RIP-2 messages which pass authentication
1959 testing shall be accepted; unauthenticated and failed
1960 authentication RIP-2 messages shall be discarded. For maximum
1961 security, RIP-1 messages should be ignored when authentication is
1962 in use (see section 4.1); otherwise, the routing information from
1963 authenticated messages will be propagated by RIP-1 routers in an
1964 unauthenticated manner. */
1965
1966 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001967 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001968 {
1969 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001970 if (packet->version == RIPv1
1971 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001972 {
1973 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001974 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001975 ("packet RIPv%d is dropped because authentication enabled",
1976 packet->version);
paul718e3742002-12-13 20:15:29 +00001977 rip_peer_bad_packet (&from);
1978 return -1;
1979 }
1980
1981 /* Check RIPv2 authentication. */
1982 if (packet->version == RIPv2)
1983 {
paulca5e5162004-06-06 22:06:33 +00001984 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001985 {
paulca5e5162004-06-06 22:06:33 +00001986 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001987 {
1988 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1989 if (! ret)
1990 {
1991 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001992 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001993 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001994 rip_peer_bad_packet (&from);
1995 return -1;
1996 }
1997 else
1998 {
1999 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002000 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002001 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002002 }
2003 }
paulca5e5162004-06-06 22:06:33 +00002004 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002005 {
paulca5e5162004-06-06 22:06:33 +00002006 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002007 if (! ret)
2008 {
2009 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002010 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002011 rip_peer_bad_packet (&from);
2012 return -1;
2013 }
2014 else
2015 {
2016 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002017 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002018 }
2019 /* Reset RIP packet length to trim MD5 data. */
2020 len = ret;
2021 }
2022 else
2023 {
2024 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002025 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002026 ntohs (packet->rte->tag));
2027 rip_peer_bad_packet (&from);
2028 return -1;
2029 }
2030 }
2031 else
2032 {
2033 /* There is no authentication in the packet. */
2034 if (ri->auth_str || ri->key_chain)
2035 {
2036 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002037 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002038 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002039 rip_peer_bad_packet (&from);
2040 return -1;
2041 }
2042 }
2043 }
2044 }
2045
2046 /* Process each command. */
2047 switch (packet->command)
2048 {
2049 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002050 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002051 break;
2052 case RIP_REQUEST:
2053 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002054 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002055 break;
2056 case RIP_TRACEON:
2057 case RIP_TRACEOFF:
2058 zlog_info ("Obsolete command %s received, please sent it to routed",
2059 lookup (rip_msg, packet->command));
2060 rip_peer_bad_packet (&from);
2061 break;
2062 case RIP_POLL_ENTRY:
2063 zlog_info ("Obsolete command %s received",
2064 lookup (rip_msg, packet->command));
2065 rip_peer_bad_packet (&from);
2066 break;
2067 default:
2068 zlog_info ("Unknown RIP command %d received", packet->command);
2069 rip_peer_bad_packet (&from);
2070 break;
2071 }
2072
2073 return len;
2074}
2075
paul718e3742002-12-13 20:15:29 +00002076/* Write routing table entry to the stream and return next index of
2077 the routing table entry in the stream. */
2078int
2079rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002080 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002081{
2082 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002083
2084 /* Write routing table entry. */
2085 if (version == RIPv1)
2086 {
2087 stream_putw (s, AF_INET);
2088 stream_putw (s, 0);
2089 stream_put_ipv4 (s, p->prefix.s_addr);
2090 stream_put_ipv4 (s, 0);
2091 stream_put_ipv4 (s, 0);
2092 stream_putl (s, rinfo->metric_out);
2093 }
2094 else
2095 {
2096 masklen2ip (p->prefixlen, &mask);
2097
2098 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002099 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002100 stream_put_ipv4 (s, p->prefix.s_addr);
2101 stream_put_ipv4 (s, mask.s_addr);
2102 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2103 stream_putl (s, rinfo->metric_out);
2104 }
2105
2106 return ++num;
2107}
2108
2109/* Send update to the ifp or spcified neighbor. */
2110void
paulc49ad8f2004-10-22 10:27:28 +00002111rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2112 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002113{
2114 int ret;
2115 struct stream *s;
2116 struct route_node *rp;
2117 struct rip_info *rinfo;
2118 struct rip_interface *ri;
2119 struct prefix_ipv4 *p;
2120 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002121 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002122 struct key *key = NULL;
2123 /* this might need to made dynamic if RIP ever supported auth methods
2124 with larger key string sizes */
2125 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2126 size_t doff; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002127 int num = 0;
paul718e3742002-12-13 20:15:29 +00002128 int rtemax;
paul01d09082003-06-08 21:22:18 +00002129 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002130
2131 /* Logging output event. */
2132 if (IS_RIP_DEBUG_EVENT)
2133 {
2134 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002135 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002136 else
ajs5d6c3772004-12-08 19:24:06 +00002137 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002138 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002139 }
2140
2141 /* Set output stream. */
2142 s = rip->obuf;
2143
2144 /* Reset stream and RTE counter. */
2145 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002146 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2147
2148 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002149 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002150
2151 /* If output interface is in simple password authentication mode, we
2152 need space for authentication data. */
2153 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2154 rtemax -= 1;
2155
2156 /* If output interface is in MD5 authentication mode, we need space
2157 for authentication header and data. */
2158 if (ri->auth_type == RIP_AUTH_MD5)
2159 rtemax -= 2;
2160
2161 /* If output interface is in simple password authentication mode
2162 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002163 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002164 {
2165 if (ri->key_chain)
2166 {
2167 struct keychain *keychain;
2168
2169 keychain = keychain_lookup (ri->key_chain);
2170 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002171 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002172 }
paulb14ee002005-02-04 23:42:41 +00002173 /* to be passed to auth functions later */
2174 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002175 }
2176
paul727d1042002-12-13 20:50:29 +00002177 if (version == RIPv1)
2178 {
paulc49ad8f2004-10-22 10:27:28 +00002179 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002180 apply_classful_mask_ipv4 (&ifaddrclass);
2181 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002182 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002183 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002184 }
2185
paul718e3742002-12-13 20:15:29 +00002186 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2187 if ((rinfo = rp->info) != NULL)
2188 {
paul727d1042002-12-13 20:50:29 +00002189 /* For RIPv1, if we are subnetted, output subnets in our network */
2190 /* that have the same mask as the output "interface". For other */
2191 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002192
2193 if (version == RIPv1)
2194 {
paul727d1042002-12-13 20:50:29 +00002195 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002196
2197 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002198 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002199 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002200
paul727d1042002-12-13 20:50:29 +00002201 if (subnetted &&
2202 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2203 {
paulc49ad8f2004-10-22 10:27:28 +00002204 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002205 (rp->p.prefixlen != 32))
2206 continue;
2207 }
2208 else
2209 {
2210 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2211 apply_classful_mask_ipv4(&classfull);
2212 if (rp->p.u.prefix4.s_addr != 0 &&
2213 classfull.prefixlen != rp->p.prefixlen)
2214 continue;
2215 }
paul718e3742002-12-13 20:15:29 +00002216 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002217 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002218 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002219 }
2220 else
2221 p = (struct prefix_ipv4 *) &rp->p;
2222
2223 /* Apply output filters. */
2224 ret = rip_outgoing_filter (p, ri);
2225 if (ret < 0)
2226 continue;
2227
2228 /* Changed route only output. */
2229 if (route_type == rip_changed_route &&
2230 (! (rinfo->flags & RIP_RTF_CHANGED)))
2231 continue;
2232
2233 /* Split horizon. */
2234 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002235 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002236 {
paul42d14d92003-11-17 09:15:18 +00002237 /*
2238 * We perform split horizon for RIP and connected route.
2239 * For rip routes, we want to suppress the route if we would
2240 * end up sending the route back on the interface that we
2241 * learned it from, with a higher metric. For connected routes,
2242 * we suppress the route if the prefix is a subset of the
2243 * source address that we are going to use for the packet
2244 * (in order to handle the case when multiple subnets are
2245 * configured on the same interface).
2246 */
2247 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002248 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002249 continue;
2250 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002251 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002252 continue;
2253 }
2254
2255 /* Preparation for route-map. */
2256 rinfo->metric_set = 0;
2257 rinfo->nexthop_out.s_addr = 0;
2258 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002259 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002260 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002261
hasso16705132003-05-25 14:49:19 +00002262 /* In order to avoid some local loops,
2263 * if the RIP route has a nexthop via this interface, keep the nexthop,
2264 * otherwise set it to 0. The nexthop should not be propagated
2265 * beyond the local broadcast/multicast area in order
2266 * to avoid an IGP multi-level recursive look-up.
2267 * see (4.4)
2268 */
paulc49ad8f2004-10-22 10:27:28 +00002269 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002270 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002271
2272 /* Interface route-map */
2273 if (ri->routemap[RIP_FILTER_OUT])
2274 {
2275 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2276 (struct prefix *) p, RMAP_RIP,
2277 rinfo);
2278
2279 if (ret == RMAP_DENYMATCH)
2280 {
2281 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002282 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002283 inet_ntoa (p->prefix), p->prefixlen);
2284 continue;
2285 }
2286 }
paul718e3742002-12-13 20:15:29 +00002287
hasso16705132003-05-25 14:49:19 +00002288 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002289 if (rip->route_map[rinfo->type].name
2290 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2291 {
2292 ret = route_map_apply (rip->route_map[rinfo->type].map,
2293 (struct prefix *)p, RMAP_RIP, rinfo);
2294
2295 if (ret == RMAP_DENYMATCH)
2296 {
2297 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002298 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002299 inet_ntoa (p->prefix), p->prefixlen);
2300 continue;
2301 }
2302 }
2303
2304 /* When route-map does not set metric. */
2305 if (! rinfo->metric_set)
2306 {
2307 /* If redistribute metric is set. */
2308 if (rip->route_map[rinfo->type].metric_config
2309 && rinfo->metric != RIP_METRIC_INFINITY)
2310 {
2311 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2312 }
2313 else
2314 {
2315 /* If the route is not connected or localy generated
2316 one, use default-metric value*/
2317 if (rinfo->type != ZEBRA_ROUTE_RIP
2318 && rinfo->type != ZEBRA_ROUTE_CONNECT
2319 && rinfo->metric != RIP_METRIC_INFINITY)
2320 rinfo->metric_out = rip->default_metric;
2321 }
2322 }
2323
2324 /* Apply offset-list */
2325 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002326 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002327
2328 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2329 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002330
2331 /* Perform split-horizon with poisoned reverse
2332 * for RIP and connected routes.
2333 **/
2334 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002335 /*
2336 * We perform split horizon for RIP and connected route.
2337 * For rip routes, we want to suppress the route if we would
2338 * end up sending the route back on the interface that we
2339 * learned it from, with a higher metric. For connected routes,
2340 * we suppress the route if the prefix is a subset of the
2341 * source address that we are going to use for the packet
2342 * (in order to handle the case when multiple subnets are
2343 * configured on the same interface).
2344 */
2345 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002346 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002347 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002348 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002349 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002350 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002351 }
paulb14ee002005-02-04 23:42:41 +00002352
2353 /* Prepare preamble, auth headers, if needs be */
2354 if (num == 0)
2355 {
2356 stream_putc (s, RIP_RESPONSE);
2357 stream_putc (s, version);
2358 stream_putw (s, 0);
2359
paul0cb8a012005-05-29 11:27:24 +00002360 /* auth header for !v1 && !no_auth */
2361 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002362 doff = rip_auth_header_write (s, ri, key, auth_str,
2363 RIP_AUTH_SIMPLE_SIZE);
2364 }
2365
paul718e3742002-12-13 20:15:29 +00002366 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002367 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002368 if (num == rtemax)
2369 {
2370 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002371 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002372
2373 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002374 to, ifc);
paul718e3742002-12-13 20:15:29 +00002375
2376 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2377 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2378 stream_get_endp(s), "SEND");
2379 num = 0;
2380 stream_reset (s);
2381 }
2382 }
2383
2384 /* Flush unwritten RTE. */
2385 if (num != 0)
2386 {
2387 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002388 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002389
paulc49ad8f2004-10-22 10:27:28 +00002390 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002391
2392 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2393 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2394 stream_get_endp (s), "SEND");
2395 num = 0;
2396 stream_reset (s);
2397 }
2398
2399 /* Statistics updates. */
2400 ri->sent_updates++;
2401}
2402
2403/* Send RIP packet to the interface. */
2404void
paulc49ad8f2004-10-22 10:27:28 +00002405rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002406{
paul718e3742002-12-13 20:15:29 +00002407 struct sockaddr_in to;
2408
2409 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002410 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002411 {
2412 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002413 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002414
paulc49ad8f2004-10-22 10:27:28 +00002415 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002416 return;
2417 }
paulc49ad8f2004-10-22 10:27:28 +00002418
paul718e3742002-12-13 20:15:29 +00002419 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002420 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002421 {
paulc49ad8f2004-10-22 10:27:28 +00002422 if (ifc->address->family == AF_INET)
2423 {
2424 /* Destination address and port setting. */
2425 memset (&to, 0, sizeof (struct sockaddr_in));
2426 if (ifc->destination)
2427 /* use specified broadcast or point-to-point destination addr */
2428 to.sin_addr = ifc->destination->u.prefix4;
2429 else
2430 /* calculate the appropriate broadcast address */
2431 to.sin_addr.s_addr =
2432 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2433 ifc->address->prefixlen);
2434 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002435
paulc49ad8f2004-10-22 10:27:28 +00002436 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002437 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002438 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2439 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002440
paulc49ad8f2004-10-22 10:27:28 +00002441 rip_output_process (ifc, &to, route_type, version);
2442 }
paul718e3742002-12-13 20:15:29 +00002443 }
2444}
2445
2446/* Update send to all interface and neighbor. */
2447void
2448rip_update_process (int route_type)
2449{
paul1eb8ef22005-04-07 07:30:20 +00002450 struct listnode *node;
2451 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002452 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002453 struct interface *ifp;
2454 struct rip_interface *ri;
2455 struct route_node *rp;
2456 struct sockaddr_in to;
2457 struct prefix_ipv4 *p;
2458
2459 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002460 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002461 {
paul718e3742002-12-13 20:15:29 +00002462 if (if_is_loopback (ifp))
2463 continue;
2464
paul2e3b2e42002-12-13 21:03:13 +00002465 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002466 continue;
2467
2468 /* Fetch RIP interface information. */
2469 ri = ifp->info;
2470
2471 /* When passive interface is specified, suppress announce to the
2472 interface. */
2473 if (ri->passive)
2474 continue;
2475
2476 if (ri->running)
2477 {
2478 if (IS_RIP_DEBUG_EVENT)
2479 {
2480 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002481 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002482 ifp->name, ifp->ifindex);
2483 else
ajs5d6c3772004-12-08 19:24:06 +00002484 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002485 ifp->ifindex);
2486 }
2487
paulcc1131a2003-10-15 23:20:17 +00002488 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002489 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002490 {
2491 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002492 int done = 0;
2493 /*
2494 * If there is no version configuration in the interface,
2495 * use rip's version setting.
2496 */
paulf38a4712003-06-07 01:10:00 +00002497 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2498 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002499
2500 ifaddr = (struct prefix_ipv4 *) connected->address;
2501
2502 if (ifaddr->family != AF_INET)
2503 continue;
2504
paul931cd542004-01-23 15:31:42 +00002505 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002506 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002507 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002508 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002509 done = 1;
2510 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2511 break;
2512
paulf38a4712003-06-07 01:10:00 +00002513 }
paul718e3742002-12-13 20:15:29 +00002514 }
2515 }
2516
2517 /* RIP send updates to each neighbor. */
2518 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2519 if (rp->info != NULL)
2520 {
2521 p = (struct prefix_ipv4 *) &rp->p;
2522
2523 ifp = if_lookup_address (p->prefix);
2524 if (! ifp)
2525 {
paulc49ad8f2004-10-22 10:27:28 +00002526 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002527 inet_ntoa (p->prefix));
2528 continue;
2529 }
paulc49ad8f2004-10-22 10:27:28 +00002530
2531 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2532 {
2533 zlog_warn ("Neighbor %s doesnt have connected network",
2534 inet_ntoa (p->prefix));
2535 continue;
2536 }
2537
paul718e3742002-12-13 20:15:29 +00002538 /* Set destination address and port */
2539 memset (&to, 0, sizeof (struct sockaddr_in));
2540 to.sin_addr = p->prefix;
2541 to.sin_port = htons (RIP_PORT_DEFAULT);
2542
2543 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002544 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002545 }
2546}
2547
2548/* RIP's periodical timer. */
2549int
2550rip_update (struct thread *t)
2551{
2552 /* Clear timer pointer. */
2553 rip->t_update = NULL;
2554
2555 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002556 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002557
2558 /* Process update output. */
2559 rip_update_process (rip_all_route);
2560
2561 /* Triggered updates may be suppressed if a regular update is due by
2562 the time the triggered update would be sent. */
2563 if (rip->t_triggered_interval)
2564 {
2565 thread_cancel (rip->t_triggered_interval);
2566 rip->t_triggered_interval = NULL;
2567 }
2568 rip->trigger = 0;
2569
2570 /* Register myself. */
2571 rip_event (RIP_UPDATE_EVENT, 0);
2572
2573 return 0;
2574}
2575
2576/* Walk down the RIP routing table then clear changed flag. */
2577void
2578rip_clear_changed_flag ()
2579{
2580 struct route_node *rp;
2581 struct rip_info *rinfo;
2582
2583 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2584 if ((rinfo = rp->info) != NULL)
2585 if (rinfo->flags & RIP_RTF_CHANGED)
2586 rinfo->flags &= ~RIP_RTF_CHANGED;
2587}
2588
2589/* Triggered update interval timer. */
2590int
2591rip_triggered_interval (struct thread *t)
2592{
2593 int rip_triggered_update (struct thread *);
2594
2595 rip->t_triggered_interval = NULL;
2596
2597 if (rip->trigger)
2598 {
2599 rip->trigger = 0;
2600 rip_triggered_update (t);
2601 }
2602 return 0;
2603}
2604
2605/* Execute triggered update. */
2606int
2607rip_triggered_update (struct thread *t)
2608{
2609 int interval;
2610
2611 /* Clear thred pointer. */
2612 rip->t_triggered_update = NULL;
2613
2614 /* Cancel interval timer. */
2615 if (rip->t_triggered_interval)
2616 {
2617 thread_cancel (rip->t_triggered_interval);
2618 rip->t_triggered_interval = NULL;
2619 }
2620 rip->trigger = 0;
2621
2622 /* Logging triggered update. */
2623 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002624 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002625
2626 /* Split Horizon processing is done when generating triggered
2627 updates as well as normal updates (see section 2.6). */
2628 rip_update_process (rip_changed_route);
2629
2630 /* Once all of the triggered updates have been generated, the route
2631 change flags should be cleared. */
2632 rip_clear_changed_flag ();
2633
2634 /* After a triggered update is sent, a timer should be set for a
2635 random interval between 1 and 5 seconds. If other changes that
2636 would trigger updates occur before the timer expires, a single
2637 update is triggered when the timer expires. */
2638 interval = (random () % 5) + 1;
2639
2640 rip->t_triggered_interval =
2641 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2642
2643 return 0;
2644}
2645
2646/* Withdraw redistributed route. */
2647void
2648rip_redistribute_withdraw (int type)
2649{
2650 struct route_node *rp;
2651 struct rip_info *rinfo;
2652
2653 if (!rip)
2654 return;
2655
2656 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2657 if ((rinfo = rp->info) != NULL)
2658 {
2659 if (rinfo->type == type
2660 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2661 {
2662 /* Perform poisoned reverse. */
2663 rinfo->metric = RIP_METRIC_INFINITY;
2664 RIP_TIMER_ON (rinfo->t_garbage_collect,
2665 rip_garbage_collect, rip->garbage_time);
2666 RIP_TIMER_OFF (rinfo->t_timeout);
2667 rinfo->flags |= RIP_RTF_CHANGED;
2668
hasso16705132003-05-25 14:49:19 +00002669 if (IS_RIP_DEBUG_EVENT) {
2670 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2671
ajs5d6c3772004-12-08 19:24:06 +00002672 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002673 inet_ntoa(p->prefix), p->prefixlen,
2674 ifindex2ifname(rinfo->ifindex));
2675 }
2676
paul718e3742002-12-13 20:15:29 +00002677 rip_event (RIP_TRIGGERED_UPDATE, 0);
2678 }
2679 }
2680}
2681
2682/* Create new RIP instance and set it to global variable. */
2683int
2684rip_create ()
2685{
2686 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2687 memset (rip, 0, sizeof (struct rip));
2688
2689 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002690 rip->version_send = RI_RIP_VERSION_2;
2691 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002692 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2693 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2694 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2695 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2696
2697 /* Initialize RIP routig table. */
2698 rip->table = route_table_init ();
2699 rip->route = route_table_init ();
2700 rip->neighbor = route_table_init ();
2701
2702 /* Make output stream. */
2703 rip->obuf = stream_new (1500);
2704
2705 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002706 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002707 if (rip->sock < 0)
2708 return rip->sock;
2709
2710 /* Create read and timer thread. */
2711 rip_event (RIP_READ, rip->sock);
2712 rip_event (RIP_UPDATE_EVENT, 1);
2713
2714 return 0;
2715}
2716
2717/* Sned RIP request to the destination. */
2718int
2719rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002720 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002721{
2722 struct rte *rte;
2723 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002724 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002725
2726 memset (&rip_packet, 0, sizeof (rip_packet));
2727
2728 rip_packet.command = RIP_REQUEST;
2729 rip_packet.version = version;
2730 rte = rip_packet.rte;
2731 rte->metric = htonl (RIP_METRIC_INFINITY);
2732
paul931cd542004-01-23 15:31:42 +00002733 if (connected)
2734 {
2735 /*
2736 * connected is only sent for ripv1 case, or when
2737 * interface does not support multicast. Caller loops
2738 * over each connected address for this case.
2739 */
paul11dde9c2004-05-31 14:00:00 +00002740 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002741 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002742 return -1;
2743 else
2744 return sizeof (rip_packet);
2745 }
2746
paulcc1131a2003-10-15 23:20:17 +00002747 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002748 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002749 {
2750 struct prefix_ipv4 *p;
2751
2752 p = (struct prefix_ipv4 *) connected->address;
2753
2754 if (p->family != AF_INET)
2755 continue;
2756
paul11dde9c2004-05-31 14:00:00 +00002757 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002758 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002759 return -1;
2760 }
2761 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002762}
2763
2764int
2765rip_update_jitter (unsigned long time)
2766{
paul239389b2004-05-05 14:09:37 +00002767#define JITTER_BOUND 4
2768 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2769 Given that, we cannot let time be less than JITTER_BOUND seconds.
2770 The RIPv2 RFC says jitter should be small compared to
2771 update_time. We consider 1/JITTER_BOUND to be small.
2772 */
2773
2774 int jitter_input = time;
2775 int jitter;
2776
2777 if (jitter_input < JITTER_BOUND)
2778 jitter_input = JITTER_BOUND;
2779
2780 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2781
2782 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002783}
2784
2785void
2786rip_event (enum rip_event event, int sock)
2787{
2788 int jitter = 0;
2789
2790 switch (event)
2791 {
2792 case RIP_READ:
2793 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2794 break;
2795 case RIP_UPDATE_EVENT:
2796 if (rip->t_update)
2797 {
2798 thread_cancel (rip->t_update);
2799 rip->t_update = NULL;
2800 }
2801 jitter = rip_update_jitter (rip->update_time);
2802 rip->t_update =
2803 thread_add_timer (master, rip_update, NULL,
2804 sock ? 2 : rip->update_time + jitter);
2805 break;
2806 case RIP_TRIGGERED_UPDATE:
2807 if (rip->t_triggered_interval)
2808 rip->trigger = 1;
2809 else if (! rip->t_triggered_update)
2810 rip->t_triggered_update =
2811 thread_add_event (master, rip_triggered_update, NULL, 0);
2812 break;
2813 default:
2814 break;
2815 }
2816}
2817
2818DEFUN (router_rip,
2819 router_rip_cmd,
2820 "router rip",
2821 "Enable a routing process\n"
2822 "Routing Information Protocol (RIP)\n")
2823{
2824 int ret;
2825
2826 /* If rip is not enabled before. */
2827 if (! rip)
2828 {
2829 ret = rip_create ();
2830 if (ret < 0)
2831 {
2832 zlog_info ("Can't create RIP");
2833 return CMD_WARNING;
2834 }
2835 }
2836 vty->node = RIP_NODE;
2837 vty->index = rip;
2838
2839 return CMD_SUCCESS;
2840}
2841
2842DEFUN (no_router_rip,
2843 no_router_rip_cmd,
2844 "no router rip",
2845 NO_STR
2846 "Enable a routing process\n"
2847 "Routing Information Protocol (RIP)\n")
2848{
2849 if (rip)
2850 rip_clean ();
2851 return CMD_SUCCESS;
2852}
2853
2854DEFUN (rip_version,
2855 rip_version_cmd,
2856 "version <1-2>",
2857 "Set routing protocol version\n"
2858 "version\n")
2859{
2860 int version;
2861
2862 version = atoi (argv[0]);
2863 if (version != RIPv1 && version != RIPv2)
2864 {
2865 vty_out (vty, "invalid rip version %d%s", version,
2866 VTY_NEWLINE);
2867 return CMD_WARNING;
2868 }
paulf38a4712003-06-07 01:10:00 +00002869 rip->version_send = version;
2870 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002871
2872 return CMD_SUCCESS;
2873}
2874
2875DEFUN (no_rip_version,
2876 no_rip_version_cmd,
2877 "no version",
2878 NO_STR
2879 "Set routing protocol version\n")
2880{
2881 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002882 rip->version_send = RI_RIP_VERSION_2;
2883 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002884
2885 return CMD_SUCCESS;
2886}
2887
2888ALIAS (no_rip_version,
2889 no_rip_version_val_cmd,
2890 "no version <1-2>",
2891 NO_STR
2892 "Set routing protocol version\n"
2893 "version\n")
2894
2895DEFUN (rip_route,
2896 rip_route_cmd,
2897 "route A.B.C.D/M",
2898 "RIP static route configuration\n"
2899 "IP prefix <network>/<length>\n")
2900{
2901 int ret;
2902 struct prefix_ipv4 p;
2903 struct route_node *node;
2904
2905 ret = str2prefix_ipv4 (argv[0], &p);
2906 if (ret < 0)
2907 {
2908 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2909 return CMD_WARNING;
2910 }
2911 apply_mask_ipv4 (&p);
2912
2913 /* For router rip configuration. */
2914 node = route_node_get (rip->route, (struct prefix *) &p);
2915
2916 if (node->info)
2917 {
2918 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2919 route_unlock_node (node);
2920 return CMD_WARNING;
2921 }
2922
hasso8a676be2004-10-08 06:36:38 +00002923 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002924
2925 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2926
2927 return CMD_SUCCESS;
2928}
2929
2930DEFUN (no_rip_route,
2931 no_rip_route_cmd,
2932 "no route A.B.C.D/M",
2933 NO_STR
2934 "RIP static route configuration\n"
2935 "IP prefix <network>/<length>\n")
2936{
2937 int ret;
2938 struct prefix_ipv4 p;
2939 struct route_node *node;
2940
2941 ret = str2prefix_ipv4 (argv[0], &p);
2942 if (ret < 0)
2943 {
2944 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2945 return CMD_WARNING;
2946 }
2947 apply_mask_ipv4 (&p);
2948
2949 /* For router rip configuration. */
2950 node = route_node_lookup (rip->route, (struct prefix *) &p);
2951 if (! node)
2952 {
2953 vty_out (vty, "Can't find route %s.%s", argv[0],
2954 VTY_NEWLINE);
2955 return CMD_WARNING;
2956 }
2957
2958 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2959 route_unlock_node (node);
2960
2961 node->info = NULL;
2962 route_unlock_node (node);
2963
2964 return CMD_SUCCESS;
2965}
2966
2967void
2968rip_update_default_metric ()
2969{
2970 struct route_node *np;
2971 struct rip_info *rinfo;
2972
2973 for (np = route_top (rip->table); np; np = route_next (np))
2974 if ((rinfo = np->info) != NULL)
2975 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2976 rinfo->metric = rip->default_metric;
2977}
2978
2979DEFUN (rip_default_metric,
2980 rip_default_metric_cmd,
2981 "default-metric <1-16>",
2982 "Set a metric of redistribute routes\n"
2983 "Default metric\n")
2984{
2985 if (rip)
2986 {
2987 rip->default_metric = atoi (argv[0]);
2988 /* rip_update_default_metric (); */
2989 }
2990 return CMD_SUCCESS;
2991}
2992
2993DEFUN (no_rip_default_metric,
2994 no_rip_default_metric_cmd,
2995 "no default-metric",
2996 NO_STR
2997 "Set a metric of redistribute routes\n"
2998 "Default metric\n")
2999{
3000 if (rip)
3001 {
3002 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3003 /* rip_update_default_metric (); */
3004 }
3005 return CMD_SUCCESS;
3006}
3007
3008ALIAS (no_rip_default_metric,
3009 no_rip_default_metric_val_cmd,
3010 "no default-metric <1-16>",
3011 NO_STR
3012 "Set a metric of redistribute routes\n"
3013 "Default metric\n")
3014
3015DEFUN (rip_timers,
3016 rip_timers_cmd,
3017 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3018 "Adjust routing timers\n"
3019 "Basic routing protocol update timers\n"
3020 "Routing table update timer value in second. Default is 30.\n"
3021 "Routing information timeout timer. Default is 180.\n"
3022 "Garbage collection timer. Default is 120.\n")
3023{
3024 unsigned long update;
3025 unsigned long timeout;
3026 unsigned long garbage;
3027 char *endptr = NULL;
3028 unsigned long RIP_TIMER_MAX = 2147483647;
3029 unsigned long RIP_TIMER_MIN = 5;
3030
3031 update = strtoul (argv[0], &endptr, 10);
3032 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3033 {
3034 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3035 return CMD_WARNING;
3036 }
3037
3038 timeout = strtoul (argv[1], &endptr, 10);
3039 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3040 {
3041 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3042 return CMD_WARNING;
3043 }
3044
3045 garbage = strtoul (argv[2], &endptr, 10);
3046 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3047 {
3048 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3049 return CMD_WARNING;
3050 }
3051
3052 /* Set each timer value. */
3053 rip->update_time = update;
3054 rip->timeout_time = timeout;
3055 rip->garbage_time = garbage;
3056
3057 /* Reset update timer thread. */
3058 rip_event (RIP_UPDATE_EVENT, 0);
3059
3060 return CMD_SUCCESS;
3061}
3062
3063DEFUN (no_rip_timers,
3064 no_rip_timers_cmd,
3065 "no timers basic",
3066 NO_STR
3067 "Adjust routing timers\n"
3068 "Basic routing protocol update timers\n")
3069{
3070 /* Set each timer value to the default. */
3071 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3072 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3073 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3074
3075 /* Reset update timer thread. */
3076 rip_event (RIP_UPDATE_EVENT, 0);
3077
3078 return CMD_SUCCESS;
3079}
hasso16705132003-05-25 14:49:19 +00003080
3081ALIAS (no_rip_timers,
3082 no_rip_timers_val_cmd,
3083 "no timers basic <0-65535> <0-65535> <0-65535>",
3084 NO_STR
3085 "Adjust routing timers\n"
3086 "Basic routing protocol update timers\n"
3087 "Routing table update timer value in second. Default is 30.\n"
3088 "Routing information timeout timer. Default is 180.\n"
3089 "Garbage collection timer. Default is 120.\n")
3090
paul718e3742002-12-13 20:15:29 +00003091
3092struct route_table *rip_distance_table;
3093
3094struct rip_distance
3095{
3096 /* Distance value for the IP source prefix. */
3097 u_char distance;
3098
3099 /* Name of the access-list to be matched. */
3100 char *access_list;
3101};
3102
3103struct rip_distance *
3104rip_distance_new ()
3105{
3106 struct rip_distance *new;
3107 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3108 memset (new, 0, sizeof (struct rip_distance));
3109 return new;
3110}
3111
3112void
3113rip_distance_free (struct rip_distance *rdistance)
3114{
3115 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3116}
3117
3118int
hasso98b718a2004-10-11 12:57:57 +00003119rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3120 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003121{
3122 int ret;
3123 struct prefix_ipv4 p;
3124 u_char distance;
3125 struct route_node *rn;
3126 struct rip_distance *rdistance;
3127
3128 ret = str2prefix_ipv4 (ip_str, &p);
3129 if (ret == 0)
3130 {
3131 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3132 return CMD_WARNING;
3133 }
3134
3135 distance = atoi (distance_str);
3136
3137 /* Get RIP distance node. */
3138 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3139 if (rn->info)
3140 {
3141 rdistance = rn->info;
3142 route_unlock_node (rn);
3143 }
3144 else
3145 {
3146 rdistance = rip_distance_new ();
3147 rn->info = rdistance;
3148 }
3149
3150 /* Set distance value. */
3151 rdistance->distance = distance;
3152
3153 /* Reset access-list configuration. */
3154 if (rdistance->access_list)
3155 {
3156 free (rdistance->access_list);
3157 rdistance->access_list = NULL;
3158 }
3159 if (access_list_str)
3160 rdistance->access_list = strdup (access_list_str);
3161
3162 return CMD_SUCCESS;
3163}
3164
3165int
hasso98b718a2004-10-11 12:57:57 +00003166rip_distance_unset (struct vty *vty, const char *distance_str,
3167 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003168{
3169 int ret;
3170 struct prefix_ipv4 p;
3171 u_char distance;
3172 struct route_node *rn;
3173 struct rip_distance *rdistance;
3174
3175 ret = str2prefix_ipv4 (ip_str, &p);
3176 if (ret == 0)
3177 {
3178 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3179 return CMD_WARNING;
3180 }
3181
3182 distance = atoi (distance_str);
3183
3184 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3185 if (! rn)
3186 {
3187 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3188 return CMD_WARNING;
3189 }
3190
3191 rdistance = rn->info;
3192
3193 if (rdistance->access_list)
3194 free (rdistance->access_list);
3195 rip_distance_free (rdistance);
3196
3197 rn->info = NULL;
3198 route_unlock_node (rn);
3199 route_unlock_node (rn);
3200
3201 return CMD_SUCCESS;
3202}
3203
3204void
3205rip_distance_reset ()
3206{
3207 struct route_node *rn;
3208 struct rip_distance *rdistance;
3209
3210 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3211 if ((rdistance = rn->info) != NULL)
3212 {
3213 if (rdistance->access_list)
3214 free (rdistance->access_list);
3215 rip_distance_free (rdistance);
3216 rn->info = NULL;
3217 route_unlock_node (rn);
3218 }
3219}
3220
3221/* Apply RIP information to distance method. */
3222u_char
3223rip_distance_apply (struct rip_info *rinfo)
3224{
3225 struct route_node *rn;
3226 struct prefix_ipv4 p;
3227 struct rip_distance *rdistance;
3228 struct access_list *alist;
3229
3230 if (! rip)
3231 return 0;
3232
3233 memset (&p, 0, sizeof (struct prefix_ipv4));
3234 p.family = AF_INET;
3235 p.prefix = rinfo->from;
3236 p.prefixlen = IPV4_MAX_BITLEN;
3237
3238 /* Check source address. */
3239 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3240 if (rn)
3241 {
3242 rdistance = rn->info;
3243 route_unlock_node (rn);
3244
3245 if (rdistance->access_list)
3246 {
3247 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3248 if (alist == NULL)
3249 return 0;
3250 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3251 return 0;
3252
3253 return rdistance->distance;
3254 }
3255 else
3256 return rdistance->distance;
3257 }
3258
3259 if (rip->distance)
3260 return rip->distance;
3261
3262 return 0;
3263}
3264
3265void
3266rip_distance_show (struct vty *vty)
3267{
3268 struct route_node *rn;
3269 struct rip_distance *rdistance;
3270 int header = 1;
3271 char buf[BUFSIZ];
3272
3273 vty_out (vty, " Distance: (default is %d)%s",
3274 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3275 VTY_NEWLINE);
3276
3277 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3278 if ((rdistance = rn->info) != NULL)
3279 {
3280 if (header)
3281 {
3282 vty_out (vty, " Address Distance List%s",
3283 VTY_NEWLINE);
3284 header = 0;
3285 }
3286 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3287 vty_out (vty, " %-20s %4d %s%s",
3288 buf, rdistance->distance,
3289 rdistance->access_list ? rdistance->access_list : "",
3290 VTY_NEWLINE);
3291 }
3292}
3293
3294DEFUN (rip_distance,
3295 rip_distance_cmd,
3296 "distance <1-255>",
3297 "Administrative distance\n"
3298 "Distance value\n")
3299{
3300 rip->distance = atoi (argv[0]);
3301 return CMD_SUCCESS;
3302}
3303
3304DEFUN (no_rip_distance,
3305 no_rip_distance_cmd,
3306 "no distance <1-255>",
3307 NO_STR
3308 "Administrative distance\n"
3309 "Distance value\n")
3310{
3311 rip->distance = 0;
3312 return CMD_SUCCESS;
3313}
3314
3315DEFUN (rip_distance_source,
3316 rip_distance_source_cmd,
3317 "distance <1-255> A.B.C.D/M",
3318 "Administrative distance\n"
3319 "Distance value\n"
3320 "IP source prefix\n")
3321{
3322 rip_distance_set (vty, argv[0], argv[1], NULL);
3323 return CMD_SUCCESS;
3324}
3325
3326DEFUN (no_rip_distance_source,
3327 no_rip_distance_source_cmd,
3328 "no distance <1-255> A.B.C.D/M",
3329 NO_STR
3330 "Administrative distance\n"
3331 "Distance value\n"
3332 "IP source prefix\n")
3333{
3334 rip_distance_unset (vty, argv[0], argv[1], NULL);
3335 return CMD_SUCCESS;
3336}
3337
3338DEFUN (rip_distance_source_access_list,
3339 rip_distance_source_access_list_cmd,
3340 "distance <1-255> A.B.C.D/M WORD",
3341 "Administrative distance\n"
3342 "Distance value\n"
3343 "IP source prefix\n"
3344 "Access list name\n")
3345{
3346 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3347 return CMD_SUCCESS;
3348}
3349
3350DEFUN (no_rip_distance_source_access_list,
3351 no_rip_distance_source_access_list_cmd,
3352 "no distance <1-255> A.B.C.D/M WORD",
3353 NO_STR
3354 "Administrative distance\n"
3355 "Distance value\n"
3356 "IP source prefix\n"
3357 "Access list name\n")
3358{
3359 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3360 return CMD_SUCCESS;
3361}
3362
3363/* Print out routes update time. */
3364void
3365rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3366{
3367 struct timeval timer_now;
3368 time_t clock;
3369 struct tm *tm;
3370#define TIME_BUF 25
3371 char timebuf [TIME_BUF];
3372 struct thread *thread;
3373
3374 gettimeofday (&timer_now, NULL);
3375
3376 if ((thread = rinfo->t_timeout) != NULL)
3377 {
3378 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3379 tm = gmtime (&clock);
3380 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3381 vty_out (vty, "%5s", timebuf);
3382 }
3383 else if ((thread = rinfo->t_garbage_collect) != NULL)
3384 {
3385 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3386 tm = gmtime (&clock);
3387 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3388 vty_out (vty, "%5s", timebuf);
3389 }
3390}
3391
hasso8a676be2004-10-08 06:36:38 +00003392const char *
paul718e3742002-12-13 20:15:29 +00003393rip_route_type_print (int sub_type)
3394{
3395 switch (sub_type)
3396 {
3397 case RIP_ROUTE_RTE:
3398 return "n";
3399 case RIP_ROUTE_STATIC:
3400 return "s";
3401 case RIP_ROUTE_DEFAULT:
3402 return "d";
3403 case RIP_ROUTE_REDISTRIBUTE:
3404 return "r";
3405 case RIP_ROUTE_INTERFACE:
3406 return "i";
3407 default:
3408 return "?";
3409 }
3410}
3411
3412DEFUN (show_ip_rip,
3413 show_ip_rip_cmd,
3414 "show ip rip",
3415 SHOW_STR
3416 IP_STR
3417 "Show RIP routes\n")
3418{
3419 struct route_node *np;
3420 struct rip_info *rinfo;
3421
3422 if (! rip)
3423 return CMD_SUCCESS;
3424
hasso16705132003-05-25 14:49:19 +00003425 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3426 "Sub-codes:%s"
3427 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003428 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003429 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003430 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003431
3432 for (np = route_top (rip->table); np; np = route_next (np))
3433 if ((rinfo = np->info) != NULL)
3434 {
3435 int len;
3436
3437 len = vty_out (vty, "%s(%s) %s/%d",
3438 /* np->lock, For debugging. */
3439 route_info[rinfo->type].str,
3440 rip_route_type_print (rinfo->sub_type),
3441 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3442
hassoa1455d82004-03-03 19:36:24 +00003443 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003444
3445 if (len > 0)
3446 vty_out (vty, "%*s", len, " ");
3447
3448 if (rinfo->nexthop.s_addr)
3449 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3450 rinfo->metric);
3451 else
3452 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3453
3454 /* Route which exist in kernel routing table. */
3455 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3456 (rinfo->sub_type == RIP_ROUTE_RTE))
3457 {
3458 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003459 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003460 rip_vty_out_uptime (vty, rinfo);
3461 }
3462 else if (rinfo->metric == RIP_METRIC_INFINITY)
3463 {
3464 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003465 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003466 rip_vty_out_uptime (vty, rinfo);
3467 }
3468 else
hasso16705132003-05-25 14:49:19 +00003469 {
3470 vty_out (vty, "self ");
3471 vty_out (vty, "%3d", rinfo->tag);
3472 }
paul718e3742002-12-13 20:15:29 +00003473
3474 vty_out (vty, "%s", VTY_NEWLINE);
3475 }
3476 return CMD_SUCCESS;
3477}
3478
3479/* Return next event time. */
3480int
3481rip_next_thread_timer (struct thread *thread)
3482{
3483 struct timeval timer_now;
3484
3485 gettimeofday (&timer_now, NULL);
3486
3487 return thread->u.sands.tv_sec - timer_now.tv_sec;
3488}
3489
hasso16705132003-05-25 14:49:19 +00003490/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3491DEFUN (show_ip_rip_status,
3492 show_ip_rip_status_cmd,
3493 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003494 SHOW_STR
3495 IP_STR
hasso16705132003-05-25 14:49:19 +00003496 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003497 "IP routing protocol process parameters and statistics\n")
3498{
hasso52dc7ee2004-09-23 19:18:23 +00003499 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003500 struct interface *ifp;
3501 struct rip_interface *ri;
3502 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003503 const char *send_version;
3504 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003505
3506 if (! rip)
3507 return CMD_SUCCESS;
3508
3509 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3510 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3511 rip->update_time);
3512 vty_out (vty, " next due in %d seconds%s",
3513 rip_next_thread_timer (rip->t_update),
3514 VTY_NEWLINE);
3515 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3516 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3517 VTY_NEWLINE);
3518
3519 /* Filtering status show. */
3520 config_show_distribute (vty);
3521
3522 /* Default metric information. */
3523 vty_out (vty, " Default redistribution metric is %d%s",
3524 rip->default_metric, VTY_NEWLINE);
3525
3526 /* Redistribute information. */
3527 vty_out (vty, " Redistributing:");
3528 config_write_rip_redistribute (vty, 0);
3529 vty_out (vty, "%s", VTY_NEWLINE);
3530
paulf38a4712003-06-07 01:10:00 +00003531 vty_out (vty, " Default version control: send version %s,",
3532 lookup(ri_version_msg,rip->version_send));
3533 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3534 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3535 else
3536 vty_out (vty, " receive version %s %s",
3537 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003538
3539 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3540
paul1eb8ef22005-04-07 07:30:20 +00003541 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003542 {
paul718e3742002-12-13 20:15:29 +00003543 ri = ifp->info;
3544
3545 if (ri->enable_network || ri->enable_interface)
3546 {
3547 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003548 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003549 else
3550 send_version = lookup (ri_version_msg, ri->ri_send);
3551
3552 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003553 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003554 else
3555 receive_version = lookup (ri_version_msg, ri->ri_receive);
3556
3557 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3558 send_version,
3559 receive_version,
3560 ri->key_chain ? ri->key_chain : "",
3561 VTY_NEWLINE);
3562 }
3563 }
3564
3565 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3566 config_write_rip_network (vty, 0);
3567
paul4aaff3f2003-06-07 01:04:45 +00003568 {
3569 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003570 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003571 {
paul4aaff3f2003-06-07 01:04:45 +00003572 ri = ifp->info;
3573
3574 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3575 {
3576 if (!found_passive)
3577 {
3578 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3579 found_passive = 1;
3580 }
3581 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3582 }
3583 }
3584 }
3585
paul718e3742002-12-13 20:15:29 +00003586 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3587 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3588 rip_peer_display (vty);
3589
3590 rip_distance_show (vty);
3591
3592 return CMD_SUCCESS;
3593}
3594
3595/* RIP configuration write function. */
3596int
3597config_write_rip (struct vty *vty)
3598{
3599 int write = 0;
3600 struct route_node *rn;
3601 struct rip_distance *rdistance;
3602
3603 if (rip)
3604 {
3605 /* Router RIP statement. */
3606 vty_out (vty, "router rip%s", VTY_NEWLINE);
3607 write++;
3608
3609 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003610 if (rip->version_send != RI_RIP_VERSION_2
3611 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3612 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003613 VTY_NEWLINE);
3614
3615 /* RIP timer configuration. */
3616 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3617 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3618 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3619 vty_out (vty, " timers basic %lu %lu %lu%s",
3620 rip->update_time,
3621 rip->timeout_time,
3622 rip->garbage_time,
3623 VTY_NEWLINE);
3624
3625 /* Default information configuration. */
3626 if (rip->default_information)
3627 {
3628 if (rip->default_information_route_map)
3629 vty_out (vty, " default-information originate route-map %s%s",
3630 rip->default_information_route_map, VTY_NEWLINE);
3631 else
3632 vty_out (vty, " default-information originate%s",
3633 VTY_NEWLINE);
3634 }
3635
3636 /* Redistribute configuration. */
3637 config_write_rip_redistribute (vty, 1);
3638
3639 /* RIP offset-list configuration. */
3640 config_write_rip_offset_list (vty);
3641
3642 /* RIP enabled network and interface configuration. */
3643 config_write_rip_network (vty, 1);
3644
3645 /* RIP default metric configuration */
3646 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3647 vty_out (vty, " default-metric %d%s",
3648 rip->default_metric, VTY_NEWLINE);
3649
3650 /* Distribute configuration. */
3651 write += config_write_distribute (vty);
3652
hasso16705132003-05-25 14:49:19 +00003653 /* Interface routemap configuration */
3654 write += config_write_if_rmap (vty);
3655
paul718e3742002-12-13 20:15:29 +00003656 /* Distance configuration. */
3657 if (rip->distance)
3658 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3659
3660 /* RIP source IP prefix distance configuration. */
3661 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3662 if ((rdistance = rn->info) != NULL)
3663 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3664 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3665 rdistance->access_list ? rdistance->access_list : "",
3666 VTY_NEWLINE);
3667
3668 /* RIP static route configuration. */
3669 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3670 if (rn->info)
3671 vty_out (vty, " route %s/%d%s",
3672 inet_ntoa (rn->p.u.prefix4),
3673 rn->p.prefixlen,
3674 VTY_NEWLINE);
3675
3676 }
3677 return write;
3678}
3679
3680/* RIP node structure. */
3681struct cmd_node rip_node =
3682{
3683 RIP_NODE,
3684 "%s(config-router)# ",
3685 1
3686};
3687
3688/* Distribute-list update functions. */
3689void
3690rip_distribute_update (struct distribute *dist)
3691{
3692 struct interface *ifp;
3693 struct rip_interface *ri;
3694 struct access_list *alist;
3695 struct prefix_list *plist;
3696
3697 if (! dist->ifname)
3698 return;
3699
3700 ifp = if_lookup_by_name (dist->ifname);
3701 if (ifp == NULL)
3702 return;
3703
3704 ri = ifp->info;
3705
3706 if (dist->list[DISTRIBUTE_IN])
3707 {
3708 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3709 if (alist)
3710 ri->list[RIP_FILTER_IN] = alist;
3711 else
3712 ri->list[RIP_FILTER_IN] = NULL;
3713 }
3714 else
3715 ri->list[RIP_FILTER_IN] = NULL;
3716
3717 if (dist->list[DISTRIBUTE_OUT])
3718 {
3719 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3720 if (alist)
3721 ri->list[RIP_FILTER_OUT] = alist;
3722 else
3723 ri->list[RIP_FILTER_OUT] = NULL;
3724 }
3725 else
3726 ri->list[RIP_FILTER_OUT] = NULL;
3727
3728 if (dist->prefix[DISTRIBUTE_IN])
3729 {
3730 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3731 if (plist)
3732 ri->prefix[RIP_FILTER_IN] = plist;
3733 else
3734 ri->prefix[RIP_FILTER_IN] = NULL;
3735 }
3736 else
3737 ri->prefix[RIP_FILTER_IN] = NULL;
3738
3739 if (dist->prefix[DISTRIBUTE_OUT])
3740 {
3741 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3742 if (plist)
3743 ri->prefix[RIP_FILTER_OUT] = plist;
3744 else
3745 ri->prefix[RIP_FILTER_OUT] = NULL;
3746 }
3747 else
3748 ri->prefix[RIP_FILTER_OUT] = NULL;
3749}
3750
3751void
3752rip_distribute_update_interface (struct interface *ifp)
3753{
3754 struct distribute *dist;
3755
3756 dist = distribute_lookup (ifp->name);
3757 if (dist)
3758 rip_distribute_update (dist);
3759}
3760
3761/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003762/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003763void
paul02ff83c2004-06-11 11:27:03 +00003764rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003765{
3766 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003767 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003768
paul1eb8ef22005-04-07 07:30:20 +00003769 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3770 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003771}
paul11dde9c2004-05-31 14:00:00 +00003772/* ARGSUSED */
3773void
3774rip_distribute_update_all_wrapper(struct access_list *notused)
3775{
paul02ff83c2004-06-11 11:27:03 +00003776 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003777}
paul718e3742002-12-13 20:15:29 +00003778
3779/* Delete all added rip route. */
3780void
3781rip_clean ()
3782{
3783 int i;
3784 struct route_node *rp;
3785 struct rip_info *rinfo;
3786
3787 if (rip)
3788 {
3789 /* Clear RIP routes */
3790 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3791 if ((rinfo = rp->info) != NULL)
3792 {
3793 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3794 rinfo->sub_type == RIP_ROUTE_RTE)
3795 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3796 &rinfo->nexthop, rinfo->metric);
3797
3798 RIP_TIMER_OFF (rinfo->t_timeout);
3799 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3800
3801 rp->info = NULL;
3802 route_unlock_node (rp);
3803
3804 rip_info_free (rinfo);
3805 }
3806
3807 /* Cancel RIP related timers. */
3808 RIP_TIMER_OFF (rip->t_update);
3809 RIP_TIMER_OFF (rip->t_triggered_update);
3810 RIP_TIMER_OFF (rip->t_triggered_interval);
3811
3812 /* Cancel read thread. */
3813 if (rip->t_read)
3814 {
3815 thread_cancel (rip->t_read);
3816 rip->t_read = NULL;
3817 }
3818
3819 /* Close RIP socket. */
3820 if (rip->sock >= 0)
3821 {
3822 close (rip->sock);
3823 rip->sock = -1;
3824 }
3825
3826 /* Static RIP route configuration. */
3827 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3828 if (rp->info)
3829 {
3830 rp->info = NULL;
3831 route_unlock_node (rp);
3832 }
3833
3834 /* RIP neighbor configuration. */
3835 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3836 if (rp->info)
3837 {
3838 rp->info = NULL;
3839 route_unlock_node (rp);
3840 }
3841
3842 /* Redistribute related clear. */
3843 if (rip->default_information_route_map)
3844 free (rip->default_information_route_map);
3845
3846 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3847 if (rip->route_map[i].name)
3848 free (rip->route_map[i].name);
3849
3850 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3851 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3852 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3853
3854 XFREE (MTYPE_RIP, rip);
3855 rip = NULL;
3856 }
3857
3858 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003859 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003860 rip_offset_clean ();
3861 rip_interface_clean ();
3862 rip_distance_reset ();
3863 rip_redistribute_clean ();
3864}
3865
3866/* Reset all values to the default settings. */
3867void
3868rip_reset ()
3869{
3870 /* Reset global counters. */
3871 rip_global_route_changes = 0;
3872 rip_global_queries = 0;
3873
3874 /* Call ripd related reset functions. */
3875 rip_debug_reset ();
3876 rip_route_map_reset ();
3877
3878 /* Call library reset functions. */
3879 vty_reset ();
3880 access_list_reset ();
3881 prefix_list_reset ();
3882
3883 distribute_list_reset ();
3884
3885 rip_interface_reset ();
3886 rip_distance_reset ();
3887
3888 rip_zclient_reset ();
3889}
3890
hasso16705132003-05-25 14:49:19 +00003891void
3892rip_if_rmap_update (struct if_rmap *if_rmap)
3893{
3894 struct interface *ifp;
3895 struct rip_interface *ri;
3896 struct route_map *rmap;
3897
3898 ifp = if_lookup_by_name (if_rmap->ifname);
3899 if (ifp == NULL)
3900 return;
3901
3902 ri = ifp->info;
3903
3904 if (if_rmap->routemap[IF_RMAP_IN])
3905 {
3906 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3907 if (rmap)
3908 ri->routemap[IF_RMAP_IN] = rmap;
3909 else
3910 ri->routemap[IF_RMAP_IN] = NULL;
3911 }
3912 else
3913 ri->routemap[RIP_FILTER_IN] = NULL;
3914
3915 if (if_rmap->routemap[IF_RMAP_OUT])
3916 {
3917 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3918 if (rmap)
3919 ri->routemap[IF_RMAP_OUT] = rmap;
3920 else
3921 ri->routemap[IF_RMAP_OUT] = NULL;
3922 }
3923 else
3924 ri->routemap[RIP_FILTER_OUT] = NULL;
3925}
3926
3927void
3928rip_if_rmap_update_interface (struct interface *ifp)
3929{
3930 struct if_rmap *if_rmap;
3931
3932 if_rmap = if_rmap_lookup (ifp->name);
3933 if (if_rmap)
3934 rip_if_rmap_update (if_rmap);
3935}
3936
3937void
3938rip_routemap_update_redistribute (void)
3939{
3940 int i;
3941
3942 if (rip)
3943 {
3944 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3945 {
3946 if (rip->route_map[i].name)
3947 rip->route_map[i].map =
3948 route_map_lookup_by_name (rip->route_map[i].name);
3949 }
3950 }
3951}
3952
paul11dde9c2004-05-31 14:00:00 +00003953/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003954void
hasso98b718a2004-10-11 12:57:57 +00003955rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003956{
3957 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003958 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003959
paul1eb8ef22005-04-07 07:30:20 +00003960 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3961 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003962
3963 rip_routemap_update_redistribute ();
3964}
3965
paul718e3742002-12-13 20:15:29 +00003966/* Allocate new rip structure and set default value. */
3967void
3968rip_init ()
3969{
3970 /* Randomize for triggered update random(). */
3971 srand (time (NULL));
3972
3973 /* Install top nodes. */
3974 install_node (&rip_node, config_write_rip);
3975
3976 /* Install rip commands. */
3977 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003978 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003979 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003980 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003981 install_element (CONFIG_NODE, &router_rip_cmd);
3982 install_element (CONFIG_NODE, &no_router_rip_cmd);
3983
3984 install_default (RIP_NODE);
3985 install_element (RIP_NODE, &rip_version_cmd);
3986 install_element (RIP_NODE, &no_rip_version_cmd);
3987 install_element (RIP_NODE, &no_rip_version_val_cmd);
3988 install_element (RIP_NODE, &rip_default_metric_cmd);
3989 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3990 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3991 install_element (RIP_NODE, &rip_timers_cmd);
3992 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003993 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003994 install_element (RIP_NODE, &rip_route_cmd);
3995 install_element (RIP_NODE, &no_rip_route_cmd);
3996 install_element (RIP_NODE, &rip_distance_cmd);
3997 install_element (RIP_NODE, &no_rip_distance_cmd);
3998 install_element (RIP_NODE, &rip_distance_source_cmd);
3999 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4000 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4001 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4002
4003 /* Debug related init. */
4004 rip_debug_init ();
4005
paul718e3742002-12-13 20:15:29 +00004006 /* SNMP init. */
4007#ifdef HAVE_SNMP
4008 rip_snmp_init ();
4009#endif /* HAVE_SNMP */
4010
4011 /* Access list install. */
4012 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004013 access_list_add_hook (rip_distribute_update_all_wrapper);
4014 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004015
4016 /* Prefix list initialize.*/
4017 prefix_list_init ();
4018 prefix_list_add_hook (rip_distribute_update_all);
4019 prefix_list_delete_hook (rip_distribute_update_all);
4020
4021 /* Distribute list install. */
4022 distribute_list_init (RIP_NODE);
4023 distribute_list_add_hook (rip_distribute_update);
4024 distribute_list_delete_hook (rip_distribute_update);
4025
hasso16705132003-05-25 14:49:19 +00004026 /* Route-map */
4027 rip_route_map_init ();
4028 rip_offset_init ();
4029
4030 route_map_add_hook (rip_routemap_update);
4031 route_map_delete_hook (rip_routemap_update);
4032
4033 if_rmap_init (RIP_NODE);
4034 if_rmap_hook_add (rip_if_rmap_update);
4035 if_rmap_hook_delete (rip_if_rmap_update);
4036
paul718e3742002-12-13 20:15:29 +00004037 /* Distance control. */
4038 rip_distance_table = route_table_init ();
4039}