blob: d21485e513fca3aefd8f2ff7cb6fb3337cfd1049 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "if.h"
25#include "command.h"
26#include "prefix.h"
27#include "table.h"
28#include "thread.h"
29#include "memory.h"
30#include "log.h"
31#include "stream.h"
32#include "filter.h"
33#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000034#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000035#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000036#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000037#include "plist.h"
38#include "distribute.h"
39#include "md5-gnu.h"
40#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000041#include "privs.h"
paul718e3742002-12-13 20:15:29 +000042
43#include "ripd/ripd.h"
44#include "ripd/rip_debug.h"
45
paul0b3acf42004-09-17 08:39:08 +000046/* UDP receive buffer size */
47#define RIP_UDP_RCV_BUF 41600
48
49/* privileges global */
pauledd7c242003-06-04 13:59:38 +000050extern struct zebra_privs_t ripd_privs;
51
paul718e3742002-12-13 20:15:29 +000052/* RIP Structure. */
53struct rip *rip = NULL;
54
55/* RIP neighbor address table. */
56struct route_table *rip_neighbor_table;
57
58/* RIP route changes. */
59long rip_global_route_changes = 0;
60
61/* RIP queries. */
62long rip_global_queries = 0;
63
64/* Prototypes. */
65void rip_event (enum rip_event, int);
66
paulc49ad8f2004-10-22 10:27:28 +000067void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
paul718e3742002-12-13 20:15:29 +000068
69/* RIP output routes type. */
70enum
71{
72 rip_all_route,
73 rip_changed_route
74};
75
76/* RIP command strings. */
77struct message rip_msg[] =
78{
79 {RIP_REQUEST, "REQUEST"},
80 {RIP_RESPONSE, "RESPONSE"},
81 {RIP_TRACEON, "TRACEON"},
82 {RIP_TRACEOFF, "TRACEOFF"},
83 {RIP_POLL, "POLL"},
84 {RIP_POLL_ENTRY, "POLL ENTRY"},
85 {0, NULL}
86};
87
88/* Each route type's strings and default preference. */
89struct
90{
91 int key;
hasso8a676be2004-10-08 06:36:38 +000092 const char *str;
93 const char *str_long;
paul718e3742002-12-13 20:15:29 +000094} route_info[] =
95{
96 { ZEBRA_ROUTE_SYSTEM, "X", "system"},
97 { ZEBRA_ROUTE_KERNEL, "K", "kernel"},
98 { ZEBRA_ROUTE_CONNECT, "C", "connected"},
99 { ZEBRA_ROUTE_STATIC, "S", "static"},
100 { ZEBRA_ROUTE_RIP, "R", "rip"},
101 { ZEBRA_ROUTE_RIPNG, "R", "ripng"},
102 { ZEBRA_ROUTE_OSPF, "O", "ospf"},
103 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"},
hasso8a676be2004-10-08 06:36:38 +0000104 { ZEBRA_ROUTE_ISIS, "I", "isis"},
paul718e3742002-12-13 20:15:29 +0000105 { ZEBRA_ROUTE_BGP, "B", "bgp"}
106};
107
108/* Utility function to set boradcast option to the socket. */
109int
110sockopt_broadcast (int sock)
111{
112 int ret;
113 int on = 1;
114
115 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
116 if (ret < 0)
117 {
118 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
119 return -1;
120 }
121 return 0;
122}
123
124int
125rip_route_rte (struct rip_info *rinfo)
126{
127 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
128}
129
130struct rip_info *
131rip_info_new ()
132{
133 struct rip_info *new;
134
135 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
136 memset (new, 0, sizeof (struct rip_info));
137 return new;
138}
139
140void
141rip_info_free (struct rip_info *rinfo)
142{
143 XFREE (MTYPE_RIP_INFO, rinfo);
144}
145
146/* RIP route garbage collect timer. */
147int
148rip_garbage_collect (struct thread *t)
149{
150 struct rip_info *rinfo;
151 struct route_node *rp;
152
153 rinfo = THREAD_ARG (t);
154 rinfo->t_garbage_collect = NULL;
155
156 /* Off timeout timer. */
157 RIP_TIMER_OFF (rinfo->t_timeout);
158
159 /* Get route_node pointer. */
160 rp = rinfo->rp;
161
162 /* Unlock route_node. */
163 rp->info = NULL;
164 route_unlock_node (rp);
165
166 /* Free RIP routing information. */
167 rip_info_free (rinfo);
168
169 return 0;
170}
171
172/* Timeout RIP routes. */
173int
174rip_timeout (struct thread *t)
175{
176 struct rip_info *rinfo;
177 struct route_node *rn;
178
179 rinfo = THREAD_ARG (t);
180 rinfo->t_timeout = NULL;
181
182 rn = rinfo->rp;
183
184 /* - The garbage-collection timer is set for 120 seconds. */
185 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
186 rip->garbage_time);
187
188 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
189 rinfo->metric);
190 /* - The metric for the route is set to 16 (infinity). This causes
191 the route to be removed from service. */
192 rinfo->metric = RIP_METRIC_INFINITY;
193 rinfo->flags &= ~RIP_RTF_FIB;
194
195 /* - The route change flag is to indicate that this entry has been
196 changed. */
197 rinfo->flags |= RIP_RTF_CHANGED;
198
199 /* - The output process is signalled to trigger a response. */
200 rip_event (RIP_TRIGGERED_UPDATE, 0);
201
202 return 0;
203}
204
205void
206rip_timeout_update (struct rip_info *rinfo)
207{
208 if (rinfo->metric != RIP_METRIC_INFINITY)
209 {
210 RIP_TIMER_OFF (rinfo->t_timeout);
211 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
212 }
213}
214
215int
216rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
217{
218 struct distribute *dist;
219 struct access_list *alist;
220 struct prefix_list *plist;
221
222 /* Input distribute-list filtering. */
223 if (ri->list[RIP_FILTER_IN])
224 {
225 if (access_list_apply (ri->list[RIP_FILTER_IN],
226 (struct prefix *) p) == FILTER_DENY)
227 {
228 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000229 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000230 inet_ntoa (p->prefix), p->prefixlen);
231 return -1;
232 }
233 }
234 if (ri->prefix[RIP_FILTER_IN])
235 {
236 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
237 (struct prefix *) p) == PREFIX_DENY)
238 {
239 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000240 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000241 inet_ntoa (p->prefix), p->prefixlen);
242 return -1;
243 }
244 }
245
246 /* All interface filter check. */
247 dist = distribute_lookup (NULL);
248 if (dist)
249 {
250 if (dist->list[DISTRIBUTE_IN])
251 {
252 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
253
254 if (alist)
255 {
256 if (access_list_apply (alist,
257 (struct prefix *) p) == FILTER_DENY)
258 {
259 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000260 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000261 inet_ntoa (p->prefix), p->prefixlen);
262 return -1;
263 }
264 }
265 }
266 if (dist->prefix[DISTRIBUTE_IN])
267 {
268 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
269
270 if (plist)
271 {
272 if (prefix_list_apply (plist,
273 (struct prefix *) p) == PREFIX_DENY)
274 {
275 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000276 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000277 inet_ntoa (p->prefix), p->prefixlen);
278 return -1;
279 }
280 }
281 }
282 }
283 return 0;
284}
285
286int
287rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
288{
289 struct distribute *dist;
290 struct access_list *alist;
291 struct prefix_list *plist;
292
293 if (ri->list[RIP_FILTER_OUT])
294 {
295 if (access_list_apply (ri->list[RIP_FILTER_OUT],
296 (struct prefix *) p) == FILTER_DENY)
297 {
298 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000299 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000300 inet_ntoa (p->prefix), p->prefixlen);
301 return -1;
302 }
303 }
304 if (ri->prefix[RIP_FILTER_OUT])
305 {
306 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
307 (struct prefix *) p) == PREFIX_DENY)
308 {
309 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000310 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000311 inet_ntoa (p->prefix), p->prefixlen);
312 return -1;
313 }
314 }
315
316 /* All interface filter check. */
317 dist = distribute_lookup (NULL);
318 if (dist)
319 {
320 if (dist->list[DISTRIBUTE_OUT])
321 {
322 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
323
324 if (alist)
325 {
326 if (access_list_apply (alist,
327 (struct prefix *) p) == FILTER_DENY)
328 {
329 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000330 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000331 inet_ntoa (p->prefix), p->prefixlen);
332 return -1;
333 }
334 }
335 }
336 if (dist->prefix[DISTRIBUTE_OUT])
337 {
338 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
339
340 if (plist)
341 {
342 if (prefix_list_apply (plist,
343 (struct prefix *) p) == PREFIX_DENY)
344 {
345 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000346 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000347 inet_ntoa (p->prefix), p->prefixlen);
348 return -1;
349 }
350 }
351 }
352 }
353 return 0;
354}
355
356/* Check nexthop address validity. */
357static int
358rip_nexthop_check (struct in_addr *addr)
359{
hasso52dc7ee2004-09-23 19:18:23 +0000360 struct listnode *node;
361 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000362 struct interface *ifp;
363 struct connected *ifc;
364 struct prefix *p;
365
366 /* If nexthop address matches local configured address then it is
367 invalid nexthop. */
paul1eb8ef22005-04-07 07:30:20 +0000368 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000369 {
paul1eb8ef22005-04-07 07:30:20 +0000370 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000371 {
paul718e3742002-12-13 20:15:29 +0000372 p = ifc->address;
373
374 if (p->family == AF_INET
375 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
376 return -1;
377 }
378 }
379 return 0;
380}
381
382/* RIP add route to routing table. */
383void
384rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000385 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000386{
387 int ret;
388 struct prefix_ipv4 p;
389 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000390 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000391 struct rip_interface *ri;
392 struct in_addr *nexthop;
393 u_char oldmetric;
394 int same = 0;
395
396 /* Make prefix structure. */
397 memset (&p, 0, sizeof (struct prefix_ipv4));
398 p.family = AF_INET;
399 p.prefix = rte->prefix;
400 p.prefixlen = ip_masklen (rte->mask);
401
402 /* Make sure mask is applied. */
403 apply_mask_ipv4 (&p);
404
405 /* Apply input filters. */
406 ri = ifp->info;
407
408 ret = rip_incoming_filter (&p, ri);
409 if (ret < 0)
410 return;
411
hasso16705132003-05-25 14:49:19 +0000412 /* Modify entry according to the interface routemap. */
413 if (ri->routemap[RIP_FILTER_IN])
414 {
415 int ret;
416 struct rip_info newinfo;
417
418 memset (&newinfo, 0, sizeof (newinfo));
419 newinfo.type = ZEBRA_ROUTE_RIP;
420 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000421 newinfo.nexthop = rte->nexthop;
422 newinfo.from = from->sin_addr;
423 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000424 newinfo.metric = rte->metric;
425 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000426 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000427
428 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000429 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
430 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000431
432 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000433 {
434 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000435 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000436 inet_ntoa (p.prefix), p.prefixlen);
437 return;
438 }
hasso16705132003-05-25 14:49:19 +0000439
440 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000441 rte->nexthop = newinfo.nexthop_out;
442 rte->tag = htons (newinfo.tag_out); /* XXX */
443 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000444 }
445
paul718e3742002-12-13 20:15:29 +0000446 /* Once the entry has been validated, update the metric by
447 adding the cost of the network on wich the message
448 arrived. If the result is greater than infinity, use infinity
449 (RFC2453 Sec. 3.9.2) */
450 /* Zebra ripd can handle offset-list in. */
451 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
452
453 /* If offset-list does not modify the metric use interface's
454 metric. */
paula87552c2004-05-03 20:00:17 +0000455 if (!ret)
paul718e3742002-12-13 20:15:29 +0000456 rte->metric += ifp->metric;
457
458 if (rte->metric > RIP_METRIC_INFINITY)
459 rte->metric = RIP_METRIC_INFINITY;
460
461 /* Set nexthop pointer. */
462 if (rte->nexthop.s_addr == 0)
463 nexthop = &from->sin_addr;
464 else
465 nexthop = &rte->nexthop;
466
hasso16705132003-05-25 14:49:19 +0000467 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000468 if (rip_nexthop_check (nexthop) < 0)
469 {
470 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000471 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000472 return;
473 }
474
475 /* Get index for the prefix. */
476 rp = route_node_get (rip->table, (struct prefix *) &p);
477
478 /* Check to see whether there is already RIP route on the table. */
479 rinfo = rp->info;
480
481 if (rinfo)
482 {
483 /* Redistributed route check. */
484 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000485 && rinfo->metric != RIP_METRIC_INFINITY)
486 return;
paul718e3742002-12-13 20:15:29 +0000487
488 /* Local static route. */
489 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000490 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
491 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
492 && rinfo->metric != RIP_METRIC_INFINITY)
493 return;
paul718e3742002-12-13 20:15:29 +0000494 }
paula87552c2004-05-03 20:00:17 +0000495
496 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000497 {
498 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000499 for the destination prefix. If there is no such route, add
500 this route to the routing table, unless the metric is
501 infinity (there is no point in adding a route which
502 unusable). */
paul718e3742002-12-13 20:15:29 +0000503 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000504 {
505 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000506
paula87552c2004-05-03 20:00:17 +0000507 /* - Setting the destination prefix and length to those in
508 the RTE. */
509 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000510
paula87552c2004-05-03 20:00:17 +0000511 /* - Setting the metric to the newly calculated metric (as
512 described above). */
513 rinfo->metric = rte->metric;
514 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000515
paula87552c2004-05-03 20:00:17 +0000516 /* - Set the next hop address to be the address of the router
517 from which the datagram came or the next hop address
518 specified by a next hop RTE. */
519 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
520 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
521 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000522
paula87552c2004-05-03 20:00:17 +0000523 /* - Initialize the timeout for the route. If the
524 garbage-collection timer is running for this route, stop it
525 (see section 2.3 for a discussion of the timers). */
526 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000527
paula87552c2004-05-03 20:00:17 +0000528 /* - Set the route change flag. */
529 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Signal the output process to trigger an update (see section
532 2.5). */
533 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000534
paula87552c2004-05-03 20:00:17 +0000535 /* Finally, route goes into the kernel. */
536 rinfo->type = ZEBRA_ROUTE_RIP;
537 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000538
paula87552c2004-05-03 20:00:17 +0000539 /* Set distance value. */
540 rinfo->distance = rip_distance_apply (rinfo);
541
542 rp->info = rinfo;
543 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
544 rinfo->distance);
545 rinfo->flags |= RIP_RTF_FIB;
546 }
paul718e3742002-12-13 20:15:29 +0000547 }
548 else
549 {
550 /* Route is there but we are not sure the route is RIP or not. */
551 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000552
paul718e3742002-12-13 20:15:29 +0000553 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000554 to the address of the router from which the datagram came.
555 If this datagram is from the same router as the existing
556 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000557 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000558 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000559
560 if (same)
paula87552c2004-05-03 20:00:17 +0000561 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000562
paulb94f9db2004-05-01 20:45:38 +0000563
564 /* Fill in a minimaly temporary rip_info structure, for a future
565 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000566 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000567 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000568 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000569
570
paul718e3742002-12-13 20:15:29 +0000571 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000572 router as the existing route, and the new metric is different
573 than the old one; or, if the new metric is lower than the old
574 one, or if the tag has been changed; or if there is a route
575 with a lower administrave distance; or an update of the
576 distance on the actual route; do the following actions: */
577 if ((same && rinfo->metric != rte->metric)
578 || (rte->metric < rinfo->metric)
579 || ((same)
580 && (rinfo->metric == rte->metric)
581 && ntohs (rte->tag) != rinfo->tag)
582 || (rinfo->distance > rip_distance_apply (&rinfotmp))
583 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
584 {
585 /* - Adopt the route from the datagram. That is, put the
586 new metric in, and adjust the next hop address (if
587 necessary). */
588 oldmetric = rinfo->metric;
589 rinfo->metric = rte->metric;
590 rinfo->tag = ntohs (rte->tag);
591 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
592 rinfo->ifindex = ifp->ifindex;
593 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000594
paula87552c2004-05-03 20:00:17 +0000595 /* Should a new route to this network be established
596 while the garbage-collection timer is running, the
597 new route will replace the one that is about to be
598 deleted. In this case the garbage-collection timer
599 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000600
paula87552c2004-05-03 20:00:17 +0000601 if (oldmetric == RIP_METRIC_INFINITY &&
602 rinfo->metric < RIP_METRIC_INFINITY)
603 {
604 rinfo->type = ZEBRA_ROUTE_RIP;
605 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000606
paula87552c2004-05-03 20:00:17 +0000607 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000608
paula87552c2004-05-03 20:00:17 +0000609 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
610 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
613 rinfo->distance);
614 rinfo->flags |= RIP_RTF_FIB;
615 }
paul718e3742002-12-13 20:15:29 +0000616
paula87552c2004-05-03 20:00:17 +0000617 /* Update nexthop and/or metric value. */
618 if (oldmetric != RIP_METRIC_INFINITY)
619 {
620 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
621 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
622 rinfo->distance);
623 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000624
paula87552c2004-05-03 20:00:17 +0000625 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
626 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
627 }
paul718e3742002-12-13 20:15:29 +0000628
paula87552c2004-05-03 20:00:17 +0000629 /* - Set the route change flag and signal the output process
630 to trigger an update. */
631 rinfo->flags |= RIP_RTF_CHANGED;
632 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000633
paula87552c2004-05-03 20:00:17 +0000634 /* - If the new metric is infinity, start the deletion
635 process (described above); */
636 if (rinfo->metric == RIP_METRIC_INFINITY)
637 {
638 /* If the new metric is infinity, the deletion process
639 begins for the route, which is no longer used for
640 routing packets. Note that the deletion process is
641 started only when the metric is first set to
642 infinity. If the metric was already infinity, then a
643 new deletion process is not started. */
644 if (oldmetric != RIP_METRIC_INFINITY)
645 {
646 /* - The garbage-collection timer is set for 120 seconds. */
647 RIP_TIMER_ON (rinfo->t_garbage_collect,
648 rip_garbage_collect, rip->garbage_time);
649 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000650
paula87552c2004-05-03 20:00:17 +0000651 /* - The metric for the route is set to 16
652 (infinity). This causes the route to be removed
653 from service. */
654 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
655 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000656
paula87552c2004-05-03 20:00:17 +0000657 /* - The route change flag is to indicate that this
658 entry has been changed. */
659 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000660 response. */
paula87552c2004-05-03 20:00:17 +0000661 ; /* Above processes are already done previously. */
662 }
663 }
664 else
665 {
666 /* otherwise, re-initialize the timeout. */
667 rip_timeout_update (rinfo);
668 }
669 }
paul718e3742002-12-13 20:15:29 +0000670 /* Unlock tempolary lock of the route. */
671 route_unlock_node (rp);
672 }
673}
674
675/* Dump RIP packet */
676void
hasso8a676be2004-10-08 06:36:38 +0000677rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000678{
679 caddr_t lim;
680 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000681 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000682 char pbuf[BUFSIZ], nbuf[BUFSIZ];
683 u_char netmask = 0;
684 u_char *p;
685
686 /* Set command string. */
687 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
688 command_str = lookup (rip_msg, packet->command);
689 else
690 command_str = "unknown";
691
692 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000693 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000694 sndrcv, command_str, packet->version, size);
695
696 /* Dump each routing table entry. */
697 rte = packet->rte;
698
699 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
700 {
701 if (packet->version == RIPv2)
702 {
703 netmask = ip_masklen (rte->mask);
704
paulca5e5162004-06-06 22:06:33 +0000705 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000706 {
paulca5e5162004-06-06 22:06:33 +0000707 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000708 {
709 p = (u_char *)&rte->prefix;
710
ajs5d6c3772004-12-08 19:24:06 +0000711 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000712 ntohs (rte->family), ntohs (rte->tag), p);
713 }
paulca5e5162004-06-06 22:06:33 +0000714 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000715 {
716 struct rip_md5_info *md5;
717
718 md5 = (struct rip_md5_info *) &packet->rte;
719
ajs5d6c3772004-12-08 19:24:06 +0000720 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000721 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000722 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000723 " Auth Data len %d",
724 ntohs (md5->packet_len), md5->keyid,
725 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000726 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000727 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000728 }
paulca5e5162004-06-06 22:06:33 +0000729 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000730 {
731 p = (u_char *)&rte->prefix;
732
ajs5d6c3772004-12-08 19:24:06 +0000733 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000734 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000735 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000736 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000737 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
738 p[7], p[9], p[10], p[11], p[12], p[13],
739 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000740 }
741 else
742 {
ajs5d6c3772004-12-08 19:24:06 +0000743 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000744 ntohs (rte->family), ntohs (rte->tag));
745 }
746 }
747 else
ajs5d6c3772004-12-08 19:24:06 +0000748 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000749 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
750 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
751 BUFSIZ), ntohs (rte->family),
752 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000753 }
754 else
755 {
ajs5d6c3772004-12-08 19:24:06 +0000756 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000757 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
758 ntohs (rte->family), ntohs (rte->tag),
759 (u_long)ntohl (rte->metric));
760 }
761 }
762}
763
764/* Check if the destination address is valid (unicast; not net 0
765 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
766 check net 0 because we accept default route. */
767int
768rip_destination_check (struct in_addr addr)
769{
770 u_int32_t destination;
771
772 /* Convert to host byte order. */
773 destination = ntohl (addr.s_addr);
774
775 if (IPV4_NET127 (destination))
776 return 0;
777
778 /* Net 0 may match to the default route. */
779 if (IPV4_NET0 (destination) && destination != 0)
780 return 0;
781
782 /* Unicast address must belong to class A, B, C. */
783 if (IN_CLASSA (destination))
784 return 1;
785 if (IN_CLASSB (destination))
786 return 1;
787 if (IN_CLASSC (destination))
788 return 1;
789
790 return 0;
791}
792
793/* RIP version 2 authentication. */
794int
795rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
796 struct interface *ifp)
797{
798 struct rip_interface *ri;
799 char *auth_str;
800
801 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000802 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000803 inet_ntoa (from->sin_addr));
804
805 ri = ifp->info;
806
807 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000808 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000809 return 0;
810
811 /* Simple password authentication. */
812 if (ri->auth_str)
813 {
814 auth_str = (char *) &rte->prefix;
815
816 if (strncmp (auth_str, ri->auth_str, 16) == 0)
817 return 1;
818 }
819 if (ri->key_chain)
820 {
821 struct keychain *keychain;
822 struct key *key;
823
824 keychain = keychain_lookup (ri->key_chain);
825 if (keychain == NULL)
826 return 0;
827
828 key = key_match_for_accept (keychain, (char *) &rte->prefix);
829 if (key)
830 return 1;
831 }
832 return 0;
833}
834
835/* RIP version 2 authentication with MD5. */
836int
837rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000838 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000839{
840 struct rip_interface *ri;
841 struct rip_md5_info *md5;
842 struct rip_md5_data *md5data;
843 struct keychain *keychain;
844 struct key *key;
845 struct md5_ctx ctx;
846 u_char pdigest[RIP_AUTH_MD5_SIZE];
847 u_char digest[RIP_AUTH_MD5_SIZE];
848 u_int16_t packet_len;
849 char *auth_str = NULL;
850
851 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000852 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000853 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000854
855 ri = ifp->info;
856 md5 = (struct rip_md5_info *) &packet->rte;
857
858 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000859 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000860 return 0;
861
paulca5e5162004-06-06 22:06:33 +0000862 /* If the authentication length is less than 16, then it must be wrong for
863 * any interpretation of rfc2082. Some implementations also interpret
864 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000865 */
paulca5e5162004-06-06 22:06:33 +0000866 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
867 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000868 {
869 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000870 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000871 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000872 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000873 }
paul718e3742002-12-13 20:15:29 +0000874
paulca5e5162004-06-06 22:06:33 +0000875 /* grab and verify check packet length */
876 packet_len = ntohs (md5->packet_len);
877
878 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
879 {
880 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000881 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000882 "greater than received length %d!",
883 md5->packet_len, length);
884 return 0;
885 }
886
887 /* retrieve authentication data */
888 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
889
paul718e3742002-12-13 20:15:29 +0000890 if (ri->key_chain)
891 {
892 keychain = keychain_lookup (ri->key_chain);
893 if (keychain == NULL)
894 return 0;
895
896 key = key_lookup_for_accept (keychain, md5->keyid);
897 if (key == NULL)
898 return 0;
899
900 auth_str = key->string;
901 }
902
903 if (ri->auth_str)
904 auth_str = ri->auth_str;
905
906 if (! auth_str)
907 return 0;
908
909 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000910
911 /* Save digest to pdigest. */
912 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
913
914 /* Overwrite digest by my secret. */
915 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000916 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000917
918 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000919 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000920 &ctx);
paul718e3742002-12-13 20:15:29 +0000921 md5_finish_ctx (&ctx, digest);
922
923 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
924 return packet_len;
925 else
926 return 0;
927}
928
paulb14ee002005-02-04 23:42:41 +0000929/* Pick correct auth string for sends, prepare auth_str buffer for use.
930 * (left justified and padded).
931 *
932 * presumes one of ri or key is valid, and that the auth strings they point
933 * to are nul terminated. If neither are present, auth_str will be fully
934 * zero padded.
935 *
936 */
937static void
938rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
939 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000940{
paulb14ee002005-02-04 23:42:41 +0000941 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000942
paulb14ee002005-02-04 23:42:41 +0000943 memset (auth_str, 0, len);
944 if (key && key->string)
945 strncpy (auth_str, key->string, len);
946 else if (ri->auth_str)
947 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000948
paulb14ee002005-02-04 23:42:41 +0000949 return;
950}
paul718e3742002-12-13 20:15:29 +0000951
paulb14ee002005-02-04 23:42:41 +0000952/* Write RIPv2 simple password authentication information
953 *
954 * auth_str is presumed to be 2 bytes and correctly prepared
955 * (left justified and zero padded).
956 */
957static void
958rip_auth_simple_write (struct stream *s, char *auth_str, int len)
959{
960 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +0000961
paulb14ee002005-02-04 23:42:41 +0000962 stream_putw (s, RIP_FAMILY_AUTH);
963 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
964 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
965
966 return;
967}
968
969/* write RIPv2 MD5 "authentication header"
970 * (uses the auth key data field)
971 *
972 * Digest offset field is set to 0.
973 *
974 * returns: offset of the digest offset field, which must be set when
975 * length to the auth-data MD5 digest is known.
976 */
977static size_t
978rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
979 struct key *key)
980{
981 size_t len = 0;
982
983 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +0000984
985 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000986 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000987 stream_putw (s, RIP_AUTH_MD5);
988
paulb14ee002005-02-04 23:42:41 +0000989 /* MD5 AH digest offset field.
990 *
991 * Set to placeholder value here, to true value when RIP-2 Packet length
992 * is known. Actual value is set in .....().
993 */
paul9985f832005-02-09 15:51:56 +0000994 len = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +0000995 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +0000996
997 /* Key ID. */
998 if (key)
999 stream_putc (s, key->index % 256);
1000 else
1001 stream_putc (s, 1);
1002
paulca5e5162004-06-06 22:06:33 +00001003 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1004 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1005 * to be configurable.
1006 */
1007 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001008
1009 /* Sequence Number (non-decreasing). */
1010 /* RFC2080: The value used in the sequence number is
1011 arbitrary, but two suggestions are the time of the
1012 message's creation or a simple message counter. */
1013 stream_putl (s, time (NULL));
1014
1015 /* Reserved field must be zero. */
1016 stream_putl (s, 0);
1017 stream_putl (s, 0);
1018
paulb14ee002005-02-04 23:42:41 +00001019 return len;
1020}
paul718e3742002-12-13 20:15:29 +00001021
paulb14ee002005-02-04 23:42:41 +00001022/* If authentication is in used, write the appropriate header
1023 * returns stream offset to which length must later be written
1024 * or 0 if this is not required
1025 */
1026static size_t
1027rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1028 struct key *key, char *auth_str, int len)
1029{
1030 assert (ri->auth_type != RIP_NO_AUTH);
1031
1032 switch (ri->auth_type)
1033 {
1034 case RIP_AUTH_SIMPLE_PASSWORD:
1035 rip_auth_prepare_str_send (ri, key, auth_str, len);
1036 rip_auth_simple_write (s, auth_str, len);
1037 return 0;
1038 case RIP_AUTH_MD5:
1039 return rip_auth_md5_ah_write (s, ri, key);
1040 }
1041 assert (1);
1042}
1043
1044/* Write RIPv2 MD5 authentication data trailer */
1045static void
1046rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1047 char *auth_str, int authlen)
1048{
1049 unsigned long len;
1050 struct md5_ctx ctx;
1051 unsigned char digest[RIP_AUTH_MD5_SIZE];
1052
1053 /* Make it sure this interface is configured as MD5
1054 authentication. */
1055 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1056 assert (doff > 0);
1057
1058 /* Get packet length. */
1059 len = stream_get_endp(s);
1060
1061 /* Check packet length. */
1062 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1063 {
1064 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1065 return;
1066 }
1067
1068 /* Set the digest offset length in the header */
1069 stream_putw_at (s, doff, len);
1070
paul718e3742002-12-13 20:15:29 +00001071 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001072 stream_putw (s, RIP_FAMILY_AUTH);
1073 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001074
1075 /* Generate a digest for the RIP packet. */
paul718e3742002-12-13 20:15:29 +00001076 md5_init_ctx (&ctx);
1077 md5_process_bytes (s->data, s->endp, &ctx);
paulb14ee002005-02-04 23:42:41 +00001078 md5_process_bytes (auth_str, RIP_AUTH_MD5_SIZE, &ctx);
paul718e3742002-12-13 20:15:29 +00001079 md5_finish_ctx (&ctx, digest);
1080
1081 /* Copy the digest to the packet. */
1082 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1083}
1084
1085/* RIP routing information. */
1086void
1087rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001088 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001089{
1090 caddr_t lim;
1091 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001092 struct prefix_ipv4 ifaddr;
1093 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001094 int subnetted;
paul718e3742002-12-13 20:15:29 +00001095
paul727d1042002-12-13 20:50:29 +00001096 /* We don't know yet. */
1097 subnetted = -1;
1098
paul718e3742002-12-13 20:15:29 +00001099 /* The Response must be ignored if it is not from the RIP
1100 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001101 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001102 {
1103 zlog_info ("response doesn't come from RIP port: %d",
1104 from->sin_port);
1105 rip_peer_bad_packet (from);
1106 return;
1107 }
1108
1109 /* The datagram's IPv4 source address should be checked to see
1110 whether the datagram is from a valid neighbor; the source of the
1111 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001112 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001113 {
1114 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1115 inet_ntoa (from->sin_addr));
1116 rip_peer_bad_packet (from);
1117 return;
1118 }
1119
1120 /* It is also worth checking to see whether the response is from one
1121 of the router's own addresses. */
1122
1123 ; /* Alredy done in rip_read () */
1124
1125 /* Update RIP peer. */
1126 rip_peer_update (from, packet->version);
1127
1128 /* Set RTE pointer. */
1129 rte = packet->rte;
1130
1131 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1132 {
1133 /* RIPv2 authentication check. */
1134 /* If the Address Family Identifier of the first (and only the
1135 first) entry in the message is 0xFFFF, then the remainder of
1136 the entry contains the authentication. */
1137 /* If the packet gets here it means authentication enabled */
1138 /* Check is done in rip_read(). So, just skipping it */
1139 if (packet->version == RIPv2 &&
1140 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001141 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001142 continue;
1143
paulca5e5162004-06-06 22:06:33 +00001144 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001145 {
1146 /* Address family check. RIP only supports AF_INET. */
1147 zlog_info ("Unsupported family %d from %s.",
1148 ntohs (rte->family), inet_ntoa (from->sin_addr));
1149 continue;
1150 }
1151
1152 /* - is the destination address valid (e.g., unicast; not net 0
1153 or 127) */
1154 if (! rip_destination_check (rte->prefix))
1155 {
1156 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1157 rip_peer_bad_route (from);
1158 continue;
1159 }
1160
1161 /* Convert metric value to host byte order. */
1162 rte->metric = ntohl (rte->metric);
1163
1164 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1165 if (! (rte->metric >= 1 && rte->metric <= 16))
1166 {
1167 zlog_info ("Route's metric is not in the 1-16 range.");
1168 rip_peer_bad_route (from);
1169 continue;
1170 }
1171
1172 /* RIPv1 does not have nexthop value. */
1173 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1174 {
1175 zlog_info ("RIPv1 packet with nexthop value %s",
1176 inet_ntoa (rte->nexthop));
1177 rip_peer_bad_route (from);
1178 continue;
1179 }
1180
1181 /* That is, if the provided information is ignored, a possibly
1182 sub-optimal, but absolutely valid, route may be taken. If
1183 the received Next Hop is not directly reachable, it should be
1184 treated as 0.0.0.0. */
1185 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1186 {
1187 u_int32_t addrval;
1188
1189 /* Multicast address check. */
1190 addrval = ntohl (rte->nexthop.s_addr);
1191 if (IN_CLASSD (addrval))
1192 {
1193 zlog_info ("Nexthop %s is multicast address, skip this rte",
1194 inet_ntoa (rte->nexthop));
1195 continue;
1196 }
1197
1198 if (! if_lookup_address (rte->nexthop))
1199 {
1200 struct route_node *rn;
1201 struct rip_info *rinfo;
1202
1203 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1204
1205 if (rn)
1206 {
1207 rinfo = rn->info;
1208
1209 if (rinfo->type == ZEBRA_ROUTE_RIP
1210 && rinfo->sub_type == RIP_ROUTE_RTE)
1211 {
1212 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001213 zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001214 rte->nexthop = rinfo->from;
1215 }
1216 else
1217 {
1218 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001219 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001220 rte->nexthop.s_addr = 0;
1221 }
1222
1223 route_unlock_node (rn);
1224 }
1225 else
1226 {
1227 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001228 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001229 rte->nexthop.s_addr = 0;
1230 }
1231
1232 }
1233 }
1234
1235 /* For RIPv1, there won't be a valid netmask.
1236
1237 This is a best guess at the masks. If everyone was using old
1238 Ciscos before the 'ip subnet zero' option, it would be almost
1239 right too :-)
1240
1241 Cisco summarize ripv1 advertisments to the classful boundary
1242 (/16 for class B's) except when the RIP packet does to inside
1243 the classful network in question. */
1244
1245 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1246 || (packet->version == RIPv2
1247 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1248 {
1249 u_int32_t destination;
1250
paul727d1042002-12-13 20:50:29 +00001251 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001252 {
1253 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1254 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1255 apply_classful_mask_ipv4 (&ifaddrclass);
1256 subnetted = 0;
1257 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1258 subnetted = 1;
1259 }
paul727d1042002-12-13 20:50:29 +00001260
paul718e3742002-12-13 20:15:29 +00001261 destination = ntohl (rte->prefix.s_addr);
1262
paul727d1042002-12-13 20:50:29 +00001263 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001264 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001265 else if (IN_CLASSB (destination))
1266 masklen2ip (16, &rte->mask);
1267 else if (IN_CLASSC (destination))
1268 masklen2ip (24, &rte->mask);
1269
1270 if (subnetted == 1)
1271 masklen2ip (ifaddrclass.prefixlen,
1272 (struct in_addr *) &destination);
1273 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1274 ifaddrclass.prefix.s_addr))
1275 {
1276 masklen2ip (ifaddr.prefixlen, &rte->mask);
1277 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1278 masklen2ip (32, &rte->mask);
1279 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001280 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001281 }
1282 else
1283 {
1284 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1285 continue;
1286 }
1287
1288 if (IS_RIP_DEBUG_EVENT)
1289 {
ajs5d6c3772004-12-08 19:24:06 +00001290 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1291 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001292 }
1293 }
1294
1295 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1296 ignore the entry. */
1297 if ((packet->version == RIPv2)
1298 && (rte->mask.s_addr != 0)
1299 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1300 {
1301 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1302 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1303 rip_peer_bad_route (from);
1304 continue;
1305 }
1306
1307 /* Default route's netmask is ignored. */
1308 if (packet->version == RIPv2
1309 && (rte->prefix.s_addr == 0)
1310 && (rte->mask.s_addr != 0))
1311 {
1312 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001313 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001314 rte->mask.s_addr = 0;
1315 }
1316
1317 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001318 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001319 }
1320}
1321
paula4e987e2005-06-03 17:46:49 +00001322/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001323static int
paul2c61ae32005-08-16 15:22:14 +00001324rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001325{
1326 int ret;
1327 int sock;
1328 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001329
paul2c61ae32005-08-16 15:22:14 +00001330 memset (&addr, 0, sizeof (struct sockaddr_in));
1331
1332 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001333 {
paulf69bd9d2005-06-03 18:01:50 +00001334 addr.sin_family = AF_INET;
1335 addr.sin_addr.s_addr = INADDR_ANY;
paul2c61ae32005-08-16 15:22:14 +00001336#ifdef HAVE_SINLEN
1337 addr.sin_len = sizeof (struct sockaddr_in);
1338#endif /* HAVE_SINLEN */
paulf69bd9d2005-06-03 18:01:50 +00001339 }
1340
paul2c61ae32005-08-16 15:22:14 +00001341 /* sending port must always be the RIP port */
1342 addr.sin_port = htons (RIP_PORT_DEFAULT);
1343
paula4e987e2005-06-03 17:46:49 +00001344 /* Make datagram socket. */
1345 sock = socket (AF_INET, SOCK_DGRAM, 0);
1346 if (sock < 0)
1347 {
1348 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1349 exit (1);
1350 }
1351
1352 sockopt_broadcast (sock);
1353 sockopt_reuseaddr (sock);
1354 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001355#ifdef RIP_RECVMSG
1356 setsockopt_pktinfo (sock);
1357#endif /* RIP_RECVMSG */
1358
1359 if (ripd_privs.change (ZPRIVS_RAISE))
1360 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001361 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1362 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1363
paula4e987e2005-06-03 17:46:49 +00001364 {
1365 int save_errno = errno;
1366 if (ripd_privs.change (ZPRIVS_LOWER))
1367 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001368
1369 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1370 sock, inet_ntoa(addr.sin_addr),
1371 (int) ntohs(addr.sin_port),
1372 safe_strerror(save_errno));
1373
paulf69bd9d2005-06-03 18:01:50 +00001374 close (sock);
paula4e987e2005-06-03 17:46:49 +00001375 return ret;
1376 }
paulf69bd9d2005-06-03 18:01:50 +00001377
paula4e987e2005-06-03 17:46:49 +00001378 if (ripd_privs.change (ZPRIVS_LOWER))
1379 zlog_err ("rip_create_socket: could not lower privs");
1380
1381 return sock;
1382}
1383
paulc49ad8f2004-10-22 10:27:28 +00001384/* RIP packet send to destination address, on interface denoted by
1385 * by connected argument. NULL to argument denotes destination should be
1386 * should be RIP multicast group
1387 */
paul718e3742002-12-13 20:15:29 +00001388int
paulc49ad8f2004-10-22 10:27:28 +00001389rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1390 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001391{
paul931cd542004-01-23 15:31:42 +00001392 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001393 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001394
1395 assert (ifc != NULL);
1396
paul931cd542004-01-23 15:31:42 +00001397 if (IS_RIP_DEBUG_PACKET)
1398 {
paulf69bd9d2005-06-03 18:01:50 +00001399#define ADDRESS_SIZE 20
1400 char dst[ADDRESS_SIZE];
1401 dst[ADDRESS_SIZE - 1] = '\0';
1402
paul931cd542004-01-23 15:31:42 +00001403 if (to)
1404 {
paulf69bd9d2005-06-03 18:01:50 +00001405 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001406 }
1407 else
1408 {
1409 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001410 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001411 }
paulf69bd9d2005-06-03 18:01:50 +00001412#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001413 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001414 inet_ntoa(ifc->address->u.prefix4),
1415 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001416 }
paulf69bd9d2005-06-03 18:01:50 +00001417
paulc49ad8f2004-10-22 10:27:28 +00001418 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001419 {
1420 /*
1421 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1422 * with multiple addresses on the same subnet: the first address
1423 * on the subnet is configured "primary", and all subsequent addresses
1424 * on that subnet are treated as "secondary" addresses.
1425 * In order to avoid routing-table bloat on other rip listeners,
1426 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1427 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1428 * flag is set, we would end up sending a packet for a "secondary"
1429 * source address on non-linux systems.
1430 */
1431 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001432 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001433 return 0;
1434 }
1435
paul718e3742002-12-13 20:15:29 +00001436 /* Make destination address. */
1437 memset (&sin, 0, sizeof (struct sockaddr_in));
1438 sin.sin_family = AF_INET;
1439#ifdef HAVE_SIN_LEN
1440 sin.sin_len = sizeof (struct sockaddr_in);
1441#endif /* HAVE_SIN_LEN */
1442
1443 /* When destination is specified, use it's port and address. */
1444 if (to)
1445 {
paul718e3742002-12-13 20:15:29 +00001446 sin.sin_port = to->sin_port;
1447 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001448 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001449 }
1450 else
1451 {
paul2c61ae32005-08-16 15:22:14 +00001452 struct sockaddr_in from;
1453
paul718e3742002-12-13 20:15:29 +00001454 sin.sin_port = htons (RIP_PORT_DEFAULT);
1455 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001456
1457 /* multicast send should bind to local interface address */
1458 from.sin_family = AF_INET;
1459 from.sin_port = htons (RIP_PORT_DEFAULT);
1460 from.sin_addr = ifc->address->u.prefix4;
1461#ifdef HAVE_SIN_LEN
1462 from.sin_len = sizeof (struct sockaddr_in);
1463#endif /* HAVE_SIN_LEN */
1464
paul931cd542004-01-23 15:31:42 +00001465 /*
1466 * we have to open a new socket for each packet because this
1467 * is the most portable way to bind to a different source
1468 * ipv4 address for each packet.
1469 */
paul2c61ae32005-08-16 15:22:14 +00001470 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001471 {
paulf69bd9d2005-06-03 18:01:50 +00001472 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001473 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001474 }
paulc49ad8f2004-10-22 10:27:28 +00001475 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001476 }
1477
paul931cd542004-01-23 15:31:42 +00001478 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001479 sizeof (struct sockaddr_in));
1480
1481 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001482 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001483 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001484
1485 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001486 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001487
paul931cd542004-01-23 15:31:42 +00001488 if (!to)
1489 close(send_sock);
1490
paul718e3742002-12-13 20:15:29 +00001491 return ret;
1492}
1493
1494/* Add redistributed route to RIP table. */
1495void
1496rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1497 unsigned int ifindex, struct in_addr *nexthop)
1498{
1499 int ret;
1500 struct route_node *rp;
1501 struct rip_info *rinfo;
1502
1503 /* Redistribute route */
1504 ret = rip_destination_check (p->prefix);
1505 if (! ret)
1506 return;
1507
1508 rp = route_node_get (rip->table, (struct prefix *) p);
1509
1510 rinfo = rp->info;
1511
1512 if (rinfo)
1513 {
1514 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1515 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1516 && rinfo->metric != RIP_METRIC_INFINITY)
1517 {
1518 route_unlock_node (rp);
1519 return;
1520 }
1521
1522 /* Manually configured RIP route check. */
1523 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001524 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1525 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001526 {
hasso16705132003-05-25 14:49:19 +00001527 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1528 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001529 {
1530 route_unlock_node (rp);
1531 return;
1532 }
1533 }
1534
1535 RIP_TIMER_OFF (rinfo->t_timeout);
1536 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1537
1538 if (rip_route_rte (rinfo))
1539 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1540 rinfo->metric);
1541 rp->info = NULL;
1542 rip_info_free (rinfo);
1543
1544 route_unlock_node (rp);
1545 }
1546
1547 rinfo = rip_info_new ();
1548
1549 rinfo->type = type;
1550 rinfo->sub_type = sub_type;
1551 rinfo->ifindex = ifindex;
1552 rinfo->metric = 1;
1553 rinfo->rp = rp;
1554
1555 if (nexthop)
1556 rinfo->nexthop = *nexthop;
1557
1558 rinfo->flags |= RIP_RTF_FIB;
1559 rp->info = rinfo;
1560
1561 rinfo->flags |= RIP_RTF_CHANGED;
1562
hasso16705132003-05-25 14:49:19 +00001563 if (IS_RIP_DEBUG_EVENT) {
1564 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001565 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001566 inet_ntoa(p->prefix), p->prefixlen,
1567 ifindex2ifname(ifindex));
1568 else
ajs5d6c3772004-12-08 19:24:06 +00001569 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001570 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1571 ifindex2ifname(ifindex));
1572 }
1573
1574
paul718e3742002-12-13 20:15:29 +00001575 rip_event (RIP_TRIGGERED_UPDATE, 0);
1576}
1577
1578/* Delete redistributed route from RIP table. */
1579void
1580rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1581 unsigned int ifindex)
1582{
1583 int ret;
1584 struct route_node *rp;
1585 struct rip_info *rinfo;
1586
1587 ret = rip_destination_check (p->prefix);
1588 if (! ret)
1589 return;
1590
1591 rp = route_node_lookup (rip->table, (struct prefix *) p);
1592 if (rp)
1593 {
1594 rinfo = rp->info;
1595
1596 if (rinfo != NULL
1597 && rinfo->type == type
1598 && rinfo->sub_type == sub_type
1599 && rinfo->ifindex == ifindex)
1600 {
1601 /* Perform poisoned reverse. */
1602 rinfo->metric = RIP_METRIC_INFINITY;
1603 RIP_TIMER_ON (rinfo->t_garbage_collect,
1604 rip_garbage_collect, rip->garbage_time);
1605 RIP_TIMER_OFF (rinfo->t_timeout);
1606 rinfo->flags |= RIP_RTF_CHANGED;
1607
hasso16705132003-05-25 14:49:19 +00001608 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001609 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001610 inet_ntoa(p->prefix), p->prefixlen,
1611 ifindex2ifname(ifindex));
1612
paul718e3742002-12-13 20:15:29 +00001613 rip_event (RIP_TRIGGERED_UPDATE, 0);
1614 }
1615 }
1616}
1617
1618/* Response to request called from rip_read ().*/
1619void
1620rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001621 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001622{
1623 caddr_t lim;
1624 struct rte *rte;
1625 struct prefix_ipv4 p;
1626 struct route_node *rp;
1627 struct rip_info *rinfo;
1628 struct rip_interface *ri;
1629
hasso16705132003-05-25 14:49:19 +00001630 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001631 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001632 return;
1633
hasso429a0f82004-02-22 23:42:22 +00001634 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001635 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001636 if (! ri->running)
1637 return;
paul718e3742002-12-13 20:15:29 +00001638
1639 /* When passive interface is specified, suppress responses */
1640 if (ri->passive)
1641 return;
paulc49ad8f2004-10-22 10:27:28 +00001642
paul718e3742002-12-13 20:15:29 +00001643 /* RIP peer update. */
1644 rip_peer_update (from, packet->version);
1645
1646 lim = ((caddr_t) packet) + size;
1647 rte = packet->rte;
1648
1649 /* The Request is processed entry by entry. If there are no
1650 entries, no response is given. */
1651 if (lim == (caddr_t) rte)
1652 return;
1653
1654 /* There is one special case. If there is exactly one entry in the
1655 request, and it has an address family identifier of zero and a
1656 metric of infinity (i.e., 16), then this is a request to send the
1657 entire routing table. */
1658 if (lim == ((caddr_t) (rte + 1)) &&
1659 ntohs (rte->family) == 0 &&
1660 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1661 {
paulcc1131a2003-10-15 23:20:17 +00001662 struct prefix_ipv4 saddr;
1663
1664 /* saddr will be used for determining which routes to split-horizon.
1665 Since the source address we'll pick will be on the same subnet as the
1666 destination, for the purpose of split-horizoning, we'll
1667 pretend that "from" is our source address. */
1668 saddr.family = AF_INET;
1669 saddr.prefixlen = IPV4_MAX_BITLEN;
1670 saddr.prefix = from->sin_addr;
1671
paul718e3742002-12-13 20:15:29 +00001672 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001673 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001674 }
1675 else
1676 {
1677 /* Examine the list of RTEs in the Request one by one. For each
1678 entry, look up the destination in the router's routing
1679 database and, if there is a route, put that route's metric in
1680 the metric field of the RTE. If there is no explicit route
1681 to the specified destination, put infinity in the metric
1682 field. Once all the entries have been filled in, change the
1683 command from Request to Response and send the datagram back
1684 to the requestor. */
1685 p.family = AF_INET;
1686
1687 for (; ((caddr_t) rte) < lim; rte++)
1688 {
1689 p.prefix = rte->prefix;
1690 p.prefixlen = ip_masklen (rte->mask);
1691 apply_mask_ipv4 (&p);
1692
1693 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1694 if (rp)
1695 {
1696 rinfo = rp->info;
1697 rte->metric = htonl (rinfo->metric);
1698 route_unlock_node (rp);
1699 }
1700 else
1701 rte->metric = htonl (RIP_METRIC_INFINITY);
1702 }
1703 packet->command = RIP_RESPONSE;
1704
paulc49ad8f2004-10-22 10:27:28 +00001705 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001706 }
1707 rip_global_queries++;
1708}
1709
1710#if RIP_RECVMSG
1711/* Set IPv6 packet info to the socket. */
1712static int
1713setsockopt_pktinfo (int sock)
1714{
1715 int ret;
1716 int val = 1;
1717
1718 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1719 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001720 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001721 return ret;
1722}
1723
1724/* Read RIP packet by recvmsg function. */
1725int
1726rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1727 int *ifindex)
1728{
1729 int ret;
1730 struct msghdr msg;
1731 struct iovec iov;
1732 struct cmsghdr *ptr;
1733 char adata[1024];
1734
1735 msg.msg_name = (void *) from;
1736 msg.msg_namelen = sizeof (struct sockaddr_in);
1737 msg.msg_iov = &iov;
1738 msg.msg_iovlen = 1;
1739 msg.msg_control = (void *) adata;
1740 msg.msg_controllen = sizeof adata;
1741 iov.iov_base = buf;
1742 iov.iov_len = size;
1743
1744 ret = recvmsg (sock, &msg, 0);
1745 if (ret < 0)
1746 return ret;
1747
ajsb99760a2005-01-04 16:24:43 +00001748 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001749 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1750 {
1751 struct in_pktinfo *pktinfo;
1752 int i;
1753
1754 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1755 i = pktinfo->ipi_ifindex;
1756 }
1757 return ret;
1758}
1759
1760/* RIP packet read function. */
1761int
1762rip_read_new (struct thread *t)
1763{
1764 int ret;
1765 int sock;
1766 char buf[RIP_PACKET_MAXSIZ];
1767 struct sockaddr_in from;
1768 unsigned int ifindex;
1769
1770 /* Fetch socket then register myself. */
1771 sock = THREAD_FD (t);
1772 rip_event (RIP_READ, sock);
1773
1774 /* Read RIP packet. */
1775 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1776 if (ret < 0)
1777 {
ajs6099b3b2004-11-20 02:06:59 +00001778 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001779 return ret;
1780 }
1781
1782 return ret;
1783}
1784#endif /* RIP_RECVMSG */
1785
1786/* First entry point of RIP packet. */
1787int
1788rip_read (struct thread *t)
1789{
1790 int sock;
1791 int ret;
1792 int rtenum;
1793 union rip_buf rip_buf;
1794 struct rip_packet *packet;
1795 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001796 int len;
1797 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001798 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001799 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001800 struct rip_interface *ri;
1801
1802 /* Fetch socket then register myself. */
1803 sock = THREAD_FD (t);
1804 rip->t_read = NULL;
1805
1806 /* Add myself to tne next event */
1807 rip_event (RIP_READ, sock);
1808
1809 /* RIPd manages only IPv4. */
1810 memset (&from, 0, sizeof (struct sockaddr_in));
1811 fromlen = sizeof (struct sockaddr_in);
1812
1813 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1814 (struct sockaddr *) &from, &fromlen);
1815 if (len < 0)
1816 {
ajs6099b3b2004-11-20 02:06:59 +00001817 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001818 return len;
1819 }
1820
1821 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001822 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001823 {
1824 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001825 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001826 return -1;
1827 }
1828
1829 /* Which interface is this packet comes from. */
1830 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001831
paul718e3742002-12-13 20:15:29 +00001832 /* RIP packet received */
1833 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001834 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001835 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1836 ifp ? ifp->name : "unknown");
1837
1838 /* If this packet come from unknown interface, ignore it. */
1839 if (ifp == NULL)
1840 {
ajs766a0ca2004-12-15 14:55:51 +00001841 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1842 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001843 return -1;
1844 }
1845
1846 ifc = connected_lookup_address (ifp, from.sin_addr);
1847
1848 if (ifc == NULL)
1849 {
ajs766a0ca2004-12-15 14:55:51 +00001850 zlog_info ("rip_read: cannot find connected address for packet from %s "
1851 "port %d on interface %s",
1852 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001853 return -1;
1854 }
1855
1856 /* Packet length check. */
1857 if (len < RIP_PACKET_MINSIZ)
1858 {
1859 zlog_warn ("packet size %d is smaller than minimum size %d",
1860 len, RIP_PACKET_MINSIZ);
1861 rip_peer_bad_packet (&from);
1862 return len;
1863 }
1864 if (len > RIP_PACKET_MAXSIZ)
1865 {
1866 zlog_warn ("packet size %d is larger than max size %d",
1867 len, RIP_PACKET_MAXSIZ);
1868 rip_peer_bad_packet (&from);
1869 return len;
1870 }
1871
1872 /* Packet alignment check. */
1873 if ((len - RIP_PACKET_MINSIZ) % 20)
1874 {
1875 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1876 rip_peer_bad_packet (&from);
1877 return len;
1878 }
1879
1880 /* Set RTE number. */
1881 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1882
1883 /* For easy to handle. */
1884 packet = &rip_buf.rip_packet;
1885
1886 /* RIP version check. */
1887 if (packet->version == 0)
1888 {
1889 zlog_info ("version 0 with command %d received.", packet->command);
1890 rip_peer_bad_packet (&from);
1891 return -1;
1892 }
1893
1894 /* Dump RIP packet. */
1895 if (IS_RIP_DEBUG_RECV)
1896 rip_packet_dump (packet, len, "RECV");
1897
1898 /* RIP version adjust. This code should rethink now. RFC1058 says
1899 that "Version 1 implementations are to ignore this extra data and
1900 process only the fields specified in this document.". So RIPv3
1901 packet should be treated as RIPv1 ignoring must be zero field. */
1902 if (packet->version > RIPv2)
1903 packet->version = RIPv2;
1904
1905 /* Is RIP running or is this RIP neighbor ?*/
1906 ri = ifp->info;
1907 if (! ri->running && ! rip_neighbor_lookup (&from))
1908 {
1909 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001910 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001911 rip_peer_bad_packet (&from);
1912 return -1;
1913 }
1914
1915 /* RIP Version check. */
1916 if (packet->command == RIP_RESPONSE)
1917 {
paulf38a4712003-06-07 01:10:00 +00001918 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1919 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001920 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001921 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001922 {
1923 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001924 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001925 packet->version);
1926 rip_peer_bad_packet (&from);
1927 return -1;
1928 }
1929 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001930 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001931 {
1932 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001933 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001934 packet->version);
1935 rip_peer_bad_packet (&from);
1936 return -1;
1937 }
paul718e3742002-12-13 20:15:29 +00001938 }
1939
1940 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1941 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1942 accepted; authenticated RIP-2 messages shall be discarded. */
1943
1944 if ((ri->auth_type == RIP_NO_AUTH)
1945 && rtenum
paulca5e5162004-06-06 22:06:33 +00001946 && (packet->version == RIPv2)
1947 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001948 {
1949 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001950 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001951 packet->version);
1952 rip_peer_bad_packet (&from);
1953 return -1;
1954 }
1955
1956 /* If the router is configured to authenticate RIP-2 messages, then
1957 RIP-1 messages and RIP-2 messages which pass authentication
1958 testing shall be accepted; unauthenticated and failed
1959 authentication RIP-2 messages shall be discarded. For maximum
1960 security, RIP-1 messages should be ignored when authentication is
1961 in use (see section 4.1); otherwise, the routing information from
1962 authenticated messages will be propagated by RIP-1 routers in an
1963 unauthenticated manner. */
1964
1965 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001966 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001967 {
1968 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001969 if (packet->version == RIPv1
1970 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001971 {
1972 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001973 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001974 ("packet RIPv%d is dropped because authentication enabled",
1975 packet->version);
paul718e3742002-12-13 20:15:29 +00001976 rip_peer_bad_packet (&from);
1977 return -1;
1978 }
1979
1980 /* Check RIPv2 authentication. */
1981 if (packet->version == RIPv2)
1982 {
paulca5e5162004-06-06 22:06:33 +00001983 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001984 {
paulca5e5162004-06-06 22:06:33 +00001985 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001986 {
1987 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1988 if (! ret)
1989 {
1990 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001991 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001992 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001993 rip_peer_bad_packet (&from);
1994 return -1;
1995 }
1996 else
1997 {
1998 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001999 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002000 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002001 }
2002 }
paulca5e5162004-06-06 22:06:33 +00002003 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002004 {
paulca5e5162004-06-06 22:06:33 +00002005 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002006 if (! ret)
2007 {
2008 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002009 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002010 rip_peer_bad_packet (&from);
2011 return -1;
2012 }
2013 else
2014 {
2015 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002016 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002017 }
2018 /* Reset RIP packet length to trim MD5 data. */
2019 len = ret;
2020 }
2021 else
2022 {
2023 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002024 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002025 ntohs (packet->rte->tag));
2026 rip_peer_bad_packet (&from);
2027 return -1;
2028 }
2029 }
2030 else
2031 {
2032 /* There is no authentication in the packet. */
2033 if (ri->auth_str || ri->key_chain)
2034 {
2035 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002036 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002037 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002038 rip_peer_bad_packet (&from);
2039 return -1;
2040 }
2041 }
2042 }
2043 }
2044
2045 /* Process each command. */
2046 switch (packet->command)
2047 {
2048 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002049 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002050 break;
2051 case RIP_REQUEST:
2052 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002053 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002054 break;
2055 case RIP_TRACEON:
2056 case RIP_TRACEOFF:
2057 zlog_info ("Obsolete command %s received, please sent it to routed",
2058 lookup (rip_msg, packet->command));
2059 rip_peer_bad_packet (&from);
2060 break;
2061 case RIP_POLL_ENTRY:
2062 zlog_info ("Obsolete command %s received",
2063 lookup (rip_msg, packet->command));
2064 rip_peer_bad_packet (&from);
2065 break;
2066 default:
2067 zlog_info ("Unknown RIP command %d received", packet->command);
2068 rip_peer_bad_packet (&from);
2069 break;
2070 }
2071
2072 return len;
2073}
2074
paul718e3742002-12-13 20:15:29 +00002075/* Write routing table entry to the stream and return next index of
2076 the routing table entry in the stream. */
2077int
2078rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002079 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002080{
2081 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002082
2083 /* Write routing table entry. */
2084 if (version == RIPv1)
2085 {
2086 stream_putw (s, AF_INET);
2087 stream_putw (s, 0);
2088 stream_put_ipv4 (s, p->prefix.s_addr);
2089 stream_put_ipv4 (s, 0);
2090 stream_put_ipv4 (s, 0);
2091 stream_putl (s, rinfo->metric_out);
2092 }
2093 else
2094 {
2095 masklen2ip (p->prefixlen, &mask);
2096
2097 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002098 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002099 stream_put_ipv4 (s, p->prefix.s_addr);
2100 stream_put_ipv4 (s, mask.s_addr);
2101 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2102 stream_putl (s, rinfo->metric_out);
2103 }
2104
2105 return ++num;
2106}
2107
2108/* Send update to the ifp or spcified neighbor. */
2109void
paulc49ad8f2004-10-22 10:27:28 +00002110rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2111 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002112{
2113 int ret;
2114 struct stream *s;
2115 struct route_node *rp;
2116 struct rip_info *rinfo;
2117 struct rip_interface *ri;
2118 struct prefix_ipv4 *p;
2119 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002120 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002121 struct key *key = NULL;
2122 /* this might need to made dynamic if RIP ever supported auth methods
2123 with larger key string sizes */
2124 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2125 size_t doff; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002126 int num = 0;
paul718e3742002-12-13 20:15:29 +00002127 int rtemax;
paul01d09082003-06-08 21:22:18 +00002128 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002129
2130 /* Logging output event. */
2131 if (IS_RIP_DEBUG_EVENT)
2132 {
2133 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002134 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002135 else
ajs5d6c3772004-12-08 19:24:06 +00002136 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002137 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002138 }
2139
2140 /* Set output stream. */
2141 s = rip->obuf;
2142
2143 /* Reset stream and RTE counter. */
2144 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002145 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2146
2147 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002148 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002149
2150 /* If output interface is in simple password authentication mode, we
2151 need space for authentication data. */
2152 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2153 rtemax -= 1;
2154
2155 /* If output interface is in MD5 authentication mode, we need space
2156 for authentication header and data. */
2157 if (ri->auth_type == RIP_AUTH_MD5)
2158 rtemax -= 2;
2159
2160 /* If output interface is in simple password authentication mode
2161 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002162 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002163 {
2164 if (ri->key_chain)
2165 {
2166 struct keychain *keychain;
2167
2168 keychain = keychain_lookup (ri->key_chain);
2169 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002170 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002171 }
paulb14ee002005-02-04 23:42:41 +00002172 /* to be passed to auth functions later */
2173 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002174 }
2175
paul727d1042002-12-13 20:50:29 +00002176 if (version == RIPv1)
2177 {
paulc49ad8f2004-10-22 10:27:28 +00002178 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002179 apply_classful_mask_ipv4 (&ifaddrclass);
2180 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002181 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002182 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002183 }
2184
paul718e3742002-12-13 20:15:29 +00002185 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2186 if ((rinfo = rp->info) != NULL)
2187 {
paul727d1042002-12-13 20:50:29 +00002188 /* For RIPv1, if we are subnetted, output subnets in our network */
2189 /* that have the same mask as the output "interface". For other */
2190 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002191
2192 if (version == RIPv1)
2193 {
paul727d1042002-12-13 20:50:29 +00002194 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002195
2196 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002197 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002198 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002199
paul727d1042002-12-13 20:50:29 +00002200 if (subnetted &&
2201 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2202 {
paulc49ad8f2004-10-22 10:27:28 +00002203 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002204 (rp->p.prefixlen != 32))
2205 continue;
2206 }
2207 else
2208 {
2209 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2210 apply_classful_mask_ipv4(&classfull);
2211 if (rp->p.u.prefix4.s_addr != 0 &&
2212 classfull.prefixlen != rp->p.prefixlen)
2213 continue;
2214 }
paul718e3742002-12-13 20:15:29 +00002215 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002216 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002217 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002218 }
2219 else
2220 p = (struct prefix_ipv4 *) &rp->p;
2221
2222 /* Apply output filters. */
2223 ret = rip_outgoing_filter (p, ri);
2224 if (ret < 0)
2225 continue;
2226
2227 /* Changed route only output. */
2228 if (route_type == rip_changed_route &&
2229 (! (rinfo->flags & RIP_RTF_CHANGED)))
2230 continue;
2231
2232 /* Split horizon. */
2233 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002234 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002235 {
paul42d14d92003-11-17 09:15:18 +00002236 /*
2237 * We perform split horizon for RIP and connected route.
2238 * For rip routes, we want to suppress the route if we would
2239 * end up sending the route back on the interface that we
2240 * learned it from, with a higher metric. For connected routes,
2241 * we suppress the route if the prefix is a subset of the
2242 * source address that we are going to use for the packet
2243 * (in order to handle the case when multiple subnets are
2244 * configured on the same interface).
2245 */
2246 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002247 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002248 continue;
2249 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002250 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002251 continue;
2252 }
2253
2254 /* Preparation for route-map. */
2255 rinfo->metric_set = 0;
2256 rinfo->nexthop_out.s_addr = 0;
2257 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002258 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002259 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002260
hasso16705132003-05-25 14:49:19 +00002261 /* In order to avoid some local loops,
2262 * if the RIP route has a nexthop via this interface, keep the nexthop,
2263 * otherwise set it to 0. The nexthop should not be propagated
2264 * beyond the local broadcast/multicast area in order
2265 * to avoid an IGP multi-level recursive look-up.
2266 * see (4.4)
2267 */
paulc49ad8f2004-10-22 10:27:28 +00002268 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002269 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002270
2271 /* Interface route-map */
2272 if (ri->routemap[RIP_FILTER_OUT])
2273 {
2274 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2275 (struct prefix *) p, RMAP_RIP,
2276 rinfo);
2277
2278 if (ret == RMAP_DENYMATCH)
2279 {
2280 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002281 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002282 inet_ntoa (p->prefix), p->prefixlen);
2283 continue;
2284 }
2285 }
paul718e3742002-12-13 20:15:29 +00002286
hasso16705132003-05-25 14:49:19 +00002287 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002288 if (rip->route_map[rinfo->type].name
2289 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2290 {
2291 ret = route_map_apply (rip->route_map[rinfo->type].map,
2292 (struct prefix *)p, RMAP_RIP, rinfo);
2293
2294 if (ret == RMAP_DENYMATCH)
2295 {
2296 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002297 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002298 inet_ntoa (p->prefix), p->prefixlen);
2299 continue;
2300 }
2301 }
2302
2303 /* When route-map does not set metric. */
2304 if (! rinfo->metric_set)
2305 {
2306 /* If redistribute metric is set. */
2307 if (rip->route_map[rinfo->type].metric_config
2308 && rinfo->metric != RIP_METRIC_INFINITY)
2309 {
2310 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2311 }
2312 else
2313 {
2314 /* If the route is not connected or localy generated
2315 one, use default-metric value*/
2316 if (rinfo->type != ZEBRA_ROUTE_RIP
2317 && rinfo->type != ZEBRA_ROUTE_CONNECT
2318 && rinfo->metric != RIP_METRIC_INFINITY)
2319 rinfo->metric_out = rip->default_metric;
2320 }
2321 }
2322
2323 /* Apply offset-list */
2324 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002325 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002326
2327 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2328 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002329
2330 /* Perform split-horizon with poisoned reverse
2331 * for RIP and connected routes.
2332 **/
2333 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002334 /*
2335 * We perform split horizon for RIP and connected route.
2336 * For rip routes, we want to suppress the route if we would
2337 * end up sending the route back on the interface that we
2338 * learned it from, with a higher metric. For connected routes,
2339 * we suppress the route if the prefix is a subset of the
2340 * source address that we are going to use for the packet
2341 * (in order to handle the case when multiple subnets are
2342 * configured on the same interface).
2343 */
2344 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002345 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002346 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002347 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002348 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002349 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002350 }
paulb14ee002005-02-04 23:42:41 +00002351
2352 /* Prepare preamble, auth headers, if needs be */
2353 if (num == 0)
2354 {
2355 stream_putc (s, RIP_RESPONSE);
2356 stream_putc (s, version);
2357 stream_putw (s, 0);
2358
paul0cb8a012005-05-29 11:27:24 +00002359 /* auth header for !v1 && !no_auth */
2360 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002361 doff = rip_auth_header_write (s, ri, key, auth_str,
2362 RIP_AUTH_SIMPLE_SIZE);
2363 }
2364
paul718e3742002-12-13 20:15:29 +00002365 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002366 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002367 if (num == rtemax)
2368 {
2369 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002370 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002371
2372 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002373 to, ifc);
paul718e3742002-12-13 20:15:29 +00002374
2375 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2376 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2377 stream_get_endp(s), "SEND");
2378 num = 0;
2379 stream_reset (s);
2380 }
2381 }
2382
2383 /* Flush unwritten RTE. */
2384 if (num != 0)
2385 {
2386 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002387 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002388
paulc49ad8f2004-10-22 10:27:28 +00002389 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002390
2391 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2392 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2393 stream_get_endp (s), "SEND");
2394 num = 0;
2395 stream_reset (s);
2396 }
2397
2398 /* Statistics updates. */
2399 ri->sent_updates++;
2400}
2401
2402/* Send RIP packet to the interface. */
2403void
paulc49ad8f2004-10-22 10:27:28 +00002404rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002405{
paul718e3742002-12-13 20:15:29 +00002406 struct sockaddr_in to;
2407
2408 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002409 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002410 {
2411 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002412 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002413
paulc49ad8f2004-10-22 10:27:28 +00002414 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002415 return;
2416 }
paulc49ad8f2004-10-22 10:27:28 +00002417
paul718e3742002-12-13 20:15:29 +00002418 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002419 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002420 {
paulc49ad8f2004-10-22 10:27:28 +00002421 if (ifc->address->family == AF_INET)
2422 {
2423 /* Destination address and port setting. */
2424 memset (&to, 0, sizeof (struct sockaddr_in));
2425 if (ifc->destination)
2426 /* use specified broadcast or point-to-point destination addr */
2427 to.sin_addr = ifc->destination->u.prefix4;
2428 else
2429 /* calculate the appropriate broadcast address */
2430 to.sin_addr.s_addr =
2431 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2432 ifc->address->prefixlen);
2433 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002434
paulc49ad8f2004-10-22 10:27:28 +00002435 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002436 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002437 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2438 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002439
paulc49ad8f2004-10-22 10:27:28 +00002440 rip_output_process (ifc, &to, route_type, version);
2441 }
paul718e3742002-12-13 20:15:29 +00002442 }
2443}
2444
2445/* Update send to all interface and neighbor. */
2446void
2447rip_update_process (int route_type)
2448{
paul1eb8ef22005-04-07 07:30:20 +00002449 struct listnode *node;
2450 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002451 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002452 struct interface *ifp;
2453 struct rip_interface *ri;
2454 struct route_node *rp;
2455 struct sockaddr_in to;
2456 struct prefix_ipv4 *p;
2457
2458 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002459 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002460 {
paul718e3742002-12-13 20:15:29 +00002461 if (if_is_loopback (ifp))
2462 continue;
2463
paul2e3b2e42002-12-13 21:03:13 +00002464 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002465 continue;
2466
2467 /* Fetch RIP interface information. */
2468 ri = ifp->info;
2469
2470 /* When passive interface is specified, suppress announce to the
2471 interface. */
2472 if (ri->passive)
2473 continue;
2474
2475 if (ri->running)
2476 {
2477 if (IS_RIP_DEBUG_EVENT)
2478 {
2479 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002480 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002481 ifp->name, ifp->ifindex);
2482 else
ajs5d6c3772004-12-08 19:24:06 +00002483 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002484 ifp->ifindex);
2485 }
2486
paulcc1131a2003-10-15 23:20:17 +00002487 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002488 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002489 {
2490 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002491 int done = 0;
2492 /*
2493 * If there is no version configuration in the interface,
2494 * use rip's version setting.
2495 */
paulf38a4712003-06-07 01:10:00 +00002496 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2497 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002498
2499 ifaddr = (struct prefix_ipv4 *) connected->address;
2500
2501 if (ifaddr->family != AF_INET)
2502 continue;
2503
paul931cd542004-01-23 15:31:42 +00002504 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002505 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002506 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002507 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002508 done = 1;
2509 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2510 break;
2511
paulf38a4712003-06-07 01:10:00 +00002512 }
paul718e3742002-12-13 20:15:29 +00002513 }
2514 }
2515
2516 /* RIP send updates to each neighbor. */
2517 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2518 if (rp->info != NULL)
2519 {
2520 p = (struct prefix_ipv4 *) &rp->p;
2521
2522 ifp = if_lookup_address (p->prefix);
2523 if (! ifp)
2524 {
paulc49ad8f2004-10-22 10:27:28 +00002525 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002526 inet_ntoa (p->prefix));
2527 continue;
2528 }
paulc49ad8f2004-10-22 10:27:28 +00002529
2530 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2531 {
2532 zlog_warn ("Neighbor %s doesnt have connected network",
2533 inet_ntoa (p->prefix));
2534 continue;
2535 }
2536
paul718e3742002-12-13 20:15:29 +00002537 /* Set destination address and port */
2538 memset (&to, 0, sizeof (struct sockaddr_in));
2539 to.sin_addr = p->prefix;
2540 to.sin_port = htons (RIP_PORT_DEFAULT);
2541
2542 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002543 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002544 }
2545}
2546
2547/* RIP's periodical timer. */
2548int
2549rip_update (struct thread *t)
2550{
2551 /* Clear timer pointer. */
2552 rip->t_update = NULL;
2553
2554 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002555 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002556
2557 /* Process update output. */
2558 rip_update_process (rip_all_route);
2559
2560 /* Triggered updates may be suppressed if a regular update is due by
2561 the time the triggered update would be sent. */
2562 if (rip->t_triggered_interval)
2563 {
2564 thread_cancel (rip->t_triggered_interval);
2565 rip->t_triggered_interval = NULL;
2566 }
2567 rip->trigger = 0;
2568
2569 /* Register myself. */
2570 rip_event (RIP_UPDATE_EVENT, 0);
2571
2572 return 0;
2573}
2574
2575/* Walk down the RIP routing table then clear changed flag. */
2576void
2577rip_clear_changed_flag ()
2578{
2579 struct route_node *rp;
2580 struct rip_info *rinfo;
2581
2582 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2583 if ((rinfo = rp->info) != NULL)
2584 if (rinfo->flags & RIP_RTF_CHANGED)
2585 rinfo->flags &= ~RIP_RTF_CHANGED;
2586}
2587
2588/* Triggered update interval timer. */
2589int
2590rip_triggered_interval (struct thread *t)
2591{
2592 int rip_triggered_update (struct thread *);
2593
2594 rip->t_triggered_interval = NULL;
2595
2596 if (rip->trigger)
2597 {
2598 rip->trigger = 0;
2599 rip_triggered_update (t);
2600 }
2601 return 0;
2602}
2603
2604/* Execute triggered update. */
2605int
2606rip_triggered_update (struct thread *t)
2607{
2608 int interval;
2609
2610 /* Clear thred pointer. */
2611 rip->t_triggered_update = NULL;
2612
2613 /* Cancel interval timer. */
2614 if (rip->t_triggered_interval)
2615 {
2616 thread_cancel (rip->t_triggered_interval);
2617 rip->t_triggered_interval = NULL;
2618 }
2619 rip->trigger = 0;
2620
2621 /* Logging triggered update. */
2622 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002623 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002624
2625 /* Split Horizon processing is done when generating triggered
2626 updates as well as normal updates (see section 2.6). */
2627 rip_update_process (rip_changed_route);
2628
2629 /* Once all of the triggered updates have been generated, the route
2630 change flags should be cleared. */
2631 rip_clear_changed_flag ();
2632
2633 /* After a triggered update is sent, a timer should be set for a
2634 random interval between 1 and 5 seconds. If other changes that
2635 would trigger updates occur before the timer expires, a single
2636 update is triggered when the timer expires. */
2637 interval = (random () % 5) + 1;
2638
2639 rip->t_triggered_interval =
2640 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2641
2642 return 0;
2643}
2644
2645/* Withdraw redistributed route. */
2646void
2647rip_redistribute_withdraw (int type)
2648{
2649 struct route_node *rp;
2650 struct rip_info *rinfo;
2651
2652 if (!rip)
2653 return;
2654
2655 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2656 if ((rinfo = rp->info) != NULL)
2657 {
2658 if (rinfo->type == type
2659 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2660 {
2661 /* Perform poisoned reverse. */
2662 rinfo->metric = RIP_METRIC_INFINITY;
2663 RIP_TIMER_ON (rinfo->t_garbage_collect,
2664 rip_garbage_collect, rip->garbage_time);
2665 RIP_TIMER_OFF (rinfo->t_timeout);
2666 rinfo->flags |= RIP_RTF_CHANGED;
2667
hasso16705132003-05-25 14:49:19 +00002668 if (IS_RIP_DEBUG_EVENT) {
2669 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2670
ajs5d6c3772004-12-08 19:24:06 +00002671 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002672 inet_ntoa(p->prefix), p->prefixlen,
2673 ifindex2ifname(rinfo->ifindex));
2674 }
2675
paul718e3742002-12-13 20:15:29 +00002676 rip_event (RIP_TRIGGERED_UPDATE, 0);
2677 }
2678 }
2679}
2680
2681/* Create new RIP instance and set it to global variable. */
2682int
2683rip_create ()
2684{
2685 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2686 memset (rip, 0, sizeof (struct rip));
2687
2688 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002689 rip->version_send = RI_RIP_VERSION_2;
2690 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002691 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2692 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2693 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2694 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2695
2696 /* Initialize RIP routig table. */
2697 rip->table = route_table_init ();
2698 rip->route = route_table_init ();
2699 rip->neighbor = route_table_init ();
2700
2701 /* Make output stream. */
2702 rip->obuf = stream_new (1500);
2703
2704 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002705 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002706 if (rip->sock < 0)
2707 return rip->sock;
2708
2709 /* Create read and timer thread. */
2710 rip_event (RIP_READ, rip->sock);
2711 rip_event (RIP_UPDATE_EVENT, 1);
2712
2713 return 0;
2714}
2715
2716/* Sned RIP request to the destination. */
2717int
2718rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002719 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002720{
2721 struct rte *rte;
2722 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002723 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002724
2725 memset (&rip_packet, 0, sizeof (rip_packet));
2726
2727 rip_packet.command = RIP_REQUEST;
2728 rip_packet.version = version;
2729 rte = rip_packet.rte;
2730 rte->metric = htonl (RIP_METRIC_INFINITY);
2731
paul931cd542004-01-23 15:31:42 +00002732 if (connected)
2733 {
2734 /*
2735 * connected is only sent for ripv1 case, or when
2736 * interface does not support multicast. Caller loops
2737 * over each connected address for this case.
2738 */
paul11dde9c2004-05-31 14:00:00 +00002739 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002740 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002741 return -1;
2742 else
2743 return sizeof (rip_packet);
2744 }
2745
paulcc1131a2003-10-15 23:20:17 +00002746 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002747 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002748 {
2749 struct prefix_ipv4 *p;
2750
2751 p = (struct prefix_ipv4 *) connected->address;
2752
2753 if (p->family != AF_INET)
2754 continue;
2755
paul11dde9c2004-05-31 14:00:00 +00002756 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002757 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002758 return -1;
2759 }
2760 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002761}
2762
2763int
2764rip_update_jitter (unsigned long time)
2765{
paul239389b2004-05-05 14:09:37 +00002766#define JITTER_BOUND 4
2767 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2768 Given that, we cannot let time be less than JITTER_BOUND seconds.
2769 The RIPv2 RFC says jitter should be small compared to
2770 update_time. We consider 1/JITTER_BOUND to be small.
2771 */
2772
2773 int jitter_input = time;
2774 int jitter;
2775
2776 if (jitter_input < JITTER_BOUND)
2777 jitter_input = JITTER_BOUND;
2778
2779 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2780
2781 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002782}
2783
2784void
2785rip_event (enum rip_event event, int sock)
2786{
2787 int jitter = 0;
2788
2789 switch (event)
2790 {
2791 case RIP_READ:
2792 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2793 break;
2794 case RIP_UPDATE_EVENT:
2795 if (rip->t_update)
2796 {
2797 thread_cancel (rip->t_update);
2798 rip->t_update = NULL;
2799 }
2800 jitter = rip_update_jitter (rip->update_time);
2801 rip->t_update =
2802 thread_add_timer (master, rip_update, NULL,
2803 sock ? 2 : rip->update_time + jitter);
2804 break;
2805 case RIP_TRIGGERED_UPDATE:
2806 if (rip->t_triggered_interval)
2807 rip->trigger = 1;
2808 else if (! rip->t_triggered_update)
2809 rip->t_triggered_update =
2810 thread_add_event (master, rip_triggered_update, NULL, 0);
2811 break;
2812 default:
2813 break;
2814 }
2815}
2816
2817DEFUN (router_rip,
2818 router_rip_cmd,
2819 "router rip",
2820 "Enable a routing process\n"
2821 "Routing Information Protocol (RIP)\n")
2822{
2823 int ret;
2824
2825 /* If rip is not enabled before. */
2826 if (! rip)
2827 {
2828 ret = rip_create ();
2829 if (ret < 0)
2830 {
2831 zlog_info ("Can't create RIP");
2832 return CMD_WARNING;
2833 }
2834 }
2835 vty->node = RIP_NODE;
2836 vty->index = rip;
2837
2838 return CMD_SUCCESS;
2839}
2840
2841DEFUN (no_router_rip,
2842 no_router_rip_cmd,
2843 "no router rip",
2844 NO_STR
2845 "Enable a routing process\n"
2846 "Routing Information Protocol (RIP)\n")
2847{
2848 if (rip)
2849 rip_clean ();
2850 return CMD_SUCCESS;
2851}
2852
2853DEFUN (rip_version,
2854 rip_version_cmd,
2855 "version <1-2>",
2856 "Set routing protocol version\n"
2857 "version\n")
2858{
2859 int version;
2860
2861 version = atoi (argv[0]);
2862 if (version != RIPv1 && version != RIPv2)
2863 {
2864 vty_out (vty, "invalid rip version %d%s", version,
2865 VTY_NEWLINE);
2866 return CMD_WARNING;
2867 }
paulf38a4712003-06-07 01:10:00 +00002868 rip->version_send = version;
2869 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002870
2871 return CMD_SUCCESS;
2872}
2873
2874DEFUN (no_rip_version,
2875 no_rip_version_cmd,
2876 "no version",
2877 NO_STR
2878 "Set routing protocol version\n")
2879{
2880 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002881 rip->version_send = RI_RIP_VERSION_2;
2882 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002883
2884 return CMD_SUCCESS;
2885}
2886
2887ALIAS (no_rip_version,
2888 no_rip_version_val_cmd,
2889 "no version <1-2>",
2890 NO_STR
2891 "Set routing protocol version\n"
2892 "version\n")
2893
2894DEFUN (rip_route,
2895 rip_route_cmd,
2896 "route A.B.C.D/M",
2897 "RIP static route configuration\n"
2898 "IP prefix <network>/<length>\n")
2899{
2900 int ret;
2901 struct prefix_ipv4 p;
2902 struct route_node *node;
2903
2904 ret = str2prefix_ipv4 (argv[0], &p);
2905 if (ret < 0)
2906 {
2907 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2908 return CMD_WARNING;
2909 }
2910 apply_mask_ipv4 (&p);
2911
2912 /* For router rip configuration. */
2913 node = route_node_get (rip->route, (struct prefix *) &p);
2914
2915 if (node->info)
2916 {
2917 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2918 route_unlock_node (node);
2919 return CMD_WARNING;
2920 }
2921
hasso8a676be2004-10-08 06:36:38 +00002922 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002923
2924 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2925
2926 return CMD_SUCCESS;
2927}
2928
2929DEFUN (no_rip_route,
2930 no_rip_route_cmd,
2931 "no route A.B.C.D/M",
2932 NO_STR
2933 "RIP static route configuration\n"
2934 "IP prefix <network>/<length>\n")
2935{
2936 int ret;
2937 struct prefix_ipv4 p;
2938 struct route_node *node;
2939
2940 ret = str2prefix_ipv4 (argv[0], &p);
2941 if (ret < 0)
2942 {
2943 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2944 return CMD_WARNING;
2945 }
2946 apply_mask_ipv4 (&p);
2947
2948 /* For router rip configuration. */
2949 node = route_node_lookup (rip->route, (struct prefix *) &p);
2950 if (! node)
2951 {
2952 vty_out (vty, "Can't find route %s.%s", argv[0],
2953 VTY_NEWLINE);
2954 return CMD_WARNING;
2955 }
2956
2957 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2958 route_unlock_node (node);
2959
2960 node->info = NULL;
2961 route_unlock_node (node);
2962
2963 return CMD_SUCCESS;
2964}
2965
2966void
2967rip_update_default_metric ()
2968{
2969 struct route_node *np;
2970 struct rip_info *rinfo;
2971
2972 for (np = route_top (rip->table); np; np = route_next (np))
2973 if ((rinfo = np->info) != NULL)
2974 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2975 rinfo->metric = rip->default_metric;
2976}
2977
2978DEFUN (rip_default_metric,
2979 rip_default_metric_cmd,
2980 "default-metric <1-16>",
2981 "Set a metric of redistribute routes\n"
2982 "Default metric\n")
2983{
2984 if (rip)
2985 {
2986 rip->default_metric = atoi (argv[0]);
2987 /* rip_update_default_metric (); */
2988 }
2989 return CMD_SUCCESS;
2990}
2991
2992DEFUN (no_rip_default_metric,
2993 no_rip_default_metric_cmd,
2994 "no default-metric",
2995 NO_STR
2996 "Set a metric of redistribute routes\n"
2997 "Default metric\n")
2998{
2999 if (rip)
3000 {
3001 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3002 /* rip_update_default_metric (); */
3003 }
3004 return CMD_SUCCESS;
3005}
3006
3007ALIAS (no_rip_default_metric,
3008 no_rip_default_metric_val_cmd,
3009 "no default-metric <1-16>",
3010 NO_STR
3011 "Set a metric of redistribute routes\n"
3012 "Default metric\n")
3013
3014DEFUN (rip_timers,
3015 rip_timers_cmd,
3016 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3017 "Adjust routing timers\n"
3018 "Basic routing protocol update timers\n"
3019 "Routing table update timer value in second. Default is 30.\n"
3020 "Routing information timeout timer. Default is 180.\n"
3021 "Garbage collection timer. Default is 120.\n")
3022{
3023 unsigned long update;
3024 unsigned long timeout;
3025 unsigned long garbage;
3026 char *endptr = NULL;
3027 unsigned long RIP_TIMER_MAX = 2147483647;
3028 unsigned long RIP_TIMER_MIN = 5;
3029
3030 update = strtoul (argv[0], &endptr, 10);
3031 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3032 {
3033 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3034 return CMD_WARNING;
3035 }
3036
3037 timeout = strtoul (argv[1], &endptr, 10);
3038 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3039 {
3040 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3041 return CMD_WARNING;
3042 }
3043
3044 garbage = strtoul (argv[2], &endptr, 10);
3045 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3046 {
3047 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3048 return CMD_WARNING;
3049 }
3050
3051 /* Set each timer value. */
3052 rip->update_time = update;
3053 rip->timeout_time = timeout;
3054 rip->garbage_time = garbage;
3055
3056 /* Reset update timer thread. */
3057 rip_event (RIP_UPDATE_EVENT, 0);
3058
3059 return CMD_SUCCESS;
3060}
3061
3062DEFUN (no_rip_timers,
3063 no_rip_timers_cmd,
3064 "no timers basic",
3065 NO_STR
3066 "Adjust routing timers\n"
3067 "Basic routing protocol update timers\n")
3068{
3069 /* Set each timer value to the default. */
3070 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3071 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3072 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3073
3074 /* Reset update timer thread. */
3075 rip_event (RIP_UPDATE_EVENT, 0);
3076
3077 return CMD_SUCCESS;
3078}
hasso16705132003-05-25 14:49:19 +00003079
3080ALIAS (no_rip_timers,
3081 no_rip_timers_val_cmd,
3082 "no timers basic <0-65535> <0-65535> <0-65535>",
3083 NO_STR
3084 "Adjust routing timers\n"
3085 "Basic routing protocol update timers\n"
3086 "Routing table update timer value in second. Default is 30.\n"
3087 "Routing information timeout timer. Default is 180.\n"
3088 "Garbage collection timer. Default is 120.\n")
3089
paul718e3742002-12-13 20:15:29 +00003090
3091struct route_table *rip_distance_table;
3092
3093struct rip_distance
3094{
3095 /* Distance value for the IP source prefix. */
3096 u_char distance;
3097
3098 /* Name of the access-list to be matched. */
3099 char *access_list;
3100};
3101
3102struct rip_distance *
3103rip_distance_new ()
3104{
3105 struct rip_distance *new;
3106 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3107 memset (new, 0, sizeof (struct rip_distance));
3108 return new;
3109}
3110
3111void
3112rip_distance_free (struct rip_distance *rdistance)
3113{
3114 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3115}
3116
3117int
hasso98b718a2004-10-11 12:57:57 +00003118rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3119 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003120{
3121 int ret;
3122 struct prefix_ipv4 p;
3123 u_char distance;
3124 struct route_node *rn;
3125 struct rip_distance *rdistance;
3126
3127 ret = str2prefix_ipv4 (ip_str, &p);
3128 if (ret == 0)
3129 {
3130 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3131 return CMD_WARNING;
3132 }
3133
3134 distance = atoi (distance_str);
3135
3136 /* Get RIP distance node. */
3137 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3138 if (rn->info)
3139 {
3140 rdistance = rn->info;
3141 route_unlock_node (rn);
3142 }
3143 else
3144 {
3145 rdistance = rip_distance_new ();
3146 rn->info = rdistance;
3147 }
3148
3149 /* Set distance value. */
3150 rdistance->distance = distance;
3151
3152 /* Reset access-list configuration. */
3153 if (rdistance->access_list)
3154 {
3155 free (rdistance->access_list);
3156 rdistance->access_list = NULL;
3157 }
3158 if (access_list_str)
3159 rdistance->access_list = strdup (access_list_str);
3160
3161 return CMD_SUCCESS;
3162}
3163
3164int
hasso98b718a2004-10-11 12:57:57 +00003165rip_distance_unset (struct vty *vty, const char *distance_str,
3166 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003167{
3168 int ret;
3169 struct prefix_ipv4 p;
3170 u_char distance;
3171 struct route_node *rn;
3172 struct rip_distance *rdistance;
3173
3174 ret = str2prefix_ipv4 (ip_str, &p);
3175 if (ret == 0)
3176 {
3177 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3178 return CMD_WARNING;
3179 }
3180
3181 distance = atoi (distance_str);
3182
3183 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3184 if (! rn)
3185 {
3186 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3187 return CMD_WARNING;
3188 }
3189
3190 rdistance = rn->info;
3191
3192 if (rdistance->access_list)
3193 free (rdistance->access_list);
3194 rip_distance_free (rdistance);
3195
3196 rn->info = NULL;
3197 route_unlock_node (rn);
3198 route_unlock_node (rn);
3199
3200 return CMD_SUCCESS;
3201}
3202
3203void
3204rip_distance_reset ()
3205{
3206 struct route_node *rn;
3207 struct rip_distance *rdistance;
3208
3209 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3210 if ((rdistance = rn->info) != NULL)
3211 {
3212 if (rdistance->access_list)
3213 free (rdistance->access_list);
3214 rip_distance_free (rdistance);
3215 rn->info = NULL;
3216 route_unlock_node (rn);
3217 }
3218}
3219
3220/* Apply RIP information to distance method. */
3221u_char
3222rip_distance_apply (struct rip_info *rinfo)
3223{
3224 struct route_node *rn;
3225 struct prefix_ipv4 p;
3226 struct rip_distance *rdistance;
3227 struct access_list *alist;
3228
3229 if (! rip)
3230 return 0;
3231
3232 memset (&p, 0, sizeof (struct prefix_ipv4));
3233 p.family = AF_INET;
3234 p.prefix = rinfo->from;
3235 p.prefixlen = IPV4_MAX_BITLEN;
3236
3237 /* Check source address. */
3238 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3239 if (rn)
3240 {
3241 rdistance = rn->info;
3242 route_unlock_node (rn);
3243
3244 if (rdistance->access_list)
3245 {
3246 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3247 if (alist == NULL)
3248 return 0;
3249 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3250 return 0;
3251
3252 return rdistance->distance;
3253 }
3254 else
3255 return rdistance->distance;
3256 }
3257
3258 if (rip->distance)
3259 return rip->distance;
3260
3261 return 0;
3262}
3263
3264void
3265rip_distance_show (struct vty *vty)
3266{
3267 struct route_node *rn;
3268 struct rip_distance *rdistance;
3269 int header = 1;
3270 char buf[BUFSIZ];
3271
3272 vty_out (vty, " Distance: (default is %d)%s",
3273 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3274 VTY_NEWLINE);
3275
3276 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3277 if ((rdistance = rn->info) != NULL)
3278 {
3279 if (header)
3280 {
3281 vty_out (vty, " Address Distance List%s",
3282 VTY_NEWLINE);
3283 header = 0;
3284 }
3285 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3286 vty_out (vty, " %-20s %4d %s%s",
3287 buf, rdistance->distance,
3288 rdistance->access_list ? rdistance->access_list : "",
3289 VTY_NEWLINE);
3290 }
3291}
3292
3293DEFUN (rip_distance,
3294 rip_distance_cmd,
3295 "distance <1-255>",
3296 "Administrative distance\n"
3297 "Distance value\n")
3298{
3299 rip->distance = atoi (argv[0]);
3300 return CMD_SUCCESS;
3301}
3302
3303DEFUN (no_rip_distance,
3304 no_rip_distance_cmd,
3305 "no distance <1-255>",
3306 NO_STR
3307 "Administrative distance\n"
3308 "Distance value\n")
3309{
3310 rip->distance = 0;
3311 return CMD_SUCCESS;
3312}
3313
3314DEFUN (rip_distance_source,
3315 rip_distance_source_cmd,
3316 "distance <1-255> A.B.C.D/M",
3317 "Administrative distance\n"
3318 "Distance value\n"
3319 "IP source prefix\n")
3320{
3321 rip_distance_set (vty, argv[0], argv[1], NULL);
3322 return CMD_SUCCESS;
3323}
3324
3325DEFUN (no_rip_distance_source,
3326 no_rip_distance_source_cmd,
3327 "no distance <1-255> A.B.C.D/M",
3328 NO_STR
3329 "Administrative distance\n"
3330 "Distance value\n"
3331 "IP source prefix\n")
3332{
3333 rip_distance_unset (vty, argv[0], argv[1], NULL);
3334 return CMD_SUCCESS;
3335}
3336
3337DEFUN (rip_distance_source_access_list,
3338 rip_distance_source_access_list_cmd,
3339 "distance <1-255> A.B.C.D/M WORD",
3340 "Administrative distance\n"
3341 "Distance value\n"
3342 "IP source prefix\n"
3343 "Access list name\n")
3344{
3345 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3346 return CMD_SUCCESS;
3347}
3348
3349DEFUN (no_rip_distance_source_access_list,
3350 no_rip_distance_source_access_list_cmd,
3351 "no distance <1-255> A.B.C.D/M WORD",
3352 NO_STR
3353 "Administrative distance\n"
3354 "Distance value\n"
3355 "IP source prefix\n"
3356 "Access list name\n")
3357{
3358 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3359 return CMD_SUCCESS;
3360}
3361
3362/* Print out routes update time. */
3363void
3364rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3365{
3366 struct timeval timer_now;
3367 time_t clock;
3368 struct tm *tm;
3369#define TIME_BUF 25
3370 char timebuf [TIME_BUF];
3371 struct thread *thread;
3372
3373 gettimeofday (&timer_now, NULL);
3374
3375 if ((thread = rinfo->t_timeout) != NULL)
3376 {
3377 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3378 tm = gmtime (&clock);
3379 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3380 vty_out (vty, "%5s", timebuf);
3381 }
3382 else if ((thread = rinfo->t_garbage_collect) != NULL)
3383 {
3384 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3385 tm = gmtime (&clock);
3386 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3387 vty_out (vty, "%5s", timebuf);
3388 }
3389}
3390
hasso8a676be2004-10-08 06:36:38 +00003391const char *
paul718e3742002-12-13 20:15:29 +00003392rip_route_type_print (int sub_type)
3393{
3394 switch (sub_type)
3395 {
3396 case RIP_ROUTE_RTE:
3397 return "n";
3398 case RIP_ROUTE_STATIC:
3399 return "s";
3400 case RIP_ROUTE_DEFAULT:
3401 return "d";
3402 case RIP_ROUTE_REDISTRIBUTE:
3403 return "r";
3404 case RIP_ROUTE_INTERFACE:
3405 return "i";
3406 default:
3407 return "?";
3408 }
3409}
3410
3411DEFUN (show_ip_rip,
3412 show_ip_rip_cmd,
3413 "show ip rip",
3414 SHOW_STR
3415 IP_STR
3416 "Show RIP routes\n")
3417{
3418 struct route_node *np;
3419 struct rip_info *rinfo;
3420
3421 if (! rip)
3422 return CMD_SUCCESS;
3423
hasso16705132003-05-25 14:49:19 +00003424 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3425 "Sub-codes:%s"
3426 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003427 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003428 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003429 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003430
3431 for (np = route_top (rip->table); np; np = route_next (np))
3432 if ((rinfo = np->info) != NULL)
3433 {
3434 int len;
3435
3436 len = vty_out (vty, "%s(%s) %s/%d",
3437 /* np->lock, For debugging. */
3438 route_info[rinfo->type].str,
3439 rip_route_type_print (rinfo->sub_type),
3440 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3441
hassoa1455d82004-03-03 19:36:24 +00003442 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003443
3444 if (len > 0)
3445 vty_out (vty, "%*s", len, " ");
3446
3447 if (rinfo->nexthop.s_addr)
3448 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3449 rinfo->metric);
3450 else
3451 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3452
3453 /* Route which exist in kernel routing table. */
3454 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3455 (rinfo->sub_type == RIP_ROUTE_RTE))
3456 {
3457 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003458 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003459 rip_vty_out_uptime (vty, rinfo);
3460 }
3461 else if (rinfo->metric == RIP_METRIC_INFINITY)
3462 {
3463 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003464 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003465 rip_vty_out_uptime (vty, rinfo);
3466 }
3467 else
hasso16705132003-05-25 14:49:19 +00003468 {
3469 vty_out (vty, "self ");
3470 vty_out (vty, "%3d", rinfo->tag);
3471 }
paul718e3742002-12-13 20:15:29 +00003472
3473 vty_out (vty, "%s", VTY_NEWLINE);
3474 }
3475 return CMD_SUCCESS;
3476}
3477
3478/* Return next event time. */
3479int
3480rip_next_thread_timer (struct thread *thread)
3481{
3482 struct timeval timer_now;
3483
3484 gettimeofday (&timer_now, NULL);
3485
3486 return thread->u.sands.tv_sec - timer_now.tv_sec;
3487}
3488
hasso16705132003-05-25 14:49:19 +00003489/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3490DEFUN (show_ip_rip_status,
3491 show_ip_rip_status_cmd,
3492 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003493 SHOW_STR
3494 IP_STR
hasso16705132003-05-25 14:49:19 +00003495 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003496 "IP routing protocol process parameters and statistics\n")
3497{
hasso52dc7ee2004-09-23 19:18:23 +00003498 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003499 struct interface *ifp;
3500 struct rip_interface *ri;
3501 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003502 const char *send_version;
3503 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003504
3505 if (! rip)
3506 return CMD_SUCCESS;
3507
3508 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3509 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3510 rip->update_time);
3511 vty_out (vty, " next due in %d seconds%s",
3512 rip_next_thread_timer (rip->t_update),
3513 VTY_NEWLINE);
3514 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3515 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3516 VTY_NEWLINE);
3517
3518 /* Filtering status show. */
3519 config_show_distribute (vty);
3520
3521 /* Default metric information. */
3522 vty_out (vty, " Default redistribution metric is %d%s",
3523 rip->default_metric, VTY_NEWLINE);
3524
3525 /* Redistribute information. */
3526 vty_out (vty, " Redistributing:");
3527 config_write_rip_redistribute (vty, 0);
3528 vty_out (vty, "%s", VTY_NEWLINE);
3529
paulf38a4712003-06-07 01:10:00 +00003530 vty_out (vty, " Default version control: send version %s,",
3531 lookup(ri_version_msg,rip->version_send));
3532 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3533 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3534 else
3535 vty_out (vty, " receive version %s %s",
3536 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003537
3538 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3539
paul1eb8ef22005-04-07 07:30:20 +00003540 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003541 {
paul718e3742002-12-13 20:15:29 +00003542 ri = ifp->info;
3543
3544 if (ri->enable_network || ri->enable_interface)
3545 {
3546 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003547 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003548 else
3549 send_version = lookup (ri_version_msg, ri->ri_send);
3550
3551 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003552 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003553 else
3554 receive_version = lookup (ri_version_msg, ri->ri_receive);
3555
3556 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3557 send_version,
3558 receive_version,
3559 ri->key_chain ? ri->key_chain : "",
3560 VTY_NEWLINE);
3561 }
3562 }
3563
3564 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3565 config_write_rip_network (vty, 0);
3566
paul4aaff3f2003-06-07 01:04:45 +00003567 {
3568 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003569 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003570 {
paul4aaff3f2003-06-07 01:04:45 +00003571 ri = ifp->info;
3572
3573 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3574 {
3575 if (!found_passive)
3576 {
3577 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3578 found_passive = 1;
3579 }
3580 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3581 }
3582 }
3583 }
3584
paul718e3742002-12-13 20:15:29 +00003585 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3586 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3587 rip_peer_display (vty);
3588
3589 rip_distance_show (vty);
3590
3591 return CMD_SUCCESS;
3592}
3593
3594/* RIP configuration write function. */
3595int
3596config_write_rip (struct vty *vty)
3597{
3598 int write = 0;
3599 struct route_node *rn;
3600 struct rip_distance *rdistance;
3601
3602 if (rip)
3603 {
3604 /* Router RIP statement. */
3605 vty_out (vty, "router rip%s", VTY_NEWLINE);
3606 write++;
3607
3608 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003609 if (rip->version_send != RI_RIP_VERSION_2
3610 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3611 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003612 VTY_NEWLINE);
3613
3614 /* RIP timer configuration. */
3615 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3616 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3617 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3618 vty_out (vty, " timers basic %lu %lu %lu%s",
3619 rip->update_time,
3620 rip->timeout_time,
3621 rip->garbage_time,
3622 VTY_NEWLINE);
3623
3624 /* Default information configuration. */
3625 if (rip->default_information)
3626 {
3627 if (rip->default_information_route_map)
3628 vty_out (vty, " default-information originate route-map %s%s",
3629 rip->default_information_route_map, VTY_NEWLINE);
3630 else
3631 vty_out (vty, " default-information originate%s",
3632 VTY_NEWLINE);
3633 }
3634
3635 /* Redistribute configuration. */
3636 config_write_rip_redistribute (vty, 1);
3637
3638 /* RIP offset-list configuration. */
3639 config_write_rip_offset_list (vty);
3640
3641 /* RIP enabled network and interface configuration. */
3642 config_write_rip_network (vty, 1);
3643
3644 /* RIP default metric configuration */
3645 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3646 vty_out (vty, " default-metric %d%s",
3647 rip->default_metric, VTY_NEWLINE);
3648
3649 /* Distribute configuration. */
3650 write += config_write_distribute (vty);
3651
hasso16705132003-05-25 14:49:19 +00003652 /* Interface routemap configuration */
3653 write += config_write_if_rmap (vty);
3654
paul718e3742002-12-13 20:15:29 +00003655 /* Distance configuration. */
3656 if (rip->distance)
3657 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3658
3659 /* RIP source IP prefix distance configuration. */
3660 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3661 if ((rdistance = rn->info) != NULL)
3662 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3663 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3664 rdistance->access_list ? rdistance->access_list : "",
3665 VTY_NEWLINE);
3666
3667 /* RIP static route configuration. */
3668 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3669 if (rn->info)
3670 vty_out (vty, " route %s/%d%s",
3671 inet_ntoa (rn->p.u.prefix4),
3672 rn->p.prefixlen,
3673 VTY_NEWLINE);
3674
3675 }
3676 return write;
3677}
3678
3679/* RIP node structure. */
3680struct cmd_node rip_node =
3681{
3682 RIP_NODE,
3683 "%s(config-router)# ",
3684 1
3685};
3686
3687/* Distribute-list update functions. */
3688void
3689rip_distribute_update (struct distribute *dist)
3690{
3691 struct interface *ifp;
3692 struct rip_interface *ri;
3693 struct access_list *alist;
3694 struct prefix_list *plist;
3695
3696 if (! dist->ifname)
3697 return;
3698
3699 ifp = if_lookup_by_name (dist->ifname);
3700 if (ifp == NULL)
3701 return;
3702
3703 ri = ifp->info;
3704
3705 if (dist->list[DISTRIBUTE_IN])
3706 {
3707 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3708 if (alist)
3709 ri->list[RIP_FILTER_IN] = alist;
3710 else
3711 ri->list[RIP_FILTER_IN] = NULL;
3712 }
3713 else
3714 ri->list[RIP_FILTER_IN] = NULL;
3715
3716 if (dist->list[DISTRIBUTE_OUT])
3717 {
3718 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3719 if (alist)
3720 ri->list[RIP_FILTER_OUT] = alist;
3721 else
3722 ri->list[RIP_FILTER_OUT] = NULL;
3723 }
3724 else
3725 ri->list[RIP_FILTER_OUT] = NULL;
3726
3727 if (dist->prefix[DISTRIBUTE_IN])
3728 {
3729 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3730 if (plist)
3731 ri->prefix[RIP_FILTER_IN] = plist;
3732 else
3733 ri->prefix[RIP_FILTER_IN] = NULL;
3734 }
3735 else
3736 ri->prefix[RIP_FILTER_IN] = NULL;
3737
3738 if (dist->prefix[DISTRIBUTE_OUT])
3739 {
3740 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3741 if (plist)
3742 ri->prefix[RIP_FILTER_OUT] = plist;
3743 else
3744 ri->prefix[RIP_FILTER_OUT] = NULL;
3745 }
3746 else
3747 ri->prefix[RIP_FILTER_OUT] = NULL;
3748}
3749
3750void
3751rip_distribute_update_interface (struct interface *ifp)
3752{
3753 struct distribute *dist;
3754
3755 dist = distribute_lookup (ifp->name);
3756 if (dist)
3757 rip_distribute_update (dist);
3758}
3759
3760/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003761/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003762void
paul02ff83c2004-06-11 11:27:03 +00003763rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003764{
3765 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003766 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003767
paul1eb8ef22005-04-07 07:30:20 +00003768 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3769 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003770}
paul11dde9c2004-05-31 14:00:00 +00003771/* ARGSUSED */
3772void
3773rip_distribute_update_all_wrapper(struct access_list *notused)
3774{
paul02ff83c2004-06-11 11:27:03 +00003775 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003776}
paul718e3742002-12-13 20:15:29 +00003777
3778/* Delete all added rip route. */
3779void
3780rip_clean ()
3781{
3782 int i;
3783 struct route_node *rp;
3784 struct rip_info *rinfo;
3785
3786 if (rip)
3787 {
3788 /* Clear RIP routes */
3789 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3790 if ((rinfo = rp->info) != NULL)
3791 {
3792 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3793 rinfo->sub_type == RIP_ROUTE_RTE)
3794 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3795 &rinfo->nexthop, rinfo->metric);
3796
3797 RIP_TIMER_OFF (rinfo->t_timeout);
3798 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3799
3800 rp->info = NULL;
3801 route_unlock_node (rp);
3802
3803 rip_info_free (rinfo);
3804 }
3805
3806 /* Cancel RIP related timers. */
3807 RIP_TIMER_OFF (rip->t_update);
3808 RIP_TIMER_OFF (rip->t_triggered_update);
3809 RIP_TIMER_OFF (rip->t_triggered_interval);
3810
3811 /* Cancel read thread. */
3812 if (rip->t_read)
3813 {
3814 thread_cancel (rip->t_read);
3815 rip->t_read = NULL;
3816 }
3817
3818 /* Close RIP socket. */
3819 if (rip->sock >= 0)
3820 {
3821 close (rip->sock);
3822 rip->sock = -1;
3823 }
3824
3825 /* Static RIP route configuration. */
3826 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3827 if (rp->info)
3828 {
3829 rp->info = NULL;
3830 route_unlock_node (rp);
3831 }
3832
3833 /* RIP neighbor configuration. */
3834 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3835 if (rp->info)
3836 {
3837 rp->info = NULL;
3838 route_unlock_node (rp);
3839 }
3840
3841 /* Redistribute related clear. */
3842 if (rip->default_information_route_map)
3843 free (rip->default_information_route_map);
3844
3845 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3846 if (rip->route_map[i].name)
3847 free (rip->route_map[i].name);
3848
3849 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3850 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3851 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3852
3853 XFREE (MTYPE_RIP, rip);
3854 rip = NULL;
3855 }
3856
3857 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003858 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003859 rip_offset_clean ();
3860 rip_interface_clean ();
3861 rip_distance_reset ();
3862 rip_redistribute_clean ();
3863}
3864
3865/* Reset all values to the default settings. */
3866void
3867rip_reset ()
3868{
3869 /* Reset global counters. */
3870 rip_global_route_changes = 0;
3871 rip_global_queries = 0;
3872
3873 /* Call ripd related reset functions. */
3874 rip_debug_reset ();
3875 rip_route_map_reset ();
3876
3877 /* Call library reset functions. */
3878 vty_reset ();
3879 access_list_reset ();
3880 prefix_list_reset ();
3881
3882 distribute_list_reset ();
3883
3884 rip_interface_reset ();
3885 rip_distance_reset ();
3886
3887 rip_zclient_reset ();
3888}
3889
hasso16705132003-05-25 14:49:19 +00003890void
3891rip_if_rmap_update (struct if_rmap *if_rmap)
3892{
3893 struct interface *ifp;
3894 struct rip_interface *ri;
3895 struct route_map *rmap;
3896
3897 ifp = if_lookup_by_name (if_rmap->ifname);
3898 if (ifp == NULL)
3899 return;
3900
3901 ri = ifp->info;
3902
3903 if (if_rmap->routemap[IF_RMAP_IN])
3904 {
3905 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3906 if (rmap)
3907 ri->routemap[IF_RMAP_IN] = rmap;
3908 else
3909 ri->routemap[IF_RMAP_IN] = NULL;
3910 }
3911 else
3912 ri->routemap[RIP_FILTER_IN] = NULL;
3913
3914 if (if_rmap->routemap[IF_RMAP_OUT])
3915 {
3916 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3917 if (rmap)
3918 ri->routemap[IF_RMAP_OUT] = rmap;
3919 else
3920 ri->routemap[IF_RMAP_OUT] = NULL;
3921 }
3922 else
3923 ri->routemap[RIP_FILTER_OUT] = NULL;
3924}
3925
3926void
3927rip_if_rmap_update_interface (struct interface *ifp)
3928{
3929 struct if_rmap *if_rmap;
3930
3931 if_rmap = if_rmap_lookup (ifp->name);
3932 if (if_rmap)
3933 rip_if_rmap_update (if_rmap);
3934}
3935
3936void
3937rip_routemap_update_redistribute (void)
3938{
3939 int i;
3940
3941 if (rip)
3942 {
3943 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3944 {
3945 if (rip->route_map[i].name)
3946 rip->route_map[i].map =
3947 route_map_lookup_by_name (rip->route_map[i].name);
3948 }
3949 }
3950}
3951
paul11dde9c2004-05-31 14:00:00 +00003952/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003953void
hasso98b718a2004-10-11 12:57:57 +00003954rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003955{
3956 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003957 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003958
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3960 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003961
3962 rip_routemap_update_redistribute ();
3963}
3964
paul718e3742002-12-13 20:15:29 +00003965/* Allocate new rip structure and set default value. */
3966void
3967rip_init ()
3968{
3969 /* Randomize for triggered update random(). */
3970 srand (time (NULL));
3971
3972 /* Install top nodes. */
3973 install_node (&rip_node, config_write_rip);
3974
3975 /* Install rip commands. */
3976 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003977 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003978 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003979 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003980 install_element (CONFIG_NODE, &router_rip_cmd);
3981 install_element (CONFIG_NODE, &no_router_rip_cmd);
3982
3983 install_default (RIP_NODE);
3984 install_element (RIP_NODE, &rip_version_cmd);
3985 install_element (RIP_NODE, &no_rip_version_cmd);
3986 install_element (RIP_NODE, &no_rip_version_val_cmd);
3987 install_element (RIP_NODE, &rip_default_metric_cmd);
3988 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3989 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3990 install_element (RIP_NODE, &rip_timers_cmd);
3991 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003992 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003993 install_element (RIP_NODE, &rip_route_cmd);
3994 install_element (RIP_NODE, &no_rip_route_cmd);
3995 install_element (RIP_NODE, &rip_distance_cmd);
3996 install_element (RIP_NODE, &no_rip_distance_cmd);
3997 install_element (RIP_NODE, &rip_distance_source_cmd);
3998 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3999 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4000 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4001
4002 /* Debug related init. */
4003 rip_debug_init ();
4004
paul718e3742002-12-13 20:15:29 +00004005 /* SNMP init. */
4006#ifdef HAVE_SNMP
4007 rip_snmp_init ();
4008#endif /* HAVE_SNMP */
4009
4010 /* Access list install. */
4011 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004012 access_list_add_hook (rip_distribute_update_all_wrapper);
4013 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004014
4015 /* Prefix list initialize.*/
4016 prefix_list_init ();
4017 prefix_list_add_hook (rip_distribute_update_all);
4018 prefix_list_delete_hook (rip_distribute_update_all);
4019
4020 /* Distribute list install. */
4021 distribute_list_init (RIP_NODE);
4022 distribute_list_add_hook (rip_distribute_update);
4023 distribute_list_delete_hook (rip_distribute_update);
4024
hasso16705132003-05-25 14:49:19 +00004025 /* Route-map */
4026 rip_route_map_init ();
4027 rip_offset_init ();
4028
4029 route_map_add_hook (rip_routemap_update);
4030 route_map_delete_hook (rip_routemap_update);
4031
4032 if_rmap_init (RIP_NODE);
4033 if_rmap_hook_add (rip_if_rmap_update);
4034 if_rmap_hook_delete (rip_if_rmap_update);
4035
paul718e3742002-12-13 20:15:29 +00004036 /* Distance control. */
4037 rip_distance_table = route_table_init ();
4038}