blob: b5d130e89aa5e0a51541c3647c8c9b646c96bcd5 [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. */
368 for (node = listhead (iflist); node; nextnode (node))
369 {
370 ifp = getdata (node);
371
372 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
373 {
374 ifc = getdata (cnode);
375 p = ifc->address;
376
377 if (p->family == AF_INET
378 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
379 return -1;
380 }
381 }
382 return 0;
383}
384
385/* RIP add route to routing table. */
386void
387rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000388 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000389{
390 int ret;
391 struct prefix_ipv4 p;
392 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000393 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000394 struct rip_interface *ri;
395 struct in_addr *nexthop;
396 u_char oldmetric;
397 int same = 0;
398
399 /* Make prefix structure. */
400 memset (&p, 0, sizeof (struct prefix_ipv4));
401 p.family = AF_INET;
402 p.prefix = rte->prefix;
403 p.prefixlen = ip_masklen (rte->mask);
404
405 /* Make sure mask is applied. */
406 apply_mask_ipv4 (&p);
407
408 /* Apply input filters. */
409 ri = ifp->info;
410
411 ret = rip_incoming_filter (&p, ri);
412 if (ret < 0)
413 return;
414
hasso16705132003-05-25 14:49:19 +0000415 /* Modify entry according to the interface routemap. */
416 if (ri->routemap[RIP_FILTER_IN])
417 {
418 int ret;
419 struct rip_info newinfo;
420
421 memset (&newinfo, 0, sizeof (newinfo));
422 newinfo.type = ZEBRA_ROUTE_RIP;
423 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000424 newinfo.nexthop = rte->nexthop;
425 newinfo.from = from->sin_addr;
426 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000427 newinfo.metric = rte->metric;
428 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000429 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000430
431 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000432 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
433 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000434
435 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000436 {
437 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000438 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000439 inet_ntoa (p.prefix), p.prefixlen);
440 return;
441 }
hasso16705132003-05-25 14:49:19 +0000442
443 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000444 rte->nexthop = newinfo.nexthop_out;
445 rte->tag = htons (newinfo.tag_out); /* XXX */
446 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000447 }
448
paul718e3742002-12-13 20:15:29 +0000449 /* Once the entry has been validated, update the metric by
450 adding the cost of the network on wich the message
451 arrived. If the result is greater than infinity, use infinity
452 (RFC2453 Sec. 3.9.2) */
453 /* Zebra ripd can handle offset-list in. */
454 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
455
456 /* If offset-list does not modify the metric use interface's
457 metric. */
paula87552c2004-05-03 20:00:17 +0000458 if (!ret)
paul718e3742002-12-13 20:15:29 +0000459 rte->metric += ifp->metric;
460
461 if (rte->metric > RIP_METRIC_INFINITY)
462 rte->metric = RIP_METRIC_INFINITY;
463
464 /* Set nexthop pointer. */
465 if (rte->nexthop.s_addr == 0)
466 nexthop = &from->sin_addr;
467 else
468 nexthop = &rte->nexthop;
469
hasso16705132003-05-25 14:49:19 +0000470 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000471 if (rip_nexthop_check (nexthop) < 0)
472 {
473 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000474 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000475 return;
476 }
477
478 /* Get index for the prefix. */
479 rp = route_node_get (rip->table, (struct prefix *) &p);
480
481 /* Check to see whether there is already RIP route on the table. */
482 rinfo = rp->info;
483
484 if (rinfo)
485 {
486 /* Redistributed route check. */
487 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000488 && rinfo->metric != RIP_METRIC_INFINITY)
489 return;
paul718e3742002-12-13 20:15:29 +0000490
491 /* Local static route. */
492 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000493 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
494 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
495 && rinfo->metric != RIP_METRIC_INFINITY)
496 return;
paul718e3742002-12-13 20:15:29 +0000497 }
paula87552c2004-05-03 20:00:17 +0000498
499 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000500 {
501 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000502 for the destination prefix. If there is no such route, add
503 this route to the routing table, unless the metric is
504 infinity (there is no point in adding a route which
505 unusable). */
paul718e3742002-12-13 20:15:29 +0000506 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000507 {
508 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000509
paula87552c2004-05-03 20:00:17 +0000510 /* - Setting the destination prefix and length to those in
511 the RTE. */
512 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000513
paula87552c2004-05-03 20:00:17 +0000514 /* - Setting the metric to the newly calculated metric (as
515 described above). */
516 rinfo->metric = rte->metric;
517 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000518
paula87552c2004-05-03 20:00:17 +0000519 /* - Set the next hop address to be the address of the router
520 from which the datagram came or the next hop address
521 specified by a next hop RTE. */
522 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
523 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
524 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000525
paula87552c2004-05-03 20:00:17 +0000526 /* - Initialize the timeout for the route. If the
527 garbage-collection timer is running for this route, stop it
528 (see section 2.3 for a discussion of the timers). */
529 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Set the route change flag. */
532 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000533
paula87552c2004-05-03 20:00:17 +0000534 /* - Signal the output process to trigger an update (see section
535 2.5). */
536 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000537
paula87552c2004-05-03 20:00:17 +0000538 /* Finally, route goes into the kernel. */
539 rinfo->type = ZEBRA_ROUTE_RIP;
540 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000541
paula87552c2004-05-03 20:00:17 +0000542 /* Set distance value. */
543 rinfo->distance = rip_distance_apply (rinfo);
544
545 rp->info = rinfo;
546 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
547 rinfo->distance);
548 rinfo->flags |= RIP_RTF_FIB;
549 }
paul718e3742002-12-13 20:15:29 +0000550 }
551 else
552 {
553 /* Route is there but we are not sure the route is RIP or not. */
554 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000555
paul718e3742002-12-13 20:15:29 +0000556 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000557 to the address of the router from which the datagram came.
558 If this datagram is from the same router as the existing
559 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000560 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000561 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000562
563 if (same)
paula87552c2004-05-03 20:00:17 +0000564 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000565
paulb94f9db2004-05-01 20:45:38 +0000566
567 /* Fill in a minimaly temporary rip_info structure, for a future
568 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000569 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000570 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000571 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000572
573
paul718e3742002-12-13 20:15:29 +0000574 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000575 router as the existing route, and the new metric is different
576 than the old one; or, if the new metric is lower than the old
577 one, or if the tag has been changed; or if there is a route
578 with a lower administrave distance; or an update of the
579 distance on the actual route; do the following actions: */
580 if ((same && rinfo->metric != rte->metric)
581 || (rte->metric < rinfo->metric)
582 || ((same)
583 && (rinfo->metric == rte->metric)
584 && ntohs (rte->tag) != rinfo->tag)
585 || (rinfo->distance > rip_distance_apply (&rinfotmp))
586 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
587 {
588 /* - Adopt the route from the datagram. That is, put the
589 new metric in, and adjust the next hop address (if
590 necessary). */
591 oldmetric = rinfo->metric;
592 rinfo->metric = rte->metric;
593 rinfo->tag = ntohs (rte->tag);
594 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
595 rinfo->ifindex = ifp->ifindex;
596 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000597
paula87552c2004-05-03 20:00:17 +0000598 /* Should a new route to this network be established
599 while the garbage-collection timer is running, the
600 new route will replace the one that is about to be
601 deleted. In this case the garbage-collection timer
602 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000603
paula87552c2004-05-03 20:00:17 +0000604 if (oldmetric == RIP_METRIC_INFINITY &&
605 rinfo->metric < RIP_METRIC_INFINITY)
606 {
607 rinfo->type = ZEBRA_ROUTE_RIP;
608 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000609
paula87552c2004-05-03 20:00:17 +0000610 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
613 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000614
paula87552c2004-05-03 20:00:17 +0000615 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
616 rinfo->distance);
617 rinfo->flags |= RIP_RTF_FIB;
618 }
paul718e3742002-12-13 20:15:29 +0000619
paula87552c2004-05-03 20:00:17 +0000620 /* Update nexthop and/or metric value. */
621 if (oldmetric != RIP_METRIC_INFINITY)
622 {
623 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
624 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
625 rinfo->distance);
626 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000627
paula87552c2004-05-03 20:00:17 +0000628 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
629 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
630 }
paul718e3742002-12-13 20:15:29 +0000631
paula87552c2004-05-03 20:00:17 +0000632 /* - Set the route change flag and signal the output process
633 to trigger an update. */
634 rinfo->flags |= RIP_RTF_CHANGED;
635 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000636
paula87552c2004-05-03 20:00:17 +0000637 /* - If the new metric is infinity, start the deletion
638 process (described above); */
639 if (rinfo->metric == RIP_METRIC_INFINITY)
640 {
641 /* If the new metric is infinity, the deletion process
642 begins for the route, which is no longer used for
643 routing packets. Note that the deletion process is
644 started only when the metric is first set to
645 infinity. If the metric was already infinity, then a
646 new deletion process is not started. */
647 if (oldmetric != RIP_METRIC_INFINITY)
648 {
649 /* - The garbage-collection timer is set for 120 seconds. */
650 RIP_TIMER_ON (rinfo->t_garbage_collect,
651 rip_garbage_collect, rip->garbage_time);
652 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000653
paula87552c2004-05-03 20:00:17 +0000654 /* - The metric for the route is set to 16
655 (infinity). This causes the route to be removed
656 from service. */
657 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
658 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000659
paula87552c2004-05-03 20:00:17 +0000660 /* - The route change flag is to indicate that this
661 entry has been changed. */
662 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000663 response. */
paula87552c2004-05-03 20:00:17 +0000664 ; /* Above processes are already done previously. */
665 }
666 }
667 else
668 {
669 /* otherwise, re-initialize the timeout. */
670 rip_timeout_update (rinfo);
671 }
672 }
paul718e3742002-12-13 20:15:29 +0000673 /* Unlock tempolary lock of the route. */
674 route_unlock_node (rp);
675 }
676}
677
678/* Dump RIP packet */
679void
hasso8a676be2004-10-08 06:36:38 +0000680rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000681{
682 caddr_t lim;
683 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000684 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000685 char pbuf[BUFSIZ], nbuf[BUFSIZ];
686 u_char netmask = 0;
687 u_char *p;
688
689 /* Set command string. */
690 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
691 command_str = lookup (rip_msg, packet->command);
692 else
693 command_str = "unknown";
694
695 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000696 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000697 sndrcv, command_str, packet->version, size);
698
699 /* Dump each routing table entry. */
700 rte = packet->rte;
701
702 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
703 {
704 if (packet->version == RIPv2)
705 {
706 netmask = ip_masklen (rte->mask);
707
paulca5e5162004-06-06 22:06:33 +0000708 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000709 {
paulca5e5162004-06-06 22:06:33 +0000710 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000711 {
712 p = (u_char *)&rte->prefix;
713
ajs5d6c3772004-12-08 19:24:06 +0000714 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000715 ntohs (rte->family), ntohs (rte->tag), p);
716 }
paulca5e5162004-06-06 22:06:33 +0000717 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000718 {
719 struct rip_md5_info *md5;
720
721 md5 = (struct rip_md5_info *) &packet->rte;
722
ajs5d6c3772004-12-08 19:24:06 +0000723 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000724 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000725 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000726 " Auth Data len %d",
727 ntohs (md5->packet_len), md5->keyid,
728 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000729 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000730 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000731 }
paulca5e5162004-06-06 22:06:33 +0000732 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000733 {
734 p = (u_char *)&rte->prefix;
735
ajs5d6c3772004-12-08 19:24:06 +0000736 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000737 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000738 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000739 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000740 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
741 p[7], p[9], p[10], p[11], p[12], p[13],
742 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000743 }
744 else
745 {
ajs5d6c3772004-12-08 19:24:06 +0000746 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000747 ntohs (rte->family), ntohs (rte->tag));
748 }
749 }
750 else
ajs5d6c3772004-12-08 19:24:06 +0000751 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000752 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
753 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
754 BUFSIZ), ntohs (rte->family),
755 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000756 }
757 else
758 {
ajs5d6c3772004-12-08 19:24:06 +0000759 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000760 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
761 ntohs (rte->family), ntohs (rte->tag),
762 (u_long)ntohl (rte->metric));
763 }
764 }
765}
766
767/* Check if the destination address is valid (unicast; not net 0
768 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
769 check net 0 because we accept default route. */
770int
771rip_destination_check (struct in_addr addr)
772{
773 u_int32_t destination;
774
775 /* Convert to host byte order. */
776 destination = ntohl (addr.s_addr);
777
778 if (IPV4_NET127 (destination))
779 return 0;
780
781 /* Net 0 may match to the default route. */
782 if (IPV4_NET0 (destination) && destination != 0)
783 return 0;
784
785 /* Unicast address must belong to class A, B, C. */
786 if (IN_CLASSA (destination))
787 return 1;
788 if (IN_CLASSB (destination))
789 return 1;
790 if (IN_CLASSC (destination))
791 return 1;
792
793 return 0;
794}
795
796/* RIP version 2 authentication. */
797int
798rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
799 struct interface *ifp)
800{
801 struct rip_interface *ri;
802 char *auth_str;
803
804 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000805 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000806 inet_ntoa (from->sin_addr));
807
808 ri = ifp->info;
809
810 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000811 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000812 return 0;
813
814 /* Simple password authentication. */
815 if (ri->auth_str)
816 {
817 auth_str = (char *) &rte->prefix;
818
819 if (strncmp (auth_str, ri->auth_str, 16) == 0)
820 return 1;
821 }
822 if (ri->key_chain)
823 {
824 struct keychain *keychain;
825 struct key *key;
826
827 keychain = keychain_lookup (ri->key_chain);
828 if (keychain == NULL)
829 return 0;
830
831 key = key_match_for_accept (keychain, (char *) &rte->prefix);
832 if (key)
833 return 1;
834 }
835 return 0;
836}
837
838/* RIP version 2 authentication with MD5. */
839int
840rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000841 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
843 struct rip_interface *ri;
844 struct rip_md5_info *md5;
845 struct rip_md5_data *md5data;
846 struct keychain *keychain;
847 struct key *key;
848 struct md5_ctx ctx;
849 u_char pdigest[RIP_AUTH_MD5_SIZE];
850 u_char digest[RIP_AUTH_MD5_SIZE];
851 u_int16_t packet_len;
852 char *auth_str = NULL;
853
854 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000855 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000856 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000857
858 ri = ifp->info;
859 md5 = (struct rip_md5_info *) &packet->rte;
860
861 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000862 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000863 return 0;
864
paulca5e5162004-06-06 22:06:33 +0000865 /* If the authentication length is less than 16, then it must be wrong for
866 * any interpretation of rfc2082. Some implementations also interpret
867 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000868 */
paulca5e5162004-06-06 22:06:33 +0000869 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
870 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000871 {
872 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000873 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000874 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000875 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000876 }
paul718e3742002-12-13 20:15:29 +0000877
paulca5e5162004-06-06 22:06:33 +0000878 /* grab and verify check packet length */
879 packet_len = ntohs (md5->packet_len);
880
881 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
882 {
883 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000884 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000885 "greater than received length %d!",
886 md5->packet_len, length);
887 return 0;
888 }
889
890 /* retrieve authentication data */
891 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
892
paul718e3742002-12-13 20:15:29 +0000893 if (ri->key_chain)
894 {
895 keychain = keychain_lookup (ri->key_chain);
896 if (keychain == NULL)
897 return 0;
898
899 key = key_lookup_for_accept (keychain, md5->keyid);
900 if (key == NULL)
901 return 0;
902
903 auth_str = key->string;
904 }
905
906 if (ri->auth_str)
907 auth_str = ri->auth_str;
908
909 if (! auth_str)
910 return 0;
911
912 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000913
914 /* Save digest to pdigest. */
915 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
916
917 /* Overwrite digest by my secret. */
918 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000919 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000920
921 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000922 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000923 &ctx);
paul718e3742002-12-13 20:15:29 +0000924 md5_finish_ctx (&ctx, digest);
925
926 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
927 return packet_len;
928 else
929 return 0;
930}
931
932void
933rip_auth_md5_set (struct stream *s, struct interface *ifp)
934{
935 struct rip_interface *ri;
936 struct keychain *keychain = NULL;
937 struct key *key = NULL;
938 unsigned long len;
939 struct md5_ctx ctx;
940 unsigned char secret[RIP_AUTH_MD5_SIZE];
941 unsigned char digest[RIP_AUTH_MD5_SIZE];
942 char *auth_str = NULL;
943
944 ri = ifp->info;
945
946 /* Make it sure this interface is configured as MD5
947 authentication. */
948 if (ri->auth_type != RIP_AUTH_MD5)
949 return;
950
951 /* Lookup key chain. */
952 if (ri->key_chain)
953 {
954 keychain = keychain_lookup (ri->key_chain);
955 if (keychain == NULL)
956 return;
957
958 /* Lookup key. */
959 key = key_lookup_for_send (keychain);
960 if (key == NULL)
961 return;
962
963 auth_str = key->string;
964 }
965
966 if (ri->auth_str)
967 auth_str = ri->auth_str;
968
969 if (! auth_str)
970 return;
971
972 /* Get packet length. */
973 len = s->putp;
974
975 /* Check packet length. */
976 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
977 {
978 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
979 return;
980 }
981
982 /* Move RTE. */
983 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
984 s->data + RIP_HEADER_SIZE,
985 len - RIP_HEADER_SIZE);
986
987 /* Set pointer to authentication header. */
988 stream_set_putp (s, RIP_HEADER_SIZE);
989 len += RIP_RTE_SIZE;
990
991 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000992 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000993 stream_putw (s, RIP_AUTH_MD5);
994
995 /* RIP-2 Packet length. Actual value is filled in
996 rip_auth_md5_set(). */
997 stream_putw (s, len);
998
999 /* Key ID. */
1000 if (key)
1001 stream_putc (s, key->index % 256);
1002 else
1003 stream_putc (s, 1);
1004
paulca5e5162004-06-06 22:06:33 +00001005 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1006 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1007 * to be configurable.
1008 */
1009 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001010
1011 /* Sequence Number (non-decreasing). */
1012 /* RFC2080: The value used in the sequence number is
1013 arbitrary, but two suggestions are the time of the
1014 message's creation or a simple message counter. */
1015 stream_putl (s, time (NULL));
1016
1017 /* Reserved field must be zero. */
1018 stream_putl (s, 0);
1019 stream_putl (s, 0);
1020
1021 /* Set pointer to authentication data. */
1022 stream_set_putp (s, len);
1023
1024 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001025 stream_putw (s, RIP_FAMILY_AUTH);
1026 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001027
1028 /* Generate a digest for the RIP packet. */
1029 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001030 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001031 md5_init_ctx (&ctx);
1032 md5_process_bytes (s->data, s->endp, &ctx);
1033 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1034 md5_finish_ctx (&ctx, digest);
1035
1036 /* Copy the digest to the packet. */
1037 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1038}
1039
1040/* RIP routing information. */
1041void
1042rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001043 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001044{
1045 caddr_t lim;
1046 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001047 struct prefix_ipv4 ifaddr;
1048 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001049 int subnetted;
paul718e3742002-12-13 20:15:29 +00001050
paul727d1042002-12-13 20:50:29 +00001051 /* We don't know yet. */
1052 subnetted = -1;
1053
paul718e3742002-12-13 20:15:29 +00001054 /* The Response must be ignored if it is not from the RIP
1055 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001056 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001057 {
1058 zlog_info ("response doesn't come from RIP port: %d",
1059 from->sin_port);
1060 rip_peer_bad_packet (from);
1061 return;
1062 }
1063
1064 /* The datagram's IPv4 source address should be checked to see
1065 whether the datagram is from a valid neighbor; the source of the
1066 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001067 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001068 {
1069 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1070 inet_ntoa (from->sin_addr));
1071 rip_peer_bad_packet (from);
1072 return;
1073 }
1074
1075 /* It is also worth checking to see whether the response is from one
1076 of the router's own addresses. */
1077
1078 ; /* Alredy done in rip_read () */
1079
1080 /* Update RIP peer. */
1081 rip_peer_update (from, packet->version);
1082
1083 /* Set RTE pointer. */
1084 rte = packet->rte;
1085
1086 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1087 {
1088 /* RIPv2 authentication check. */
1089 /* If the Address Family Identifier of the first (and only the
1090 first) entry in the message is 0xFFFF, then the remainder of
1091 the entry contains the authentication. */
1092 /* If the packet gets here it means authentication enabled */
1093 /* Check is done in rip_read(). So, just skipping it */
1094 if (packet->version == RIPv2 &&
1095 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001096 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001097 continue;
1098
paulca5e5162004-06-06 22:06:33 +00001099 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001100 {
1101 /* Address family check. RIP only supports AF_INET. */
1102 zlog_info ("Unsupported family %d from %s.",
1103 ntohs (rte->family), inet_ntoa (from->sin_addr));
1104 continue;
1105 }
1106
1107 /* - is the destination address valid (e.g., unicast; not net 0
1108 or 127) */
1109 if (! rip_destination_check (rte->prefix))
1110 {
1111 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1112 rip_peer_bad_route (from);
1113 continue;
1114 }
1115
1116 /* Convert metric value to host byte order. */
1117 rte->metric = ntohl (rte->metric);
1118
1119 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1120 if (! (rte->metric >= 1 && rte->metric <= 16))
1121 {
1122 zlog_info ("Route's metric is not in the 1-16 range.");
1123 rip_peer_bad_route (from);
1124 continue;
1125 }
1126
1127 /* RIPv1 does not have nexthop value. */
1128 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1129 {
1130 zlog_info ("RIPv1 packet with nexthop value %s",
1131 inet_ntoa (rte->nexthop));
1132 rip_peer_bad_route (from);
1133 continue;
1134 }
1135
1136 /* That is, if the provided information is ignored, a possibly
1137 sub-optimal, but absolutely valid, route may be taken. If
1138 the received Next Hop is not directly reachable, it should be
1139 treated as 0.0.0.0. */
1140 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1141 {
1142 u_int32_t addrval;
1143
1144 /* Multicast address check. */
1145 addrval = ntohl (rte->nexthop.s_addr);
1146 if (IN_CLASSD (addrval))
1147 {
1148 zlog_info ("Nexthop %s is multicast address, skip this rte",
1149 inet_ntoa (rte->nexthop));
1150 continue;
1151 }
1152
1153 if (! if_lookup_address (rte->nexthop))
1154 {
1155 struct route_node *rn;
1156 struct rip_info *rinfo;
1157
1158 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1159
1160 if (rn)
1161 {
1162 rinfo = rn->info;
1163
1164 if (rinfo->type == ZEBRA_ROUTE_RIP
1165 && rinfo->sub_type == RIP_ROUTE_RTE)
1166 {
1167 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001168 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 +00001169 rte->nexthop = rinfo->from;
1170 }
1171 else
1172 {
1173 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001174 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 +00001175 rte->nexthop.s_addr = 0;
1176 }
1177
1178 route_unlock_node (rn);
1179 }
1180 else
1181 {
1182 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001183 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 +00001184 rte->nexthop.s_addr = 0;
1185 }
1186
1187 }
1188 }
1189
1190 /* For RIPv1, there won't be a valid netmask.
1191
1192 This is a best guess at the masks. If everyone was using old
1193 Ciscos before the 'ip subnet zero' option, it would be almost
1194 right too :-)
1195
1196 Cisco summarize ripv1 advertisments to the classful boundary
1197 (/16 for class B's) except when the RIP packet does to inside
1198 the classful network in question. */
1199
1200 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1201 || (packet->version == RIPv2
1202 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1203 {
1204 u_int32_t destination;
1205
paul727d1042002-12-13 20:50:29 +00001206 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001207 {
1208 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1209 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1210 apply_classful_mask_ipv4 (&ifaddrclass);
1211 subnetted = 0;
1212 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1213 subnetted = 1;
1214 }
paul727d1042002-12-13 20:50:29 +00001215
paul718e3742002-12-13 20:15:29 +00001216 destination = ntohl (rte->prefix.s_addr);
1217
paul727d1042002-12-13 20:50:29 +00001218 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001219 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001220 else if (IN_CLASSB (destination))
1221 masklen2ip (16, &rte->mask);
1222 else if (IN_CLASSC (destination))
1223 masklen2ip (24, &rte->mask);
1224
1225 if (subnetted == 1)
1226 masklen2ip (ifaddrclass.prefixlen,
1227 (struct in_addr *) &destination);
1228 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1229 ifaddrclass.prefix.s_addr))
1230 {
1231 masklen2ip (ifaddr.prefixlen, &rte->mask);
1232 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1233 masklen2ip (32, &rte->mask);
1234 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001235 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001236 }
1237 else
1238 {
1239 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1240 continue;
1241 }
1242
1243 if (IS_RIP_DEBUG_EVENT)
1244 {
ajs5d6c3772004-12-08 19:24:06 +00001245 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1246 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001247 }
1248 }
1249
1250 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1251 ignore the entry. */
1252 if ((packet->version == RIPv2)
1253 && (rte->mask.s_addr != 0)
1254 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1255 {
1256 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1257 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1258 rip_peer_bad_route (from);
1259 continue;
1260 }
1261
1262 /* Default route's netmask is ignored. */
1263 if (packet->version == RIPv2
1264 && (rte->prefix.s_addr == 0)
1265 && (rte->mask.s_addr != 0))
1266 {
1267 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001268 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001269 rte->mask.s_addr = 0;
1270 }
1271
1272 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001273 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001274 }
1275}
1276
paulc49ad8f2004-10-22 10:27:28 +00001277/* RIP packet send to destination address, on interface denoted by
1278 * by connected argument. NULL to argument denotes destination should be
1279 * should be RIP multicast group
1280 */
paul718e3742002-12-13 20:15:29 +00001281int
paulc49ad8f2004-10-22 10:27:28 +00001282rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1283 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001284{
paul931cd542004-01-23 15:31:42 +00001285 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001286 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001287
1288 assert (ifc != NULL);
1289
paul931cd542004-01-23 15:31:42 +00001290 if (IS_RIP_DEBUG_PACKET)
1291 {
1292 char dst[20];
1293 if (to)
1294 {
1295 strcpy(dst, inet_ntoa(to->sin_addr));
1296 }
1297 else
1298 {
1299 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1300 strcpy(dst, inet_ntoa(sin.sin_addr));
1301 }
ajs5d6c3772004-12-08 19:24:06 +00001302 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001303 inet_ntoa(ifc->address->u.prefix4),
1304 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001305 }
paulc49ad8f2004-10-22 10:27:28 +00001306 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001307 {
1308 /*
1309 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1310 * with multiple addresses on the same subnet: the first address
1311 * on the subnet is configured "primary", and all subsequent addresses
1312 * on that subnet are treated as "secondary" addresses.
1313 * In order to avoid routing-table bloat on other rip listeners,
1314 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1315 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1316 * flag is set, we would end up sending a packet for a "secondary"
1317 * source address on non-linux systems.
1318 */
1319 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001320 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001321 return 0;
1322 }
1323
paul718e3742002-12-13 20:15:29 +00001324 /* Make destination address. */
1325 memset (&sin, 0, sizeof (struct sockaddr_in));
1326 sin.sin_family = AF_INET;
1327#ifdef HAVE_SIN_LEN
1328 sin.sin_len = sizeof (struct sockaddr_in);
1329#endif /* HAVE_SIN_LEN */
1330
1331 /* When destination is specified, use it's port and address. */
1332 if (to)
1333 {
paul718e3742002-12-13 20:15:29 +00001334 sin.sin_port = to->sin_port;
1335 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001336 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001337 }
1338 else
1339 {
paul718e3742002-12-13 20:15:29 +00001340
1341 sin.sin_port = htons (RIP_PORT_DEFAULT);
1342 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1343
paul931cd542004-01-23 15:31:42 +00001344 /*
1345 * we have to open a new socket for each packet because this
1346 * is the most portable way to bind to a different source
1347 * ipv4 address for each packet.
1348 */
1349 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1350 if (send_sock < 0)
1351 {
1352 zlog_warn("rip_send_packet could not create socket %s",
ajs6099b3b2004-11-20 02:06:59 +00001353 safe_strerror(errno));
paul931cd542004-01-23 15:31:42 +00001354 return -1;
1355 }
1356 sockopt_broadcast (send_sock);
1357 sockopt_reuseaddr (send_sock);
1358 sockopt_reuseport (send_sock);
1359#ifdef RIP_RECVMSG
1360 setsockopt_pktinfo (send_sock);
1361#endif /* RIP_RECVMSG */
paulc49ad8f2004-10-22 10:27:28 +00001362 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001363 }
1364
paul931cd542004-01-23 15:31:42 +00001365 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001366 sizeof (struct sockaddr_in));
1367
1368 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001369 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001370 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001371
1372 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001373 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001374
paul931cd542004-01-23 15:31:42 +00001375 if (!to)
1376 close(send_sock);
1377
paul718e3742002-12-13 20:15:29 +00001378 return ret;
1379}
1380
1381/* Add redistributed route to RIP table. */
1382void
1383rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1384 unsigned int ifindex, struct in_addr *nexthop)
1385{
1386 int ret;
1387 struct route_node *rp;
1388 struct rip_info *rinfo;
1389
1390 /* Redistribute route */
1391 ret = rip_destination_check (p->prefix);
1392 if (! ret)
1393 return;
1394
1395 rp = route_node_get (rip->table, (struct prefix *) p);
1396
1397 rinfo = rp->info;
1398
1399 if (rinfo)
1400 {
1401 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1402 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1403 && rinfo->metric != RIP_METRIC_INFINITY)
1404 {
1405 route_unlock_node (rp);
1406 return;
1407 }
1408
1409 /* Manually configured RIP route check. */
1410 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001411 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1412 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001413 {
hasso16705132003-05-25 14:49:19 +00001414 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1415 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001416 {
1417 route_unlock_node (rp);
1418 return;
1419 }
1420 }
1421
1422 RIP_TIMER_OFF (rinfo->t_timeout);
1423 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1424
1425 if (rip_route_rte (rinfo))
1426 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1427 rinfo->metric);
1428 rp->info = NULL;
1429 rip_info_free (rinfo);
1430
1431 route_unlock_node (rp);
1432 }
1433
1434 rinfo = rip_info_new ();
1435
1436 rinfo->type = type;
1437 rinfo->sub_type = sub_type;
1438 rinfo->ifindex = ifindex;
1439 rinfo->metric = 1;
1440 rinfo->rp = rp;
1441
1442 if (nexthop)
1443 rinfo->nexthop = *nexthop;
1444
1445 rinfo->flags |= RIP_RTF_FIB;
1446 rp->info = rinfo;
1447
1448 rinfo->flags |= RIP_RTF_CHANGED;
1449
hasso16705132003-05-25 14:49:19 +00001450 if (IS_RIP_DEBUG_EVENT) {
1451 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001452 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001453 inet_ntoa(p->prefix), p->prefixlen,
1454 ifindex2ifname(ifindex));
1455 else
ajs5d6c3772004-12-08 19:24:06 +00001456 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001457 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1458 ifindex2ifname(ifindex));
1459 }
1460
1461
paul718e3742002-12-13 20:15:29 +00001462 rip_event (RIP_TRIGGERED_UPDATE, 0);
1463}
1464
1465/* Delete redistributed route from RIP table. */
1466void
1467rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1468 unsigned int ifindex)
1469{
1470 int ret;
1471 struct route_node *rp;
1472 struct rip_info *rinfo;
1473
1474 ret = rip_destination_check (p->prefix);
1475 if (! ret)
1476 return;
1477
1478 rp = route_node_lookup (rip->table, (struct prefix *) p);
1479 if (rp)
1480 {
1481 rinfo = rp->info;
1482
1483 if (rinfo != NULL
1484 && rinfo->type == type
1485 && rinfo->sub_type == sub_type
1486 && rinfo->ifindex == ifindex)
1487 {
1488 /* Perform poisoned reverse. */
1489 rinfo->metric = RIP_METRIC_INFINITY;
1490 RIP_TIMER_ON (rinfo->t_garbage_collect,
1491 rip_garbage_collect, rip->garbage_time);
1492 RIP_TIMER_OFF (rinfo->t_timeout);
1493 rinfo->flags |= RIP_RTF_CHANGED;
1494
hasso16705132003-05-25 14:49:19 +00001495 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001496 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001497 inet_ntoa(p->prefix), p->prefixlen,
1498 ifindex2ifname(ifindex));
1499
paul718e3742002-12-13 20:15:29 +00001500 rip_event (RIP_TRIGGERED_UPDATE, 0);
1501 }
1502 }
1503}
1504
1505/* Response to request called from rip_read ().*/
1506void
1507rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001508 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001509{
1510 caddr_t lim;
1511 struct rte *rte;
1512 struct prefix_ipv4 p;
1513 struct route_node *rp;
1514 struct rip_info *rinfo;
1515 struct rip_interface *ri;
1516
hasso16705132003-05-25 14:49:19 +00001517 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001518 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001519 return;
1520
hasso429a0f82004-02-22 23:42:22 +00001521 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001522 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001523 if (! ri->running)
1524 return;
paul718e3742002-12-13 20:15:29 +00001525
1526 /* When passive interface is specified, suppress responses */
1527 if (ri->passive)
1528 return;
paulc49ad8f2004-10-22 10:27:28 +00001529
paul718e3742002-12-13 20:15:29 +00001530 /* RIP peer update. */
1531 rip_peer_update (from, packet->version);
1532
1533 lim = ((caddr_t) packet) + size;
1534 rte = packet->rte;
1535
1536 /* The Request is processed entry by entry. If there are no
1537 entries, no response is given. */
1538 if (lim == (caddr_t) rte)
1539 return;
1540
1541 /* There is one special case. If there is exactly one entry in the
1542 request, and it has an address family identifier of zero and a
1543 metric of infinity (i.e., 16), then this is a request to send the
1544 entire routing table. */
1545 if (lim == ((caddr_t) (rte + 1)) &&
1546 ntohs (rte->family) == 0 &&
1547 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1548 {
paulcc1131a2003-10-15 23:20:17 +00001549 struct prefix_ipv4 saddr;
1550
1551 /* saddr will be used for determining which routes to split-horizon.
1552 Since the source address we'll pick will be on the same subnet as the
1553 destination, for the purpose of split-horizoning, we'll
1554 pretend that "from" is our source address. */
1555 saddr.family = AF_INET;
1556 saddr.prefixlen = IPV4_MAX_BITLEN;
1557 saddr.prefix = from->sin_addr;
1558
paul718e3742002-12-13 20:15:29 +00001559 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001560 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001561 }
1562 else
1563 {
1564 /* Examine the list of RTEs in the Request one by one. For each
1565 entry, look up the destination in the router's routing
1566 database and, if there is a route, put that route's metric in
1567 the metric field of the RTE. If there is no explicit route
1568 to the specified destination, put infinity in the metric
1569 field. Once all the entries have been filled in, change the
1570 command from Request to Response and send the datagram back
1571 to the requestor. */
1572 p.family = AF_INET;
1573
1574 for (; ((caddr_t) rte) < lim; rte++)
1575 {
1576 p.prefix = rte->prefix;
1577 p.prefixlen = ip_masklen (rte->mask);
1578 apply_mask_ipv4 (&p);
1579
1580 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1581 if (rp)
1582 {
1583 rinfo = rp->info;
1584 rte->metric = htonl (rinfo->metric);
1585 route_unlock_node (rp);
1586 }
1587 else
1588 rte->metric = htonl (RIP_METRIC_INFINITY);
1589 }
1590 packet->command = RIP_RESPONSE;
1591
paulc49ad8f2004-10-22 10:27:28 +00001592 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001593 }
1594 rip_global_queries++;
1595}
1596
1597#if RIP_RECVMSG
1598/* Set IPv6 packet info to the socket. */
1599static int
1600setsockopt_pktinfo (int sock)
1601{
1602 int ret;
1603 int val = 1;
1604
1605 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1606 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001607 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001608 return ret;
1609}
1610
1611/* Read RIP packet by recvmsg function. */
1612int
1613rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1614 int *ifindex)
1615{
1616 int ret;
1617 struct msghdr msg;
1618 struct iovec iov;
1619 struct cmsghdr *ptr;
1620 char adata[1024];
1621
1622 msg.msg_name = (void *) from;
1623 msg.msg_namelen = sizeof (struct sockaddr_in);
1624 msg.msg_iov = &iov;
1625 msg.msg_iovlen = 1;
1626 msg.msg_control = (void *) adata;
1627 msg.msg_controllen = sizeof adata;
1628 iov.iov_base = buf;
1629 iov.iov_len = size;
1630
1631 ret = recvmsg (sock, &msg, 0);
1632 if (ret < 0)
1633 return ret;
1634
ajsb99760a2005-01-04 16:24:43 +00001635 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001636 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1637 {
1638 struct in_pktinfo *pktinfo;
1639 int i;
1640
1641 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1642 i = pktinfo->ipi_ifindex;
1643 }
1644 return ret;
1645}
1646
1647/* RIP packet read function. */
1648int
1649rip_read_new (struct thread *t)
1650{
1651 int ret;
1652 int sock;
1653 char buf[RIP_PACKET_MAXSIZ];
1654 struct sockaddr_in from;
1655 unsigned int ifindex;
1656
1657 /* Fetch socket then register myself. */
1658 sock = THREAD_FD (t);
1659 rip_event (RIP_READ, sock);
1660
1661 /* Read RIP packet. */
1662 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1663 if (ret < 0)
1664 {
ajs6099b3b2004-11-20 02:06:59 +00001665 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001666 return ret;
1667 }
1668
1669 return ret;
1670}
1671#endif /* RIP_RECVMSG */
1672
1673/* First entry point of RIP packet. */
1674int
1675rip_read (struct thread *t)
1676{
1677 int sock;
1678 int ret;
1679 int rtenum;
1680 union rip_buf rip_buf;
1681 struct rip_packet *packet;
1682 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001683 int len;
1684 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001685 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001686 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001687 struct rip_interface *ri;
1688
1689 /* Fetch socket then register myself. */
1690 sock = THREAD_FD (t);
1691 rip->t_read = NULL;
1692
1693 /* Add myself to tne next event */
1694 rip_event (RIP_READ, sock);
1695
1696 /* RIPd manages only IPv4. */
1697 memset (&from, 0, sizeof (struct sockaddr_in));
1698 fromlen = sizeof (struct sockaddr_in);
1699
1700 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1701 (struct sockaddr *) &from, &fromlen);
1702 if (len < 0)
1703 {
ajs6099b3b2004-11-20 02:06:59 +00001704 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001705 return len;
1706 }
1707
1708 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001709 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001710 {
1711 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001712 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001713 return -1;
1714 }
1715
1716 /* Which interface is this packet comes from. */
1717 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001718
paul718e3742002-12-13 20:15:29 +00001719 /* RIP packet received */
1720 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001721 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001722 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1723 ifp ? ifp->name : "unknown");
1724
1725 /* If this packet come from unknown interface, ignore it. */
1726 if (ifp == NULL)
1727 {
ajs766a0ca2004-12-15 14:55:51 +00001728 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1729 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001730 return -1;
1731 }
1732
1733 ifc = connected_lookup_address (ifp, from.sin_addr);
1734
1735 if (ifc == NULL)
1736 {
ajs766a0ca2004-12-15 14:55:51 +00001737 zlog_info ("rip_read: cannot find connected address for packet from %s "
1738 "port %d on interface %s",
1739 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001740 return -1;
1741 }
1742
1743 /* Packet length check. */
1744 if (len < RIP_PACKET_MINSIZ)
1745 {
1746 zlog_warn ("packet size %d is smaller than minimum size %d",
1747 len, RIP_PACKET_MINSIZ);
1748 rip_peer_bad_packet (&from);
1749 return len;
1750 }
1751 if (len > RIP_PACKET_MAXSIZ)
1752 {
1753 zlog_warn ("packet size %d is larger than max size %d",
1754 len, RIP_PACKET_MAXSIZ);
1755 rip_peer_bad_packet (&from);
1756 return len;
1757 }
1758
1759 /* Packet alignment check. */
1760 if ((len - RIP_PACKET_MINSIZ) % 20)
1761 {
1762 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1763 rip_peer_bad_packet (&from);
1764 return len;
1765 }
1766
1767 /* Set RTE number. */
1768 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1769
1770 /* For easy to handle. */
1771 packet = &rip_buf.rip_packet;
1772
1773 /* RIP version check. */
1774 if (packet->version == 0)
1775 {
1776 zlog_info ("version 0 with command %d received.", packet->command);
1777 rip_peer_bad_packet (&from);
1778 return -1;
1779 }
1780
1781 /* Dump RIP packet. */
1782 if (IS_RIP_DEBUG_RECV)
1783 rip_packet_dump (packet, len, "RECV");
1784
1785 /* RIP version adjust. This code should rethink now. RFC1058 says
1786 that "Version 1 implementations are to ignore this extra data and
1787 process only the fields specified in this document.". So RIPv3
1788 packet should be treated as RIPv1 ignoring must be zero field. */
1789 if (packet->version > RIPv2)
1790 packet->version = RIPv2;
1791
1792 /* Is RIP running or is this RIP neighbor ?*/
1793 ri = ifp->info;
1794 if (! ri->running && ! rip_neighbor_lookup (&from))
1795 {
1796 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001797 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001798 rip_peer_bad_packet (&from);
1799 return -1;
1800 }
1801
1802 /* RIP Version check. */
1803 if (packet->command == RIP_RESPONSE)
1804 {
paulf38a4712003-06-07 01:10:00 +00001805 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1806 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001807 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001808 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001809 {
1810 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001811 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001812 packet->version);
1813 rip_peer_bad_packet (&from);
1814 return -1;
1815 }
1816 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001817 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001818 {
1819 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001820 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001821 packet->version);
1822 rip_peer_bad_packet (&from);
1823 return -1;
1824 }
paul718e3742002-12-13 20:15:29 +00001825 }
1826
1827 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1828 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1829 accepted; authenticated RIP-2 messages shall be discarded. */
1830
1831 if ((ri->auth_type == RIP_NO_AUTH)
1832 && rtenum
paulca5e5162004-06-06 22:06:33 +00001833 && (packet->version == RIPv2)
1834 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001835 {
1836 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001837 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001838 packet->version);
1839 rip_peer_bad_packet (&from);
1840 return -1;
1841 }
1842
1843 /* If the router is configured to authenticate RIP-2 messages, then
1844 RIP-1 messages and RIP-2 messages which pass authentication
1845 testing shall be accepted; unauthenticated and failed
1846 authentication RIP-2 messages shall be discarded. For maximum
1847 security, RIP-1 messages should be ignored when authentication is
1848 in use (see section 4.1); otherwise, the routing information from
1849 authenticated messages will be propagated by RIP-1 routers in an
1850 unauthenticated manner. */
1851
1852 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001853 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001854 {
1855 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001856 if (packet->version == RIPv1
1857 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001858 {
1859 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001860 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001861 ("packet RIPv%d is dropped because authentication enabled",
1862 packet->version);
paul718e3742002-12-13 20:15:29 +00001863 rip_peer_bad_packet (&from);
1864 return -1;
1865 }
1866
1867 /* Check RIPv2 authentication. */
1868 if (packet->version == RIPv2)
1869 {
paulca5e5162004-06-06 22:06:33 +00001870 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001871 {
paulca5e5162004-06-06 22:06:33 +00001872 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001873 {
1874 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1875 if (! ret)
1876 {
1877 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001878 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001879 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001880 rip_peer_bad_packet (&from);
1881 return -1;
1882 }
1883 else
1884 {
1885 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001886 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001887 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001888 }
1889 }
paulca5e5162004-06-06 22:06:33 +00001890 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001891 {
paulca5e5162004-06-06 22:06:33 +00001892 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001893 if (! ret)
1894 {
1895 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001896 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001897 rip_peer_bad_packet (&from);
1898 return -1;
1899 }
1900 else
1901 {
1902 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001903 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001904 }
1905 /* Reset RIP packet length to trim MD5 data. */
1906 len = ret;
1907 }
1908 else
1909 {
1910 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001911 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00001912 ntohs (packet->rte->tag));
1913 rip_peer_bad_packet (&from);
1914 return -1;
1915 }
1916 }
1917 else
1918 {
1919 /* There is no authentication in the packet. */
1920 if (ri->auth_str || ri->key_chain)
1921 {
1922 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001923 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001924 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001925 rip_peer_bad_packet (&from);
1926 return -1;
1927 }
1928 }
1929 }
1930 }
1931
1932 /* Process each command. */
1933 switch (packet->command)
1934 {
1935 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00001936 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001937 break;
1938 case RIP_REQUEST:
1939 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00001940 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001941 break;
1942 case RIP_TRACEON:
1943 case RIP_TRACEOFF:
1944 zlog_info ("Obsolete command %s received, please sent it to routed",
1945 lookup (rip_msg, packet->command));
1946 rip_peer_bad_packet (&from);
1947 break;
1948 case RIP_POLL_ENTRY:
1949 zlog_info ("Obsolete command %s received",
1950 lookup (rip_msg, packet->command));
1951 rip_peer_bad_packet (&from);
1952 break;
1953 default:
1954 zlog_info ("Unknown RIP command %d received", packet->command);
1955 rip_peer_bad_packet (&from);
1956 break;
1957 }
1958
1959 return len;
1960}
1961
1962/* Make socket for RIP protocol. */
1963int
1964rip_create_socket ()
1965{
1966 int ret;
1967 int sock;
1968 struct sockaddr_in addr;
1969 struct servent *sp;
1970
1971 memset (&addr, 0, sizeof (struct sockaddr_in));
1972
1973 /* Set RIP port. */
1974 sp = getservbyname ("router", "udp");
1975 if (sp)
1976 addr.sin_port = sp->s_port;
1977 else
1978 addr.sin_port = htons (RIP_PORT_DEFAULT);
1979
1980 /* Address shoud be any address. */
1981 addr.sin_family = AF_INET;
1982 addr.sin_addr.s_addr = INADDR_ANY;
1983
1984 /* Make datagram socket. */
1985 sock = socket (AF_INET, SOCK_DGRAM, 0);
1986 if (sock < 0)
1987 {
ajs6a52d0d2005-01-30 18:49:28 +00001988 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
paul718e3742002-12-13 20:15:29 +00001989 exit (1);
1990 }
1991
1992 sockopt_broadcast (sock);
1993 sockopt_reuseaddr (sock);
1994 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00001995 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00001996#ifdef RIP_RECVMSG
1997 setsockopt_pktinfo (sock);
1998#endif /* RIP_RECVMSG */
1999
pauledd7c242003-06-04 13:59:38 +00002000 if (ripd_privs.change (ZPRIVS_RAISE))
2001 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00002002 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
2003 if (ret < 0)
2004 {
ajs79853452005-01-30 17:40:29 +00002005 int save_errno = errno;
pauld62262a2003-11-17 09:08:45 +00002006 if (ripd_privs.change (ZPRIVS_LOWER))
2007 zlog_err ("rip_create_socket: could not lower privs");
ajs79853452005-01-30 17:40:29 +00002008 zlog_err("cannot bind to port %d: %s",
2009 (int)ntohs(addr.sin_port), safe_strerror(save_errno));
paul718e3742002-12-13 20:15:29 +00002010 return ret;
2011 }
pauledd7c242003-06-04 13:59:38 +00002012 if (ripd_privs.change (ZPRIVS_LOWER))
2013 zlog_err ("rip_create_socket: could not lower privs");
2014
paul718e3742002-12-13 20:15:29 +00002015 return sock;
2016}
2017
2018/* Write routing table entry to the stream and return next index of
2019 the routing table entry in the stream. */
2020int
2021rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2022 u_char version, struct rip_info *rinfo, struct interface *ifp)
2023{
2024 struct in_addr mask;
2025 struct rip_interface *ri;
2026
2027 /* RIP packet header. */
2028 if (num == 0)
2029 {
2030 stream_putc (s, RIP_RESPONSE);
2031 stream_putc (s, version);
2032 stream_putw (s, 0);
2033
2034 /* In case of we need RIPv2 authentication. */
2035 if (version == RIPv2 && ifp)
2036 {
2037 ri = ifp->info;
2038
2039 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2040 {
2041 if (ri->auth_str)
2042 {
paulca5e5162004-06-06 22:06:33 +00002043 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002044 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2045
2046 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002047 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002048 stream_set_putp (s, s->putp + 16);
2049
2050 num++;
2051 }
2052 if (ri->key_chain)
2053 {
2054 struct keychain *keychain;
2055 struct key *key;
2056
2057 keychain = keychain_lookup (ri->key_chain);
2058
2059 if (keychain)
2060 {
2061 key = key_lookup_for_send (keychain);
2062
2063 if (key)
2064 {
paulca5e5162004-06-06 22:06:33 +00002065 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002066 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2067
2068 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002069 strncpy ((char *)(s->data + s->putp),
2070 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002071 stream_set_putp (s, s->putp + 16);
2072
2073 num++;
2074 }
2075 }
2076 }
2077 }
2078 }
2079 }
2080
2081 /* Write routing table entry. */
2082 if (version == RIPv1)
2083 {
2084 stream_putw (s, AF_INET);
2085 stream_putw (s, 0);
2086 stream_put_ipv4 (s, p->prefix.s_addr);
2087 stream_put_ipv4 (s, 0);
2088 stream_put_ipv4 (s, 0);
2089 stream_putl (s, rinfo->metric_out);
2090 }
2091 else
2092 {
2093 masklen2ip (p->prefixlen, &mask);
2094
2095 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002096 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002097 stream_put_ipv4 (s, p->prefix.s_addr);
2098 stream_put_ipv4 (s, mask.s_addr);
2099 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2100 stream_putl (s, rinfo->metric_out);
2101 }
2102
2103 return ++num;
2104}
2105
2106/* Send update to the ifp or spcified neighbor. */
2107void
paulc49ad8f2004-10-22 10:27:28 +00002108rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2109 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002110{
2111 int ret;
2112 struct stream *s;
2113 struct route_node *rp;
2114 struct rip_info *rinfo;
2115 struct rip_interface *ri;
2116 struct prefix_ipv4 *p;
2117 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002118 struct prefix_ipv4 ifaddrclass;
paul718e3742002-12-13 20:15:29 +00002119 int num;
2120 int rtemax;
paul01d09082003-06-08 21:22:18 +00002121 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002122
2123 /* Logging output event. */
2124 if (IS_RIP_DEBUG_EVENT)
2125 {
2126 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002127 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002128 else
ajs5d6c3772004-12-08 19:24:06 +00002129 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002130 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002131 }
2132
2133 /* Set output stream. */
2134 s = rip->obuf;
2135
2136 /* Reset stream and RTE counter. */
2137 stream_reset (s);
2138 num = 0;
2139 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2140
2141 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002142 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002143
2144 /* If output interface is in simple password authentication mode, we
2145 need space for authentication data. */
2146 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2147 rtemax -= 1;
2148
2149 /* If output interface is in MD5 authentication mode, we need space
2150 for authentication header and data. */
2151 if (ri->auth_type == RIP_AUTH_MD5)
2152 rtemax -= 2;
2153
2154 /* If output interface is in simple password authentication mode
2155 and string or keychain is specified we need space for auth. data */
2156 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2157 {
2158 if (ri->key_chain)
2159 {
2160 struct keychain *keychain;
2161
2162 keychain = keychain_lookup (ri->key_chain);
2163 if (keychain)
2164 if (key_lookup_for_send (keychain))
2165 rtemax -=1;
2166 }
2167 else
2168 if (ri->auth_str)
2169 rtemax -=1;
2170 }
2171
paul727d1042002-12-13 20:50:29 +00002172 if (version == RIPv1)
2173 {
paulc49ad8f2004-10-22 10:27:28 +00002174 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002175 apply_classful_mask_ipv4 (&ifaddrclass);
2176 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002177 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002178 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002179 }
2180
paul718e3742002-12-13 20:15:29 +00002181 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2182 if ((rinfo = rp->info) != NULL)
2183 {
paul727d1042002-12-13 20:50:29 +00002184 /* For RIPv1, if we are subnetted, output subnets in our network */
2185 /* that have the same mask as the output "interface". For other */
2186 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002187
2188 if (version == RIPv1)
2189 {
paul727d1042002-12-13 20:50:29 +00002190 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002191
2192 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002193 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002194 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002195
paul727d1042002-12-13 20:50:29 +00002196 if (subnetted &&
2197 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2198 {
paulc49ad8f2004-10-22 10:27:28 +00002199 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002200 (rp->p.prefixlen != 32))
2201 continue;
2202 }
2203 else
2204 {
2205 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2206 apply_classful_mask_ipv4(&classfull);
2207 if (rp->p.u.prefix4.s_addr != 0 &&
2208 classfull.prefixlen != rp->p.prefixlen)
2209 continue;
2210 }
paul718e3742002-12-13 20:15:29 +00002211 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002212 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002213 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002214 }
2215 else
2216 p = (struct prefix_ipv4 *) &rp->p;
2217
2218 /* Apply output filters. */
2219 ret = rip_outgoing_filter (p, ri);
2220 if (ret < 0)
2221 continue;
2222
2223 /* Changed route only output. */
2224 if (route_type == rip_changed_route &&
2225 (! (rinfo->flags & RIP_RTF_CHANGED)))
2226 continue;
2227
2228 /* Split horizon. */
2229 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002230 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002231 {
paul42d14d92003-11-17 09:15:18 +00002232 /*
2233 * We perform split horizon for RIP and connected route.
2234 * For rip routes, we want to suppress the route if we would
2235 * end up sending the route back on the interface that we
2236 * learned it from, with a higher metric. For connected routes,
2237 * we suppress the route if the prefix is a subset of the
2238 * source address that we are going to use for the packet
2239 * (in order to handle the case when multiple subnets are
2240 * configured on the same interface).
2241 */
2242 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002243 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002244 continue;
2245 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002246 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002247 continue;
2248 }
2249
2250 /* Preparation for route-map. */
2251 rinfo->metric_set = 0;
2252 rinfo->nexthop_out.s_addr = 0;
2253 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002254 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002255 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002256
hasso16705132003-05-25 14:49:19 +00002257 /* In order to avoid some local loops,
2258 * if the RIP route has a nexthop via this interface, keep the nexthop,
2259 * otherwise set it to 0. The nexthop should not be propagated
2260 * beyond the local broadcast/multicast area in order
2261 * to avoid an IGP multi-level recursive look-up.
2262 * see (4.4)
2263 */
paulc49ad8f2004-10-22 10:27:28 +00002264 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002265 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002266
2267 /* Interface route-map */
2268 if (ri->routemap[RIP_FILTER_OUT])
2269 {
2270 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2271 (struct prefix *) p, RMAP_RIP,
2272 rinfo);
2273
2274 if (ret == RMAP_DENYMATCH)
2275 {
2276 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002277 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002278 inet_ntoa (p->prefix), p->prefixlen);
2279 continue;
2280 }
2281 }
paul718e3742002-12-13 20:15:29 +00002282
hasso16705132003-05-25 14:49:19 +00002283 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002284 if (rip->route_map[rinfo->type].name
2285 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2286 {
2287 ret = route_map_apply (rip->route_map[rinfo->type].map,
2288 (struct prefix *)p, RMAP_RIP, rinfo);
2289
2290 if (ret == RMAP_DENYMATCH)
2291 {
2292 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002293 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002294 inet_ntoa (p->prefix), p->prefixlen);
2295 continue;
2296 }
2297 }
2298
2299 /* When route-map does not set metric. */
2300 if (! rinfo->metric_set)
2301 {
2302 /* If redistribute metric is set. */
2303 if (rip->route_map[rinfo->type].metric_config
2304 && rinfo->metric != RIP_METRIC_INFINITY)
2305 {
2306 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2307 }
2308 else
2309 {
2310 /* If the route is not connected or localy generated
2311 one, use default-metric value*/
2312 if (rinfo->type != ZEBRA_ROUTE_RIP
2313 && rinfo->type != ZEBRA_ROUTE_CONNECT
2314 && rinfo->metric != RIP_METRIC_INFINITY)
2315 rinfo->metric_out = rip->default_metric;
2316 }
2317 }
2318
2319 /* Apply offset-list */
2320 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002321 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002322
2323 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2324 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002325
2326 /* Perform split-horizon with poisoned reverse
2327 * for RIP and connected routes.
2328 **/
2329 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002330 /*
2331 * We perform split horizon for RIP and connected route.
2332 * For rip routes, we want to suppress the route if we would
2333 * end up sending the route back on the interface that we
2334 * learned it from, with a higher metric. For connected routes,
2335 * we suppress the route if the prefix is a subset of the
2336 * source address that we are going to use for the packet
2337 * (in order to handle the case when multiple subnets are
2338 * configured on the same interface).
2339 */
2340 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002341 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002342 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002343 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002344 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002345 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002346 }
2347
paul718e3742002-12-13 20:15:29 +00002348 /* Write RTE to the stream. */
paulc49ad8f2004-10-22 10:27:28 +00002349 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002350 if (num == rtemax)
2351 {
2352 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002353 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002354
2355 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002356 to, ifc);
paul718e3742002-12-13 20:15:29 +00002357
2358 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2359 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2360 stream_get_endp(s), "SEND");
2361 num = 0;
2362 stream_reset (s);
2363 }
2364 }
2365
2366 /* Flush unwritten RTE. */
2367 if (num != 0)
2368 {
2369 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002370 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002371
paulc49ad8f2004-10-22 10:27:28 +00002372 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002373
2374 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2375 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2376 stream_get_endp (s), "SEND");
2377 num = 0;
2378 stream_reset (s);
2379 }
2380
2381 /* Statistics updates. */
2382 ri->sent_updates++;
2383}
2384
2385/* Send RIP packet to the interface. */
2386void
paulc49ad8f2004-10-22 10:27:28 +00002387rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002388{
paul718e3742002-12-13 20:15:29 +00002389 struct sockaddr_in to;
2390
2391 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002392 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002393 {
2394 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002395 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002396
paulc49ad8f2004-10-22 10:27:28 +00002397 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002398 return;
2399 }
paulc49ad8f2004-10-22 10:27:28 +00002400
paul718e3742002-12-13 20:15:29 +00002401 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002402 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002403 {
paulc49ad8f2004-10-22 10:27:28 +00002404 if (ifc->address->family == AF_INET)
2405 {
2406 /* Destination address and port setting. */
2407 memset (&to, 0, sizeof (struct sockaddr_in));
2408 if (ifc->destination)
2409 /* use specified broadcast or point-to-point destination addr */
2410 to.sin_addr = ifc->destination->u.prefix4;
2411 else
2412 /* calculate the appropriate broadcast address */
2413 to.sin_addr.s_addr =
2414 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2415 ifc->address->prefixlen);
2416 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002417
paulc49ad8f2004-10-22 10:27:28 +00002418 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002419 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002420 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2421 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002422
paulc49ad8f2004-10-22 10:27:28 +00002423 rip_output_process (ifc, &to, route_type, version);
2424 }
paul718e3742002-12-13 20:15:29 +00002425 }
2426}
2427
2428/* Update send to all interface and neighbor. */
2429void
2430rip_update_process (int route_type)
2431{
hasso52dc7ee2004-09-23 19:18:23 +00002432 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002433 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002434 struct interface *ifp;
2435 struct rip_interface *ri;
2436 struct route_node *rp;
2437 struct sockaddr_in to;
2438 struct prefix_ipv4 *p;
2439
2440 /* Send RIP update to each interface. */
2441 for (node = listhead (iflist); node; nextnode (node))
2442 {
2443 ifp = getdata (node);
2444
2445 if (if_is_loopback (ifp))
2446 continue;
2447
paul2e3b2e42002-12-13 21:03:13 +00002448 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002449 continue;
2450
2451 /* Fetch RIP interface information. */
2452 ri = ifp->info;
2453
2454 /* When passive interface is specified, suppress announce to the
2455 interface. */
2456 if (ri->passive)
2457 continue;
2458
2459 if (ri->running)
2460 {
2461 if (IS_RIP_DEBUG_EVENT)
2462 {
2463 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002464 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002465 ifp->name, ifp->ifindex);
2466 else
ajs5d6c3772004-12-08 19:24:06 +00002467 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002468 ifp->ifindex);
2469 }
2470
paulcc1131a2003-10-15 23:20:17 +00002471 /* send update on each connected network */
2472
2473 LIST_LOOP(ifp->connected, connected, ifnode)
2474 {
2475 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002476 int done = 0;
2477 /*
2478 * If there is no version configuration in the interface,
2479 * use rip's version setting.
2480 */
paulf38a4712003-06-07 01:10:00 +00002481 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2482 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002483
2484 ifaddr = (struct prefix_ipv4 *) connected->address;
2485
2486 if (ifaddr->family != AF_INET)
2487 continue;
2488
paul931cd542004-01-23 15:31:42 +00002489 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002490 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002491 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002492 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002493 done = 1;
2494 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2495 break;
2496
paulf38a4712003-06-07 01:10:00 +00002497 }
paul718e3742002-12-13 20:15:29 +00002498 }
2499 }
2500
2501 /* RIP send updates to each neighbor. */
2502 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2503 if (rp->info != NULL)
2504 {
2505 p = (struct prefix_ipv4 *) &rp->p;
2506
2507 ifp = if_lookup_address (p->prefix);
2508 if (! ifp)
2509 {
paulc49ad8f2004-10-22 10:27:28 +00002510 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002511 inet_ntoa (p->prefix));
2512 continue;
2513 }
paulc49ad8f2004-10-22 10:27:28 +00002514
2515 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2516 {
2517 zlog_warn ("Neighbor %s doesnt have connected network",
2518 inet_ntoa (p->prefix));
2519 continue;
2520 }
2521
paul718e3742002-12-13 20:15:29 +00002522 /* Set destination address and port */
2523 memset (&to, 0, sizeof (struct sockaddr_in));
2524 to.sin_addr = p->prefix;
2525 to.sin_port = htons (RIP_PORT_DEFAULT);
2526
2527 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002528 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002529 }
2530}
2531
2532/* RIP's periodical timer. */
2533int
2534rip_update (struct thread *t)
2535{
2536 /* Clear timer pointer. */
2537 rip->t_update = NULL;
2538
2539 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002540 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002541
2542 /* Process update output. */
2543 rip_update_process (rip_all_route);
2544
2545 /* Triggered updates may be suppressed if a regular update is due by
2546 the time the triggered update would be sent. */
2547 if (rip->t_triggered_interval)
2548 {
2549 thread_cancel (rip->t_triggered_interval);
2550 rip->t_triggered_interval = NULL;
2551 }
2552 rip->trigger = 0;
2553
2554 /* Register myself. */
2555 rip_event (RIP_UPDATE_EVENT, 0);
2556
2557 return 0;
2558}
2559
2560/* Walk down the RIP routing table then clear changed flag. */
2561void
2562rip_clear_changed_flag ()
2563{
2564 struct route_node *rp;
2565 struct rip_info *rinfo;
2566
2567 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2568 if ((rinfo = rp->info) != NULL)
2569 if (rinfo->flags & RIP_RTF_CHANGED)
2570 rinfo->flags &= ~RIP_RTF_CHANGED;
2571}
2572
2573/* Triggered update interval timer. */
2574int
2575rip_triggered_interval (struct thread *t)
2576{
2577 int rip_triggered_update (struct thread *);
2578
2579 rip->t_triggered_interval = NULL;
2580
2581 if (rip->trigger)
2582 {
2583 rip->trigger = 0;
2584 rip_triggered_update (t);
2585 }
2586 return 0;
2587}
2588
2589/* Execute triggered update. */
2590int
2591rip_triggered_update (struct thread *t)
2592{
2593 int interval;
2594
2595 /* Clear thred pointer. */
2596 rip->t_triggered_update = NULL;
2597
2598 /* Cancel interval timer. */
2599 if (rip->t_triggered_interval)
2600 {
2601 thread_cancel (rip->t_triggered_interval);
2602 rip->t_triggered_interval = NULL;
2603 }
2604 rip->trigger = 0;
2605
2606 /* Logging triggered update. */
2607 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002608 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002609
2610 /* Split Horizon processing is done when generating triggered
2611 updates as well as normal updates (see section 2.6). */
2612 rip_update_process (rip_changed_route);
2613
2614 /* Once all of the triggered updates have been generated, the route
2615 change flags should be cleared. */
2616 rip_clear_changed_flag ();
2617
2618 /* After a triggered update is sent, a timer should be set for a
2619 random interval between 1 and 5 seconds. If other changes that
2620 would trigger updates occur before the timer expires, a single
2621 update is triggered when the timer expires. */
2622 interval = (random () % 5) + 1;
2623
2624 rip->t_triggered_interval =
2625 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2626
2627 return 0;
2628}
2629
2630/* Withdraw redistributed route. */
2631void
2632rip_redistribute_withdraw (int type)
2633{
2634 struct route_node *rp;
2635 struct rip_info *rinfo;
2636
2637 if (!rip)
2638 return;
2639
2640 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2641 if ((rinfo = rp->info) != NULL)
2642 {
2643 if (rinfo->type == type
2644 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2645 {
2646 /* Perform poisoned reverse. */
2647 rinfo->metric = RIP_METRIC_INFINITY;
2648 RIP_TIMER_ON (rinfo->t_garbage_collect,
2649 rip_garbage_collect, rip->garbage_time);
2650 RIP_TIMER_OFF (rinfo->t_timeout);
2651 rinfo->flags |= RIP_RTF_CHANGED;
2652
hasso16705132003-05-25 14:49:19 +00002653 if (IS_RIP_DEBUG_EVENT) {
2654 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2655
ajs5d6c3772004-12-08 19:24:06 +00002656 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002657 inet_ntoa(p->prefix), p->prefixlen,
2658 ifindex2ifname(rinfo->ifindex));
2659 }
2660
paul718e3742002-12-13 20:15:29 +00002661 rip_event (RIP_TRIGGERED_UPDATE, 0);
2662 }
2663 }
2664}
2665
2666/* Create new RIP instance and set it to global variable. */
2667int
2668rip_create ()
2669{
2670 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2671 memset (rip, 0, sizeof (struct rip));
2672
2673 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002674 rip->version_send = RI_RIP_VERSION_2;
2675 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002676 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2677 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2678 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2679 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2680
2681 /* Initialize RIP routig table. */
2682 rip->table = route_table_init ();
2683 rip->route = route_table_init ();
2684 rip->neighbor = route_table_init ();
2685
2686 /* Make output stream. */
2687 rip->obuf = stream_new (1500);
2688
2689 /* Make socket. */
2690 rip->sock = rip_create_socket ();
2691 if (rip->sock < 0)
2692 return rip->sock;
2693
2694 /* Create read and timer thread. */
2695 rip_event (RIP_READ, rip->sock);
2696 rip_event (RIP_UPDATE_EVENT, 1);
2697
2698 return 0;
2699}
2700
2701/* Sned RIP request to the destination. */
2702int
2703rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002704 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002705{
2706 struct rte *rte;
2707 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002708 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002709
2710 memset (&rip_packet, 0, sizeof (rip_packet));
2711
2712 rip_packet.command = RIP_REQUEST;
2713 rip_packet.version = version;
2714 rte = rip_packet.rte;
2715 rte->metric = htonl (RIP_METRIC_INFINITY);
2716
paul931cd542004-01-23 15:31:42 +00002717 if (connected)
2718 {
2719 /*
2720 * connected is only sent for ripv1 case, or when
2721 * interface does not support multicast. Caller loops
2722 * over each connected address for this case.
2723 */
paul11dde9c2004-05-31 14:00:00 +00002724 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002725 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002726 return -1;
2727 else
2728 return sizeof (rip_packet);
2729 }
2730
paulcc1131a2003-10-15 23:20:17 +00002731 /* send request on each connected network */
2732 LIST_LOOP(ifp->connected, connected, node)
2733 {
2734 struct prefix_ipv4 *p;
2735
2736 p = (struct prefix_ipv4 *) connected->address;
2737
2738 if (p->family != AF_INET)
2739 continue;
2740
paul11dde9c2004-05-31 14:00:00 +00002741 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002742 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002743 return -1;
2744 }
2745 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002746}
2747
2748int
2749rip_update_jitter (unsigned long time)
2750{
paul239389b2004-05-05 14:09:37 +00002751#define JITTER_BOUND 4
2752 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2753 Given that, we cannot let time be less than JITTER_BOUND seconds.
2754 The RIPv2 RFC says jitter should be small compared to
2755 update_time. We consider 1/JITTER_BOUND to be small.
2756 */
2757
2758 int jitter_input = time;
2759 int jitter;
2760
2761 if (jitter_input < JITTER_BOUND)
2762 jitter_input = JITTER_BOUND;
2763
2764 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2765
2766 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002767}
2768
2769void
2770rip_event (enum rip_event event, int sock)
2771{
2772 int jitter = 0;
2773
2774 switch (event)
2775 {
2776 case RIP_READ:
2777 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2778 break;
2779 case RIP_UPDATE_EVENT:
2780 if (rip->t_update)
2781 {
2782 thread_cancel (rip->t_update);
2783 rip->t_update = NULL;
2784 }
2785 jitter = rip_update_jitter (rip->update_time);
2786 rip->t_update =
2787 thread_add_timer (master, rip_update, NULL,
2788 sock ? 2 : rip->update_time + jitter);
2789 break;
2790 case RIP_TRIGGERED_UPDATE:
2791 if (rip->t_triggered_interval)
2792 rip->trigger = 1;
2793 else if (! rip->t_triggered_update)
2794 rip->t_triggered_update =
2795 thread_add_event (master, rip_triggered_update, NULL, 0);
2796 break;
2797 default:
2798 break;
2799 }
2800}
2801
2802DEFUN (router_rip,
2803 router_rip_cmd,
2804 "router rip",
2805 "Enable a routing process\n"
2806 "Routing Information Protocol (RIP)\n")
2807{
2808 int ret;
2809
2810 /* If rip is not enabled before. */
2811 if (! rip)
2812 {
2813 ret = rip_create ();
2814 if (ret < 0)
2815 {
2816 zlog_info ("Can't create RIP");
2817 return CMD_WARNING;
2818 }
2819 }
2820 vty->node = RIP_NODE;
2821 vty->index = rip;
2822
2823 return CMD_SUCCESS;
2824}
2825
2826DEFUN (no_router_rip,
2827 no_router_rip_cmd,
2828 "no router rip",
2829 NO_STR
2830 "Enable a routing process\n"
2831 "Routing Information Protocol (RIP)\n")
2832{
2833 if (rip)
2834 rip_clean ();
2835 return CMD_SUCCESS;
2836}
2837
2838DEFUN (rip_version,
2839 rip_version_cmd,
2840 "version <1-2>",
2841 "Set routing protocol version\n"
2842 "version\n")
2843{
2844 int version;
2845
2846 version = atoi (argv[0]);
2847 if (version != RIPv1 && version != RIPv2)
2848 {
2849 vty_out (vty, "invalid rip version %d%s", version,
2850 VTY_NEWLINE);
2851 return CMD_WARNING;
2852 }
paulf38a4712003-06-07 01:10:00 +00002853 rip->version_send = version;
2854 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002855
2856 return CMD_SUCCESS;
2857}
2858
2859DEFUN (no_rip_version,
2860 no_rip_version_cmd,
2861 "no version",
2862 NO_STR
2863 "Set routing protocol version\n")
2864{
2865 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002866 rip->version_send = RI_RIP_VERSION_2;
2867 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002868
2869 return CMD_SUCCESS;
2870}
2871
2872ALIAS (no_rip_version,
2873 no_rip_version_val_cmd,
2874 "no version <1-2>",
2875 NO_STR
2876 "Set routing protocol version\n"
2877 "version\n")
2878
2879DEFUN (rip_route,
2880 rip_route_cmd,
2881 "route A.B.C.D/M",
2882 "RIP static route configuration\n"
2883 "IP prefix <network>/<length>\n")
2884{
2885 int ret;
2886 struct prefix_ipv4 p;
2887 struct route_node *node;
2888
2889 ret = str2prefix_ipv4 (argv[0], &p);
2890 if (ret < 0)
2891 {
2892 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2893 return CMD_WARNING;
2894 }
2895 apply_mask_ipv4 (&p);
2896
2897 /* For router rip configuration. */
2898 node = route_node_get (rip->route, (struct prefix *) &p);
2899
2900 if (node->info)
2901 {
2902 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2903 route_unlock_node (node);
2904 return CMD_WARNING;
2905 }
2906
hasso8a676be2004-10-08 06:36:38 +00002907 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002908
2909 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2910
2911 return CMD_SUCCESS;
2912}
2913
2914DEFUN (no_rip_route,
2915 no_rip_route_cmd,
2916 "no route A.B.C.D/M",
2917 NO_STR
2918 "RIP static route configuration\n"
2919 "IP prefix <network>/<length>\n")
2920{
2921 int ret;
2922 struct prefix_ipv4 p;
2923 struct route_node *node;
2924
2925 ret = str2prefix_ipv4 (argv[0], &p);
2926 if (ret < 0)
2927 {
2928 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2929 return CMD_WARNING;
2930 }
2931 apply_mask_ipv4 (&p);
2932
2933 /* For router rip configuration. */
2934 node = route_node_lookup (rip->route, (struct prefix *) &p);
2935 if (! node)
2936 {
2937 vty_out (vty, "Can't find route %s.%s", argv[0],
2938 VTY_NEWLINE);
2939 return CMD_WARNING;
2940 }
2941
2942 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2943 route_unlock_node (node);
2944
2945 node->info = NULL;
2946 route_unlock_node (node);
2947
2948 return CMD_SUCCESS;
2949}
2950
2951void
2952rip_update_default_metric ()
2953{
2954 struct route_node *np;
2955 struct rip_info *rinfo;
2956
2957 for (np = route_top (rip->table); np; np = route_next (np))
2958 if ((rinfo = np->info) != NULL)
2959 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2960 rinfo->metric = rip->default_metric;
2961}
2962
2963DEFUN (rip_default_metric,
2964 rip_default_metric_cmd,
2965 "default-metric <1-16>",
2966 "Set a metric of redistribute routes\n"
2967 "Default metric\n")
2968{
2969 if (rip)
2970 {
2971 rip->default_metric = atoi (argv[0]);
2972 /* rip_update_default_metric (); */
2973 }
2974 return CMD_SUCCESS;
2975}
2976
2977DEFUN (no_rip_default_metric,
2978 no_rip_default_metric_cmd,
2979 "no default-metric",
2980 NO_STR
2981 "Set a metric of redistribute routes\n"
2982 "Default metric\n")
2983{
2984 if (rip)
2985 {
2986 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2987 /* rip_update_default_metric (); */
2988 }
2989 return CMD_SUCCESS;
2990}
2991
2992ALIAS (no_rip_default_metric,
2993 no_rip_default_metric_val_cmd,
2994 "no default-metric <1-16>",
2995 NO_STR
2996 "Set a metric of redistribute routes\n"
2997 "Default metric\n")
2998
2999DEFUN (rip_timers,
3000 rip_timers_cmd,
3001 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3002 "Adjust routing timers\n"
3003 "Basic routing protocol update timers\n"
3004 "Routing table update timer value in second. Default is 30.\n"
3005 "Routing information timeout timer. Default is 180.\n"
3006 "Garbage collection timer. Default is 120.\n")
3007{
3008 unsigned long update;
3009 unsigned long timeout;
3010 unsigned long garbage;
3011 char *endptr = NULL;
3012 unsigned long RIP_TIMER_MAX = 2147483647;
3013 unsigned long RIP_TIMER_MIN = 5;
3014
3015 update = strtoul (argv[0], &endptr, 10);
3016 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3017 {
3018 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3019 return CMD_WARNING;
3020 }
3021
3022 timeout = strtoul (argv[1], &endptr, 10);
3023 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3024 {
3025 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3026 return CMD_WARNING;
3027 }
3028
3029 garbage = strtoul (argv[2], &endptr, 10);
3030 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3031 {
3032 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3033 return CMD_WARNING;
3034 }
3035
3036 /* Set each timer value. */
3037 rip->update_time = update;
3038 rip->timeout_time = timeout;
3039 rip->garbage_time = garbage;
3040
3041 /* Reset update timer thread. */
3042 rip_event (RIP_UPDATE_EVENT, 0);
3043
3044 return CMD_SUCCESS;
3045}
3046
3047DEFUN (no_rip_timers,
3048 no_rip_timers_cmd,
3049 "no timers basic",
3050 NO_STR
3051 "Adjust routing timers\n"
3052 "Basic routing protocol update timers\n")
3053{
3054 /* Set each timer value to the default. */
3055 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3056 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3057 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3058
3059 /* Reset update timer thread. */
3060 rip_event (RIP_UPDATE_EVENT, 0);
3061
3062 return CMD_SUCCESS;
3063}
hasso16705132003-05-25 14:49:19 +00003064
3065ALIAS (no_rip_timers,
3066 no_rip_timers_val_cmd,
3067 "no timers basic <0-65535> <0-65535> <0-65535>",
3068 NO_STR
3069 "Adjust routing timers\n"
3070 "Basic routing protocol update timers\n"
3071 "Routing table update timer value in second. Default is 30.\n"
3072 "Routing information timeout timer. Default is 180.\n"
3073 "Garbage collection timer. Default is 120.\n")
3074
paul718e3742002-12-13 20:15:29 +00003075
3076struct route_table *rip_distance_table;
3077
3078struct rip_distance
3079{
3080 /* Distance value for the IP source prefix. */
3081 u_char distance;
3082
3083 /* Name of the access-list to be matched. */
3084 char *access_list;
3085};
3086
3087struct rip_distance *
3088rip_distance_new ()
3089{
3090 struct rip_distance *new;
3091 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3092 memset (new, 0, sizeof (struct rip_distance));
3093 return new;
3094}
3095
3096void
3097rip_distance_free (struct rip_distance *rdistance)
3098{
3099 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3100}
3101
3102int
hasso98b718a2004-10-11 12:57:57 +00003103rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3104 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003105{
3106 int ret;
3107 struct prefix_ipv4 p;
3108 u_char distance;
3109 struct route_node *rn;
3110 struct rip_distance *rdistance;
3111
3112 ret = str2prefix_ipv4 (ip_str, &p);
3113 if (ret == 0)
3114 {
3115 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3116 return CMD_WARNING;
3117 }
3118
3119 distance = atoi (distance_str);
3120
3121 /* Get RIP distance node. */
3122 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3123 if (rn->info)
3124 {
3125 rdistance = rn->info;
3126 route_unlock_node (rn);
3127 }
3128 else
3129 {
3130 rdistance = rip_distance_new ();
3131 rn->info = rdistance;
3132 }
3133
3134 /* Set distance value. */
3135 rdistance->distance = distance;
3136
3137 /* Reset access-list configuration. */
3138 if (rdistance->access_list)
3139 {
3140 free (rdistance->access_list);
3141 rdistance->access_list = NULL;
3142 }
3143 if (access_list_str)
3144 rdistance->access_list = strdup (access_list_str);
3145
3146 return CMD_SUCCESS;
3147}
3148
3149int
hasso98b718a2004-10-11 12:57:57 +00003150rip_distance_unset (struct vty *vty, const char *distance_str,
3151 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003152{
3153 int ret;
3154 struct prefix_ipv4 p;
3155 u_char distance;
3156 struct route_node *rn;
3157 struct rip_distance *rdistance;
3158
3159 ret = str2prefix_ipv4 (ip_str, &p);
3160 if (ret == 0)
3161 {
3162 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3163 return CMD_WARNING;
3164 }
3165
3166 distance = atoi (distance_str);
3167
3168 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3169 if (! rn)
3170 {
3171 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3172 return CMD_WARNING;
3173 }
3174
3175 rdistance = rn->info;
3176
3177 if (rdistance->access_list)
3178 free (rdistance->access_list);
3179 rip_distance_free (rdistance);
3180
3181 rn->info = NULL;
3182 route_unlock_node (rn);
3183 route_unlock_node (rn);
3184
3185 return CMD_SUCCESS;
3186}
3187
3188void
3189rip_distance_reset ()
3190{
3191 struct route_node *rn;
3192 struct rip_distance *rdistance;
3193
3194 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3195 if ((rdistance = rn->info) != NULL)
3196 {
3197 if (rdistance->access_list)
3198 free (rdistance->access_list);
3199 rip_distance_free (rdistance);
3200 rn->info = NULL;
3201 route_unlock_node (rn);
3202 }
3203}
3204
3205/* Apply RIP information to distance method. */
3206u_char
3207rip_distance_apply (struct rip_info *rinfo)
3208{
3209 struct route_node *rn;
3210 struct prefix_ipv4 p;
3211 struct rip_distance *rdistance;
3212 struct access_list *alist;
3213
3214 if (! rip)
3215 return 0;
3216
3217 memset (&p, 0, sizeof (struct prefix_ipv4));
3218 p.family = AF_INET;
3219 p.prefix = rinfo->from;
3220 p.prefixlen = IPV4_MAX_BITLEN;
3221
3222 /* Check source address. */
3223 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3224 if (rn)
3225 {
3226 rdistance = rn->info;
3227 route_unlock_node (rn);
3228
3229 if (rdistance->access_list)
3230 {
3231 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3232 if (alist == NULL)
3233 return 0;
3234 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3235 return 0;
3236
3237 return rdistance->distance;
3238 }
3239 else
3240 return rdistance->distance;
3241 }
3242
3243 if (rip->distance)
3244 return rip->distance;
3245
3246 return 0;
3247}
3248
3249void
3250rip_distance_show (struct vty *vty)
3251{
3252 struct route_node *rn;
3253 struct rip_distance *rdistance;
3254 int header = 1;
3255 char buf[BUFSIZ];
3256
3257 vty_out (vty, " Distance: (default is %d)%s",
3258 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3259 VTY_NEWLINE);
3260
3261 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3262 if ((rdistance = rn->info) != NULL)
3263 {
3264 if (header)
3265 {
3266 vty_out (vty, " Address Distance List%s",
3267 VTY_NEWLINE);
3268 header = 0;
3269 }
3270 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3271 vty_out (vty, " %-20s %4d %s%s",
3272 buf, rdistance->distance,
3273 rdistance->access_list ? rdistance->access_list : "",
3274 VTY_NEWLINE);
3275 }
3276}
3277
3278DEFUN (rip_distance,
3279 rip_distance_cmd,
3280 "distance <1-255>",
3281 "Administrative distance\n"
3282 "Distance value\n")
3283{
3284 rip->distance = atoi (argv[0]);
3285 return CMD_SUCCESS;
3286}
3287
3288DEFUN (no_rip_distance,
3289 no_rip_distance_cmd,
3290 "no distance <1-255>",
3291 NO_STR
3292 "Administrative distance\n"
3293 "Distance value\n")
3294{
3295 rip->distance = 0;
3296 return CMD_SUCCESS;
3297}
3298
3299DEFUN (rip_distance_source,
3300 rip_distance_source_cmd,
3301 "distance <1-255> A.B.C.D/M",
3302 "Administrative distance\n"
3303 "Distance value\n"
3304 "IP source prefix\n")
3305{
3306 rip_distance_set (vty, argv[0], argv[1], NULL);
3307 return CMD_SUCCESS;
3308}
3309
3310DEFUN (no_rip_distance_source,
3311 no_rip_distance_source_cmd,
3312 "no distance <1-255> A.B.C.D/M",
3313 NO_STR
3314 "Administrative distance\n"
3315 "Distance value\n"
3316 "IP source prefix\n")
3317{
3318 rip_distance_unset (vty, argv[0], argv[1], NULL);
3319 return CMD_SUCCESS;
3320}
3321
3322DEFUN (rip_distance_source_access_list,
3323 rip_distance_source_access_list_cmd,
3324 "distance <1-255> A.B.C.D/M WORD",
3325 "Administrative distance\n"
3326 "Distance value\n"
3327 "IP source prefix\n"
3328 "Access list name\n")
3329{
3330 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3331 return CMD_SUCCESS;
3332}
3333
3334DEFUN (no_rip_distance_source_access_list,
3335 no_rip_distance_source_access_list_cmd,
3336 "no distance <1-255> A.B.C.D/M WORD",
3337 NO_STR
3338 "Administrative distance\n"
3339 "Distance value\n"
3340 "IP source prefix\n"
3341 "Access list name\n")
3342{
3343 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3344 return CMD_SUCCESS;
3345}
3346
3347/* Print out routes update time. */
3348void
3349rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3350{
3351 struct timeval timer_now;
3352 time_t clock;
3353 struct tm *tm;
3354#define TIME_BUF 25
3355 char timebuf [TIME_BUF];
3356 struct thread *thread;
3357
3358 gettimeofday (&timer_now, NULL);
3359
3360 if ((thread = rinfo->t_timeout) != NULL)
3361 {
3362 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3363 tm = gmtime (&clock);
3364 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3365 vty_out (vty, "%5s", timebuf);
3366 }
3367 else if ((thread = rinfo->t_garbage_collect) != NULL)
3368 {
3369 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3370 tm = gmtime (&clock);
3371 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3372 vty_out (vty, "%5s", timebuf);
3373 }
3374}
3375
hasso8a676be2004-10-08 06:36:38 +00003376const char *
paul718e3742002-12-13 20:15:29 +00003377rip_route_type_print (int sub_type)
3378{
3379 switch (sub_type)
3380 {
3381 case RIP_ROUTE_RTE:
3382 return "n";
3383 case RIP_ROUTE_STATIC:
3384 return "s";
3385 case RIP_ROUTE_DEFAULT:
3386 return "d";
3387 case RIP_ROUTE_REDISTRIBUTE:
3388 return "r";
3389 case RIP_ROUTE_INTERFACE:
3390 return "i";
3391 default:
3392 return "?";
3393 }
3394}
3395
3396DEFUN (show_ip_rip,
3397 show_ip_rip_cmd,
3398 "show ip rip",
3399 SHOW_STR
3400 IP_STR
3401 "Show RIP routes\n")
3402{
3403 struct route_node *np;
3404 struct rip_info *rinfo;
3405
3406 if (! rip)
3407 return CMD_SUCCESS;
3408
hasso16705132003-05-25 14:49:19 +00003409 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3410 "Sub-codes:%s"
3411 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003412 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003413 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003414 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003415
3416 for (np = route_top (rip->table); np; np = route_next (np))
3417 if ((rinfo = np->info) != NULL)
3418 {
3419 int len;
3420
3421 len = vty_out (vty, "%s(%s) %s/%d",
3422 /* np->lock, For debugging. */
3423 route_info[rinfo->type].str,
3424 rip_route_type_print (rinfo->sub_type),
3425 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3426
hassoa1455d82004-03-03 19:36:24 +00003427 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003428
3429 if (len > 0)
3430 vty_out (vty, "%*s", len, " ");
3431
3432 if (rinfo->nexthop.s_addr)
3433 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3434 rinfo->metric);
3435 else
3436 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3437
3438 /* Route which exist in kernel routing table. */
3439 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3440 (rinfo->sub_type == RIP_ROUTE_RTE))
3441 {
3442 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003443 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003444 rip_vty_out_uptime (vty, rinfo);
3445 }
3446 else if (rinfo->metric == RIP_METRIC_INFINITY)
3447 {
3448 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003449 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003450 rip_vty_out_uptime (vty, rinfo);
3451 }
3452 else
hasso16705132003-05-25 14:49:19 +00003453 {
3454 vty_out (vty, "self ");
3455 vty_out (vty, "%3d", rinfo->tag);
3456 }
paul718e3742002-12-13 20:15:29 +00003457
3458 vty_out (vty, "%s", VTY_NEWLINE);
3459 }
3460 return CMD_SUCCESS;
3461}
3462
3463/* Return next event time. */
3464int
3465rip_next_thread_timer (struct thread *thread)
3466{
3467 struct timeval timer_now;
3468
3469 gettimeofday (&timer_now, NULL);
3470
3471 return thread->u.sands.tv_sec - timer_now.tv_sec;
3472}
3473
hasso16705132003-05-25 14:49:19 +00003474/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3475DEFUN (show_ip_rip_status,
3476 show_ip_rip_status_cmd,
3477 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003478 SHOW_STR
3479 IP_STR
hasso16705132003-05-25 14:49:19 +00003480 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003481 "IP routing protocol process parameters and statistics\n")
3482{
hasso52dc7ee2004-09-23 19:18:23 +00003483 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003484 struct interface *ifp;
3485 struct rip_interface *ri;
3486 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003487 const char *send_version;
3488 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003489
3490 if (! rip)
3491 return CMD_SUCCESS;
3492
3493 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3494 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3495 rip->update_time);
3496 vty_out (vty, " next due in %d seconds%s",
3497 rip_next_thread_timer (rip->t_update),
3498 VTY_NEWLINE);
3499 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3500 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3501 VTY_NEWLINE);
3502
3503 /* Filtering status show. */
3504 config_show_distribute (vty);
3505
3506 /* Default metric information. */
3507 vty_out (vty, " Default redistribution metric is %d%s",
3508 rip->default_metric, VTY_NEWLINE);
3509
3510 /* Redistribute information. */
3511 vty_out (vty, " Redistributing:");
3512 config_write_rip_redistribute (vty, 0);
3513 vty_out (vty, "%s", VTY_NEWLINE);
3514
paulf38a4712003-06-07 01:10:00 +00003515 vty_out (vty, " Default version control: send version %s,",
3516 lookup(ri_version_msg,rip->version_send));
3517 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3518 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3519 else
3520 vty_out (vty, " receive version %s %s",
3521 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003522
3523 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3524
3525 for (node = listhead (iflist); node; node = nextnode (node))
3526 {
3527 ifp = getdata (node);
3528 ri = ifp->info;
3529
3530 if (ri->enable_network || ri->enable_interface)
3531 {
3532 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003533 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003534 else
3535 send_version = lookup (ri_version_msg, ri->ri_send);
3536
3537 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003538 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003539 else
3540 receive_version = lookup (ri_version_msg, ri->ri_receive);
3541
3542 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3543 send_version,
3544 receive_version,
3545 ri->key_chain ? ri->key_chain : "",
3546 VTY_NEWLINE);
3547 }
3548 }
3549
3550 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3551 config_write_rip_network (vty, 0);
3552
paul4aaff3f2003-06-07 01:04:45 +00003553 {
3554 int found_passive = 0;
3555 for (node = listhead (iflist); node; node = nextnode (node))
3556 {
3557 ifp = getdata (node);
3558 ri = ifp->info;
3559
3560 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3561 {
3562 if (!found_passive)
3563 {
3564 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3565 found_passive = 1;
3566 }
3567 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3568 }
3569 }
3570 }
3571
paul718e3742002-12-13 20:15:29 +00003572 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3573 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3574 rip_peer_display (vty);
3575
3576 rip_distance_show (vty);
3577
3578 return CMD_SUCCESS;
3579}
3580
3581/* RIP configuration write function. */
3582int
3583config_write_rip (struct vty *vty)
3584{
3585 int write = 0;
3586 struct route_node *rn;
3587 struct rip_distance *rdistance;
3588
3589 if (rip)
3590 {
3591 /* Router RIP statement. */
3592 vty_out (vty, "router rip%s", VTY_NEWLINE);
3593 write++;
3594
3595 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003596 if (rip->version_send != RI_RIP_VERSION_2
3597 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3598 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003599 VTY_NEWLINE);
3600
3601 /* RIP timer configuration. */
3602 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3603 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3604 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3605 vty_out (vty, " timers basic %lu %lu %lu%s",
3606 rip->update_time,
3607 rip->timeout_time,
3608 rip->garbage_time,
3609 VTY_NEWLINE);
3610
3611 /* Default information configuration. */
3612 if (rip->default_information)
3613 {
3614 if (rip->default_information_route_map)
3615 vty_out (vty, " default-information originate route-map %s%s",
3616 rip->default_information_route_map, VTY_NEWLINE);
3617 else
3618 vty_out (vty, " default-information originate%s",
3619 VTY_NEWLINE);
3620 }
3621
3622 /* Redistribute configuration. */
3623 config_write_rip_redistribute (vty, 1);
3624
3625 /* RIP offset-list configuration. */
3626 config_write_rip_offset_list (vty);
3627
3628 /* RIP enabled network and interface configuration. */
3629 config_write_rip_network (vty, 1);
3630
3631 /* RIP default metric configuration */
3632 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3633 vty_out (vty, " default-metric %d%s",
3634 rip->default_metric, VTY_NEWLINE);
3635
3636 /* Distribute configuration. */
3637 write += config_write_distribute (vty);
3638
hasso16705132003-05-25 14:49:19 +00003639 /* Interface routemap configuration */
3640 write += config_write_if_rmap (vty);
3641
paul718e3742002-12-13 20:15:29 +00003642 /* Distance configuration. */
3643 if (rip->distance)
3644 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3645
3646 /* RIP source IP prefix distance configuration. */
3647 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3648 if ((rdistance = rn->info) != NULL)
3649 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3650 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3651 rdistance->access_list ? rdistance->access_list : "",
3652 VTY_NEWLINE);
3653
3654 /* RIP static route configuration. */
3655 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3656 if (rn->info)
3657 vty_out (vty, " route %s/%d%s",
3658 inet_ntoa (rn->p.u.prefix4),
3659 rn->p.prefixlen,
3660 VTY_NEWLINE);
3661
3662 }
3663 return write;
3664}
3665
3666/* RIP node structure. */
3667struct cmd_node rip_node =
3668{
3669 RIP_NODE,
3670 "%s(config-router)# ",
3671 1
3672};
3673
3674/* Distribute-list update functions. */
3675void
3676rip_distribute_update (struct distribute *dist)
3677{
3678 struct interface *ifp;
3679 struct rip_interface *ri;
3680 struct access_list *alist;
3681 struct prefix_list *plist;
3682
3683 if (! dist->ifname)
3684 return;
3685
3686 ifp = if_lookup_by_name (dist->ifname);
3687 if (ifp == NULL)
3688 return;
3689
3690 ri = ifp->info;
3691
3692 if (dist->list[DISTRIBUTE_IN])
3693 {
3694 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3695 if (alist)
3696 ri->list[RIP_FILTER_IN] = alist;
3697 else
3698 ri->list[RIP_FILTER_IN] = NULL;
3699 }
3700 else
3701 ri->list[RIP_FILTER_IN] = NULL;
3702
3703 if (dist->list[DISTRIBUTE_OUT])
3704 {
3705 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3706 if (alist)
3707 ri->list[RIP_FILTER_OUT] = alist;
3708 else
3709 ri->list[RIP_FILTER_OUT] = NULL;
3710 }
3711 else
3712 ri->list[RIP_FILTER_OUT] = NULL;
3713
3714 if (dist->prefix[DISTRIBUTE_IN])
3715 {
3716 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3717 if (plist)
3718 ri->prefix[RIP_FILTER_IN] = plist;
3719 else
3720 ri->prefix[RIP_FILTER_IN] = NULL;
3721 }
3722 else
3723 ri->prefix[RIP_FILTER_IN] = NULL;
3724
3725 if (dist->prefix[DISTRIBUTE_OUT])
3726 {
3727 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3728 if (plist)
3729 ri->prefix[RIP_FILTER_OUT] = plist;
3730 else
3731 ri->prefix[RIP_FILTER_OUT] = NULL;
3732 }
3733 else
3734 ri->prefix[RIP_FILTER_OUT] = NULL;
3735}
3736
3737void
3738rip_distribute_update_interface (struct interface *ifp)
3739{
3740 struct distribute *dist;
3741
3742 dist = distribute_lookup (ifp->name);
3743 if (dist)
3744 rip_distribute_update (dist);
3745}
3746
3747/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003748/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003749void
paul02ff83c2004-06-11 11:27:03 +00003750rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003751{
3752 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003753 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003754
3755 for (node = listhead (iflist); node; nextnode (node))
3756 {
3757 ifp = getdata (node);
3758 rip_distribute_update_interface (ifp);
3759 }
3760}
paul11dde9c2004-05-31 14:00:00 +00003761/* ARGSUSED */
3762void
3763rip_distribute_update_all_wrapper(struct access_list *notused)
3764{
paul02ff83c2004-06-11 11:27:03 +00003765 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003766}
paul718e3742002-12-13 20:15:29 +00003767
3768/* Delete all added rip route. */
3769void
3770rip_clean ()
3771{
3772 int i;
3773 struct route_node *rp;
3774 struct rip_info *rinfo;
3775
3776 if (rip)
3777 {
3778 /* Clear RIP routes */
3779 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3780 if ((rinfo = rp->info) != NULL)
3781 {
3782 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3783 rinfo->sub_type == RIP_ROUTE_RTE)
3784 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3785 &rinfo->nexthop, rinfo->metric);
3786
3787 RIP_TIMER_OFF (rinfo->t_timeout);
3788 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3789
3790 rp->info = NULL;
3791 route_unlock_node (rp);
3792
3793 rip_info_free (rinfo);
3794 }
3795
3796 /* Cancel RIP related timers. */
3797 RIP_TIMER_OFF (rip->t_update);
3798 RIP_TIMER_OFF (rip->t_triggered_update);
3799 RIP_TIMER_OFF (rip->t_triggered_interval);
3800
3801 /* Cancel read thread. */
3802 if (rip->t_read)
3803 {
3804 thread_cancel (rip->t_read);
3805 rip->t_read = NULL;
3806 }
3807
3808 /* Close RIP socket. */
3809 if (rip->sock >= 0)
3810 {
3811 close (rip->sock);
3812 rip->sock = -1;
3813 }
3814
3815 /* Static RIP route configuration. */
3816 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3817 if (rp->info)
3818 {
3819 rp->info = NULL;
3820 route_unlock_node (rp);
3821 }
3822
3823 /* RIP neighbor configuration. */
3824 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3825 if (rp->info)
3826 {
3827 rp->info = NULL;
3828 route_unlock_node (rp);
3829 }
3830
3831 /* Redistribute related clear. */
3832 if (rip->default_information_route_map)
3833 free (rip->default_information_route_map);
3834
3835 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3836 if (rip->route_map[i].name)
3837 free (rip->route_map[i].name);
3838
3839 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3840 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3841 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3842
3843 XFREE (MTYPE_RIP, rip);
3844 rip = NULL;
3845 }
3846
3847 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003848 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003849 rip_offset_clean ();
3850 rip_interface_clean ();
3851 rip_distance_reset ();
3852 rip_redistribute_clean ();
3853}
3854
3855/* Reset all values to the default settings. */
3856void
3857rip_reset ()
3858{
3859 /* Reset global counters. */
3860 rip_global_route_changes = 0;
3861 rip_global_queries = 0;
3862
3863 /* Call ripd related reset functions. */
3864 rip_debug_reset ();
3865 rip_route_map_reset ();
3866
3867 /* Call library reset functions. */
3868 vty_reset ();
3869 access_list_reset ();
3870 prefix_list_reset ();
3871
3872 distribute_list_reset ();
3873
3874 rip_interface_reset ();
3875 rip_distance_reset ();
3876
3877 rip_zclient_reset ();
3878}
3879
hasso16705132003-05-25 14:49:19 +00003880void
3881rip_if_rmap_update (struct if_rmap *if_rmap)
3882{
3883 struct interface *ifp;
3884 struct rip_interface *ri;
3885 struct route_map *rmap;
3886
3887 ifp = if_lookup_by_name (if_rmap->ifname);
3888 if (ifp == NULL)
3889 return;
3890
3891 ri = ifp->info;
3892
3893 if (if_rmap->routemap[IF_RMAP_IN])
3894 {
3895 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3896 if (rmap)
3897 ri->routemap[IF_RMAP_IN] = rmap;
3898 else
3899 ri->routemap[IF_RMAP_IN] = NULL;
3900 }
3901 else
3902 ri->routemap[RIP_FILTER_IN] = NULL;
3903
3904 if (if_rmap->routemap[IF_RMAP_OUT])
3905 {
3906 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3907 if (rmap)
3908 ri->routemap[IF_RMAP_OUT] = rmap;
3909 else
3910 ri->routemap[IF_RMAP_OUT] = NULL;
3911 }
3912 else
3913 ri->routemap[RIP_FILTER_OUT] = NULL;
3914}
3915
3916void
3917rip_if_rmap_update_interface (struct interface *ifp)
3918{
3919 struct if_rmap *if_rmap;
3920
3921 if_rmap = if_rmap_lookup (ifp->name);
3922 if (if_rmap)
3923 rip_if_rmap_update (if_rmap);
3924}
3925
3926void
3927rip_routemap_update_redistribute (void)
3928{
3929 int i;
3930
3931 if (rip)
3932 {
3933 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3934 {
3935 if (rip->route_map[i].name)
3936 rip->route_map[i].map =
3937 route_map_lookup_by_name (rip->route_map[i].name);
3938 }
3939 }
3940}
3941
paul11dde9c2004-05-31 14:00:00 +00003942/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003943void
hasso98b718a2004-10-11 12:57:57 +00003944rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003945{
3946 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003947 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003948
3949 for (node = listhead (iflist); node; nextnode (node))
3950 {
3951 ifp = getdata (node);
3952 rip_if_rmap_update_interface (ifp);
3953 }
3954
3955 rip_routemap_update_redistribute ();
3956}
3957
paul718e3742002-12-13 20:15:29 +00003958/* Allocate new rip structure and set default value. */
3959void
3960rip_init ()
3961{
3962 /* Randomize for triggered update random(). */
3963 srand (time (NULL));
3964
3965 /* Install top nodes. */
3966 install_node (&rip_node, config_write_rip);
3967
3968 /* Install rip commands. */
3969 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003970 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003971 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003972 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003973 install_element (CONFIG_NODE, &router_rip_cmd);
3974 install_element (CONFIG_NODE, &no_router_rip_cmd);
3975
3976 install_default (RIP_NODE);
3977 install_element (RIP_NODE, &rip_version_cmd);
3978 install_element (RIP_NODE, &no_rip_version_cmd);
3979 install_element (RIP_NODE, &no_rip_version_val_cmd);
3980 install_element (RIP_NODE, &rip_default_metric_cmd);
3981 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3982 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3983 install_element (RIP_NODE, &rip_timers_cmd);
3984 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003985 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003986 install_element (RIP_NODE, &rip_route_cmd);
3987 install_element (RIP_NODE, &no_rip_route_cmd);
3988 install_element (RIP_NODE, &rip_distance_cmd);
3989 install_element (RIP_NODE, &no_rip_distance_cmd);
3990 install_element (RIP_NODE, &rip_distance_source_cmd);
3991 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3992 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3993 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3994
3995 /* Debug related init. */
3996 rip_debug_init ();
3997
paul718e3742002-12-13 20:15:29 +00003998 /* SNMP init. */
3999#ifdef HAVE_SNMP
4000 rip_snmp_init ();
4001#endif /* HAVE_SNMP */
4002
4003 /* Access list install. */
4004 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004005 access_list_add_hook (rip_distribute_update_all_wrapper);
4006 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004007
4008 /* Prefix list initialize.*/
4009 prefix_list_init ();
4010 prefix_list_add_hook (rip_distribute_update_all);
4011 prefix_list_delete_hook (rip_distribute_update_all);
4012
4013 /* Distribute list install. */
4014 distribute_list_init (RIP_NODE);
4015 distribute_list_add_hook (rip_distribute_update);
4016 distribute_list_delete_hook (rip_distribute_update);
4017
hasso16705132003-05-25 14:49:19 +00004018 /* Route-map */
4019 rip_route_map_init ();
4020 rip_offset_init ();
4021
4022 route_map_add_hook (rip_routemap_update);
4023 route_map_delete_hook (rip_routemap_update);
4024
4025 if_rmap_init (RIP_NODE);
4026 if_rmap_hook_add (rip_if_rmap_update);
4027 if_rmap_hook_delete (rip_if_rmap_update);
4028
paul718e3742002-12-13 20:15:29 +00004029 /* Distance control. */
4030 rip_distance_table = route_table_init ();
4031}