blob: 3267e1574887ecb3cd53dab8ac643dbabba0e23d [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
vincentfbf5d032005-09-29 11:25:50 +00002 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "command.h"
27#include "prefix.h"
28#include "table.h"
29#include "thread.h"
30#include "memory.h"
31#include "log.h"
32#include "stream.h"
33#include "filter.h"
34#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000035#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000036#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000037#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000038#include "plist.h"
39#include "distribute.h"
vincentc1a03d42005-09-28 15:47:44 +000040#include "md5.h"
paul718e3742002-12-13 20:15:29 +000041#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000042#include "privs.h"
paul718e3742002-12-13 20:15:29 +000043
44#include "ripd/ripd.h"
45#include "ripd/rip_debug.h"
46
paul0b3acf42004-09-17 08:39:08 +000047/* UDP receive buffer size */
48#define RIP_UDP_RCV_BUF 41600
49
50/* privileges global */
pauledd7c242003-06-04 13:59:38 +000051extern struct zebra_privs_t ripd_privs;
52
paul718e3742002-12-13 20:15:29 +000053/* RIP Structure. */
54struct rip *rip = NULL;
55
56/* RIP neighbor address table. */
57struct route_table *rip_neighbor_table;
58
59/* RIP route changes. */
60long rip_global_route_changes = 0;
61
62/* RIP queries. */
63long rip_global_queries = 0;
64
65/* Prototypes. */
66void rip_event (enum rip_event, int);
67
paulc49ad8f2004-10-22 10:27:28 +000068void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
paul718e3742002-12-13 20:15:29 +000069
70/* RIP output routes type. */
71enum
72{
73 rip_all_route,
74 rip_changed_route
75};
76
77/* RIP command strings. */
78struct message rip_msg[] =
79{
80 {RIP_REQUEST, "REQUEST"},
81 {RIP_RESPONSE, "RESPONSE"},
82 {RIP_TRACEON, "TRACEON"},
83 {RIP_TRACEOFF, "TRACEOFF"},
84 {RIP_POLL, "POLL"},
85 {RIP_POLL_ENTRY, "POLL ENTRY"},
86 {0, NULL}
87};
paul718e3742002-12-13 20:15:29 +000088
89/* Utility function to set boradcast option to the socket. */
90int
91sockopt_broadcast (int sock)
92{
93 int ret;
94 int on = 1;
95
96 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
97 if (ret < 0)
98 {
99 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
100 return -1;
101 }
102 return 0;
103}
104
105int
106rip_route_rte (struct rip_info *rinfo)
107{
108 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
109}
110
111struct rip_info *
112rip_info_new ()
113{
114 struct rip_info *new;
115
116 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
117 memset (new, 0, sizeof (struct rip_info));
118 return new;
119}
120
121void
122rip_info_free (struct rip_info *rinfo)
123{
124 XFREE (MTYPE_RIP_INFO, rinfo);
125}
126
127/* RIP route garbage collect timer. */
128int
129rip_garbage_collect (struct thread *t)
130{
131 struct rip_info *rinfo;
132 struct route_node *rp;
133
134 rinfo = THREAD_ARG (t);
135 rinfo->t_garbage_collect = NULL;
136
137 /* Off timeout timer. */
138 RIP_TIMER_OFF (rinfo->t_timeout);
139
140 /* Get route_node pointer. */
141 rp = rinfo->rp;
142
143 /* Unlock route_node. */
144 rp->info = NULL;
145 route_unlock_node (rp);
146
147 /* Free RIP routing information. */
148 rip_info_free (rinfo);
149
150 return 0;
151}
152
153/* Timeout RIP routes. */
154int
155rip_timeout (struct thread *t)
156{
157 struct rip_info *rinfo;
158 struct route_node *rn;
159
160 rinfo = THREAD_ARG (t);
161 rinfo->t_timeout = NULL;
162
163 rn = rinfo->rp;
164
165 /* - The garbage-collection timer is set for 120 seconds. */
166 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
167 rip->garbage_time);
168
169 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
170 rinfo->metric);
171 /* - The metric for the route is set to 16 (infinity). This causes
172 the route to be removed from service. */
173 rinfo->metric = RIP_METRIC_INFINITY;
174 rinfo->flags &= ~RIP_RTF_FIB;
175
176 /* - The route change flag is to indicate that this entry has been
177 changed. */
178 rinfo->flags |= RIP_RTF_CHANGED;
179
180 /* - The output process is signalled to trigger a response. */
181 rip_event (RIP_TRIGGERED_UPDATE, 0);
182
183 return 0;
184}
185
186void
187rip_timeout_update (struct rip_info *rinfo)
188{
189 if (rinfo->metric != RIP_METRIC_INFINITY)
190 {
191 RIP_TIMER_OFF (rinfo->t_timeout);
192 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
193 }
194}
195
196int
197rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
198{
199 struct distribute *dist;
200 struct access_list *alist;
201 struct prefix_list *plist;
202
203 /* Input distribute-list filtering. */
204 if (ri->list[RIP_FILTER_IN])
205 {
206 if (access_list_apply (ri->list[RIP_FILTER_IN],
207 (struct prefix *) p) == FILTER_DENY)
208 {
209 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000210 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000211 inet_ntoa (p->prefix), p->prefixlen);
212 return -1;
213 }
214 }
215 if (ri->prefix[RIP_FILTER_IN])
216 {
217 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
218 (struct prefix *) p) == PREFIX_DENY)
219 {
220 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000221 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000222 inet_ntoa (p->prefix), p->prefixlen);
223 return -1;
224 }
225 }
226
227 /* All interface filter check. */
228 dist = distribute_lookup (NULL);
229 if (dist)
230 {
231 if (dist->list[DISTRIBUTE_IN])
232 {
233 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
234
235 if (alist)
236 {
237 if (access_list_apply (alist,
238 (struct prefix *) p) == FILTER_DENY)
239 {
240 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000241 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000242 inet_ntoa (p->prefix), p->prefixlen);
243 return -1;
244 }
245 }
246 }
247 if (dist->prefix[DISTRIBUTE_IN])
248 {
249 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
250
251 if (plist)
252 {
253 if (prefix_list_apply (plist,
254 (struct prefix *) p) == PREFIX_DENY)
255 {
256 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000257 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000258 inet_ntoa (p->prefix), p->prefixlen);
259 return -1;
260 }
261 }
262 }
263 }
264 return 0;
265}
266
267int
268rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
269{
270 struct distribute *dist;
271 struct access_list *alist;
272 struct prefix_list *plist;
273
274 if (ri->list[RIP_FILTER_OUT])
275 {
276 if (access_list_apply (ri->list[RIP_FILTER_OUT],
277 (struct prefix *) p) == FILTER_DENY)
278 {
279 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000280 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000281 inet_ntoa (p->prefix), p->prefixlen);
282 return -1;
283 }
284 }
285 if (ri->prefix[RIP_FILTER_OUT])
286 {
287 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
288 (struct prefix *) p) == PREFIX_DENY)
289 {
290 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000291 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000292 inet_ntoa (p->prefix), p->prefixlen);
293 return -1;
294 }
295 }
296
297 /* All interface filter check. */
298 dist = distribute_lookup (NULL);
299 if (dist)
300 {
301 if (dist->list[DISTRIBUTE_OUT])
302 {
303 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
304
305 if (alist)
306 {
307 if (access_list_apply (alist,
308 (struct prefix *) p) == FILTER_DENY)
309 {
310 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000311 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000312 inet_ntoa (p->prefix), p->prefixlen);
313 return -1;
314 }
315 }
316 }
317 if (dist->prefix[DISTRIBUTE_OUT])
318 {
319 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
320
321 if (plist)
322 {
323 if (prefix_list_apply (plist,
324 (struct prefix *) p) == PREFIX_DENY)
325 {
326 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000327 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000328 inet_ntoa (p->prefix), p->prefixlen);
329 return -1;
330 }
331 }
332 }
333 }
334 return 0;
335}
336
337/* Check nexthop address validity. */
338static int
339rip_nexthop_check (struct in_addr *addr)
340{
hasso52dc7ee2004-09-23 19:18:23 +0000341 struct listnode *node;
342 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000343 struct interface *ifp;
344 struct connected *ifc;
345 struct prefix *p;
346
347 /* If nexthop address matches local configured address then it is
348 invalid nexthop. */
paul1eb8ef22005-04-07 07:30:20 +0000349 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000350 {
paul1eb8ef22005-04-07 07:30:20 +0000351 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000352 {
paul718e3742002-12-13 20:15:29 +0000353 p = ifc->address;
354
355 if (p->family == AF_INET
356 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
357 return -1;
358 }
359 }
360 return 0;
361}
362
363/* RIP add route to routing table. */
364void
365rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000366 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000367{
368 int ret;
369 struct prefix_ipv4 p;
370 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000371 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000372 struct rip_interface *ri;
373 struct in_addr *nexthop;
374 u_char oldmetric;
375 int same = 0;
vincentfbf5d032005-09-29 11:25:50 +0000376 int route_reuse = 0;
377 unsigned char old_dist, new_dist;
paul718e3742002-12-13 20:15:29 +0000378
379 /* Make prefix structure. */
380 memset (&p, 0, sizeof (struct prefix_ipv4));
381 p.family = AF_INET;
382 p.prefix = rte->prefix;
383 p.prefixlen = ip_masklen (rte->mask);
384
385 /* Make sure mask is applied. */
386 apply_mask_ipv4 (&p);
387
388 /* Apply input filters. */
389 ri = ifp->info;
390
391 ret = rip_incoming_filter (&p, ri);
392 if (ret < 0)
393 return;
394
hasso16705132003-05-25 14:49:19 +0000395 /* Modify entry according to the interface routemap. */
396 if (ri->routemap[RIP_FILTER_IN])
397 {
398 int ret;
399 struct rip_info newinfo;
400
401 memset (&newinfo, 0, sizeof (newinfo));
402 newinfo.type = ZEBRA_ROUTE_RIP;
403 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000404 newinfo.nexthop = rte->nexthop;
405 newinfo.from = from->sin_addr;
406 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000407 newinfo.metric = rte->metric;
408 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000409 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000410
411 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000412 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
413 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000414
415 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000416 {
417 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000418 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000419 inet_ntoa (p.prefix), p.prefixlen);
420 return;
421 }
hasso16705132003-05-25 14:49:19 +0000422
423 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000424 rte->nexthop = newinfo.nexthop_out;
425 rte->tag = htons (newinfo.tag_out); /* XXX */
426 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000427 }
428
paul718e3742002-12-13 20:15:29 +0000429 /* Once the entry has been validated, update the metric by
430 adding the cost of the network on wich the message
431 arrived. If the result is greater than infinity, use infinity
432 (RFC2453 Sec. 3.9.2) */
433 /* Zebra ripd can handle offset-list in. */
434 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
435
436 /* If offset-list does not modify the metric use interface's
437 metric. */
paula87552c2004-05-03 20:00:17 +0000438 if (!ret)
paul718e3742002-12-13 20:15:29 +0000439 rte->metric += ifp->metric;
440
441 if (rte->metric > RIP_METRIC_INFINITY)
442 rte->metric = RIP_METRIC_INFINITY;
443
444 /* Set nexthop pointer. */
445 if (rte->nexthop.s_addr == 0)
446 nexthop = &from->sin_addr;
447 else
448 nexthop = &rte->nexthop;
449
hasso16705132003-05-25 14:49:19 +0000450 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000451 if (rip_nexthop_check (nexthop) < 0)
452 {
453 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000454 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000455 return;
456 }
457
458 /* Get index for the prefix. */
459 rp = route_node_get (rip->table, (struct prefix *) &p);
460
461 /* Check to see whether there is already RIP route on the table. */
462 rinfo = rp->info;
463
464 if (rinfo)
465 {
paul718e3742002-12-13 20:15:29 +0000466 /* Local static route. */
467 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000468 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
469 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
470 && rinfo->metric != RIP_METRIC_INFINITY)
vincentfbf5d032005-09-29 11:25:50 +0000471 {
472 route_unlock_node (rp);
473 return;
474 }
475
476 /* Redistributed route check. */
477 if (rinfo->type != ZEBRA_ROUTE_RIP
478 && rinfo->metric != RIP_METRIC_INFINITY)
479 {
480 /* Fill in a minimaly temporary rip_info structure, for a future
481 rip_distance_apply() use) */
482 memset (&rinfotmp, 0, sizeof (rinfotmp));
483 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
484 rinfotmp.rp = rinfo->rp;
485 new_dist = rip_distance_apply (&rinfotmp);
486 new_dist = new_dist ? new_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
487 old_dist = rinfo->distance;
488 old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
489 /* If imported route does not have STRICT precedence,
490 mark it as a ghost */
491 if (new_dist > old_dist
492 || rte->metric == RIP_METRIC_INFINITY)
493 {
494 route_unlock_node (rp);
495 return;
496 }
497 else
498 {
499 RIP_TIMER_OFF (rinfo->t_timeout);
500 RIP_TIMER_OFF (rinfo->t_garbage_collect);
501
502 rp->info = NULL;
503 if (rip_route_rte (rinfo))
504 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
505 &rinfo->nexthop, rinfo->metric);
506 rip_info_free (rinfo);
507 rinfo = NULL;
508 route_reuse = 1;
509 }
510 }
paul718e3742002-12-13 20:15:29 +0000511 }
paula87552c2004-05-03 20:00:17 +0000512
513 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000514 {
515 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000516 for the destination prefix. If there is no such route, add
517 this route to the routing table, unless the metric is
518 infinity (there is no point in adding a route which
519 unusable). */
paul718e3742002-12-13 20:15:29 +0000520 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000521 {
522 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000523
paula87552c2004-05-03 20:00:17 +0000524 /* - Setting the destination prefix and length to those in
525 the RTE. */
526 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000527
paula87552c2004-05-03 20:00:17 +0000528 /* - Setting the metric to the newly calculated metric (as
529 described above). */
530 rinfo->metric = rte->metric;
531 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000532
paula87552c2004-05-03 20:00:17 +0000533 /* - Set the next hop address to be the address of the router
534 from which the datagram came or the next hop address
535 specified by a next hop RTE. */
536 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
537 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
538 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000539
paula87552c2004-05-03 20:00:17 +0000540 /* - Initialize the timeout for the route. If the
541 garbage-collection timer is running for this route, stop it
542 (see section 2.3 for a discussion of the timers). */
543 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000544
paula87552c2004-05-03 20:00:17 +0000545 /* - Set the route change flag. */
546 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000547
paula87552c2004-05-03 20:00:17 +0000548 /* - Signal the output process to trigger an update (see section
549 2.5). */
550 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000551
paula87552c2004-05-03 20:00:17 +0000552 /* Finally, route goes into the kernel. */
553 rinfo->type = ZEBRA_ROUTE_RIP;
554 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000555
paula87552c2004-05-03 20:00:17 +0000556 /* Set distance value. */
557 rinfo->distance = rip_distance_apply (rinfo);
558
559 rp->info = rinfo;
560 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
561 rinfo->distance);
562 rinfo->flags |= RIP_RTF_FIB;
563 }
vincentfbf5d032005-09-29 11:25:50 +0000564
565 /* Unlock temporary lock, i.e. same behaviour */
566 if (route_reuse)
567 route_unlock_node (rp);
paul718e3742002-12-13 20:15:29 +0000568 }
569 else
570 {
571 /* Route is there but we are not sure the route is RIP or not. */
572 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000573
paul718e3742002-12-13 20:15:29 +0000574 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000575 to the address of the router from which the datagram came.
576 If this datagram is from the same router as the existing
577 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000578 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000579 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000580
581 if (same)
paula87552c2004-05-03 20:00:17 +0000582 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000583
paulb94f9db2004-05-01 20:45:38 +0000584
585 /* Fill in a minimaly temporary rip_info structure, for a future
586 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000587 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000588 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000589 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000590
591
paul718e3742002-12-13 20:15:29 +0000592 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000593 router as the existing route, and the new metric is different
594 than the old one; or, if the new metric is lower than the old
595 one, or if the tag has been changed; or if there is a route
596 with a lower administrave distance; or an update of the
597 distance on the actual route; do the following actions: */
598 if ((same && rinfo->metric != rte->metric)
599 || (rte->metric < rinfo->metric)
600 || ((same)
601 && (rinfo->metric == rte->metric)
602 && ntohs (rte->tag) != rinfo->tag)
603 || (rinfo->distance > rip_distance_apply (&rinfotmp))
604 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
605 {
606 /* - Adopt the route from the datagram. That is, put the
607 new metric in, and adjust the next hop address (if
608 necessary). */
609 oldmetric = rinfo->metric;
610 rinfo->metric = rte->metric;
611 rinfo->tag = ntohs (rte->tag);
612 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
613 rinfo->ifindex = ifp->ifindex;
614 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000615
paula87552c2004-05-03 20:00:17 +0000616 /* Should a new route to this network be established
617 while the garbage-collection timer is running, the
618 new route will replace the one that is about to be
619 deleted. In this case the garbage-collection timer
620 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000621
paula87552c2004-05-03 20:00:17 +0000622 if (oldmetric == RIP_METRIC_INFINITY &&
623 rinfo->metric < RIP_METRIC_INFINITY)
624 {
625 rinfo->type = ZEBRA_ROUTE_RIP;
626 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000627
paula87552c2004-05-03 20:00:17 +0000628 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000629
paula87552c2004-05-03 20:00:17 +0000630 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
631 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000632
paula87552c2004-05-03 20:00:17 +0000633 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
634 rinfo->distance);
635 rinfo->flags |= RIP_RTF_FIB;
636 }
paul718e3742002-12-13 20:15:29 +0000637
paula87552c2004-05-03 20:00:17 +0000638 /* Update nexthop and/or metric value. */
639 if (oldmetric != RIP_METRIC_INFINITY)
640 {
641 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
642 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
643 rinfo->distance);
644 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000645
paula87552c2004-05-03 20:00:17 +0000646 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
647 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
648 }
paul718e3742002-12-13 20:15:29 +0000649
paula87552c2004-05-03 20:00:17 +0000650 /* - Set the route change flag and signal the output process
651 to trigger an update. */
652 rinfo->flags |= RIP_RTF_CHANGED;
653 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000654
paula87552c2004-05-03 20:00:17 +0000655 /* - If the new metric is infinity, start the deletion
656 process (described above); */
657 if (rinfo->metric == RIP_METRIC_INFINITY)
658 {
659 /* If the new metric is infinity, the deletion process
660 begins for the route, which is no longer used for
661 routing packets. Note that the deletion process is
662 started only when the metric is first set to
663 infinity. If the metric was already infinity, then a
664 new deletion process is not started. */
665 if (oldmetric != RIP_METRIC_INFINITY)
666 {
667 /* - The garbage-collection timer is set for 120 seconds. */
668 RIP_TIMER_ON (rinfo->t_garbage_collect,
669 rip_garbage_collect, rip->garbage_time);
670 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000671
paula87552c2004-05-03 20:00:17 +0000672 /* - The metric for the route is set to 16
673 (infinity). This causes the route to be removed
674 from service. */
675 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
676 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000677
paula87552c2004-05-03 20:00:17 +0000678 /* - The route change flag is to indicate that this
679 entry has been changed. */
680 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000681 response. */
paula87552c2004-05-03 20:00:17 +0000682 ; /* Above processes are already done previously. */
683 }
684 }
685 else
686 {
687 /* otherwise, re-initialize the timeout. */
688 rip_timeout_update (rinfo);
689 }
690 }
paul718e3742002-12-13 20:15:29 +0000691 /* Unlock tempolary lock of the route. */
692 route_unlock_node (rp);
693 }
694}
695
696/* Dump RIP packet */
697void
hasso8a676be2004-10-08 06:36:38 +0000698rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000699{
700 caddr_t lim;
701 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000702 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000703 char pbuf[BUFSIZ], nbuf[BUFSIZ];
704 u_char netmask = 0;
705 u_char *p;
706
707 /* Set command string. */
708 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
709 command_str = lookup (rip_msg, packet->command);
710 else
711 command_str = "unknown";
712
713 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000714 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000715 sndrcv, command_str, packet->version, size);
716
717 /* Dump each routing table entry. */
718 rte = packet->rte;
719
720 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
721 {
722 if (packet->version == RIPv2)
723 {
724 netmask = ip_masklen (rte->mask);
725
paulca5e5162004-06-06 22:06:33 +0000726 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000727 {
paulca5e5162004-06-06 22:06:33 +0000728 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000729 {
730 p = (u_char *)&rte->prefix;
731
ajs5d6c3772004-12-08 19:24:06 +0000732 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000733 ntohs (rte->family), ntohs (rte->tag), p);
734 }
paulca5e5162004-06-06 22:06:33 +0000735 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000736 {
737 struct rip_md5_info *md5;
738
739 md5 = (struct rip_md5_info *) &packet->rte;
740
ajs5d6c3772004-12-08 19:24:06 +0000741 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000742 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000743 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000744 " Auth Data len %d",
745 ntohs (md5->packet_len), md5->keyid,
746 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000747 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000748 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000749 }
paulca5e5162004-06-06 22:06:33 +0000750 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000751 {
752 p = (u_char *)&rte->prefix;
753
ajs5d6c3772004-12-08 19:24:06 +0000754 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000755 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000756 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000757 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000758 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
759 p[7], p[9], p[10], p[11], p[12], p[13],
760 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000761 }
762 else
763 {
ajs5d6c3772004-12-08 19:24:06 +0000764 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000765 ntohs (rte->family), ntohs (rte->tag));
766 }
767 }
768 else
ajs5d6c3772004-12-08 19:24:06 +0000769 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000770 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
771 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
772 BUFSIZ), ntohs (rte->family),
773 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000774 }
775 else
776 {
ajs5d6c3772004-12-08 19:24:06 +0000777 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000778 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
779 ntohs (rte->family), ntohs (rte->tag),
780 (u_long)ntohl (rte->metric));
781 }
782 }
783}
784
785/* Check if the destination address is valid (unicast; not net 0
786 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
787 check net 0 because we accept default route. */
788int
789rip_destination_check (struct in_addr addr)
790{
791 u_int32_t destination;
792
793 /* Convert to host byte order. */
794 destination = ntohl (addr.s_addr);
795
796 if (IPV4_NET127 (destination))
797 return 0;
798
799 /* Net 0 may match to the default route. */
800 if (IPV4_NET0 (destination) && destination != 0)
801 return 0;
802
803 /* Unicast address must belong to class A, B, C. */
804 if (IN_CLASSA (destination))
805 return 1;
806 if (IN_CLASSB (destination))
807 return 1;
808 if (IN_CLASSC (destination))
809 return 1;
810
811 return 0;
812}
813
814/* RIP version 2 authentication. */
815int
816rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
817 struct interface *ifp)
818{
819 struct rip_interface *ri;
820 char *auth_str;
821
822 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000823 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000824 inet_ntoa (from->sin_addr));
825
826 ri = ifp->info;
827
828 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000829 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000830 return 0;
831
832 /* Simple password authentication. */
833 if (ri->auth_str)
834 {
835 auth_str = (char *) &rte->prefix;
836
837 if (strncmp (auth_str, ri->auth_str, 16) == 0)
838 return 1;
839 }
840 if (ri->key_chain)
841 {
842 struct keychain *keychain;
843 struct key *key;
844
845 keychain = keychain_lookup (ri->key_chain);
846 if (keychain == NULL)
847 return 0;
848
849 key = key_match_for_accept (keychain, (char *) &rte->prefix);
850 if (key)
851 return 1;
852 }
853 return 0;
854}
855
856/* RIP version 2 authentication with MD5. */
857int
858rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000859 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000860{
861 struct rip_interface *ri;
862 struct rip_md5_info *md5;
863 struct rip_md5_data *md5data;
864 struct keychain *keychain;
865 struct key *key;
vincentc1a03d42005-09-28 15:47:44 +0000866 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000867 u_char pdigest[RIP_AUTH_MD5_SIZE];
868 u_char digest[RIP_AUTH_MD5_SIZE];
869 u_int16_t packet_len;
870 char *auth_str = NULL;
871
872 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000873 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000874 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000875
876 ri = ifp->info;
877 md5 = (struct rip_md5_info *) &packet->rte;
878
879 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000880 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000881 return 0;
882
paulca5e5162004-06-06 22:06:33 +0000883 /* If the authentication length is less than 16, then it must be wrong for
884 * any interpretation of rfc2082. Some implementations also interpret
885 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000886 */
paulca5e5162004-06-06 22:06:33 +0000887 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
888 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000889 {
890 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000891 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000892 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000893 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000894 }
paul718e3742002-12-13 20:15:29 +0000895
paulca5e5162004-06-06 22:06:33 +0000896 /* grab and verify check packet length */
897 packet_len = ntohs (md5->packet_len);
898
899 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
900 {
901 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000902 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000903 "greater than received length %d!",
904 md5->packet_len, length);
905 return 0;
906 }
907
908 /* retrieve authentication data */
909 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
910
paul718e3742002-12-13 20:15:29 +0000911 if (ri->key_chain)
912 {
913 keychain = keychain_lookup (ri->key_chain);
914 if (keychain == NULL)
915 return 0;
916
917 key = key_lookup_for_accept (keychain, md5->keyid);
918 if (key == NULL)
919 return 0;
920
921 auth_str = key->string;
922 }
923
924 if (ri->auth_str)
925 auth_str = ri->auth_str;
926
927 if (! auth_str)
928 return 0;
929
930 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000931
932 /* Save digest to pdigest. */
933 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
934
935 /* Overwrite digest by my secret. */
936 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000937 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000938
vincentc1a03d42005-09-28 15:47:44 +0000939 memset (&ctx, 0, sizeof(ctx));
940 MD5Init(&ctx);
941 MD5Update(&ctx, packet, packet_len + md5->auth_len);
942 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000943
944 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
945 return packet_len;
946 else
947 return 0;
948}
949
paulb14ee002005-02-04 23:42:41 +0000950/* Pick correct auth string for sends, prepare auth_str buffer for use.
951 * (left justified and padded).
952 *
953 * presumes one of ri or key is valid, and that the auth strings they point
954 * to are nul terminated. If neither are present, auth_str will be fully
955 * zero padded.
956 *
957 */
958static void
959rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
960 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000961{
paulb14ee002005-02-04 23:42:41 +0000962 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000963
paulb14ee002005-02-04 23:42:41 +0000964 memset (auth_str, 0, len);
965 if (key && key->string)
966 strncpy (auth_str, key->string, len);
967 else if (ri->auth_str)
968 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000969
paulb14ee002005-02-04 23:42:41 +0000970 return;
971}
paul718e3742002-12-13 20:15:29 +0000972
paulb14ee002005-02-04 23:42:41 +0000973/* Write RIPv2 simple password authentication information
974 *
975 * auth_str is presumed to be 2 bytes and correctly prepared
976 * (left justified and zero padded).
977 */
978static void
979rip_auth_simple_write (struct stream *s, char *auth_str, int len)
980{
981 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +0000982
paulb14ee002005-02-04 23:42:41 +0000983 stream_putw (s, RIP_FAMILY_AUTH);
984 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
985 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
986
987 return;
988}
989
990/* write RIPv2 MD5 "authentication header"
991 * (uses the auth key data field)
992 *
993 * Digest offset field is set to 0.
994 *
995 * returns: offset of the digest offset field, which must be set when
996 * length to the auth-data MD5 digest is known.
997 */
998static size_t
999rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
1000 struct key *key)
1001{
1002 size_t len = 0;
1003
1004 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +00001005
1006 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +00001007 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00001008 stream_putw (s, RIP_AUTH_MD5);
1009
paulb14ee002005-02-04 23:42:41 +00001010 /* MD5 AH digest offset field.
1011 *
1012 * Set to placeholder value here, to true value when RIP-2 Packet length
1013 * is known. Actual value is set in .....().
1014 */
paul9985f832005-02-09 15:51:56 +00001015 len = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +00001016 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +00001017
1018 /* Key ID. */
1019 if (key)
1020 stream_putc (s, key->index % 256);
1021 else
1022 stream_putc (s, 1);
1023
paulca5e5162004-06-06 22:06:33 +00001024 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1025 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1026 * to be configurable.
1027 */
1028 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001029
1030 /* Sequence Number (non-decreasing). */
1031 /* RFC2080: The value used in the sequence number is
1032 arbitrary, but two suggestions are the time of the
1033 message's creation or a simple message counter. */
1034 stream_putl (s, time (NULL));
1035
1036 /* Reserved field must be zero. */
1037 stream_putl (s, 0);
1038 stream_putl (s, 0);
1039
paulb14ee002005-02-04 23:42:41 +00001040 return len;
1041}
paul718e3742002-12-13 20:15:29 +00001042
paulb14ee002005-02-04 23:42:41 +00001043/* If authentication is in used, write the appropriate header
1044 * returns stream offset to which length must later be written
1045 * or 0 if this is not required
1046 */
1047static size_t
1048rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1049 struct key *key, char *auth_str, int len)
1050{
1051 assert (ri->auth_type != RIP_NO_AUTH);
1052
1053 switch (ri->auth_type)
1054 {
1055 case RIP_AUTH_SIMPLE_PASSWORD:
1056 rip_auth_prepare_str_send (ri, key, auth_str, len);
1057 rip_auth_simple_write (s, auth_str, len);
1058 return 0;
1059 case RIP_AUTH_MD5:
1060 return rip_auth_md5_ah_write (s, ri, key);
1061 }
1062 assert (1);
1063}
1064
1065/* Write RIPv2 MD5 authentication data trailer */
1066static void
1067rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1068 char *auth_str, int authlen)
1069{
1070 unsigned long len;
vincentc1a03d42005-09-28 15:47:44 +00001071 MD5_CTX ctx;
paulb14ee002005-02-04 23:42:41 +00001072 unsigned char digest[RIP_AUTH_MD5_SIZE];
1073
1074 /* Make it sure this interface is configured as MD5
1075 authentication. */
1076 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1077 assert (doff > 0);
1078
1079 /* Get packet length. */
1080 len = stream_get_endp(s);
1081
1082 /* Check packet length. */
1083 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1084 {
1085 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1086 return;
1087 }
1088
1089 /* Set the digest offset length in the header */
1090 stream_putw_at (s, doff, len);
1091
paul718e3742002-12-13 20:15:29 +00001092 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001093 stream_putw (s, RIP_FAMILY_AUTH);
1094 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001095
1096 /* Generate a digest for the RIP packet. */
vincentc1a03d42005-09-28 15:47:44 +00001097 memset(&ctx, 0, sizeof(ctx));
1098 MD5Init(&ctx);
1099 MD5Update(&ctx, s->data, s->endp);
1100 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1101 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +00001102
1103 /* Copy the digest to the packet. */
1104 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1105}
1106
1107/* RIP routing information. */
1108void
1109rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001110 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001111{
1112 caddr_t lim;
1113 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001114 struct prefix_ipv4 ifaddr;
1115 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001116 int subnetted;
paul718e3742002-12-13 20:15:29 +00001117
paul727d1042002-12-13 20:50:29 +00001118 /* We don't know yet. */
1119 subnetted = -1;
1120
paul718e3742002-12-13 20:15:29 +00001121 /* The Response must be ignored if it is not from the RIP
1122 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001123 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001124 {
1125 zlog_info ("response doesn't come from RIP port: %d",
1126 from->sin_port);
1127 rip_peer_bad_packet (from);
1128 return;
1129 }
1130
1131 /* The datagram's IPv4 source address should be checked to see
1132 whether the datagram is from a valid neighbor; the source of the
1133 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001134 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001135 {
1136 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1137 inet_ntoa (from->sin_addr));
1138 rip_peer_bad_packet (from);
1139 return;
1140 }
1141
1142 /* It is also worth checking to see whether the response is from one
1143 of the router's own addresses. */
1144
1145 ; /* Alredy done in rip_read () */
1146
1147 /* Update RIP peer. */
1148 rip_peer_update (from, packet->version);
1149
1150 /* Set RTE pointer. */
1151 rte = packet->rte;
1152
1153 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1154 {
1155 /* RIPv2 authentication check. */
1156 /* If the Address Family Identifier of the first (and only the
1157 first) entry in the message is 0xFFFF, then the remainder of
1158 the entry contains the authentication. */
1159 /* If the packet gets here it means authentication enabled */
1160 /* Check is done in rip_read(). So, just skipping it */
1161 if (packet->version == RIPv2 &&
1162 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001163 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001164 continue;
1165
paulca5e5162004-06-06 22:06:33 +00001166 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001167 {
1168 /* Address family check. RIP only supports AF_INET. */
1169 zlog_info ("Unsupported family %d from %s.",
1170 ntohs (rte->family), inet_ntoa (from->sin_addr));
1171 continue;
1172 }
1173
1174 /* - is the destination address valid (e.g., unicast; not net 0
1175 or 127) */
1176 if (! rip_destination_check (rte->prefix))
1177 {
1178 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1179 rip_peer_bad_route (from);
1180 continue;
1181 }
1182
1183 /* Convert metric value to host byte order. */
1184 rte->metric = ntohl (rte->metric);
1185
1186 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1187 if (! (rte->metric >= 1 && rte->metric <= 16))
1188 {
1189 zlog_info ("Route's metric is not in the 1-16 range.");
1190 rip_peer_bad_route (from);
1191 continue;
1192 }
1193
1194 /* RIPv1 does not have nexthop value. */
1195 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1196 {
1197 zlog_info ("RIPv1 packet with nexthop value %s",
1198 inet_ntoa (rte->nexthop));
1199 rip_peer_bad_route (from);
1200 continue;
1201 }
1202
1203 /* That is, if the provided information is ignored, a possibly
1204 sub-optimal, but absolutely valid, route may be taken. If
1205 the received Next Hop is not directly reachable, it should be
1206 treated as 0.0.0.0. */
1207 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1208 {
1209 u_int32_t addrval;
1210
1211 /* Multicast address check. */
1212 addrval = ntohl (rte->nexthop.s_addr);
1213 if (IN_CLASSD (addrval))
1214 {
1215 zlog_info ("Nexthop %s is multicast address, skip this rte",
1216 inet_ntoa (rte->nexthop));
1217 continue;
1218 }
1219
1220 if (! if_lookup_address (rte->nexthop))
1221 {
1222 struct route_node *rn;
1223 struct rip_info *rinfo;
1224
1225 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1226
1227 if (rn)
1228 {
1229 rinfo = rn->info;
1230
1231 if (rinfo->type == ZEBRA_ROUTE_RIP
1232 && rinfo->sub_type == RIP_ROUTE_RTE)
1233 {
1234 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001235 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 +00001236 rte->nexthop = rinfo->from;
1237 }
1238 else
1239 {
1240 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001241 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 +00001242 rte->nexthop.s_addr = 0;
1243 }
1244
1245 route_unlock_node (rn);
1246 }
1247 else
1248 {
1249 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001250 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 +00001251 rte->nexthop.s_addr = 0;
1252 }
1253
1254 }
1255 }
1256
1257 /* For RIPv1, there won't be a valid netmask.
1258
1259 This is a best guess at the masks. If everyone was using old
1260 Ciscos before the 'ip subnet zero' option, it would be almost
1261 right too :-)
1262
1263 Cisco summarize ripv1 advertisments to the classful boundary
1264 (/16 for class B's) except when the RIP packet does to inside
1265 the classful network in question. */
1266
1267 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1268 || (packet->version == RIPv2
1269 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1270 {
1271 u_int32_t destination;
1272
paul727d1042002-12-13 20:50:29 +00001273 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001274 {
1275 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1276 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1277 apply_classful_mask_ipv4 (&ifaddrclass);
1278 subnetted = 0;
1279 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1280 subnetted = 1;
1281 }
paul727d1042002-12-13 20:50:29 +00001282
paul718e3742002-12-13 20:15:29 +00001283 destination = ntohl (rte->prefix.s_addr);
1284
paul727d1042002-12-13 20:50:29 +00001285 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001286 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001287 else if (IN_CLASSB (destination))
1288 masklen2ip (16, &rte->mask);
1289 else if (IN_CLASSC (destination))
1290 masklen2ip (24, &rte->mask);
1291
1292 if (subnetted == 1)
1293 masklen2ip (ifaddrclass.prefixlen,
1294 (struct in_addr *) &destination);
1295 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1296 ifaddrclass.prefix.s_addr))
1297 {
1298 masklen2ip (ifaddr.prefixlen, &rte->mask);
1299 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1300 masklen2ip (32, &rte->mask);
1301 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001302 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001303 }
1304 else
1305 {
1306 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1307 continue;
1308 }
1309
1310 if (IS_RIP_DEBUG_EVENT)
1311 {
ajs5d6c3772004-12-08 19:24:06 +00001312 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1313 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001314 }
1315 }
1316
1317 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1318 ignore the entry. */
1319 if ((packet->version == RIPv2)
1320 && (rte->mask.s_addr != 0)
1321 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1322 {
1323 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1324 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1325 rip_peer_bad_route (from);
1326 continue;
1327 }
1328
1329 /* Default route's netmask is ignored. */
1330 if (packet->version == RIPv2
1331 && (rte->prefix.s_addr == 0)
1332 && (rte->mask.s_addr != 0))
1333 {
1334 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001335 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001336 rte->mask.s_addr = 0;
1337 }
1338
1339 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001340 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001341 }
1342}
1343
paula4e987e2005-06-03 17:46:49 +00001344/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001345static int
paul2c61ae32005-08-16 15:22:14 +00001346rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001347{
1348 int ret;
1349 int sock;
1350 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001351
paul2c61ae32005-08-16 15:22:14 +00001352 memset (&addr, 0, sizeof (struct sockaddr_in));
1353
1354 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001355 {
paulf69bd9d2005-06-03 18:01:50 +00001356 addr.sin_family = AF_INET;
1357 addr.sin_addr.s_addr = INADDR_ANY;
paul2c61ae32005-08-16 15:22:14 +00001358#ifdef HAVE_SINLEN
1359 addr.sin_len = sizeof (struct sockaddr_in);
1360#endif /* HAVE_SINLEN */
jardin38d3c162005-10-19 19:29:59 +00001361 } else {
1362 memcpy(&addr, from, sizeof(addr));
paulf69bd9d2005-06-03 18:01:50 +00001363 }
1364
paul2c61ae32005-08-16 15:22:14 +00001365 /* sending port must always be the RIP port */
1366 addr.sin_port = htons (RIP_PORT_DEFAULT);
1367
paula4e987e2005-06-03 17:46:49 +00001368 /* Make datagram socket. */
1369 sock = socket (AF_INET, SOCK_DGRAM, 0);
1370 if (sock < 0)
1371 {
1372 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1373 exit (1);
1374 }
1375
1376 sockopt_broadcast (sock);
1377 sockopt_reuseaddr (sock);
1378 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001379#ifdef RIP_RECVMSG
1380 setsockopt_pktinfo (sock);
1381#endif /* RIP_RECVMSG */
1382
1383 if (ripd_privs.change (ZPRIVS_RAISE))
1384 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001385 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1386 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1387
paula4e987e2005-06-03 17:46:49 +00001388 {
1389 int save_errno = errno;
1390 if (ripd_privs.change (ZPRIVS_LOWER))
1391 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001392
1393 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1394 sock, inet_ntoa(addr.sin_addr),
1395 (int) ntohs(addr.sin_port),
1396 safe_strerror(save_errno));
1397
paulf69bd9d2005-06-03 18:01:50 +00001398 close (sock);
paula4e987e2005-06-03 17:46:49 +00001399 return ret;
1400 }
paulf69bd9d2005-06-03 18:01:50 +00001401
paula4e987e2005-06-03 17:46:49 +00001402 if (ripd_privs.change (ZPRIVS_LOWER))
1403 zlog_err ("rip_create_socket: could not lower privs");
1404
1405 return sock;
1406}
1407
paulc49ad8f2004-10-22 10:27:28 +00001408/* RIP packet send to destination address, on interface denoted by
1409 * by connected argument. NULL to argument denotes destination should be
1410 * should be RIP multicast group
1411 */
paul718e3742002-12-13 20:15:29 +00001412int
paulc49ad8f2004-10-22 10:27:28 +00001413rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1414 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001415{
paul931cd542004-01-23 15:31:42 +00001416 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001417 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001418
1419 assert (ifc != NULL);
1420
paul931cd542004-01-23 15:31:42 +00001421 if (IS_RIP_DEBUG_PACKET)
1422 {
paulf69bd9d2005-06-03 18:01:50 +00001423#define ADDRESS_SIZE 20
1424 char dst[ADDRESS_SIZE];
1425 dst[ADDRESS_SIZE - 1] = '\0';
1426
paul931cd542004-01-23 15:31:42 +00001427 if (to)
1428 {
paulf69bd9d2005-06-03 18:01:50 +00001429 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001430 }
1431 else
1432 {
1433 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001434 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001435 }
paulf69bd9d2005-06-03 18:01:50 +00001436#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001437 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001438 inet_ntoa(ifc->address->u.prefix4),
1439 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001440 }
paulf69bd9d2005-06-03 18:01:50 +00001441
paulc49ad8f2004-10-22 10:27:28 +00001442 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001443 {
1444 /*
1445 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1446 * with multiple addresses on the same subnet: the first address
1447 * on the subnet is configured "primary", and all subsequent addresses
1448 * on that subnet are treated as "secondary" addresses.
1449 * In order to avoid routing-table bloat on other rip listeners,
1450 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1451 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1452 * flag is set, we would end up sending a packet for a "secondary"
1453 * source address on non-linux systems.
1454 */
1455 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001456 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001457 return 0;
1458 }
1459
paul718e3742002-12-13 20:15:29 +00001460 /* Make destination address. */
1461 memset (&sin, 0, sizeof (struct sockaddr_in));
1462 sin.sin_family = AF_INET;
1463#ifdef HAVE_SIN_LEN
1464 sin.sin_len = sizeof (struct sockaddr_in);
1465#endif /* HAVE_SIN_LEN */
1466
1467 /* When destination is specified, use it's port and address. */
1468 if (to)
1469 {
paul718e3742002-12-13 20:15:29 +00001470 sin.sin_port = to->sin_port;
1471 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001472 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001473 }
1474 else
1475 {
paul2c61ae32005-08-16 15:22:14 +00001476 struct sockaddr_in from;
1477
paul718e3742002-12-13 20:15:29 +00001478 sin.sin_port = htons (RIP_PORT_DEFAULT);
1479 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001480
1481 /* multicast send should bind to local interface address */
1482 from.sin_family = AF_INET;
1483 from.sin_port = htons (RIP_PORT_DEFAULT);
1484 from.sin_addr = ifc->address->u.prefix4;
1485#ifdef HAVE_SIN_LEN
1486 from.sin_len = sizeof (struct sockaddr_in);
1487#endif /* HAVE_SIN_LEN */
1488
paul931cd542004-01-23 15:31:42 +00001489 /*
1490 * we have to open a new socket for each packet because this
1491 * is the most portable way to bind to a different source
1492 * ipv4 address for each packet.
1493 */
paul2c61ae32005-08-16 15:22:14 +00001494 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001495 {
paulf69bd9d2005-06-03 18:01:50 +00001496 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001497 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001498 }
paulc49ad8f2004-10-22 10:27:28 +00001499 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001500 }
1501
paul931cd542004-01-23 15:31:42 +00001502 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001503 sizeof (struct sockaddr_in));
1504
1505 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001506 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001507 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001508
1509 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001510 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001511
paul931cd542004-01-23 15:31:42 +00001512 if (!to)
1513 close(send_sock);
1514
paul718e3742002-12-13 20:15:29 +00001515 return ret;
1516}
1517
1518/* Add redistributed route to RIP table. */
1519void
1520rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
vincentfbf5d032005-09-29 11:25:50 +00001521 unsigned int ifindex, struct in_addr *nexthop,
1522 unsigned int metric, unsigned char distance)
paul718e3742002-12-13 20:15:29 +00001523{
1524 int ret;
1525 struct route_node *rp;
1526 struct rip_info *rinfo;
1527
1528 /* Redistribute route */
1529 ret = rip_destination_check (p->prefix);
1530 if (! ret)
1531 return;
1532
1533 rp = route_node_get (rip->table, (struct prefix *) p);
1534
1535 rinfo = rp->info;
1536
1537 if (rinfo)
1538 {
1539 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1540 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1541 && rinfo->metric != RIP_METRIC_INFINITY)
1542 {
1543 route_unlock_node (rp);
1544 return;
1545 }
1546
1547 /* Manually configured RIP route check. */
1548 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001549 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1550 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001551 {
hasso16705132003-05-25 14:49:19 +00001552 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1553 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001554 {
1555 route_unlock_node (rp);
1556 return;
1557 }
1558 }
1559
1560 RIP_TIMER_OFF (rinfo->t_timeout);
1561 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1562
1563 if (rip_route_rte (rinfo))
1564 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1565 rinfo->metric);
1566 rp->info = NULL;
1567 rip_info_free (rinfo);
1568
1569 route_unlock_node (rp);
1570 }
1571
1572 rinfo = rip_info_new ();
1573
1574 rinfo->type = type;
1575 rinfo->sub_type = sub_type;
1576 rinfo->ifindex = ifindex;
1577 rinfo->metric = 1;
vincentfbf5d032005-09-29 11:25:50 +00001578 rinfo->external_metric = metric;
1579 rinfo->distance = distance;
paul718e3742002-12-13 20:15:29 +00001580 rinfo->rp = rp;
1581
1582 if (nexthop)
1583 rinfo->nexthop = *nexthop;
1584
1585 rinfo->flags |= RIP_RTF_FIB;
1586 rp->info = rinfo;
1587
1588 rinfo->flags |= RIP_RTF_CHANGED;
1589
hasso16705132003-05-25 14:49:19 +00001590 if (IS_RIP_DEBUG_EVENT) {
1591 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001592 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001593 inet_ntoa(p->prefix), p->prefixlen,
1594 ifindex2ifname(ifindex));
1595 else
ajs5d6c3772004-12-08 19:24:06 +00001596 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001597 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1598 ifindex2ifname(ifindex));
1599 }
1600
1601
paul718e3742002-12-13 20:15:29 +00001602 rip_event (RIP_TRIGGERED_UPDATE, 0);
1603}
1604
1605/* Delete redistributed route from RIP table. */
1606void
1607rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1608 unsigned int ifindex)
1609{
1610 int ret;
1611 struct route_node *rp;
1612 struct rip_info *rinfo;
1613
1614 ret = rip_destination_check (p->prefix);
1615 if (! ret)
1616 return;
1617
1618 rp = route_node_lookup (rip->table, (struct prefix *) p);
1619 if (rp)
1620 {
1621 rinfo = rp->info;
1622
1623 if (rinfo != NULL
1624 && rinfo->type == type
1625 && rinfo->sub_type == sub_type
1626 && rinfo->ifindex == ifindex)
1627 {
1628 /* Perform poisoned reverse. */
1629 rinfo->metric = RIP_METRIC_INFINITY;
1630 RIP_TIMER_ON (rinfo->t_garbage_collect,
1631 rip_garbage_collect, rip->garbage_time);
1632 RIP_TIMER_OFF (rinfo->t_timeout);
1633 rinfo->flags |= RIP_RTF_CHANGED;
1634
hasso16705132003-05-25 14:49:19 +00001635 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001636 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001637 inet_ntoa(p->prefix), p->prefixlen,
1638 ifindex2ifname(ifindex));
1639
paul718e3742002-12-13 20:15:29 +00001640 rip_event (RIP_TRIGGERED_UPDATE, 0);
1641 }
1642 }
1643}
1644
1645/* Response to request called from rip_read ().*/
1646void
1647rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001648 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001649{
1650 caddr_t lim;
1651 struct rte *rte;
1652 struct prefix_ipv4 p;
1653 struct route_node *rp;
1654 struct rip_info *rinfo;
1655 struct rip_interface *ri;
1656
hasso16705132003-05-25 14:49:19 +00001657 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001658 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001659 return;
1660
hasso429a0f82004-02-22 23:42:22 +00001661 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001662 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001663 if (! ri->running)
1664 return;
paul718e3742002-12-13 20:15:29 +00001665
1666 /* When passive interface is specified, suppress responses */
1667 if (ri->passive)
1668 return;
paulc49ad8f2004-10-22 10:27:28 +00001669
paul718e3742002-12-13 20:15:29 +00001670 /* RIP peer update. */
1671 rip_peer_update (from, packet->version);
1672
1673 lim = ((caddr_t) packet) + size;
1674 rte = packet->rte;
1675
1676 /* The Request is processed entry by entry. If there are no
1677 entries, no response is given. */
1678 if (lim == (caddr_t) rte)
1679 return;
1680
1681 /* There is one special case. If there is exactly one entry in the
1682 request, and it has an address family identifier of zero and a
1683 metric of infinity (i.e., 16), then this is a request to send the
1684 entire routing table. */
1685 if (lim == ((caddr_t) (rte + 1)) &&
1686 ntohs (rte->family) == 0 &&
1687 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1688 {
paulcc1131a2003-10-15 23:20:17 +00001689 struct prefix_ipv4 saddr;
1690
1691 /* saddr will be used for determining which routes to split-horizon.
1692 Since the source address we'll pick will be on the same subnet as the
1693 destination, for the purpose of split-horizoning, we'll
1694 pretend that "from" is our source address. */
1695 saddr.family = AF_INET;
1696 saddr.prefixlen = IPV4_MAX_BITLEN;
1697 saddr.prefix = from->sin_addr;
1698
paul718e3742002-12-13 20:15:29 +00001699 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001700 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001701 }
1702 else
1703 {
1704 /* Examine the list of RTEs in the Request one by one. For each
1705 entry, look up the destination in the router's routing
1706 database and, if there is a route, put that route's metric in
1707 the metric field of the RTE. If there is no explicit route
1708 to the specified destination, put infinity in the metric
1709 field. Once all the entries have been filled in, change the
1710 command from Request to Response and send the datagram back
1711 to the requestor. */
1712 p.family = AF_INET;
1713
1714 for (; ((caddr_t) rte) < lim; rte++)
1715 {
1716 p.prefix = rte->prefix;
1717 p.prefixlen = ip_masklen (rte->mask);
1718 apply_mask_ipv4 (&p);
1719
1720 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1721 if (rp)
1722 {
1723 rinfo = rp->info;
1724 rte->metric = htonl (rinfo->metric);
1725 route_unlock_node (rp);
1726 }
1727 else
1728 rte->metric = htonl (RIP_METRIC_INFINITY);
1729 }
1730 packet->command = RIP_RESPONSE;
1731
paulc49ad8f2004-10-22 10:27:28 +00001732 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001733 }
1734 rip_global_queries++;
1735}
1736
1737#if RIP_RECVMSG
1738/* Set IPv6 packet info to the socket. */
1739static int
1740setsockopt_pktinfo (int sock)
1741{
1742 int ret;
1743 int val = 1;
1744
1745 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1746 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001747 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001748 return ret;
1749}
1750
1751/* Read RIP packet by recvmsg function. */
1752int
1753rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1754 int *ifindex)
1755{
1756 int ret;
1757 struct msghdr msg;
1758 struct iovec iov;
1759 struct cmsghdr *ptr;
1760 char adata[1024];
1761
1762 msg.msg_name = (void *) from;
1763 msg.msg_namelen = sizeof (struct sockaddr_in);
1764 msg.msg_iov = &iov;
1765 msg.msg_iovlen = 1;
1766 msg.msg_control = (void *) adata;
1767 msg.msg_controllen = sizeof adata;
1768 iov.iov_base = buf;
1769 iov.iov_len = size;
1770
1771 ret = recvmsg (sock, &msg, 0);
1772 if (ret < 0)
1773 return ret;
1774
ajsb99760a2005-01-04 16:24:43 +00001775 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001776 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1777 {
1778 struct in_pktinfo *pktinfo;
1779 int i;
1780
1781 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1782 i = pktinfo->ipi_ifindex;
1783 }
1784 return ret;
1785}
1786
1787/* RIP packet read function. */
1788int
1789rip_read_new (struct thread *t)
1790{
1791 int ret;
1792 int sock;
1793 char buf[RIP_PACKET_MAXSIZ];
1794 struct sockaddr_in from;
1795 unsigned int ifindex;
1796
1797 /* Fetch socket then register myself. */
1798 sock = THREAD_FD (t);
1799 rip_event (RIP_READ, sock);
1800
1801 /* Read RIP packet. */
1802 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1803 if (ret < 0)
1804 {
ajs6099b3b2004-11-20 02:06:59 +00001805 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001806 return ret;
1807 }
1808
1809 return ret;
1810}
1811#endif /* RIP_RECVMSG */
1812
1813/* First entry point of RIP packet. */
1814int
1815rip_read (struct thread *t)
1816{
1817 int sock;
1818 int ret;
1819 int rtenum;
1820 union rip_buf rip_buf;
1821 struct rip_packet *packet;
1822 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001823 int len;
1824 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001825 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001826 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001827 struct rip_interface *ri;
1828
1829 /* Fetch socket then register myself. */
1830 sock = THREAD_FD (t);
1831 rip->t_read = NULL;
1832
1833 /* Add myself to tne next event */
1834 rip_event (RIP_READ, sock);
1835
1836 /* RIPd manages only IPv4. */
1837 memset (&from, 0, sizeof (struct sockaddr_in));
1838 fromlen = sizeof (struct sockaddr_in);
1839
1840 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1841 (struct sockaddr *) &from, &fromlen);
1842 if (len < 0)
1843 {
ajs6099b3b2004-11-20 02:06:59 +00001844 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001845 return len;
1846 }
1847
1848 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001849 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001850 {
1851 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001852 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001853 return -1;
1854 }
1855
1856 /* Which interface is this packet comes from. */
1857 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001858
paul718e3742002-12-13 20:15:29 +00001859 /* RIP packet received */
1860 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001861 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001862 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1863 ifp ? ifp->name : "unknown");
1864
1865 /* If this packet come from unknown interface, ignore it. */
1866 if (ifp == NULL)
1867 {
ajs766a0ca2004-12-15 14:55:51 +00001868 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1869 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001870 return -1;
1871 }
1872
1873 ifc = connected_lookup_address (ifp, from.sin_addr);
1874
1875 if (ifc == NULL)
1876 {
ajs766a0ca2004-12-15 14:55:51 +00001877 zlog_info ("rip_read: cannot find connected address for packet from %s "
1878 "port %d on interface %s",
1879 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001880 return -1;
1881 }
1882
1883 /* Packet length check. */
1884 if (len < RIP_PACKET_MINSIZ)
1885 {
1886 zlog_warn ("packet size %d is smaller than minimum size %d",
1887 len, RIP_PACKET_MINSIZ);
1888 rip_peer_bad_packet (&from);
1889 return len;
1890 }
1891 if (len > RIP_PACKET_MAXSIZ)
1892 {
1893 zlog_warn ("packet size %d is larger than max size %d",
1894 len, RIP_PACKET_MAXSIZ);
1895 rip_peer_bad_packet (&from);
1896 return len;
1897 }
1898
1899 /* Packet alignment check. */
1900 if ((len - RIP_PACKET_MINSIZ) % 20)
1901 {
1902 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1903 rip_peer_bad_packet (&from);
1904 return len;
1905 }
1906
1907 /* Set RTE number. */
1908 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1909
1910 /* For easy to handle. */
1911 packet = &rip_buf.rip_packet;
1912
1913 /* RIP version check. */
1914 if (packet->version == 0)
1915 {
1916 zlog_info ("version 0 with command %d received.", packet->command);
1917 rip_peer_bad_packet (&from);
1918 return -1;
1919 }
1920
1921 /* Dump RIP packet. */
1922 if (IS_RIP_DEBUG_RECV)
1923 rip_packet_dump (packet, len, "RECV");
1924
1925 /* RIP version adjust. This code should rethink now. RFC1058 says
1926 that "Version 1 implementations are to ignore this extra data and
1927 process only the fields specified in this document.". So RIPv3
1928 packet should be treated as RIPv1 ignoring must be zero field. */
1929 if (packet->version > RIPv2)
1930 packet->version = RIPv2;
1931
1932 /* Is RIP running or is this RIP neighbor ?*/
1933 ri = ifp->info;
1934 if (! ri->running && ! rip_neighbor_lookup (&from))
1935 {
1936 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001937 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001938 rip_peer_bad_packet (&from);
1939 return -1;
1940 }
1941
1942 /* RIP Version check. */
1943 if (packet->command == RIP_RESPONSE)
1944 {
paulf38a4712003-06-07 01:10:00 +00001945 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1946 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001947 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001948 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001949 {
1950 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001951 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001952 packet->version);
1953 rip_peer_bad_packet (&from);
1954 return -1;
1955 }
1956 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001957 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001958 {
1959 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001960 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001961 packet->version);
1962 rip_peer_bad_packet (&from);
1963 return -1;
1964 }
paul718e3742002-12-13 20:15:29 +00001965 }
1966
1967 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1968 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1969 accepted; authenticated RIP-2 messages shall be discarded. */
1970
1971 if ((ri->auth_type == RIP_NO_AUTH)
1972 && rtenum
paulca5e5162004-06-06 22:06:33 +00001973 && (packet->version == RIPv2)
1974 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001975 {
1976 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001977 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001978 packet->version);
1979 rip_peer_bad_packet (&from);
1980 return -1;
1981 }
1982
1983 /* If the router is configured to authenticate RIP-2 messages, then
1984 RIP-1 messages and RIP-2 messages which pass authentication
1985 testing shall be accepted; unauthenticated and failed
1986 authentication RIP-2 messages shall be discarded. For maximum
1987 security, RIP-1 messages should be ignored when authentication is
1988 in use (see section 4.1); otherwise, the routing information from
1989 authenticated messages will be propagated by RIP-1 routers in an
1990 unauthenticated manner. */
1991
1992 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001993 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001994 {
1995 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001996 if (packet->version == RIPv1
1997 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001998 {
1999 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002000 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002001 ("packet RIPv%d is dropped because authentication enabled",
2002 packet->version);
paul718e3742002-12-13 20:15:29 +00002003 rip_peer_bad_packet (&from);
2004 return -1;
2005 }
2006
2007 /* Check RIPv2 authentication. */
2008 if (packet->version == RIPv2)
2009 {
paulca5e5162004-06-06 22:06:33 +00002010 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00002011 {
paulca5e5162004-06-06 22:06:33 +00002012 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00002013 {
2014 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2015 if (! ret)
2016 {
2017 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002018 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002019 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00002020 rip_peer_bad_packet (&from);
2021 return -1;
2022 }
2023 else
2024 {
2025 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002026 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002027 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002028 }
2029 }
paulca5e5162004-06-06 22:06:33 +00002030 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002031 {
paulca5e5162004-06-06 22:06:33 +00002032 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002033 if (! ret)
2034 {
2035 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002036 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002037 rip_peer_bad_packet (&from);
2038 return -1;
2039 }
2040 else
2041 {
2042 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002043 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002044 }
2045 /* Reset RIP packet length to trim MD5 data. */
2046 len = ret;
2047 }
2048 else
2049 {
2050 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002051 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002052 ntohs (packet->rte->tag));
2053 rip_peer_bad_packet (&from);
2054 return -1;
2055 }
2056 }
2057 else
2058 {
2059 /* There is no authentication in the packet. */
2060 if (ri->auth_str || ri->key_chain)
2061 {
2062 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002063 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002064 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002065 rip_peer_bad_packet (&from);
2066 return -1;
2067 }
2068 }
2069 }
2070 }
2071
2072 /* Process each command. */
2073 switch (packet->command)
2074 {
2075 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002076 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002077 break;
2078 case RIP_REQUEST:
2079 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002080 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002081 break;
2082 case RIP_TRACEON:
2083 case RIP_TRACEOFF:
2084 zlog_info ("Obsolete command %s received, please sent it to routed",
2085 lookup (rip_msg, packet->command));
2086 rip_peer_bad_packet (&from);
2087 break;
2088 case RIP_POLL_ENTRY:
2089 zlog_info ("Obsolete command %s received",
2090 lookup (rip_msg, packet->command));
2091 rip_peer_bad_packet (&from);
2092 break;
2093 default:
2094 zlog_info ("Unknown RIP command %d received", packet->command);
2095 rip_peer_bad_packet (&from);
2096 break;
2097 }
2098
2099 return len;
2100}
2101
paul718e3742002-12-13 20:15:29 +00002102/* Write routing table entry to the stream and return next index of
2103 the routing table entry in the stream. */
2104int
2105rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002106 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002107{
2108 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002109
2110 /* Write routing table entry. */
2111 if (version == RIPv1)
2112 {
2113 stream_putw (s, AF_INET);
2114 stream_putw (s, 0);
2115 stream_put_ipv4 (s, p->prefix.s_addr);
2116 stream_put_ipv4 (s, 0);
2117 stream_put_ipv4 (s, 0);
2118 stream_putl (s, rinfo->metric_out);
2119 }
2120 else
2121 {
2122 masklen2ip (p->prefixlen, &mask);
2123
2124 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002125 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002126 stream_put_ipv4 (s, p->prefix.s_addr);
2127 stream_put_ipv4 (s, mask.s_addr);
2128 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2129 stream_putl (s, rinfo->metric_out);
2130 }
2131
2132 return ++num;
2133}
2134
2135/* Send update to the ifp or spcified neighbor. */
2136void
paulc49ad8f2004-10-22 10:27:28 +00002137rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2138 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002139{
2140 int ret;
2141 struct stream *s;
2142 struct route_node *rp;
2143 struct rip_info *rinfo;
2144 struct rip_interface *ri;
2145 struct prefix_ipv4 *p;
2146 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002147 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002148 struct key *key = NULL;
2149 /* this might need to made dynamic if RIP ever supported auth methods
2150 with larger key string sizes */
2151 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2152 size_t doff; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002153 int num = 0;
paul718e3742002-12-13 20:15:29 +00002154 int rtemax;
paul01d09082003-06-08 21:22:18 +00002155 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002156
2157 /* Logging output event. */
2158 if (IS_RIP_DEBUG_EVENT)
2159 {
2160 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002161 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002162 else
ajs5d6c3772004-12-08 19:24:06 +00002163 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002164 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002165 }
2166
2167 /* Set output stream. */
2168 s = rip->obuf;
2169
2170 /* Reset stream and RTE counter. */
2171 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002172 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2173
2174 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002175 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002176
2177 /* If output interface is in simple password authentication mode, we
2178 need space for authentication data. */
2179 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2180 rtemax -= 1;
2181
2182 /* If output interface is in MD5 authentication mode, we need space
2183 for authentication header and data. */
2184 if (ri->auth_type == RIP_AUTH_MD5)
2185 rtemax -= 2;
2186
2187 /* If output interface is in simple password authentication mode
2188 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002189 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002190 {
2191 if (ri->key_chain)
2192 {
2193 struct keychain *keychain;
2194
2195 keychain = keychain_lookup (ri->key_chain);
2196 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002197 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002198 }
paulb14ee002005-02-04 23:42:41 +00002199 /* to be passed to auth functions later */
2200 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002201 }
2202
paul727d1042002-12-13 20:50:29 +00002203 if (version == RIPv1)
2204 {
paulc49ad8f2004-10-22 10:27:28 +00002205 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002206 apply_classful_mask_ipv4 (&ifaddrclass);
2207 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002208 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002209 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002210 }
2211
paul718e3742002-12-13 20:15:29 +00002212 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2213 if ((rinfo = rp->info) != NULL)
2214 {
paul727d1042002-12-13 20:50:29 +00002215 /* For RIPv1, if we are subnetted, output subnets in our network */
2216 /* that have the same mask as the output "interface". For other */
2217 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002218
2219 if (version == RIPv1)
2220 {
paul727d1042002-12-13 20:50:29 +00002221 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002222
2223 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002224 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002225 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002226
paul727d1042002-12-13 20:50:29 +00002227 if (subnetted &&
2228 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2229 {
paulc49ad8f2004-10-22 10:27:28 +00002230 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002231 (rp->p.prefixlen != 32))
2232 continue;
2233 }
2234 else
2235 {
2236 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2237 apply_classful_mask_ipv4(&classfull);
2238 if (rp->p.u.prefix4.s_addr != 0 &&
2239 classfull.prefixlen != rp->p.prefixlen)
2240 continue;
2241 }
paul718e3742002-12-13 20:15:29 +00002242 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002243 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002244 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002245 }
2246 else
2247 p = (struct prefix_ipv4 *) &rp->p;
2248
2249 /* Apply output filters. */
2250 ret = rip_outgoing_filter (p, ri);
2251 if (ret < 0)
2252 continue;
2253
2254 /* Changed route only output. */
2255 if (route_type == rip_changed_route &&
2256 (! (rinfo->flags & RIP_RTF_CHANGED)))
2257 continue;
2258
2259 /* Split horizon. */
2260 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002261 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002262 {
paul42d14d92003-11-17 09:15:18 +00002263 /*
2264 * We perform split horizon for RIP and connected route.
2265 * For rip routes, we want to suppress the route if we would
2266 * end up sending the route back on the interface that we
2267 * learned it from, with a higher metric. For connected routes,
2268 * we suppress the route if the prefix is a subset of the
2269 * source address that we are going to use for the packet
2270 * (in order to handle the case when multiple subnets are
2271 * configured on the same interface).
2272 */
2273 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002274 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002275 continue;
2276 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002277 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002278 continue;
2279 }
2280
2281 /* Preparation for route-map. */
2282 rinfo->metric_set = 0;
2283 rinfo->nexthop_out.s_addr = 0;
2284 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002285 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002286 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002287
hasso16705132003-05-25 14:49:19 +00002288 /* In order to avoid some local loops,
2289 * if the RIP route has a nexthop via this interface, keep the nexthop,
2290 * otherwise set it to 0. The nexthop should not be propagated
2291 * beyond the local broadcast/multicast area in order
2292 * to avoid an IGP multi-level recursive look-up.
2293 * see (4.4)
2294 */
paulc49ad8f2004-10-22 10:27:28 +00002295 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002296 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002297
2298 /* Interface route-map */
2299 if (ri->routemap[RIP_FILTER_OUT])
2300 {
2301 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2302 (struct prefix *) p, RMAP_RIP,
2303 rinfo);
2304
2305 if (ret == RMAP_DENYMATCH)
2306 {
2307 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002308 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002309 inet_ntoa (p->prefix), p->prefixlen);
2310 continue;
2311 }
2312 }
paul718e3742002-12-13 20:15:29 +00002313
hasso16705132003-05-25 14:49:19 +00002314 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002315 if (rip->route_map[rinfo->type].name
2316 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2317 {
2318 ret = route_map_apply (rip->route_map[rinfo->type].map,
2319 (struct prefix *)p, RMAP_RIP, rinfo);
2320
2321 if (ret == RMAP_DENYMATCH)
2322 {
2323 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002324 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002325 inet_ntoa (p->prefix), p->prefixlen);
2326 continue;
2327 }
2328 }
2329
2330 /* When route-map does not set metric. */
2331 if (! rinfo->metric_set)
2332 {
2333 /* If redistribute metric is set. */
2334 if (rip->route_map[rinfo->type].metric_config
2335 && rinfo->metric != RIP_METRIC_INFINITY)
2336 {
2337 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2338 }
2339 else
2340 {
2341 /* If the route is not connected or localy generated
2342 one, use default-metric value*/
2343 if (rinfo->type != ZEBRA_ROUTE_RIP
2344 && rinfo->type != ZEBRA_ROUTE_CONNECT
2345 && rinfo->metric != RIP_METRIC_INFINITY)
2346 rinfo->metric_out = rip->default_metric;
2347 }
2348 }
2349
2350 /* Apply offset-list */
2351 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002352 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002353
2354 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2355 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002356
2357 /* Perform split-horizon with poisoned reverse
2358 * for RIP and connected routes.
2359 **/
2360 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002361 /*
2362 * We perform split horizon for RIP and connected route.
2363 * For rip routes, we want to suppress the route if we would
2364 * end up sending the route back on the interface that we
2365 * learned it from, with a higher metric. For connected routes,
2366 * we suppress the route if the prefix is a subset of the
2367 * source address that we are going to use for the packet
2368 * (in order to handle the case when multiple subnets are
2369 * configured on the same interface).
2370 */
2371 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002372 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002373 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002374 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002375 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002376 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002377 }
paulb14ee002005-02-04 23:42:41 +00002378
2379 /* Prepare preamble, auth headers, if needs be */
2380 if (num == 0)
2381 {
2382 stream_putc (s, RIP_RESPONSE);
2383 stream_putc (s, version);
2384 stream_putw (s, 0);
2385
paul0cb8a012005-05-29 11:27:24 +00002386 /* auth header for !v1 && !no_auth */
2387 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002388 doff = rip_auth_header_write (s, ri, key, auth_str,
2389 RIP_AUTH_SIMPLE_SIZE);
2390 }
2391
paul718e3742002-12-13 20:15:29 +00002392 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002393 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002394 if (num == rtemax)
2395 {
2396 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002397 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002398
2399 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002400 to, ifc);
paul718e3742002-12-13 20:15:29 +00002401
2402 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2403 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2404 stream_get_endp(s), "SEND");
2405 num = 0;
2406 stream_reset (s);
2407 }
2408 }
2409
2410 /* Flush unwritten RTE. */
2411 if (num != 0)
2412 {
2413 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002414 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002415
paulc49ad8f2004-10-22 10:27:28 +00002416 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002417
2418 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2419 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2420 stream_get_endp (s), "SEND");
2421 num = 0;
2422 stream_reset (s);
2423 }
2424
2425 /* Statistics updates. */
2426 ri->sent_updates++;
2427}
2428
2429/* Send RIP packet to the interface. */
2430void
paulc49ad8f2004-10-22 10:27:28 +00002431rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002432{
paul718e3742002-12-13 20:15:29 +00002433 struct sockaddr_in to;
2434
2435 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002436 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002437 {
2438 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002439 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002440
paulc49ad8f2004-10-22 10:27:28 +00002441 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002442 return;
2443 }
paulc49ad8f2004-10-22 10:27:28 +00002444
paul718e3742002-12-13 20:15:29 +00002445 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002446 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002447 {
paulc49ad8f2004-10-22 10:27:28 +00002448 if (ifc->address->family == AF_INET)
2449 {
2450 /* Destination address and port setting. */
2451 memset (&to, 0, sizeof (struct sockaddr_in));
2452 if (ifc->destination)
2453 /* use specified broadcast or point-to-point destination addr */
2454 to.sin_addr = ifc->destination->u.prefix4;
2455 else
2456 /* calculate the appropriate broadcast address */
2457 to.sin_addr.s_addr =
2458 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2459 ifc->address->prefixlen);
2460 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002461
paulc49ad8f2004-10-22 10:27:28 +00002462 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002463 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002464 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2465 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002466
paulc49ad8f2004-10-22 10:27:28 +00002467 rip_output_process (ifc, &to, route_type, version);
2468 }
paul718e3742002-12-13 20:15:29 +00002469 }
2470}
2471
2472/* Update send to all interface and neighbor. */
2473void
2474rip_update_process (int route_type)
2475{
paul1eb8ef22005-04-07 07:30:20 +00002476 struct listnode *node;
2477 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002478 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002479 struct interface *ifp;
2480 struct rip_interface *ri;
2481 struct route_node *rp;
2482 struct sockaddr_in to;
2483 struct prefix_ipv4 *p;
2484
2485 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002486 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002487 {
paul718e3742002-12-13 20:15:29 +00002488 if (if_is_loopback (ifp))
2489 continue;
2490
paul2e3b2e42002-12-13 21:03:13 +00002491 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002492 continue;
2493
2494 /* Fetch RIP interface information. */
2495 ri = ifp->info;
2496
2497 /* When passive interface is specified, suppress announce to the
2498 interface. */
2499 if (ri->passive)
2500 continue;
2501
2502 if (ri->running)
2503 {
2504 if (IS_RIP_DEBUG_EVENT)
2505 {
2506 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002507 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002508 ifp->name, ifp->ifindex);
2509 else
ajs5d6c3772004-12-08 19:24:06 +00002510 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002511 ifp->ifindex);
2512 }
2513
paulcc1131a2003-10-15 23:20:17 +00002514 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002515 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002516 {
2517 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002518 int done = 0;
2519 /*
2520 * If there is no version configuration in the interface,
2521 * use rip's version setting.
2522 */
paulf38a4712003-06-07 01:10:00 +00002523 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2524 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002525
2526 ifaddr = (struct prefix_ipv4 *) connected->address;
2527
2528 if (ifaddr->family != AF_INET)
2529 continue;
2530
paul931cd542004-01-23 15:31:42 +00002531 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002532 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002533 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002534 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002535 done = 1;
2536 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2537 break;
2538
paulf38a4712003-06-07 01:10:00 +00002539 }
paul718e3742002-12-13 20:15:29 +00002540 }
2541 }
2542
2543 /* RIP send updates to each neighbor. */
2544 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2545 if (rp->info != NULL)
2546 {
2547 p = (struct prefix_ipv4 *) &rp->p;
2548
2549 ifp = if_lookup_address (p->prefix);
2550 if (! ifp)
2551 {
paulc49ad8f2004-10-22 10:27:28 +00002552 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002553 inet_ntoa (p->prefix));
2554 continue;
2555 }
paulc49ad8f2004-10-22 10:27:28 +00002556
2557 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2558 {
2559 zlog_warn ("Neighbor %s doesnt have connected network",
2560 inet_ntoa (p->prefix));
2561 continue;
2562 }
2563
paul718e3742002-12-13 20:15:29 +00002564 /* Set destination address and port */
2565 memset (&to, 0, sizeof (struct sockaddr_in));
2566 to.sin_addr = p->prefix;
2567 to.sin_port = htons (RIP_PORT_DEFAULT);
2568
2569 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002570 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002571 }
2572}
2573
2574/* RIP's periodical timer. */
2575int
2576rip_update (struct thread *t)
2577{
2578 /* Clear timer pointer. */
2579 rip->t_update = NULL;
2580
2581 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002582 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002583
2584 /* Process update output. */
2585 rip_update_process (rip_all_route);
2586
2587 /* Triggered updates may be suppressed if a regular update is due by
2588 the time the triggered update would be sent. */
2589 if (rip->t_triggered_interval)
2590 {
2591 thread_cancel (rip->t_triggered_interval);
2592 rip->t_triggered_interval = NULL;
2593 }
2594 rip->trigger = 0;
2595
2596 /* Register myself. */
2597 rip_event (RIP_UPDATE_EVENT, 0);
2598
2599 return 0;
2600}
2601
2602/* Walk down the RIP routing table then clear changed flag. */
2603void
2604rip_clear_changed_flag ()
2605{
2606 struct route_node *rp;
2607 struct rip_info *rinfo;
2608
2609 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2610 if ((rinfo = rp->info) != NULL)
2611 if (rinfo->flags & RIP_RTF_CHANGED)
2612 rinfo->flags &= ~RIP_RTF_CHANGED;
2613}
2614
2615/* Triggered update interval timer. */
2616int
2617rip_triggered_interval (struct thread *t)
2618{
2619 int rip_triggered_update (struct thread *);
2620
2621 rip->t_triggered_interval = NULL;
2622
2623 if (rip->trigger)
2624 {
2625 rip->trigger = 0;
2626 rip_triggered_update (t);
2627 }
2628 return 0;
2629}
2630
2631/* Execute triggered update. */
2632int
2633rip_triggered_update (struct thread *t)
2634{
2635 int interval;
2636
2637 /* Clear thred pointer. */
2638 rip->t_triggered_update = NULL;
2639
2640 /* Cancel interval timer. */
2641 if (rip->t_triggered_interval)
2642 {
2643 thread_cancel (rip->t_triggered_interval);
2644 rip->t_triggered_interval = NULL;
2645 }
2646 rip->trigger = 0;
2647
2648 /* Logging triggered update. */
2649 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002650 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002651
2652 /* Split Horizon processing is done when generating triggered
2653 updates as well as normal updates (see section 2.6). */
2654 rip_update_process (rip_changed_route);
2655
2656 /* Once all of the triggered updates have been generated, the route
2657 change flags should be cleared. */
2658 rip_clear_changed_flag ();
2659
2660 /* After a triggered update is sent, a timer should be set for a
2661 random interval between 1 and 5 seconds. If other changes that
2662 would trigger updates occur before the timer expires, a single
2663 update is triggered when the timer expires. */
2664 interval = (random () % 5) + 1;
2665
2666 rip->t_triggered_interval =
2667 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2668
2669 return 0;
2670}
2671
2672/* Withdraw redistributed route. */
2673void
2674rip_redistribute_withdraw (int type)
2675{
2676 struct route_node *rp;
2677 struct rip_info *rinfo;
2678
2679 if (!rip)
2680 return;
2681
2682 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2683 if ((rinfo = rp->info) != NULL)
2684 {
2685 if (rinfo->type == type
2686 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2687 {
2688 /* Perform poisoned reverse. */
2689 rinfo->metric = RIP_METRIC_INFINITY;
2690 RIP_TIMER_ON (rinfo->t_garbage_collect,
2691 rip_garbage_collect, rip->garbage_time);
2692 RIP_TIMER_OFF (rinfo->t_timeout);
2693 rinfo->flags |= RIP_RTF_CHANGED;
2694
hasso16705132003-05-25 14:49:19 +00002695 if (IS_RIP_DEBUG_EVENT) {
2696 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2697
ajs5d6c3772004-12-08 19:24:06 +00002698 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002699 inet_ntoa(p->prefix), p->prefixlen,
2700 ifindex2ifname(rinfo->ifindex));
2701 }
2702
paul718e3742002-12-13 20:15:29 +00002703 rip_event (RIP_TRIGGERED_UPDATE, 0);
2704 }
2705 }
2706}
2707
2708/* Create new RIP instance and set it to global variable. */
2709int
2710rip_create ()
2711{
2712 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2713 memset (rip, 0, sizeof (struct rip));
2714
2715 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002716 rip->version_send = RI_RIP_VERSION_2;
2717 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002718 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2719 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2720 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2721 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2722
2723 /* Initialize RIP routig table. */
2724 rip->table = route_table_init ();
2725 rip->route = route_table_init ();
2726 rip->neighbor = route_table_init ();
2727
2728 /* Make output stream. */
2729 rip->obuf = stream_new (1500);
2730
2731 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002732 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002733 if (rip->sock < 0)
2734 return rip->sock;
2735
2736 /* Create read and timer thread. */
2737 rip_event (RIP_READ, rip->sock);
2738 rip_event (RIP_UPDATE_EVENT, 1);
2739
2740 return 0;
2741}
2742
2743/* Sned RIP request to the destination. */
2744int
2745rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002746 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002747{
2748 struct rte *rte;
2749 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002750 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002751
2752 memset (&rip_packet, 0, sizeof (rip_packet));
2753
2754 rip_packet.command = RIP_REQUEST;
2755 rip_packet.version = version;
2756 rte = rip_packet.rte;
2757 rte->metric = htonl (RIP_METRIC_INFINITY);
2758
paul931cd542004-01-23 15:31:42 +00002759 if (connected)
2760 {
2761 /*
2762 * connected is only sent for ripv1 case, or when
2763 * interface does not support multicast. Caller loops
2764 * over each connected address for this case.
2765 */
paul11dde9c2004-05-31 14:00:00 +00002766 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002767 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002768 return -1;
2769 else
2770 return sizeof (rip_packet);
2771 }
2772
paulcc1131a2003-10-15 23:20:17 +00002773 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002774 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002775 {
2776 struct prefix_ipv4 *p;
2777
2778 p = (struct prefix_ipv4 *) connected->address;
2779
2780 if (p->family != AF_INET)
2781 continue;
2782
paul11dde9c2004-05-31 14:00:00 +00002783 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002784 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002785 return -1;
2786 }
2787 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002788}
2789
2790int
2791rip_update_jitter (unsigned long time)
2792{
paul239389b2004-05-05 14:09:37 +00002793#define JITTER_BOUND 4
2794 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2795 Given that, we cannot let time be less than JITTER_BOUND seconds.
2796 The RIPv2 RFC says jitter should be small compared to
2797 update_time. We consider 1/JITTER_BOUND to be small.
2798 */
2799
2800 int jitter_input = time;
2801 int jitter;
2802
2803 if (jitter_input < JITTER_BOUND)
2804 jitter_input = JITTER_BOUND;
2805
2806 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2807
2808 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002809}
2810
2811void
2812rip_event (enum rip_event event, int sock)
2813{
2814 int jitter = 0;
2815
2816 switch (event)
2817 {
2818 case RIP_READ:
2819 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2820 break;
2821 case RIP_UPDATE_EVENT:
2822 if (rip->t_update)
2823 {
2824 thread_cancel (rip->t_update);
2825 rip->t_update = NULL;
2826 }
2827 jitter = rip_update_jitter (rip->update_time);
2828 rip->t_update =
2829 thread_add_timer (master, rip_update, NULL,
2830 sock ? 2 : rip->update_time + jitter);
2831 break;
2832 case RIP_TRIGGERED_UPDATE:
2833 if (rip->t_triggered_interval)
2834 rip->trigger = 1;
2835 else if (! rip->t_triggered_update)
2836 rip->t_triggered_update =
2837 thread_add_event (master, rip_triggered_update, NULL, 0);
2838 break;
2839 default:
2840 break;
2841 }
2842}
2843
2844DEFUN (router_rip,
2845 router_rip_cmd,
2846 "router rip",
2847 "Enable a routing process\n"
2848 "Routing Information Protocol (RIP)\n")
2849{
2850 int ret;
2851
2852 /* If rip is not enabled before. */
2853 if (! rip)
2854 {
2855 ret = rip_create ();
2856 if (ret < 0)
2857 {
2858 zlog_info ("Can't create RIP");
2859 return CMD_WARNING;
2860 }
2861 }
2862 vty->node = RIP_NODE;
2863 vty->index = rip;
2864
2865 return CMD_SUCCESS;
2866}
2867
2868DEFUN (no_router_rip,
2869 no_router_rip_cmd,
2870 "no router rip",
2871 NO_STR
2872 "Enable a routing process\n"
2873 "Routing Information Protocol (RIP)\n")
2874{
2875 if (rip)
2876 rip_clean ();
2877 return CMD_SUCCESS;
2878}
2879
2880DEFUN (rip_version,
2881 rip_version_cmd,
2882 "version <1-2>",
2883 "Set routing protocol version\n"
2884 "version\n")
2885{
2886 int version;
2887
2888 version = atoi (argv[0]);
2889 if (version != RIPv1 && version != RIPv2)
2890 {
2891 vty_out (vty, "invalid rip version %d%s", version,
2892 VTY_NEWLINE);
2893 return CMD_WARNING;
2894 }
paulf38a4712003-06-07 01:10:00 +00002895 rip->version_send = version;
2896 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002897
2898 return CMD_SUCCESS;
2899}
2900
2901DEFUN (no_rip_version,
2902 no_rip_version_cmd,
2903 "no version",
2904 NO_STR
2905 "Set routing protocol version\n")
2906{
2907 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002908 rip->version_send = RI_RIP_VERSION_2;
2909 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002910
2911 return CMD_SUCCESS;
2912}
2913
2914ALIAS (no_rip_version,
2915 no_rip_version_val_cmd,
2916 "no version <1-2>",
2917 NO_STR
2918 "Set routing protocol version\n"
2919 "version\n")
2920
2921DEFUN (rip_route,
2922 rip_route_cmd,
2923 "route A.B.C.D/M",
2924 "RIP static route configuration\n"
2925 "IP prefix <network>/<length>\n")
2926{
2927 int ret;
2928 struct prefix_ipv4 p;
2929 struct route_node *node;
2930
2931 ret = str2prefix_ipv4 (argv[0], &p);
2932 if (ret < 0)
2933 {
2934 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2935 return CMD_WARNING;
2936 }
2937 apply_mask_ipv4 (&p);
2938
2939 /* For router rip configuration. */
2940 node = route_node_get (rip->route, (struct prefix *) &p);
2941
2942 if (node->info)
2943 {
2944 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2945 route_unlock_node (node);
2946 return CMD_WARNING;
2947 }
2948
hasso8a676be2004-10-08 06:36:38 +00002949 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002950
vincentfbf5d032005-09-29 11:25:50 +00002951 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
paul718e3742002-12-13 20:15:29 +00002952
2953 return CMD_SUCCESS;
2954}
2955
2956DEFUN (no_rip_route,
2957 no_rip_route_cmd,
2958 "no route A.B.C.D/M",
2959 NO_STR
2960 "RIP static route configuration\n"
2961 "IP prefix <network>/<length>\n")
2962{
2963 int ret;
2964 struct prefix_ipv4 p;
2965 struct route_node *node;
2966
2967 ret = str2prefix_ipv4 (argv[0], &p);
2968 if (ret < 0)
2969 {
2970 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2971 return CMD_WARNING;
2972 }
2973 apply_mask_ipv4 (&p);
2974
2975 /* For router rip configuration. */
2976 node = route_node_lookup (rip->route, (struct prefix *) &p);
2977 if (! node)
2978 {
2979 vty_out (vty, "Can't find route %s.%s", argv[0],
2980 VTY_NEWLINE);
2981 return CMD_WARNING;
2982 }
2983
2984 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2985 route_unlock_node (node);
2986
2987 node->info = NULL;
2988 route_unlock_node (node);
2989
2990 return CMD_SUCCESS;
2991}
2992
2993void
2994rip_update_default_metric ()
2995{
2996 struct route_node *np;
2997 struct rip_info *rinfo;
2998
2999 for (np = route_top (rip->table); np; np = route_next (np))
3000 if ((rinfo = np->info) != NULL)
3001 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3002 rinfo->metric = rip->default_metric;
3003}
3004
3005DEFUN (rip_default_metric,
3006 rip_default_metric_cmd,
3007 "default-metric <1-16>",
3008 "Set a metric of redistribute routes\n"
3009 "Default metric\n")
3010{
3011 if (rip)
3012 {
3013 rip->default_metric = atoi (argv[0]);
3014 /* rip_update_default_metric (); */
3015 }
3016 return CMD_SUCCESS;
3017}
3018
3019DEFUN (no_rip_default_metric,
3020 no_rip_default_metric_cmd,
3021 "no default-metric",
3022 NO_STR
3023 "Set a metric of redistribute routes\n"
3024 "Default metric\n")
3025{
3026 if (rip)
3027 {
3028 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3029 /* rip_update_default_metric (); */
3030 }
3031 return CMD_SUCCESS;
3032}
3033
3034ALIAS (no_rip_default_metric,
3035 no_rip_default_metric_val_cmd,
3036 "no default-metric <1-16>",
3037 NO_STR
3038 "Set a metric of redistribute routes\n"
3039 "Default metric\n")
3040
3041DEFUN (rip_timers,
3042 rip_timers_cmd,
3043 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3044 "Adjust routing timers\n"
3045 "Basic routing protocol update timers\n"
3046 "Routing table update timer value in second. Default is 30.\n"
3047 "Routing information timeout timer. Default is 180.\n"
3048 "Garbage collection timer. Default is 120.\n")
3049{
3050 unsigned long update;
3051 unsigned long timeout;
3052 unsigned long garbage;
3053 char *endptr = NULL;
3054 unsigned long RIP_TIMER_MAX = 2147483647;
3055 unsigned long RIP_TIMER_MIN = 5;
3056
3057 update = strtoul (argv[0], &endptr, 10);
3058 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3059 {
3060 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3061 return CMD_WARNING;
3062 }
3063
3064 timeout = strtoul (argv[1], &endptr, 10);
3065 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3066 {
3067 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3068 return CMD_WARNING;
3069 }
3070
3071 garbage = strtoul (argv[2], &endptr, 10);
3072 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3073 {
3074 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3075 return CMD_WARNING;
3076 }
3077
3078 /* Set each timer value. */
3079 rip->update_time = update;
3080 rip->timeout_time = timeout;
3081 rip->garbage_time = garbage;
3082
3083 /* Reset update timer thread. */
3084 rip_event (RIP_UPDATE_EVENT, 0);
3085
3086 return CMD_SUCCESS;
3087}
3088
3089DEFUN (no_rip_timers,
3090 no_rip_timers_cmd,
3091 "no timers basic",
3092 NO_STR
3093 "Adjust routing timers\n"
3094 "Basic routing protocol update timers\n")
3095{
3096 /* Set each timer value to the default. */
3097 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3098 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3099 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3100
3101 /* Reset update timer thread. */
3102 rip_event (RIP_UPDATE_EVENT, 0);
3103
3104 return CMD_SUCCESS;
3105}
hasso16705132003-05-25 14:49:19 +00003106
3107ALIAS (no_rip_timers,
3108 no_rip_timers_val_cmd,
3109 "no timers basic <0-65535> <0-65535> <0-65535>",
3110 NO_STR
3111 "Adjust routing timers\n"
3112 "Basic routing protocol update timers\n"
3113 "Routing table update timer value in second. Default is 30.\n"
3114 "Routing information timeout timer. Default is 180.\n"
3115 "Garbage collection timer. Default is 120.\n")
3116
paul718e3742002-12-13 20:15:29 +00003117
3118struct route_table *rip_distance_table;
3119
3120struct rip_distance
3121{
3122 /* Distance value for the IP source prefix. */
3123 u_char distance;
3124
3125 /* Name of the access-list to be matched. */
3126 char *access_list;
3127};
3128
3129struct rip_distance *
3130rip_distance_new ()
3131{
3132 struct rip_distance *new;
3133 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3134 memset (new, 0, sizeof (struct rip_distance));
3135 return new;
3136}
3137
3138void
3139rip_distance_free (struct rip_distance *rdistance)
3140{
3141 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3142}
3143
3144int
hasso98b718a2004-10-11 12:57:57 +00003145rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3146 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003147{
3148 int ret;
3149 struct prefix_ipv4 p;
3150 u_char distance;
3151 struct route_node *rn;
3152 struct rip_distance *rdistance;
3153
3154 ret = str2prefix_ipv4 (ip_str, &p);
3155 if (ret == 0)
3156 {
3157 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3158 return CMD_WARNING;
3159 }
3160
3161 distance = atoi (distance_str);
3162
3163 /* Get RIP distance node. */
3164 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3165 if (rn->info)
3166 {
3167 rdistance = rn->info;
3168 route_unlock_node (rn);
3169 }
3170 else
3171 {
3172 rdistance = rip_distance_new ();
3173 rn->info = rdistance;
3174 }
3175
3176 /* Set distance value. */
3177 rdistance->distance = distance;
3178
3179 /* Reset access-list configuration. */
3180 if (rdistance->access_list)
3181 {
3182 free (rdistance->access_list);
3183 rdistance->access_list = NULL;
3184 }
3185 if (access_list_str)
3186 rdistance->access_list = strdup (access_list_str);
3187
3188 return CMD_SUCCESS;
3189}
3190
3191int
hasso98b718a2004-10-11 12:57:57 +00003192rip_distance_unset (struct vty *vty, const char *distance_str,
3193 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003194{
3195 int ret;
3196 struct prefix_ipv4 p;
3197 u_char distance;
3198 struct route_node *rn;
3199 struct rip_distance *rdistance;
3200
3201 ret = str2prefix_ipv4 (ip_str, &p);
3202 if (ret == 0)
3203 {
3204 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3205 return CMD_WARNING;
3206 }
3207
3208 distance = atoi (distance_str);
3209
3210 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3211 if (! rn)
3212 {
3213 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3214 return CMD_WARNING;
3215 }
3216
3217 rdistance = rn->info;
3218
3219 if (rdistance->access_list)
3220 free (rdistance->access_list);
3221 rip_distance_free (rdistance);
3222
3223 rn->info = NULL;
3224 route_unlock_node (rn);
3225 route_unlock_node (rn);
3226
3227 return CMD_SUCCESS;
3228}
3229
3230void
3231rip_distance_reset ()
3232{
3233 struct route_node *rn;
3234 struct rip_distance *rdistance;
3235
3236 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3237 if ((rdistance = rn->info) != NULL)
3238 {
3239 if (rdistance->access_list)
3240 free (rdistance->access_list);
3241 rip_distance_free (rdistance);
3242 rn->info = NULL;
3243 route_unlock_node (rn);
3244 }
3245}
3246
3247/* Apply RIP information to distance method. */
3248u_char
3249rip_distance_apply (struct rip_info *rinfo)
3250{
3251 struct route_node *rn;
3252 struct prefix_ipv4 p;
3253 struct rip_distance *rdistance;
3254 struct access_list *alist;
3255
3256 if (! rip)
3257 return 0;
3258
3259 memset (&p, 0, sizeof (struct prefix_ipv4));
3260 p.family = AF_INET;
3261 p.prefix = rinfo->from;
3262 p.prefixlen = IPV4_MAX_BITLEN;
3263
3264 /* Check source address. */
3265 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3266 if (rn)
3267 {
3268 rdistance = rn->info;
3269 route_unlock_node (rn);
3270
3271 if (rdistance->access_list)
3272 {
3273 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3274 if (alist == NULL)
3275 return 0;
3276 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3277 return 0;
3278
3279 return rdistance->distance;
3280 }
3281 else
3282 return rdistance->distance;
3283 }
3284
3285 if (rip->distance)
3286 return rip->distance;
3287
3288 return 0;
3289}
3290
3291void
3292rip_distance_show (struct vty *vty)
3293{
3294 struct route_node *rn;
3295 struct rip_distance *rdistance;
3296 int header = 1;
3297 char buf[BUFSIZ];
3298
3299 vty_out (vty, " Distance: (default is %d)%s",
3300 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3301 VTY_NEWLINE);
3302
3303 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3304 if ((rdistance = rn->info) != NULL)
3305 {
3306 if (header)
3307 {
3308 vty_out (vty, " Address Distance List%s",
3309 VTY_NEWLINE);
3310 header = 0;
3311 }
3312 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3313 vty_out (vty, " %-20s %4d %s%s",
3314 buf, rdistance->distance,
3315 rdistance->access_list ? rdistance->access_list : "",
3316 VTY_NEWLINE);
3317 }
3318}
3319
3320DEFUN (rip_distance,
3321 rip_distance_cmd,
3322 "distance <1-255>",
3323 "Administrative distance\n"
3324 "Distance value\n")
3325{
3326 rip->distance = atoi (argv[0]);
3327 return CMD_SUCCESS;
3328}
3329
3330DEFUN (no_rip_distance,
3331 no_rip_distance_cmd,
3332 "no distance <1-255>",
3333 NO_STR
3334 "Administrative distance\n"
3335 "Distance value\n")
3336{
3337 rip->distance = 0;
3338 return CMD_SUCCESS;
3339}
3340
3341DEFUN (rip_distance_source,
3342 rip_distance_source_cmd,
3343 "distance <1-255> A.B.C.D/M",
3344 "Administrative distance\n"
3345 "Distance value\n"
3346 "IP source prefix\n")
3347{
3348 rip_distance_set (vty, argv[0], argv[1], NULL);
3349 return CMD_SUCCESS;
3350}
3351
3352DEFUN (no_rip_distance_source,
3353 no_rip_distance_source_cmd,
3354 "no distance <1-255> A.B.C.D/M",
3355 NO_STR
3356 "Administrative distance\n"
3357 "Distance value\n"
3358 "IP source prefix\n")
3359{
3360 rip_distance_unset (vty, argv[0], argv[1], NULL);
3361 return CMD_SUCCESS;
3362}
3363
3364DEFUN (rip_distance_source_access_list,
3365 rip_distance_source_access_list_cmd,
3366 "distance <1-255> A.B.C.D/M WORD",
3367 "Administrative distance\n"
3368 "Distance value\n"
3369 "IP source prefix\n"
3370 "Access list name\n")
3371{
3372 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3373 return CMD_SUCCESS;
3374}
3375
3376DEFUN (no_rip_distance_source_access_list,
3377 no_rip_distance_source_access_list_cmd,
3378 "no distance <1-255> A.B.C.D/M WORD",
3379 NO_STR
3380 "Administrative distance\n"
3381 "Distance value\n"
3382 "IP source prefix\n"
3383 "Access list name\n")
3384{
3385 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3386 return CMD_SUCCESS;
3387}
3388
3389/* Print out routes update time. */
3390void
3391rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3392{
3393 struct timeval timer_now;
3394 time_t clock;
3395 struct tm *tm;
3396#define TIME_BUF 25
3397 char timebuf [TIME_BUF];
3398 struct thread *thread;
3399
3400 gettimeofday (&timer_now, NULL);
3401
3402 if ((thread = rinfo->t_timeout) != NULL)
3403 {
3404 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3405 tm = gmtime (&clock);
3406 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3407 vty_out (vty, "%5s", timebuf);
3408 }
3409 else if ((thread = rinfo->t_garbage_collect) != NULL)
3410 {
3411 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3412 tm = gmtime (&clock);
3413 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3414 vty_out (vty, "%5s", timebuf);
3415 }
3416}
3417
hasso8a676be2004-10-08 06:36:38 +00003418const char *
paul718e3742002-12-13 20:15:29 +00003419rip_route_type_print (int sub_type)
3420{
3421 switch (sub_type)
3422 {
3423 case RIP_ROUTE_RTE:
3424 return "n";
3425 case RIP_ROUTE_STATIC:
3426 return "s";
3427 case RIP_ROUTE_DEFAULT:
3428 return "d";
3429 case RIP_ROUTE_REDISTRIBUTE:
3430 return "r";
3431 case RIP_ROUTE_INTERFACE:
3432 return "i";
3433 default:
3434 return "?";
3435 }
3436}
3437
3438DEFUN (show_ip_rip,
3439 show_ip_rip_cmd,
3440 "show ip rip",
3441 SHOW_STR
3442 IP_STR
3443 "Show RIP routes\n")
3444{
3445 struct route_node *np;
3446 struct rip_info *rinfo;
3447
3448 if (! rip)
3449 return CMD_SUCCESS;
3450
hasso16705132003-05-25 14:49:19 +00003451 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3452 "Sub-codes:%s"
3453 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003454 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003455 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003456 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003457
3458 for (np = route_top (rip->table); np; np = route_next (np))
3459 if ((rinfo = np->info) != NULL)
3460 {
3461 int len;
3462
ajsf52d13c2005-10-01 17:38:06 +00003463 len = vty_out (vty, "%c(%s) %s/%d",
paul718e3742002-12-13 20:15:29 +00003464 /* np->lock, For debugging. */
ajsf52d13c2005-10-01 17:38:06 +00003465 zebra_route_char(rinfo->type),
paul718e3742002-12-13 20:15:29 +00003466 rip_route_type_print (rinfo->sub_type),
3467 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3468
hassoa1455d82004-03-03 19:36:24 +00003469 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003470
3471 if (len > 0)
3472 vty_out (vty, "%*s", len, " ");
3473
3474 if (rinfo->nexthop.s_addr)
3475 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3476 rinfo->metric);
3477 else
3478 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3479
3480 /* Route which exist in kernel routing table. */
3481 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3482 (rinfo->sub_type == RIP_ROUTE_RTE))
3483 {
3484 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003485 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003486 rip_vty_out_uptime (vty, rinfo);
3487 }
3488 else if (rinfo->metric == RIP_METRIC_INFINITY)
3489 {
3490 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003491 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003492 rip_vty_out_uptime (vty, rinfo);
3493 }
3494 else
hasso16705132003-05-25 14:49:19 +00003495 {
vincentfbf5d032005-09-29 11:25:50 +00003496 if (rinfo->external_metric)
3497 {
3498 len = vty_out (vty, "self (%s:%d)",
ajsf52d13c2005-10-01 17:38:06 +00003499 zebra_route_string(rinfo->type),
vincentfbf5d032005-09-29 11:25:50 +00003500 rinfo->external_metric);
3501 len = 16 - len;
3502 if (len > 0)
3503 vty_out (vty, "%*s", len, " ");
3504 }
3505 else
3506 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003507 vty_out (vty, "%3d", rinfo->tag);
3508 }
paul718e3742002-12-13 20:15:29 +00003509
3510 vty_out (vty, "%s", VTY_NEWLINE);
3511 }
3512 return CMD_SUCCESS;
3513}
3514
3515/* Return next event time. */
3516int
3517rip_next_thread_timer (struct thread *thread)
3518{
3519 struct timeval timer_now;
3520
3521 gettimeofday (&timer_now, NULL);
3522
3523 return thread->u.sands.tv_sec - timer_now.tv_sec;
3524}
3525
hasso16705132003-05-25 14:49:19 +00003526/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3527DEFUN (show_ip_rip_status,
3528 show_ip_rip_status_cmd,
3529 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003530 SHOW_STR
3531 IP_STR
hasso16705132003-05-25 14:49:19 +00003532 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003533 "IP routing protocol process parameters and statistics\n")
3534{
hasso52dc7ee2004-09-23 19:18:23 +00003535 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003536 struct interface *ifp;
3537 struct rip_interface *ri;
3538 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003539 const char *send_version;
3540 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003541
3542 if (! rip)
3543 return CMD_SUCCESS;
3544
3545 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3546 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3547 rip->update_time);
3548 vty_out (vty, " next due in %d seconds%s",
3549 rip_next_thread_timer (rip->t_update),
3550 VTY_NEWLINE);
3551 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3552 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3553 VTY_NEWLINE);
3554
3555 /* Filtering status show. */
3556 config_show_distribute (vty);
3557
3558 /* Default metric information. */
3559 vty_out (vty, " Default redistribution metric is %d%s",
3560 rip->default_metric, VTY_NEWLINE);
3561
3562 /* Redistribute information. */
3563 vty_out (vty, " Redistributing:");
3564 config_write_rip_redistribute (vty, 0);
3565 vty_out (vty, "%s", VTY_NEWLINE);
3566
paulf38a4712003-06-07 01:10:00 +00003567 vty_out (vty, " Default version control: send version %s,",
3568 lookup(ri_version_msg,rip->version_send));
3569 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3570 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3571 else
3572 vty_out (vty, " receive version %s %s",
3573 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003574
3575 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3576
paul1eb8ef22005-04-07 07:30:20 +00003577 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003578 {
paul718e3742002-12-13 20:15:29 +00003579 ri = ifp->info;
3580
3581 if (ri->enable_network || ri->enable_interface)
3582 {
3583 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003584 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003585 else
3586 send_version = lookup (ri_version_msg, ri->ri_send);
3587
3588 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003589 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003590 else
3591 receive_version = lookup (ri_version_msg, ri->ri_receive);
3592
3593 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3594 send_version,
3595 receive_version,
3596 ri->key_chain ? ri->key_chain : "",
3597 VTY_NEWLINE);
3598 }
3599 }
3600
3601 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3602 config_write_rip_network (vty, 0);
3603
paul4aaff3f2003-06-07 01:04:45 +00003604 {
3605 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003606 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003607 {
paul4aaff3f2003-06-07 01:04:45 +00003608 ri = ifp->info;
3609
3610 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3611 {
3612 if (!found_passive)
3613 {
3614 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3615 found_passive = 1;
3616 }
3617 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3618 }
3619 }
3620 }
3621
paul718e3742002-12-13 20:15:29 +00003622 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3623 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3624 rip_peer_display (vty);
3625
3626 rip_distance_show (vty);
3627
3628 return CMD_SUCCESS;
3629}
3630
3631/* RIP configuration write function. */
3632int
3633config_write_rip (struct vty *vty)
3634{
3635 int write = 0;
3636 struct route_node *rn;
3637 struct rip_distance *rdistance;
3638
3639 if (rip)
3640 {
3641 /* Router RIP statement. */
3642 vty_out (vty, "router rip%s", VTY_NEWLINE);
3643 write++;
3644
3645 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003646 if (rip->version_send != RI_RIP_VERSION_2
3647 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3648 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003649 VTY_NEWLINE);
3650
3651 /* RIP timer configuration. */
3652 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3653 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3654 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3655 vty_out (vty, " timers basic %lu %lu %lu%s",
3656 rip->update_time,
3657 rip->timeout_time,
3658 rip->garbage_time,
3659 VTY_NEWLINE);
3660
3661 /* Default information configuration. */
3662 if (rip->default_information)
3663 {
3664 if (rip->default_information_route_map)
3665 vty_out (vty, " default-information originate route-map %s%s",
3666 rip->default_information_route_map, VTY_NEWLINE);
3667 else
3668 vty_out (vty, " default-information originate%s",
3669 VTY_NEWLINE);
3670 }
3671
3672 /* Redistribute configuration. */
3673 config_write_rip_redistribute (vty, 1);
3674
3675 /* RIP offset-list configuration. */
3676 config_write_rip_offset_list (vty);
3677
3678 /* RIP enabled network and interface configuration. */
3679 config_write_rip_network (vty, 1);
3680
3681 /* RIP default metric configuration */
3682 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3683 vty_out (vty, " default-metric %d%s",
3684 rip->default_metric, VTY_NEWLINE);
3685
3686 /* Distribute configuration. */
3687 write += config_write_distribute (vty);
3688
hasso16705132003-05-25 14:49:19 +00003689 /* Interface routemap configuration */
3690 write += config_write_if_rmap (vty);
3691
paul718e3742002-12-13 20:15:29 +00003692 /* Distance configuration. */
3693 if (rip->distance)
3694 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3695
3696 /* RIP source IP prefix distance configuration. */
3697 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3698 if ((rdistance = rn->info) != NULL)
3699 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3700 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3701 rdistance->access_list ? rdistance->access_list : "",
3702 VTY_NEWLINE);
3703
3704 /* RIP static route configuration. */
3705 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3706 if (rn->info)
3707 vty_out (vty, " route %s/%d%s",
3708 inet_ntoa (rn->p.u.prefix4),
3709 rn->p.prefixlen,
3710 VTY_NEWLINE);
3711
3712 }
3713 return write;
3714}
3715
3716/* RIP node structure. */
3717struct cmd_node rip_node =
3718{
3719 RIP_NODE,
3720 "%s(config-router)# ",
3721 1
3722};
3723
3724/* Distribute-list update functions. */
3725void
3726rip_distribute_update (struct distribute *dist)
3727{
3728 struct interface *ifp;
3729 struct rip_interface *ri;
3730 struct access_list *alist;
3731 struct prefix_list *plist;
3732
3733 if (! dist->ifname)
3734 return;
3735
3736 ifp = if_lookup_by_name (dist->ifname);
3737 if (ifp == NULL)
3738 return;
3739
3740 ri = ifp->info;
3741
3742 if (dist->list[DISTRIBUTE_IN])
3743 {
3744 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3745 if (alist)
3746 ri->list[RIP_FILTER_IN] = alist;
3747 else
3748 ri->list[RIP_FILTER_IN] = NULL;
3749 }
3750 else
3751 ri->list[RIP_FILTER_IN] = NULL;
3752
3753 if (dist->list[DISTRIBUTE_OUT])
3754 {
3755 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3756 if (alist)
3757 ri->list[RIP_FILTER_OUT] = alist;
3758 else
3759 ri->list[RIP_FILTER_OUT] = NULL;
3760 }
3761 else
3762 ri->list[RIP_FILTER_OUT] = NULL;
3763
3764 if (dist->prefix[DISTRIBUTE_IN])
3765 {
3766 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3767 if (plist)
3768 ri->prefix[RIP_FILTER_IN] = plist;
3769 else
3770 ri->prefix[RIP_FILTER_IN] = NULL;
3771 }
3772 else
3773 ri->prefix[RIP_FILTER_IN] = NULL;
3774
3775 if (dist->prefix[DISTRIBUTE_OUT])
3776 {
3777 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3778 if (plist)
3779 ri->prefix[RIP_FILTER_OUT] = plist;
3780 else
3781 ri->prefix[RIP_FILTER_OUT] = NULL;
3782 }
3783 else
3784 ri->prefix[RIP_FILTER_OUT] = NULL;
3785}
3786
3787void
3788rip_distribute_update_interface (struct interface *ifp)
3789{
3790 struct distribute *dist;
3791
3792 dist = distribute_lookup (ifp->name);
3793 if (dist)
3794 rip_distribute_update (dist);
3795}
3796
3797/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003798/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003799void
paul02ff83c2004-06-11 11:27:03 +00003800rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003801{
3802 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003803 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003804
paul1eb8ef22005-04-07 07:30:20 +00003805 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3806 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003807}
paul11dde9c2004-05-31 14:00:00 +00003808/* ARGSUSED */
3809void
3810rip_distribute_update_all_wrapper(struct access_list *notused)
3811{
paul02ff83c2004-06-11 11:27:03 +00003812 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003813}
paul718e3742002-12-13 20:15:29 +00003814
3815/* Delete all added rip route. */
3816void
3817rip_clean ()
3818{
3819 int i;
3820 struct route_node *rp;
3821 struct rip_info *rinfo;
3822
3823 if (rip)
3824 {
3825 /* Clear RIP routes */
3826 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3827 if ((rinfo = rp->info) != NULL)
3828 {
3829 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3830 rinfo->sub_type == RIP_ROUTE_RTE)
3831 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3832 &rinfo->nexthop, rinfo->metric);
3833
3834 RIP_TIMER_OFF (rinfo->t_timeout);
3835 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3836
3837 rp->info = NULL;
3838 route_unlock_node (rp);
3839
3840 rip_info_free (rinfo);
3841 }
3842
3843 /* Cancel RIP related timers. */
3844 RIP_TIMER_OFF (rip->t_update);
3845 RIP_TIMER_OFF (rip->t_triggered_update);
3846 RIP_TIMER_OFF (rip->t_triggered_interval);
3847
3848 /* Cancel read thread. */
3849 if (rip->t_read)
3850 {
3851 thread_cancel (rip->t_read);
3852 rip->t_read = NULL;
3853 }
3854
3855 /* Close RIP socket. */
3856 if (rip->sock >= 0)
3857 {
3858 close (rip->sock);
3859 rip->sock = -1;
3860 }
3861
3862 /* Static RIP route configuration. */
3863 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3864 if (rp->info)
3865 {
3866 rp->info = NULL;
3867 route_unlock_node (rp);
3868 }
3869
3870 /* RIP neighbor configuration. */
3871 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3872 if (rp->info)
3873 {
3874 rp->info = NULL;
3875 route_unlock_node (rp);
3876 }
3877
3878 /* Redistribute related clear. */
3879 if (rip->default_information_route_map)
3880 free (rip->default_information_route_map);
3881
3882 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3883 if (rip->route_map[i].name)
3884 free (rip->route_map[i].name);
3885
3886 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3887 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3888 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3889
3890 XFREE (MTYPE_RIP, rip);
3891 rip = NULL;
3892 }
3893
3894 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003895 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003896 rip_offset_clean ();
3897 rip_interface_clean ();
3898 rip_distance_reset ();
3899 rip_redistribute_clean ();
3900}
3901
3902/* Reset all values to the default settings. */
3903void
3904rip_reset ()
3905{
3906 /* Reset global counters. */
3907 rip_global_route_changes = 0;
3908 rip_global_queries = 0;
3909
3910 /* Call ripd related reset functions. */
3911 rip_debug_reset ();
3912 rip_route_map_reset ();
3913
3914 /* Call library reset functions. */
3915 vty_reset ();
3916 access_list_reset ();
3917 prefix_list_reset ();
3918
3919 distribute_list_reset ();
3920
3921 rip_interface_reset ();
3922 rip_distance_reset ();
3923
3924 rip_zclient_reset ();
3925}
3926
hasso16705132003-05-25 14:49:19 +00003927void
3928rip_if_rmap_update (struct if_rmap *if_rmap)
3929{
3930 struct interface *ifp;
3931 struct rip_interface *ri;
3932 struct route_map *rmap;
3933
3934 ifp = if_lookup_by_name (if_rmap->ifname);
3935 if (ifp == NULL)
3936 return;
3937
3938 ri = ifp->info;
3939
3940 if (if_rmap->routemap[IF_RMAP_IN])
3941 {
3942 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3943 if (rmap)
3944 ri->routemap[IF_RMAP_IN] = rmap;
3945 else
3946 ri->routemap[IF_RMAP_IN] = NULL;
3947 }
3948 else
3949 ri->routemap[RIP_FILTER_IN] = NULL;
3950
3951 if (if_rmap->routemap[IF_RMAP_OUT])
3952 {
3953 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3954 if (rmap)
3955 ri->routemap[IF_RMAP_OUT] = rmap;
3956 else
3957 ri->routemap[IF_RMAP_OUT] = NULL;
3958 }
3959 else
3960 ri->routemap[RIP_FILTER_OUT] = NULL;
3961}
3962
3963void
3964rip_if_rmap_update_interface (struct interface *ifp)
3965{
3966 struct if_rmap *if_rmap;
3967
3968 if_rmap = if_rmap_lookup (ifp->name);
3969 if (if_rmap)
3970 rip_if_rmap_update (if_rmap);
3971}
3972
3973void
3974rip_routemap_update_redistribute (void)
3975{
3976 int i;
3977
3978 if (rip)
3979 {
3980 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3981 {
3982 if (rip->route_map[i].name)
3983 rip->route_map[i].map =
3984 route_map_lookup_by_name (rip->route_map[i].name);
3985 }
3986 }
3987}
3988
paul11dde9c2004-05-31 14:00:00 +00003989/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003990void
hasso98b718a2004-10-11 12:57:57 +00003991rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003992{
3993 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003994 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003995
paul1eb8ef22005-04-07 07:30:20 +00003996 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3997 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003998
3999 rip_routemap_update_redistribute ();
4000}
4001
paul718e3742002-12-13 20:15:29 +00004002/* Allocate new rip structure and set default value. */
4003void
4004rip_init ()
4005{
4006 /* Randomize for triggered update random(). */
4007 srand (time (NULL));
4008
4009 /* Install top nodes. */
4010 install_node (&rip_node, config_write_rip);
4011
4012 /* Install rip commands. */
4013 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004014 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004015 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004016 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004017 install_element (CONFIG_NODE, &router_rip_cmd);
4018 install_element (CONFIG_NODE, &no_router_rip_cmd);
4019
4020 install_default (RIP_NODE);
4021 install_element (RIP_NODE, &rip_version_cmd);
4022 install_element (RIP_NODE, &no_rip_version_cmd);
4023 install_element (RIP_NODE, &no_rip_version_val_cmd);
4024 install_element (RIP_NODE, &rip_default_metric_cmd);
4025 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4026 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4027 install_element (RIP_NODE, &rip_timers_cmd);
4028 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00004029 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00004030 install_element (RIP_NODE, &rip_route_cmd);
4031 install_element (RIP_NODE, &no_rip_route_cmd);
4032 install_element (RIP_NODE, &rip_distance_cmd);
4033 install_element (RIP_NODE, &no_rip_distance_cmd);
4034 install_element (RIP_NODE, &rip_distance_source_cmd);
4035 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4036 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4037 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4038
4039 /* Debug related init. */
4040 rip_debug_init ();
4041
paul718e3742002-12-13 20:15:29 +00004042 /* SNMP init. */
4043#ifdef HAVE_SNMP
4044 rip_snmp_init ();
4045#endif /* HAVE_SNMP */
4046
4047 /* Access list install. */
4048 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004049 access_list_add_hook (rip_distribute_update_all_wrapper);
4050 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004051
4052 /* Prefix list initialize.*/
4053 prefix_list_init ();
4054 prefix_list_add_hook (rip_distribute_update_all);
4055 prefix_list_delete_hook (rip_distribute_update_all);
4056
4057 /* Distribute list install. */
4058 distribute_list_init (RIP_NODE);
4059 distribute_list_add_hook (rip_distribute_update);
4060 distribute_list_delete_hook (rip_distribute_update);
4061
hasso16705132003-05-25 14:49:19 +00004062 /* Route-map */
4063 rip_route_map_init ();
4064 rip_offset_init ();
4065
4066 route_map_add_hook (rip_routemap_update);
4067 route_map_delete_hook (rip_routemap_update);
4068
4069 if_rmap_init (RIP_NODE);
4070 if_rmap_hook_add (rip_if_rmap_update);
4071 if_rmap_hook_delete (rip_if_rmap_update);
4072
paul718e3742002-12-13 20:15:29 +00004073 /* Distance control. */
4074 rip_distance_table = route_table_init ();
4075}