blob: fd1f2da6785ec48a404d4440e1896df77b28e873 [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 */
paulf69bd9d2005-06-03 18:01:50 +00001361 }
1362
paul2c61ae32005-08-16 15:22:14 +00001363 /* sending port must always be the RIP port */
1364 addr.sin_port = htons (RIP_PORT_DEFAULT);
1365
paula4e987e2005-06-03 17:46:49 +00001366 /* Make datagram socket. */
1367 sock = socket (AF_INET, SOCK_DGRAM, 0);
1368 if (sock < 0)
1369 {
1370 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1371 exit (1);
1372 }
1373
1374 sockopt_broadcast (sock);
1375 sockopt_reuseaddr (sock);
1376 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001377#ifdef RIP_RECVMSG
1378 setsockopt_pktinfo (sock);
1379#endif /* RIP_RECVMSG */
1380
1381 if (ripd_privs.change (ZPRIVS_RAISE))
1382 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001383 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1384 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1385
paula4e987e2005-06-03 17:46:49 +00001386 {
1387 int save_errno = errno;
1388 if (ripd_privs.change (ZPRIVS_LOWER))
1389 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001390
1391 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1392 sock, inet_ntoa(addr.sin_addr),
1393 (int) ntohs(addr.sin_port),
1394 safe_strerror(save_errno));
1395
paulf69bd9d2005-06-03 18:01:50 +00001396 close (sock);
paula4e987e2005-06-03 17:46:49 +00001397 return ret;
1398 }
paulf69bd9d2005-06-03 18:01:50 +00001399
paula4e987e2005-06-03 17:46:49 +00001400 if (ripd_privs.change (ZPRIVS_LOWER))
1401 zlog_err ("rip_create_socket: could not lower privs");
1402
1403 return sock;
1404}
1405
paulc49ad8f2004-10-22 10:27:28 +00001406/* RIP packet send to destination address, on interface denoted by
1407 * by connected argument. NULL to argument denotes destination should be
1408 * should be RIP multicast group
1409 */
paul718e3742002-12-13 20:15:29 +00001410int
paulc49ad8f2004-10-22 10:27:28 +00001411rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1412 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001413{
paul931cd542004-01-23 15:31:42 +00001414 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001415 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001416
1417 assert (ifc != NULL);
1418
paul931cd542004-01-23 15:31:42 +00001419 if (IS_RIP_DEBUG_PACKET)
1420 {
paulf69bd9d2005-06-03 18:01:50 +00001421#define ADDRESS_SIZE 20
1422 char dst[ADDRESS_SIZE];
1423 dst[ADDRESS_SIZE - 1] = '\0';
1424
paul931cd542004-01-23 15:31:42 +00001425 if (to)
1426 {
paulf69bd9d2005-06-03 18:01:50 +00001427 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001428 }
1429 else
1430 {
1431 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001432 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001433 }
paulf69bd9d2005-06-03 18:01:50 +00001434#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001435 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001436 inet_ntoa(ifc->address->u.prefix4),
1437 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001438 }
paulf69bd9d2005-06-03 18:01:50 +00001439
paulc49ad8f2004-10-22 10:27:28 +00001440 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001441 {
1442 /*
1443 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1444 * with multiple addresses on the same subnet: the first address
1445 * on the subnet is configured "primary", and all subsequent addresses
1446 * on that subnet are treated as "secondary" addresses.
1447 * In order to avoid routing-table bloat on other rip listeners,
1448 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1449 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1450 * flag is set, we would end up sending a packet for a "secondary"
1451 * source address on non-linux systems.
1452 */
1453 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001454 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001455 return 0;
1456 }
1457
paul718e3742002-12-13 20:15:29 +00001458 /* Make destination address. */
1459 memset (&sin, 0, sizeof (struct sockaddr_in));
1460 sin.sin_family = AF_INET;
1461#ifdef HAVE_SIN_LEN
1462 sin.sin_len = sizeof (struct sockaddr_in);
1463#endif /* HAVE_SIN_LEN */
1464
1465 /* When destination is specified, use it's port and address. */
1466 if (to)
1467 {
paul718e3742002-12-13 20:15:29 +00001468 sin.sin_port = to->sin_port;
1469 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001470 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001471 }
1472 else
1473 {
paul2c61ae32005-08-16 15:22:14 +00001474 struct sockaddr_in from;
1475
paul718e3742002-12-13 20:15:29 +00001476 sin.sin_port = htons (RIP_PORT_DEFAULT);
1477 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001478
1479 /* multicast send should bind to local interface address */
1480 from.sin_family = AF_INET;
1481 from.sin_port = htons (RIP_PORT_DEFAULT);
1482 from.sin_addr = ifc->address->u.prefix4;
1483#ifdef HAVE_SIN_LEN
1484 from.sin_len = sizeof (struct sockaddr_in);
1485#endif /* HAVE_SIN_LEN */
1486
paul931cd542004-01-23 15:31:42 +00001487 /*
1488 * we have to open a new socket for each packet because this
1489 * is the most portable way to bind to a different source
1490 * ipv4 address for each packet.
1491 */
paul2c61ae32005-08-16 15:22:14 +00001492 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001493 {
paulf69bd9d2005-06-03 18:01:50 +00001494 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001495 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001496 }
paulc49ad8f2004-10-22 10:27:28 +00001497 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001498 }
1499
paul931cd542004-01-23 15:31:42 +00001500 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001501 sizeof (struct sockaddr_in));
1502
1503 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001504 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001505 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001506
1507 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001508 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001509
paul931cd542004-01-23 15:31:42 +00001510 if (!to)
1511 close(send_sock);
1512
paul718e3742002-12-13 20:15:29 +00001513 return ret;
1514}
1515
1516/* Add redistributed route to RIP table. */
1517void
1518rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
vincentfbf5d032005-09-29 11:25:50 +00001519 unsigned int ifindex, struct in_addr *nexthop,
1520 unsigned int metric, unsigned char distance)
paul718e3742002-12-13 20:15:29 +00001521{
1522 int ret;
1523 struct route_node *rp;
1524 struct rip_info *rinfo;
1525
1526 /* Redistribute route */
1527 ret = rip_destination_check (p->prefix);
1528 if (! ret)
1529 return;
1530
1531 rp = route_node_get (rip->table, (struct prefix *) p);
1532
1533 rinfo = rp->info;
1534
1535 if (rinfo)
1536 {
1537 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1538 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1539 && rinfo->metric != RIP_METRIC_INFINITY)
1540 {
1541 route_unlock_node (rp);
1542 return;
1543 }
1544
1545 /* Manually configured RIP route check. */
1546 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001547 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1548 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001549 {
hasso16705132003-05-25 14:49:19 +00001550 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1551 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001552 {
1553 route_unlock_node (rp);
1554 return;
1555 }
1556 }
1557
1558 RIP_TIMER_OFF (rinfo->t_timeout);
1559 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1560
1561 if (rip_route_rte (rinfo))
1562 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1563 rinfo->metric);
1564 rp->info = NULL;
1565 rip_info_free (rinfo);
1566
1567 route_unlock_node (rp);
1568 }
1569
1570 rinfo = rip_info_new ();
1571
1572 rinfo->type = type;
1573 rinfo->sub_type = sub_type;
1574 rinfo->ifindex = ifindex;
1575 rinfo->metric = 1;
vincentfbf5d032005-09-29 11:25:50 +00001576 rinfo->external_metric = metric;
1577 rinfo->distance = distance;
paul718e3742002-12-13 20:15:29 +00001578 rinfo->rp = rp;
1579
1580 if (nexthop)
1581 rinfo->nexthop = *nexthop;
1582
1583 rinfo->flags |= RIP_RTF_FIB;
1584 rp->info = rinfo;
1585
1586 rinfo->flags |= RIP_RTF_CHANGED;
1587
hasso16705132003-05-25 14:49:19 +00001588 if (IS_RIP_DEBUG_EVENT) {
1589 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001590 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001591 inet_ntoa(p->prefix), p->prefixlen,
1592 ifindex2ifname(ifindex));
1593 else
ajs5d6c3772004-12-08 19:24:06 +00001594 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001595 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1596 ifindex2ifname(ifindex));
1597 }
1598
1599
paul718e3742002-12-13 20:15:29 +00001600 rip_event (RIP_TRIGGERED_UPDATE, 0);
1601}
1602
1603/* Delete redistributed route from RIP table. */
1604void
1605rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1606 unsigned int ifindex)
1607{
1608 int ret;
1609 struct route_node *rp;
1610 struct rip_info *rinfo;
1611
1612 ret = rip_destination_check (p->prefix);
1613 if (! ret)
1614 return;
1615
1616 rp = route_node_lookup (rip->table, (struct prefix *) p);
1617 if (rp)
1618 {
1619 rinfo = rp->info;
1620
1621 if (rinfo != NULL
1622 && rinfo->type == type
1623 && rinfo->sub_type == sub_type
1624 && rinfo->ifindex == ifindex)
1625 {
1626 /* Perform poisoned reverse. */
1627 rinfo->metric = RIP_METRIC_INFINITY;
1628 RIP_TIMER_ON (rinfo->t_garbage_collect,
1629 rip_garbage_collect, rip->garbage_time);
1630 RIP_TIMER_OFF (rinfo->t_timeout);
1631 rinfo->flags |= RIP_RTF_CHANGED;
1632
hasso16705132003-05-25 14:49:19 +00001633 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001634 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001635 inet_ntoa(p->prefix), p->prefixlen,
1636 ifindex2ifname(ifindex));
1637
paul718e3742002-12-13 20:15:29 +00001638 rip_event (RIP_TRIGGERED_UPDATE, 0);
1639 }
1640 }
1641}
1642
1643/* Response to request called from rip_read ().*/
1644void
1645rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001646 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001647{
1648 caddr_t lim;
1649 struct rte *rte;
1650 struct prefix_ipv4 p;
1651 struct route_node *rp;
1652 struct rip_info *rinfo;
1653 struct rip_interface *ri;
1654
hasso16705132003-05-25 14:49:19 +00001655 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001656 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001657 return;
1658
hasso429a0f82004-02-22 23:42:22 +00001659 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001660 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001661 if (! ri->running)
1662 return;
paul718e3742002-12-13 20:15:29 +00001663
1664 /* When passive interface is specified, suppress responses */
1665 if (ri->passive)
1666 return;
paulc49ad8f2004-10-22 10:27:28 +00001667
paul718e3742002-12-13 20:15:29 +00001668 /* RIP peer update. */
1669 rip_peer_update (from, packet->version);
1670
1671 lim = ((caddr_t) packet) + size;
1672 rte = packet->rte;
1673
1674 /* The Request is processed entry by entry. If there are no
1675 entries, no response is given. */
1676 if (lim == (caddr_t) rte)
1677 return;
1678
1679 /* There is one special case. If there is exactly one entry in the
1680 request, and it has an address family identifier of zero and a
1681 metric of infinity (i.e., 16), then this is a request to send the
1682 entire routing table. */
1683 if (lim == ((caddr_t) (rte + 1)) &&
1684 ntohs (rte->family) == 0 &&
1685 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1686 {
paulcc1131a2003-10-15 23:20:17 +00001687 struct prefix_ipv4 saddr;
1688
1689 /* saddr will be used for determining which routes to split-horizon.
1690 Since the source address we'll pick will be on the same subnet as the
1691 destination, for the purpose of split-horizoning, we'll
1692 pretend that "from" is our source address. */
1693 saddr.family = AF_INET;
1694 saddr.prefixlen = IPV4_MAX_BITLEN;
1695 saddr.prefix = from->sin_addr;
1696
paul718e3742002-12-13 20:15:29 +00001697 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001698 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001699 }
1700 else
1701 {
1702 /* Examine the list of RTEs in the Request one by one. For each
1703 entry, look up the destination in the router's routing
1704 database and, if there is a route, put that route's metric in
1705 the metric field of the RTE. If there is no explicit route
1706 to the specified destination, put infinity in the metric
1707 field. Once all the entries have been filled in, change the
1708 command from Request to Response and send the datagram back
1709 to the requestor. */
1710 p.family = AF_INET;
1711
1712 for (; ((caddr_t) rte) < lim; rte++)
1713 {
1714 p.prefix = rte->prefix;
1715 p.prefixlen = ip_masklen (rte->mask);
1716 apply_mask_ipv4 (&p);
1717
1718 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1719 if (rp)
1720 {
1721 rinfo = rp->info;
1722 rte->metric = htonl (rinfo->metric);
1723 route_unlock_node (rp);
1724 }
1725 else
1726 rte->metric = htonl (RIP_METRIC_INFINITY);
1727 }
1728 packet->command = RIP_RESPONSE;
1729
paulc49ad8f2004-10-22 10:27:28 +00001730 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001731 }
1732 rip_global_queries++;
1733}
1734
1735#if RIP_RECVMSG
1736/* Set IPv6 packet info to the socket. */
1737static int
1738setsockopt_pktinfo (int sock)
1739{
1740 int ret;
1741 int val = 1;
1742
1743 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1744 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001745 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001746 return ret;
1747}
1748
1749/* Read RIP packet by recvmsg function. */
1750int
1751rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1752 int *ifindex)
1753{
1754 int ret;
1755 struct msghdr msg;
1756 struct iovec iov;
1757 struct cmsghdr *ptr;
1758 char adata[1024];
1759
1760 msg.msg_name = (void *) from;
1761 msg.msg_namelen = sizeof (struct sockaddr_in);
1762 msg.msg_iov = &iov;
1763 msg.msg_iovlen = 1;
1764 msg.msg_control = (void *) adata;
1765 msg.msg_controllen = sizeof adata;
1766 iov.iov_base = buf;
1767 iov.iov_len = size;
1768
1769 ret = recvmsg (sock, &msg, 0);
1770 if (ret < 0)
1771 return ret;
1772
ajsb99760a2005-01-04 16:24:43 +00001773 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001774 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1775 {
1776 struct in_pktinfo *pktinfo;
1777 int i;
1778
1779 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1780 i = pktinfo->ipi_ifindex;
1781 }
1782 return ret;
1783}
1784
1785/* RIP packet read function. */
1786int
1787rip_read_new (struct thread *t)
1788{
1789 int ret;
1790 int sock;
1791 char buf[RIP_PACKET_MAXSIZ];
1792 struct sockaddr_in from;
1793 unsigned int ifindex;
1794
1795 /* Fetch socket then register myself. */
1796 sock = THREAD_FD (t);
1797 rip_event (RIP_READ, sock);
1798
1799 /* Read RIP packet. */
1800 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1801 if (ret < 0)
1802 {
ajs6099b3b2004-11-20 02:06:59 +00001803 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001804 return ret;
1805 }
1806
1807 return ret;
1808}
1809#endif /* RIP_RECVMSG */
1810
1811/* First entry point of RIP packet. */
1812int
1813rip_read (struct thread *t)
1814{
1815 int sock;
1816 int ret;
1817 int rtenum;
1818 union rip_buf rip_buf;
1819 struct rip_packet *packet;
1820 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001821 int len;
1822 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001823 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001824 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001825 struct rip_interface *ri;
1826
1827 /* Fetch socket then register myself. */
1828 sock = THREAD_FD (t);
1829 rip->t_read = NULL;
1830
1831 /* Add myself to tne next event */
1832 rip_event (RIP_READ, sock);
1833
1834 /* RIPd manages only IPv4. */
1835 memset (&from, 0, sizeof (struct sockaddr_in));
1836 fromlen = sizeof (struct sockaddr_in);
1837
1838 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1839 (struct sockaddr *) &from, &fromlen);
1840 if (len < 0)
1841 {
ajs6099b3b2004-11-20 02:06:59 +00001842 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001843 return len;
1844 }
1845
1846 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001847 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001848 {
1849 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001850 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001851 return -1;
1852 }
1853
1854 /* Which interface is this packet comes from. */
1855 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001856
paul718e3742002-12-13 20:15:29 +00001857 /* RIP packet received */
1858 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001859 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001860 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1861 ifp ? ifp->name : "unknown");
1862
1863 /* If this packet come from unknown interface, ignore it. */
1864 if (ifp == NULL)
1865 {
ajs766a0ca2004-12-15 14:55:51 +00001866 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1867 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001868 return -1;
1869 }
1870
1871 ifc = connected_lookup_address (ifp, from.sin_addr);
1872
1873 if (ifc == NULL)
1874 {
ajs766a0ca2004-12-15 14:55:51 +00001875 zlog_info ("rip_read: cannot find connected address for packet from %s "
1876 "port %d on interface %s",
1877 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001878 return -1;
1879 }
1880
1881 /* Packet length check. */
1882 if (len < RIP_PACKET_MINSIZ)
1883 {
1884 zlog_warn ("packet size %d is smaller than minimum size %d",
1885 len, RIP_PACKET_MINSIZ);
1886 rip_peer_bad_packet (&from);
1887 return len;
1888 }
1889 if (len > RIP_PACKET_MAXSIZ)
1890 {
1891 zlog_warn ("packet size %d is larger than max size %d",
1892 len, RIP_PACKET_MAXSIZ);
1893 rip_peer_bad_packet (&from);
1894 return len;
1895 }
1896
1897 /* Packet alignment check. */
1898 if ((len - RIP_PACKET_MINSIZ) % 20)
1899 {
1900 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1901 rip_peer_bad_packet (&from);
1902 return len;
1903 }
1904
1905 /* Set RTE number. */
1906 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1907
1908 /* For easy to handle. */
1909 packet = &rip_buf.rip_packet;
1910
1911 /* RIP version check. */
1912 if (packet->version == 0)
1913 {
1914 zlog_info ("version 0 with command %d received.", packet->command);
1915 rip_peer_bad_packet (&from);
1916 return -1;
1917 }
1918
1919 /* Dump RIP packet. */
1920 if (IS_RIP_DEBUG_RECV)
1921 rip_packet_dump (packet, len, "RECV");
1922
1923 /* RIP version adjust. This code should rethink now. RFC1058 says
1924 that "Version 1 implementations are to ignore this extra data and
1925 process only the fields specified in this document.". So RIPv3
1926 packet should be treated as RIPv1 ignoring must be zero field. */
1927 if (packet->version > RIPv2)
1928 packet->version = RIPv2;
1929
1930 /* Is RIP running or is this RIP neighbor ?*/
1931 ri = ifp->info;
1932 if (! ri->running && ! rip_neighbor_lookup (&from))
1933 {
1934 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001935 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001936 rip_peer_bad_packet (&from);
1937 return -1;
1938 }
1939
1940 /* RIP Version check. */
1941 if (packet->command == RIP_RESPONSE)
1942 {
paulf38a4712003-06-07 01:10:00 +00001943 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1944 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001945 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001946 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001947 {
1948 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001949 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001950 packet->version);
1951 rip_peer_bad_packet (&from);
1952 return -1;
1953 }
1954 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001955 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001956 {
1957 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001958 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001959 packet->version);
1960 rip_peer_bad_packet (&from);
1961 return -1;
1962 }
paul718e3742002-12-13 20:15:29 +00001963 }
1964
1965 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1966 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1967 accepted; authenticated RIP-2 messages shall be discarded. */
1968
1969 if ((ri->auth_type == RIP_NO_AUTH)
1970 && rtenum
paulca5e5162004-06-06 22:06:33 +00001971 && (packet->version == RIPv2)
1972 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001973 {
1974 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001975 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001976 packet->version);
1977 rip_peer_bad_packet (&from);
1978 return -1;
1979 }
1980
1981 /* If the router is configured to authenticate RIP-2 messages, then
1982 RIP-1 messages and RIP-2 messages which pass authentication
1983 testing shall be accepted; unauthenticated and failed
1984 authentication RIP-2 messages shall be discarded. For maximum
1985 security, RIP-1 messages should be ignored when authentication is
1986 in use (see section 4.1); otherwise, the routing information from
1987 authenticated messages will be propagated by RIP-1 routers in an
1988 unauthenticated manner. */
1989
1990 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001991 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001992 {
1993 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001994 if (packet->version == RIPv1
1995 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001996 {
1997 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001998 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001999 ("packet RIPv%d is dropped because authentication enabled",
2000 packet->version);
paul718e3742002-12-13 20:15:29 +00002001 rip_peer_bad_packet (&from);
2002 return -1;
2003 }
2004
2005 /* Check RIPv2 authentication. */
2006 if (packet->version == RIPv2)
2007 {
paulca5e5162004-06-06 22:06:33 +00002008 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00002009 {
paulca5e5162004-06-06 22:06:33 +00002010 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00002011 {
2012 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2013 if (! ret)
2014 {
2015 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002016 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002017 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00002018 rip_peer_bad_packet (&from);
2019 return -1;
2020 }
2021 else
2022 {
2023 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002024 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002025 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002026 }
2027 }
paulca5e5162004-06-06 22:06:33 +00002028 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002029 {
paulca5e5162004-06-06 22:06:33 +00002030 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002031 if (! ret)
2032 {
2033 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002034 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002035 rip_peer_bad_packet (&from);
2036 return -1;
2037 }
2038 else
2039 {
2040 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002041 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002042 }
2043 /* Reset RIP packet length to trim MD5 data. */
2044 len = ret;
2045 }
2046 else
2047 {
2048 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002049 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002050 ntohs (packet->rte->tag));
2051 rip_peer_bad_packet (&from);
2052 return -1;
2053 }
2054 }
2055 else
2056 {
2057 /* There is no authentication in the packet. */
2058 if (ri->auth_str || ri->key_chain)
2059 {
2060 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002061 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002062 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002063 rip_peer_bad_packet (&from);
2064 return -1;
2065 }
2066 }
2067 }
2068 }
2069
2070 /* Process each command. */
2071 switch (packet->command)
2072 {
2073 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002074 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002075 break;
2076 case RIP_REQUEST:
2077 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002078 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002079 break;
2080 case RIP_TRACEON:
2081 case RIP_TRACEOFF:
2082 zlog_info ("Obsolete command %s received, please sent it to routed",
2083 lookup (rip_msg, packet->command));
2084 rip_peer_bad_packet (&from);
2085 break;
2086 case RIP_POLL_ENTRY:
2087 zlog_info ("Obsolete command %s received",
2088 lookup (rip_msg, packet->command));
2089 rip_peer_bad_packet (&from);
2090 break;
2091 default:
2092 zlog_info ("Unknown RIP command %d received", packet->command);
2093 rip_peer_bad_packet (&from);
2094 break;
2095 }
2096
2097 return len;
2098}
2099
paul718e3742002-12-13 20:15:29 +00002100/* Write routing table entry to the stream and return next index of
2101 the routing table entry in the stream. */
2102int
2103rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002104 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002105{
2106 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002107
2108 /* Write routing table entry. */
2109 if (version == RIPv1)
2110 {
2111 stream_putw (s, AF_INET);
2112 stream_putw (s, 0);
2113 stream_put_ipv4 (s, p->prefix.s_addr);
2114 stream_put_ipv4 (s, 0);
2115 stream_put_ipv4 (s, 0);
2116 stream_putl (s, rinfo->metric_out);
2117 }
2118 else
2119 {
2120 masklen2ip (p->prefixlen, &mask);
2121
2122 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002123 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002124 stream_put_ipv4 (s, p->prefix.s_addr);
2125 stream_put_ipv4 (s, mask.s_addr);
2126 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2127 stream_putl (s, rinfo->metric_out);
2128 }
2129
2130 return ++num;
2131}
2132
2133/* Send update to the ifp or spcified neighbor. */
2134void
paulc49ad8f2004-10-22 10:27:28 +00002135rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2136 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002137{
2138 int ret;
2139 struct stream *s;
2140 struct route_node *rp;
2141 struct rip_info *rinfo;
2142 struct rip_interface *ri;
2143 struct prefix_ipv4 *p;
2144 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002145 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002146 struct key *key = NULL;
2147 /* this might need to made dynamic if RIP ever supported auth methods
2148 with larger key string sizes */
2149 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2150 size_t doff; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002151 int num = 0;
paul718e3742002-12-13 20:15:29 +00002152 int rtemax;
paul01d09082003-06-08 21:22:18 +00002153 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002154
2155 /* Logging output event. */
2156 if (IS_RIP_DEBUG_EVENT)
2157 {
2158 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002159 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002160 else
ajs5d6c3772004-12-08 19:24:06 +00002161 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002162 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002163 }
2164
2165 /* Set output stream. */
2166 s = rip->obuf;
2167
2168 /* Reset stream and RTE counter. */
2169 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002170 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2171
2172 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002173 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002174
2175 /* If output interface is in simple password authentication mode, we
2176 need space for authentication data. */
2177 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2178 rtemax -= 1;
2179
2180 /* If output interface is in MD5 authentication mode, we need space
2181 for authentication header and data. */
2182 if (ri->auth_type == RIP_AUTH_MD5)
2183 rtemax -= 2;
2184
2185 /* If output interface is in simple password authentication mode
2186 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002187 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002188 {
2189 if (ri->key_chain)
2190 {
2191 struct keychain *keychain;
2192
2193 keychain = keychain_lookup (ri->key_chain);
2194 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002195 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002196 }
paulb14ee002005-02-04 23:42:41 +00002197 /* to be passed to auth functions later */
2198 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002199 }
2200
paul727d1042002-12-13 20:50:29 +00002201 if (version == RIPv1)
2202 {
paulc49ad8f2004-10-22 10:27:28 +00002203 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002204 apply_classful_mask_ipv4 (&ifaddrclass);
2205 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002206 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002207 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002208 }
2209
paul718e3742002-12-13 20:15:29 +00002210 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2211 if ((rinfo = rp->info) != NULL)
2212 {
paul727d1042002-12-13 20:50:29 +00002213 /* For RIPv1, if we are subnetted, output subnets in our network */
2214 /* that have the same mask as the output "interface". For other */
2215 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002216
2217 if (version == RIPv1)
2218 {
paul727d1042002-12-13 20:50:29 +00002219 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002220
2221 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002222 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002223 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002224
paul727d1042002-12-13 20:50:29 +00002225 if (subnetted &&
2226 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2227 {
paulc49ad8f2004-10-22 10:27:28 +00002228 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002229 (rp->p.prefixlen != 32))
2230 continue;
2231 }
2232 else
2233 {
2234 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2235 apply_classful_mask_ipv4(&classfull);
2236 if (rp->p.u.prefix4.s_addr != 0 &&
2237 classfull.prefixlen != rp->p.prefixlen)
2238 continue;
2239 }
paul718e3742002-12-13 20:15:29 +00002240 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002241 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002242 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002243 }
2244 else
2245 p = (struct prefix_ipv4 *) &rp->p;
2246
2247 /* Apply output filters. */
2248 ret = rip_outgoing_filter (p, ri);
2249 if (ret < 0)
2250 continue;
2251
2252 /* Changed route only output. */
2253 if (route_type == rip_changed_route &&
2254 (! (rinfo->flags & RIP_RTF_CHANGED)))
2255 continue;
2256
2257 /* Split horizon. */
2258 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002259 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002260 {
paul42d14d92003-11-17 09:15:18 +00002261 /*
2262 * We perform split horizon for RIP and connected route.
2263 * For rip routes, we want to suppress the route if we would
2264 * end up sending the route back on the interface that we
2265 * learned it from, with a higher metric. For connected routes,
2266 * we suppress the route if the prefix is a subset of the
2267 * source address that we are going to use for the packet
2268 * (in order to handle the case when multiple subnets are
2269 * configured on the same interface).
2270 */
2271 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002272 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002273 continue;
2274 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002275 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002276 continue;
2277 }
2278
2279 /* Preparation for route-map. */
2280 rinfo->metric_set = 0;
2281 rinfo->nexthop_out.s_addr = 0;
2282 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002283 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002284 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002285
hasso16705132003-05-25 14:49:19 +00002286 /* In order to avoid some local loops,
2287 * if the RIP route has a nexthop via this interface, keep the nexthop,
2288 * otherwise set it to 0. The nexthop should not be propagated
2289 * beyond the local broadcast/multicast area in order
2290 * to avoid an IGP multi-level recursive look-up.
2291 * see (4.4)
2292 */
paulc49ad8f2004-10-22 10:27:28 +00002293 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002294 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002295
2296 /* Interface route-map */
2297 if (ri->routemap[RIP_FILTER_OUT])
2298 {
2299 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2300 (struct prefix *) p, RMAP_RIP,
2301 rinfo);
2302
2303 if (ret == RMAP_DENYMATCH)
2304 {
2305 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002306 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002307 inet_ntoa (p->prefix), p->prefixlen);
2308 continue;
2309 }
2310 }
paul718e3742002-12-13 20:15:29 +00002311
hasso16705132003-05-25 14:49:19 +00002312 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002313 if (rip->route_map[rinfo->type].name
2314 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2315 {
2316 ret = route_map_apply (rip->route_map[rinfo->type].map,
2317 (struct prefix *)p, RMAP_RIP, rinfo);
2318
2319 if (ret == RMAP_DENYMATCH)
2320 {
2321 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002322 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002323 inet_ntoa (p->prefix), p->prefixlen);
2324 continue;
2325 }
2326 }
2327
2328 /* When route-map does not set metric. */
2329 if (! rinfo->metric_set)
2330 {
2331 /* If redistribute metric is set. */
2332 if (rip->route_map[rinfo->type].metric_config
2333 && rinfo->metric != RIP_METRIC_INFINITY)
2334 {
2335 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2336 }
2337 else
2338 {
2339 /* If the route is not connected or localy generated
2340 one, use default-metric value*/
2341 if (rinfo->type != ZEBRA_ROUTE_RIP
2342 && rinfo->type != ZEBRA_ROUTE_CONNECT
2343 && rinfo->metric != RIP_METRIC_INFINITY)
2344 rinfo->metric_out = rip->default_metric;
2345 }
2346 }
2347
2348 /* Apply offset-list */
2349 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002350 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002351
2352 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2353 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002354
2355 /* Perform split-horizon with poisoned reverse
2356 * for RIP and connected routes.
2357 **/
2358 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002359 /*
2360 * We perform split horizon for RIP and connected route.
2361 * For rip routes, we want to suppress the route if we would
2362 * end up sending the route back on the interface that we
2363 * learned it from, with a higher metric. For connected routes,
2364 * we suppress the route if the prefix is a subset of the
2365 * source address that we are going to use for the packet
2366 * (in order to handle the case when multiple subnets are
2367 * configured on the same interface).
2368 */
2369 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002370 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002371 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002372 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002373 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002374 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002375 }
paulb14ee002005-02-04 23:42:41 +00002376
2377 /* Prepare preamble, auth headers, if needs be */
2378 if (num == 0)
2379 {
2380 stream_putc (s, RIP_RESPONSE);
2381 stream_putc (s, version);
2382 stream_putw (s, 0);
2383
paul0cb8a012005-05-29 11:27:24 +00002384 /* auth header for !v1 && !no_auth */
2385 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002386 doff = rip_auth_header_write (s, ri, key, auth_str,
2387 RIP_AUTH_SIMPLE_SIZE);
2388 }
2389
paul718e3742002-12-13 20:15:29 +00002390 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002391 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002392 if (num == rtemax)
2393 {
2394 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002395 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002396
2397 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002398 to, ifc);
paul718e3742002-12-13 20:15:29 +00002399
2400 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2401 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2402 stream_get_endp(s), "SEND");
2403 num = 0;
2404 stream_reset (s);
2405 }
2406 }
2407
2408 /* Flush unwritten RTE. */
2409 if (num != 0)
2410 {
2411 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002412 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002413
paulc49ad8f2004-10-22 10:27:28 +00002414 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002415
2416 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2417 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2418 stream_get_endp (s), "SEND");
2419 num = 0;
2420 stream_reset (s);
2421 }
2422
2423 /* Statistics updates. */
2424 ri->sent_updates++;
2425}
2426
2427/* Send RIP packet to the interface. */
2428void
paulc49ad8f2004-10-22 10:27:28 +00002429rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002430{
paul718e3742002-12-13 20:15:29 +00002431 struct sockaddr_in to;
2432
2433 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002434 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002435 {
2436 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002437 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002438
paulc49ad8f2004-10-22 10:27:28 +00002439 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002440 return;
2441 }
paulc49ad8f2004-10-22 10:27:28 +00002442
paul718e3742002-12-13 20:15:29 +00002443 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002444 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002445 {
paulc49ad8f2004-10-22 10:27:28 +00002446 if (ifc->address->family == AF_INET)
2447 {
2448 /* Destination address and port setting. */
2449 memset (&to, 0, sizeof (struct sockaddr_in));
2450 if (ifc->destination)
2451 /* use specified broadcast or point-to-point destination addr */
2452 to.sin_addr = ifc->destination->u.prefix4;
2453 else
2454 /* calculate the appropriate broadcast address */
2455 to.sin_addr.s_addr =
2456 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2457 ifc->address->prefixlen);
2458 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002459
paulc49ad8f2004-10-22 10:27:28 +00002460 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002461 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002462 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2463 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002464
paulc49ad8f2004-10-22 10:27:28 +00002465 rip_output_process (ifc, &to, route_type, version);
2466 }
paul718e3742002-12-13 20:15:29 +00002467 }
2468}
2469
2470/* Update send to all interface and neighbor. */
2471void
2472rip_update_process (int route_type)
2473{
paul1eb8ef22005-04-07 07:30:20 +00002474 struct listnode *node;
2475 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002476 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002477 struct interface *ifp;
2478 struct rip_interface *ri;
2479 struct route_node *rp;
2480 struct sockaddr_in to;
2481 struct prefix_ipv4 *p;
2482
2483 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002484 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002485 {
paul718e3742002-12-13 20:15:29 +00002486 if (if_is_loopback (ifp))
2487 continue;
2488
paul2e3b2e42002-12-13 21:03:13 +00002489 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002490 continue;
2491
2492 /* Fetch RIP interface information. */
2493 ri = ifp->info;
2494
2495 /* When passive interface is specified, suppress announce to the
2496 interface. */
2497 if (ri->passive)
2498 continue;
2499
2500 if (ri->running)
2501 {
2502 if (IS_RIP_DEBUG_EVENT)
2503 {
2504 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002505 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002506 ifp->name, ifp->ifindex);
2507 else
ajs5d6c3772004-12-08 19:24:06 +00002508 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002509 ifp->ifindex);
2510 }
2511
paulcc1131a2003-10-15 23:20:17 +00002512 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002513 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002514 {
2515 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002516 int done = 0;
2517 /*
2518 * If there is no version configuration in the interface,
2519 * use rip's version setting.
2520 */
paulf38a4712003-06-07 01:10:00 +00002521 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2522 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002523
2524 ifaddr = (struct prefix_ipv4 *) connected->address;
2525
2526 if (ifaddr->family != AF_INET)
2527 continue;
2528
paul931cd542004-01-23 15:31:42 +00002529 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002530 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002531 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002532 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002533 done = 1;
2534 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2535 break;
2536
paulf38a4712003-06-07 01:10:00 +00002537 }
paul718e3742002-12-13 20:15:29 +00002538 }
2539 }
2540
2541 /* RIP send updates to each neighbor. */
2542 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2543 if (rp->info != NULL)
2544 {
2545 p = (struct prefix_ipv4 *) &rp->p;
2546
2547 ifp = if_lookup_address (p->prefix);
2548 if (! ifp)
2549 {
paulc49ad8f2004-10-22 10:27:28 +00002550 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002551 inet_ntoa (p->prefix));
2552 continue;
2553 }
paulc49ad8f2004-10-22 10:27:28 +00002554
2555 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2556 {
2557 zlog_warn ("Neighbor %s doesnt have connected network",
2558 inet_ntoa (p->prefix));
2559 continue;
2560 }
2561
paul718e3742002-12-13 20:15:29 +00002562 /* Set destination address and port */
2563 memset (&to, 0, sizeof (struct sockaddr_in));
2564 to.sin_addr = p->prefix;
2565 to.sin_port = htons (RIP_PORT_DEFAULT);
2566
2567 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002568 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002569 }
2570}
2571
2572/* RIP's periodical timer. */
2573int
2574rip_update (struct thread *t)
2575{
2576 /* Clear timer pointer. */
2577 rip->t_update = NULL;
2578
2579 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002580 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002581
2582 /* Process update output. */
2583 rip_update_process (rip_all_route);
2584
2585 /* Triggered updates may be suppressed if a regular update is due by
2586 the time the triggered update would be sent. */
2587 if (rip->t_triggered_interval)
2588 {
2589 thread_cancel (rip->t_triggered_interval);
2590 rip->t_triggered_interval = NULL;
2591 }
2592 rip->trigger = 0;
2593
2594 /* Register myself. */
2595 rip_event (RIP_UPDATE_EVENT, 0);
2596
2597 return 0;
2598}
2599
2600/* Walk down the RIP routing table then clear changed flag. */
2601void
2602rip_clear_changed_flag ()
2603{
2604 struct route_node *rp;
2605 struct rip_info *rinfo;
2606
2607 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2608 if ((rinfo = rp->info) != NULL)
2609 if (rinfo->flags & RIP_RTF_CHANGED)
2610 rinfo->flags &= ~RIP_RTF_CHANGED;
2611}
2612
2613/* Triggered update interval timer. */
2614int
2615rip_triggered_interval (struct thread *t)
2616{
2617 int rip_triggered_update (struct thread *);
2618
2619 rip->t_triggered_interval = NULL;
2620
2621 if (rip->trigger)
2622 {
2623 rip->trigger = 0;
2624 rip_triggered_update (t);
2625 }
2626 return 0;
2627}
2628
2629/* Execute triggered update. */
2630int
2631rip_triggered_update (struct thread *t)
2632{
2633 int interval;
2634
2635 /* Clear thred pointer. */
2636 rip->t_triggered_update = NULL;
2637
2638 /* Cancel interval timer. */
2639 if (rip->t_triggered_interval)
2640 {
2641 thread_cancel (rip->t_triggered_interval);
2642 rip->t_triggered_interval = NULL;
2643 }
2644 rip->trigger = 0;
2645
2646 /* Logging triggered update. */
2647 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002648 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002649
2650 /* Split Horizon processing is done when generating triggered
2651 updates as well as normal updates (see section 2.6). */
2652 rip_update_process (rip_changed_route);
2653
2654 /* Once all of the triggered updates have been generated, the route
2655 change flags should be cleared. */
2656 rip_clear_changed_flag ();
2657
2658 /* After a triggered update is sent, a timer should be set for a
2659 random interval between 1 and 5 seconds. If other changes that
2660 would trigger updates occur before the timer expires, a single
2661 update is triggered when the timer expires. */
2662 interval = (random () % 5) + 1;
2663
2664 rip->t_triggered_interval =
2665 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2666
2667 return 0;
2668}
2669
2670/* Withdraw redistributed route. */
2671void
2672rip_redistribute_withdraw (int type)
2673{
2674 struct route_node *rp;
2675 struct rip_info *rinfo;
2676
2677 if (!rip)
2678 return;
2679
2680 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2681 if ((rinfo = rp->info) != NULL)
2682 {
2683 if (rinfo->type == type
2684 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2685 {
2686 /* Perform poisoned reverse. */
2687 rinfo->metric = RIP_METRIC_INFINITY;
2688 RIP_TIMER_ON (rinfo->t_garbage_collect,
2689 rip_garbage_collect, rip->garbage_time);
2690 RIP_TIMER_OFF (rinfo->t_timeout);
2691 rinfo->flags |= RIP_RTF_CHANGED;
2692
hasso16705132003-05-25 14:49:19 +00002693 if (IS_RIP_DEBUG_EVENT) {
2694 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2695
ajs5d6c3772004-12-08 19:24:06 +00002696 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002697 inet_ntoa(p->prefix), p->prefixlen,
2698 ifindex2ifname(rinfo->ifindex));
2699 }
2700
paul718e3742002-12-13 20:15:29 +00002701 rip_event (RIP_TRIGGERED_UPDATE, 0);
2702 }
2703 }
2704}
2705
2706/* Create new RIP instance and set it to global variable. */
2707int
2708rip_create ()
2709{
2710 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2711 memset (rip, 0, sizeof (struct rip));
2712
2713 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002714 rip->version_send = RI_RIP_VERSION_2;
2715 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002716 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2717 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2718 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2719 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2720
2721 /* Initialize RIP routig table. */
2722 rip->table = route_table_init ();
2723 rip->route = route_table_init ();
2724 rip->neighbor = route_table_init ();
2725
2726 /* Make output stream. */
2727 rip->obuf = stream_new (1500);
2728
2729 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002730 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002731 if (rip->sock < 0)
2732 return rip->sock;
2733
2734 /* Create read and timer thread. */
2735 rip_event (RIP_READ, rip->sock);
2736 rip_event (RIP_UPDATE_EVENT, 1);
2737
2738 return 0;
2739}
2740
2741/* Sned RIP request to the destination. */
2742int
2743rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002744 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002745{
2746 struct rte *rte;
2747 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002748 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002749
2750 memset (&rip_packet, 0, sizeof (rip_packet));
2751
2752 rip_packet.command = RIP_REQUEST;
2753 rip_packet.version = version;
2754 rte = rip_packet.rte;
2755 rte->metric = htonl (RIP_METRIC_INFINITY);
2756
paul931cd542004-01-23 15:31:42 +00002757 if (connected)
2758 {
2759 /*
2760 * connected is only sent for ripv1 case, or when
2761 * interface does not support multicast. Caller loops
2762 * over each connected address for this case.
2763 */
paul11dde9c2004-05-31 14:00:00 +00002764 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002765 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002766 return -1;
2767 else
2768 return sizeof (rip_packet);
2769 }
2770
paulcc1131a2003-10-15 23:20:17 +00002771 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002772 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002773 {
2774 struct prefix_ipv4 *p;
2775
2776 p = (struct prefix_ipv4 *) connected->address;
2777
2778 if (p->family != AF_INET)
2779 continue;
2780
paul11dde9c2004-05-31 14:00:00 +00002781 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002782 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002783 return -1;
2784 }
2785 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002786}
2787
2788int
2789rip_update_jitter (unsigned long time)
2790{
paul239389b2004-05-05 14:09:37 +00002791#define JITTER_BOUND 4
2792 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2793 Given that, we cannot let time be less than JITTER_BOUND seconds.
2794 The RIPv2 RFC says jitter should be small compared to
2795 update_time. We consider 1/JITTER_BOUND to be small.
2796 */
2797
2798 int jitter_input = time;
2799 int jitter;
2800
2801 if (jitter_input < JITTER_BOUND)
2802 jitter_input = JITTER_BOUND;
2803
2804 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2805
2806 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002807}
2808
2809void
2810rip_event (enum rip_event event, int sock)
2811{
2812 int jitter = 0;
2813
2814 switch (event)
2815 {
2816 case RIP_READ:
2817 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2818 break;
2819 case RIP_UPDATE_EVENT:
2820 if (rip->t_update)
2821 {
2822 thread_cancel (rip->t_update);
2823 rip->t_update = NULL;
2824 }
2825 jitter = rip_update_jitter (rip->update_time);
2826 rip->t_update =
2827 thread_add_timer (master, rip_update, NULL,
2828 sock ? 2 : rip->update_time + jitter);
2829 break;
2830 case RIP_TRIGGERED_UPDATE:
2831 if (rip->t_triggered_interval)
2832 rip->trigger = 1;
2833 else if (! rip->t_triggered_update)
2834 rip->t_triggered_update =
2835 thread_add_event (master, rip_triggered_update, NULL, 0);
2836 break;
2837 default:
2838 break;
2839 }
2840}
2841
2842DEFUN (router_rip,
2843 router_rip_cmd,
2844 "router rip",
2845 "Enable a routing process\n"
2846 "Routing Information Protocol (RIP)\n")
2847{
2848 int ret;
2849
2850 /* If rip is not enabled before. */
2851 if (! rip)
2852 {
2853 ret = rip_create ();
2854 if (ret < 0)
2855 {
2856 zlog_info ("Can't create RIP");
2857 return CMD_WARNING;
2858 }
2859 }
2860 vty->node = RIP_NODE;
2861 vty->index = rip;
2862
2863 return CMD_SUCCESS;
2864}
2865
2866DEFUN (no_router_rip,
2867 no_router_rip_cmd,
2868 "no router rip",
2869 NO_STR
2870 "Enable a routing process\n"
2871 "Routing Information Protocol (RIP)\n")
2872{
2873 if (rip)
2874 rip_clean ();
2875 return CMD_SUCCESS;
2876}
2877
2878DEFUN (rip_version,
2879 rip_version_cmd,
2880 "version <1-2>",
2881 "Set routing protocol version\n"
2882 "version\n")
2883{
2884 int version;
2885
2886 version = atoi (argv[0]);
2887 if (version != RIPv1 && version != RIPv2)
2888 {
2889 vty_out (vty, "invalid rip version %d%s", version,
2890 VTY_NEWLINE);
2891 return CMD_WARNING;
2892 }
paulf38a4712003-06-07 01:10:00 +00002893 rip->version_send = version;
2894 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002895
2896 return CMD_SUCCESS;
2897}
2898
2899DEFUN (no_rip_version,
2900 no_rip_version_cmd,
2901 "no version",
2902 NO_STR
2903 "Set routing protocol version\n")
2904{
2905 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002906 rip->version_send = RI_RIP_VERSION_2;
2907 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002908
2909 return CMD_SUCCESS;
2910}
2911
2912ALIAS (no_rip_version,
2913 no_rip_version_val_cmd,
2914 "no version <1-2>",
2915 NO_STR
2916 "Set routing protocol version\n"
2917 "version\n")
2918
2919DEFUN (rip_route,
2920 rip_route_cmd,
2921 "route A.B.C.D/M",
2922 "RIP static route configuration\n"
2923 "IP prefix <network>/<length>\n")
2924{
2925 int ret;
2926 struct prefix_ipv4 p;
2927 struct route_node *node;
2928
2929 ret = str2prefix_ipv4 (argv[0], &p);
2930 if (ret < 0)
2931 {
2932 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2933 return CMD_WARNING;
2934 }
2935 apply_mask_ipv4 (&p);
2936
2937 /* For router rip configuration. */
2938 node = route_node_get (rip->route, (struct prefix *) &p);
2939
2940 if (node->info)
2941 {
2942 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2943 route_unlock_node (node);
2944 return CMD_WARNING;
2945 }
2946
hasso8a676be2004-10-08 06:36:38 +00002947 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002948
vincentfbf5d032005-09-29 11:25:50 +00002949 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
paul718e3742002-12-13 20:15:29 +00002950
2951 return CMD_SUCCESS;
2952}
2953
2954DEFUN (no_rip_route,
2955 no_rip_route_cmd,
2956 "no route A.B.C.D/M",
2957 NO_STR
2958 "RIP static route configuration\n"
2959 "IP prefix <network>/<length>\n")
2960{
2961 int ret;
2962 struct prefix_ipv4 p;
2963 struct route_node *node;
2964
2965 ret = str2prefix_ipv4 (argv[0], &p);
2966 if (ret < 0)
2967 {
2968 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2969 return CMD_WARNING;
2970 }
2971 apply_mask_ipv4 (&p);
2972
2973 /* For router rip configuration. */
2974 node = route_node_lookup (rip->route, (struct prefix *) &p);
2975 if (! node)
2976 {
2977 vty_out (vty, "Can't find route %s.%s", argv[0],
2978 VTY_NEWLINE);
2979 return CMD_WARNING;
2980 }
2981
2982 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2983 route_unlock_node (node);
2984
2985 node->info = NULL;
2986 route_unlock_node (node);
2987
2988 return CMD_SUCCESS;
2989}
2990
2991void
2992rip_update_default_metric ()
2993{
2994 struct route_node *np;
2995 struct rip_info *rinfo;
2996
2997 for (np = route_top (rip->table); np; np = route_next (np))
2998 if ((rinfo = np->info) != NULL)
2999 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3000 rinfo->metric = rip->default_metric;
3001}
3002
3003DEFUN (rip_default_metric,
3004 rip_default_metric_cmd,
3005 "default-metric <1-16>",
3006 "Set a metric of redistribute routes\n"
3007 "Default metric\n")
3008{
3009 if (rip)
3010 {
3011 rip->default_metric = atoi (argv[0]);
3012 /* rip_update_default_metric (); */
3013 }
3014 return CMD_SUCCESS;
3015}
3016
3017DEFUN (no_rip_default_metric,
3018 no_rip_default_metric_cmd,
3019 "no default-metric",
3020 NO_STR
3021 "Set a metric of redistribute routes\n"
3022 "Default metric\n")
3023{
3024 if (rip)
3025 {
3026 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3027 /* rip_update_default_metric (); */
3028 }
3029 return CMD_SUCCESS;
3030}
3031
3032ALIAS (no_rip_default_metric,
3033 no_rip_default_metric_val_cmd,
3034 "no default-metric <1-16>",
3035 NO_STR
3036 "Set a metric of redistribute routes\n"
3037 "Default metric\n")
3038
3039DEFUN (rip_timers,
3040 rip_timers_cmd,
3041 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3042 "Adjust routing timers\n"
3043 "Basic routing protocol update timers\n"
3044 "Routing table update timer value in second. Default is 30.\n"
3045 "Routing information timeout timer. Default is 180.\n"
3046 "Garbage collection timer. Default is 120.\n")
3047{
3048 unsigned long update;
3049 unsigned long timeout;
3050 unsigned long garbage;
3051 char *endptr = NULL;
3052 unsigned long RIP_TIMER_MAX = 2147483647;
3053 unsigned long RIP_TIMER_MIN = 5;
3054
3055 update = strtoul (argv[0], &endptr, 10);
3056 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3057 {
3058 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3059 return CMD_WARNING;
3060 }
3061
3062 timeout = strtoul (argv[1], &endptr, 10);
3063 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3064 {
3065 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3066 return CMD_WARNING;
3067 }
3068
3069 garbage = strtoul (argv[2], &endptr, 10);
3070 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3071 {
3072 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3073 return CMD_WARNING;
3074 }
3075
3076 /* Set each timer value. */
3077 rip->update_time = update;
3078 rip->timeout_time = timeout;
3079 rip->garbage_time = garbage;
3080
3081 /* Reset update timer thread. */
3082 rip_event (RIP_UPDATE_EVENT, 0);
3083
3084 return CMD_SUCCESS;
3085}
3086
3087DEFUN (no_rip_timers,
3088 no_rip_timers_cmd,
3089 "no timers basic",
3090 NO_STR
3091 "Adjust routing timers\n"
3092 "Basic routing protocol update timers\n")
3093{
3094 /* Set each timer value to the default. */
3095 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3096 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3097 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3098
3099 /* Reset update timer thread. */
3100 rip_event (RIP_UPDATE_EVENT, 0);
3101
3102 return CMD_SUCCESS;
3103}
hasso16705132003-05-25 14:49:19 +00003104
3105ALIAS (no_rip_timers,
3106 no_rip_timers_val_cmd,
3107 "no timers basic <0-65535> <0-65535> <0-65535>",
3108 NO_STR
3109 "Adjust routing timers\n"
3110 "Basic routing protocol update timers\n"
3111 "Routing table update timer value in second. Default is 30.\n"
3112 "Routing information timeout timer. Default is 180.\n"
3113 "Garbage collection timer. Default is 120.\n")
3114
paul718e3742002-12-13 20:15:29 +00003115
3116struct route_table *rip_distance_table;
3117
3118struct rip_distance
3119{
3120 /* Distance value for the IP source prefix. */
3121 u_char distance;
3122
3123 /* Name of the access-list to be matched. */
3124 char *access_list;
3125};
3126
3127struct rip_distance *
3128rip_distance_new ()
3129{
3130 struct rip_distance *new;
3131 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3132 memset (new, 0, sizeof (struct rip_distance));
3133 return new;
3134}
3135
3136void
3137rip_distance_free (struct rip_distance *rdistance)
3138{
3139 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3140}
3141
3142int
hasso98b718a2004-10-11 12:57:57 +00003143rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3144 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003145{
3146 int ret;
3147 struct prefix_ipv4 p;
3148 u_char distance;
3149 struct route_node *rn;
3150 struct rip_distance *rdistance;
3151
3152 ret = str2prefix_ipv4 (ip_str, &p);
3153 if (ret == 0)
3154 {
3155 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3156 return CMD_WARNING;
3157 }
3158
3159 distance = atoi (distance_str);
3160
3161 /* Get RIP distance node. */
3162 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3163 if (rn->info)
3164 {
3165 rdistance = rn->info;
3166 route_unlock_node (rn);
3167 }
3168 else
3169 {
3170 rdistance = rip_distance_new ();
3171 rn->info = rdistance;
3172 }
3173
3174 /* Set distance value. */
3175 rdistance->distance = distance;
3176
3177 /* Reset access-list configuration. */
3178 if (rdistance->access_list)
3179 {
3180 free (rdistance->access_list);
3181 rdistance->access_list = NULL;
3182 }
3183 if (access_list_str)
3184 rdistance->access_list = strdup (access_list_str);
3185
3186 return CMD_SUCCESS;
3187}
3188
3189int
hasso98b718a2004-10-11 12:57:57 +00003190rip_distance_unset (struct vty *vty, const char *distance_str,
3191 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003192{
3193 int ret;
3194 struct prefix_ipv4 p;
3195 u_char distance;
3196 struct route_node *rn;
3197 struct rip_distance *rdistance;
3198
3199 ret = str2prefix_ipv4 (ip_str, &p);
3200 if (ret == 0)
3201 {
3202 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3203 return CMD_WARNING;
3204 }
3205
3206 distance = atoi (distance_str);
3207
3208 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3209 if (! rn)
3210 {
3211 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3212 return CMD_WARNING;
3213 }
3214
3215 rdistance = rn->info;
3216
3217 if (rdistance->access_list)
3218 free (rdistance->access_list);
3219 rip_distance_free (rdistance);
3220
3221 rn->info = NULL;
3222 route_unlock_node (rn);
3223 route_unlock_node (rn);
3224
3225 return CMD_SUCCESS;
3226}
3227
3228void
3229rip_distance_reset ()
3230{
3231 struct route_node *rn;
3232 struct rip_distance *rdistance;
3233
3234 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3235 if ((rdistance = rn->info) != NULL)
3236 {
3237 if (rdistance->access_list)
3238 free (rdistance->access_list);
3239 rip_distance_free (rdistance);
3240 rn->info = NULL;
3241 route_unlock_node (rn);
3242 }
3243}
3244
3245/* Apply RIP information to distance method. */
3246u_char
3247rip_distance_apply (struct rip_info *rinfo)
3248{
3249 struct route_node *rn;
3250 struct prefix_ipv4 p;
3251 struct rip_distance *rdistance;
3252 struct access_list *alist;
3253
3254 if (! rip)
3255 return 0;
3256
3257 memset (&p, 0, sizeof (struct prefix_ipv4));
3258 p.family = AF_INET;
3259 p.prefix = rinfo->from;
3260 p.prefixlen = IPV4_MAX_BITLEN;
3261
3262 /* Check source address. */
3263 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3264 if (rn)
3265 {
3266 rdistance = rn->info;
3267 route_unlock_node (rn);
3268
3269 if (rdistance->access_list)
3270 {
3271 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3272 if (alist == NULL)
3273 return 0;
3274 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3275 return 0;
3276
3277 return rdistance->distance;
3278 }
3279 else
3280 return rdistance->distance;
3281 }
3282
3283 if (rip->distance)
3284 return rip->distance;
3285
3286 return 0;
3287}
3288
3289void
3290rip_distance_show (struct vty *vty)
3291{
3292 struct route_node *rn;
3293 struct rip_distance *rdistance;
3294 int header = 1;
3295 char buf[BUFSIZ];
3296
3297 vty_out (vty, " Distance: (default is %d)%s",
3298 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3299 VTY_NEWLINE);
3300
3301 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3302 if ((rdistance = rn->info) != NULL)
3303 {
3304 if (header)
3305 {
3306 vty_out (vty, " Address Distance List%s",
3307 VTY_NEWLINE);
3308 header = 0;
3309 }
3310 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3311 vty_out (vty, " %-20s %4d %s%s",
3312 buf, rdistance->distance,
3313 rdistance->access_list ? rdistance->access_list : "",
3314 VTY_NEWLINE);
3315 }
3316}
3317
3318DEFUN (rip_distance,
3319 rip_distance_cmd,
3320 "distance <1-255>",
3321 "Administrative distance\n"
3322 "Distance value\n")
3323{
3324 rip->distance = atoi (argv[0]);
3325 return CMD_SUCCESS;
3326}
3327
3328DEFUN (no_rip_distance,
3329 no_rip_distance_cmd,
3330 "no distance <1-255>",
3331 NO_STR
3332 "Administrative distance\n"
3333 "Distance value\n")
3334{
3335 rip->distance = 0;
3336 return CMD_SUCCESS;
3337}
3338
3339DEFUN (rip_distance_source,
3340 rip_distance_source_cmd,
3341 "distance <1-255> A.B.C.D/M",
3342 "Administrative distance\n"
3343 "Distance value\n"
3344 "IP source prefix\n")
3345{
3346 rip_distance_set (vty, argv[0], argv[1], NULL);
3347 return CMD_SUCCESS;
3348}
3349
3350DEFUN (no_rip_distance_source,
3351 no_rip_distance_source_cmd,
3352 "no distance <1-255> A.B.C.D/M",
3353 NO_STR
3354 "Administrative distance\n"
3355 "Distance value\n"
3356 "IP source prefix\n")
3357{
3358 rip_distance_unset (vty, argv[0], argv[1], NULL);
3359 return CMD_SUCCESS;
3360}
3361
3362DEFUN (rip_distance_source_access_list,
3363 rip_distance_source_access_list_cmd,
3364 "distance <1-255> A.B.C.D/M WORD",
3365 "Administrative distance\n"
3366 "Distance value\n"
3367 "IP source prefix\n"
3368 "Access list name\n")
3369{
3370 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3371 return CMD_SUCCESS;
3372}
3373
3374DEFUN (no_rip_distance_source_access_list,
3375 no_rip_distance_source_access_list_cmd,
3376 "no distance <1-255> A.B.C.D/M WORD",
3377 NO_STR
3378 "Administrative distance\n"
3379 "Distance value\n"
3380 "IP source prefix\n"
3381 "Access list name\n")
3382{
3383 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3384 return CMD_SUCCESS;
3385}
3386
3387/* Print out routes update time. */
3388void
3389rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3390{
3391 struct timeval timer_now;
3392 time_t clock;
3393 struct tm *tm;
3394#define TIME_BUF 25
3395 char timebuf [TIME_BUF];
3396 struct thread *thread;
3397
3398 gettimeofday (&timer_now, NULL);
3399
3400 if ((thread = rinfo->t_timeout) != NULL)
3401 {
3402 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3403 tm = gmtime (&clock);
3404 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3405 vty_out (vty, "%5s", timebuf);
3406 }
3407 else if ((thread = rinfo->t_garbage_collect) != NULL)
3408 {
3409 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3410 tm = gmtime (&clock);
3411 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3412 vty_out (vty, "%5s", timebuf);
3413 }
3414}
3415
hasso8a676be2004-10-08 06:36:38 +00003416const char *
paul718e3742002-12-13 20:15:29 +00003417rip_route_type_print (int sub_type)
3418{
3419 switch (sub_type)
3420 {
3421 case RIP_ROUTE_RTE:
3422 return "n";
3423 case RIP_ROUTE_STATIC:
3424 return "s";
3425 case RIP_ROUTE_DEFAULT:
3426 return "d";
3427 case RIP_ROUTE_REDISTRIBUTE:
3428 return "r";
3429 case RIP_ROUTE_INTERFACE:
3430 return "i";
3431 default:
3432 return "?";
3433 }
3434}
3435
3436DEFUN (show_ip_rip,
3437 show_ip_rip_cmd,
3438 "show ip rip",
3439 SHOW_STR
3440 IP_STR
3441 "Show RIP routes\n")
3442{
3443 struct route_node *np;
3444 struct rip_info *rinfo;
3445
3446 if (! rip)
3447 return CMD_SUCCESS;
3448
hasso16705132003-05-25 14:49:19 +00003449 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3450 "Sub-codes:%s"
3451 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003452 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003453 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003454 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003455
3456 for (np = route_top (rip->table); np; np = route_next (np))
3457 if ((rinfo = np->info) != NULL)
3458 {
3459 int len;
3460
ajsf52d13c2005-10-01 17:38:06 +00003461 len = vty_out (vty, "%c(%s) %s/%d",
paul718e3742002-12-13 20:15:29 +00003462 /* np->lock, For debugging. */
ajsf52d13c2005-10-01 17:38:06 +00003463 zebra_route_char(rinfo->type),
paul718e3742002-12-13 20:15:29 +00003464 rip_route_type_print (rinfo->sub_type),
3465 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3466
hassoa1455d82004-03-03 19:36:24 +00003467 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003468
3469 if (len > 0)
3470 vty_out (vty, "%*s", len, " ");
3471
3472 if (rinfo->nexthop.s_addr)
3473 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3474 rinfo->metric);
3475 else
3476 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3477
3478 /* Route which exist in kernel routing table. */
3479 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3480 (rinfo->sub_type == RIP_ROUTE_RTE))
3481 {
3482 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003483 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003484 rip_vty_out_uptime (vty, rinfo);
3485 }
3486 else if (rinfo->metric == RIP_METRIC_INFINITY)
3487 {
3488 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003489 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003490 rip_vty_out_uptime (vty, rinfo);
3491 }
3492 else
hasso16705132003-05-25 14:49:19 +00003493 {
vincentfbf5d032005-09-29 11:25:50 +00003494 if (rinfo->external_metric)
3495 {
3496 len = vty_out (vty, "self (%s:%d)",
ajsf52d13c2005-10-01 17:38:06 +00003497 zebra_route_string(rinfo->type),
vincentfbf5d032005-09-29 11:25:50 +00003498 rinfo->external_metric);
3499 len = 16 - len;
3500 if (len > 0)
3501 vty_out (vty, "%*s", len, " ");
3502 }
3503 else
3504 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003505 vty_out (vty, "%3d", rinfo->tag);
3506 }
paul718e3742002-12-13 20:15:29 +00003507
3508 vty_out (vty, "%s", VTY_NEWLINE);
3509 }
3510 return CMD_SUCCESS;
3511}
3512
3513/* Return next event time. */
3514int
3515rip_next_thread_timer (struct thread *thread)
3516{
3517 struct timeval timer_now;
3518
3519 gettimeofday (&timer_now, NULL);
3520
3521 return thread->u.sands.tv_sec - timer_now.tv_sec;
3522}
3523
hasso16705132003-05-25 14:49:19 +00003524/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3525DEFUN (show_ip_rip_status,
3526 show_ip_rip_status_cmd,
3527 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003528 SHOW_STR
3529 IP_STR
hasso16705132003-05-25 14:49:19 +00003530 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003531 "IP routing protocol process parameters and statistics\n")
3532{
hasso52dc7ee2004-09-23 19:18:23 +00003533 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003534 struct interface *ifp;
3535 struct rip_interface *ri;
3536 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003537 const char *send_version;
3538 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003539
3540 if (! rip)
3541 return CMD_SUCCESS;
3542
3543 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3544 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3545 rip->update_time);
3546 vty_out (vty, " next due in %d seconds%s",
3547 rip_next_thread_timer (rip->t_update),
3548 VTY_NEWLINE);
3549 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3550 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3551 VTY_NEWLINE);
3552
3553 /* Filtering status show. */
3554 config_show_distribute (vty);
3555
3556 /* Default metric information. */
3557 vty_out (vty, " Default redistribution metric is %d%s",
3558 rip->default_metric, VTY_NEWLINE);
3559
3560 /* Redistribute information. */
3561 vty_out (vty, " Redistributing:");
3562 config_write_rip_redistribute (vty, 0);
3563 vty_out (vty, "%s", VTY_NEWLINE);
3564
paulf38a4712003-06-07 01:10:00 +00003565 vty_out (vty, " Default version control: send version %s,",
3566 lookup(ri_version_msg,rip->version_send));
3567 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3568 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3569 else
3570 vty_out (vty, " receive version %s %s",
3571 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003572
3573 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3574
paul1eb8ef22005-04-07 07:30:20 +00003575 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003576 {
paul718e3742002-12-13 20:15:29 +00003577 ri = ifp->info;
3578
3579 if (ri->enable_network || ri->enable_interface)
3580 {
3581 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003582 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003583 else
3584 send_version = lookup (ri_version_msg, ri->ri_send);
3585
3586 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003587 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003588 else
3589 receive_version = lookup (ri_version_msg, ri->ri_receive);
3590
3591 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3592 send_version,
3593 receive_version,
3594 ri->key_chain ? ri->key_chain : "",
3595 VTY_NEWLINE);
3596 }
3597 }
3598
3599 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3600 config_write_rip_network (vty, 0);
3601
paul4aaff3f2003-06-07 01:04:45 +00003602 {
3603 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003604 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003605 {
paul4aaff3f2003-06-07 01:04:45 +00003606 ri = ifp->info;
3607
3608 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3609 {
3610 if (!found_passive)
3611 {
3612 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3613 found_passive = 1;
3614 }
3615 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3616 }
3617 }
3618 }
3619
paul718e3742002-12-13 20:15:29 +00003620 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3621 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3622 rip_peer_display (vty);
3623
3624 rip_distance_show (vty);
3625
3626 return CMD_SUCCESS;
3627}
3628
3629/* RIP configuration write function. */
3630int
3631config_write_rip (struct vty *vty)
3632{
3633 int write = 0;
3634 struct route_node *rn;
3635 struct rip_distance *rdistance;
3636
3637 if (rip)
3638 {
3639 /* Router RIP statement. */
3640 vty_out (vty, "router rip%s", VTY_NEWLINE);
3641 write++;
3642
3643 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003644 if (rip->version_send != RI_RIP_VERSION_2
3645 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3646 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003647 VTY_NEWLINE);
3648
3649 /* RIP timer configuration. */
3650 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3651 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3652 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3653 vty_out (vty, " timers basic %lu %lu %lu%s",
3654 rip->update_time,
3655 rip->timeout_time,
3656 rip->garbage_time,
3657 VTY_NEWLINE);
3658
3659 /* Default information configuration. */
3660 if (rip->default_information)
3661 {
3662 if (rip->default_information_route_map)
3663 vty_out (vty, " default-information originate route-map %s%s",
3664 rip->default_information_route_map, VTY_NEWLINE);
3665 else
3666 vty_out (vty, " default-information originate%s",
3667 VTY_NEWLINE);
3668 }
3669
3670 /* Redistribute configuration. */
3671 config_write_rip_redistribute (vty, 1);
3672
3673 /* RIP offset-list configuration. */
3674 config_write_rip_offset_list (vty);
3675
3676 /* RIP enabled network and interface configuration. */
3677 config_write_rip_network (vty, 1);
3678
3679 /* RIP default metric configuration */
3680 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3681 vty_out (vty, " default-metric %d%s",
3682 rip->default_metric, VTY_NEWLINE);
3683
3684 /* Distribute configuration. */
3685 write += config_write_distribute (vty);
3686
hasso16705132003-05-25 14:49:19 +00003687 /* Interface routemap configuration */
3688 write += config_write_if_rmap (vty);
3689
paul718e3742002-12-13 20:15:29 +00003690 /* Distance configuration. */
3691 if (rip->distance)
3692 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3693
3694 /* RIP source IP prefix distance configuration. */
3695 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3696 if ((rdistance = rn->info) != NULL)
3697 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3698 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3699 rdistance->access_list ? rdistance->access_list : "",
3700 VTY_NEWLINE);
3701
3702 /* RIP static route configuration. */
3703 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3704 if (rn->info)
3705 vty_out (vty, " route %s/%d%s",
3706 inet_ntoa (rn->p.u.prefix4),
3707 rn->p.prefixlen,
3708 VTY_NEWLINE);
3709
3710 }
3711 return write;
3712}
3713
3714/* RIP node structure. */
3715struct cmd_node rip_node =
3716{
3717 RIP_NODE,
3718 "%s(config-router)# ",
3719 1
3720};
3721
3722/* Distribute-list update functions. */
3723void
3724rip_distribute_update (struct distribute *dist)
3725{
3726 struct interface *ifp;
3727 struct rip_interface *ri;
3728 struct access_list *alist;
3729 struct prefix_list *plist;
3730
3731 if (! dist->ifname)
3732 return;
3733
3734 ifp = if_lookup_by_name (dist->ifname);
3735 if (ifp == NULL)
3736 return;
3737
3738 ri = ifp->info;
3739
3740 if (dist->list[DISTRIBUTE_IN])
3741 {
3742 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3743 if (alist)
3744 ri->list[RIP_FILTER_IN] = alist;
3745 else
3746 ri->list[RIP_FILTER_IN] = NULL;
3747 }
3748 else
3749 ri->list[RIP_FILTER_IN] = NULL;
3750
3751 if (dist->list[DISTRIBUTE_OUT])
3752 {
3753 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3754 if (alist)
3755 ri->list[RIP_FILTER_OUT] = alist;
3756 else
3757 ri->list[RIP_FILTER_OUT] = NULL;
3758 }
3759 else
3760 ri->list[RIP_FILTER_OUT] = NULL;
3761
3762 if (dist->prefix[DISTRIBUTE_IN])
3763 {
3764 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3765 if (plist)
3766 ri->prefix[RIP_FILTER_IN] = plist;
3767 else
3768 ri->prefix[RIP_FILTER_IN] = NULL;
3769 }
3770 else
3771 ri->prefix[RIP_FILTER_IN] = NULL;
3772
3773 if (dist->prefix[DISTRIBUTE_OUT])
3774 {
3775 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3776 if (plist)
3777 ri->prefix[RIP_FILTER_OUT] = plist;
3778 else
3779 ri->prefix[RIP_FILTER_OUT] = NULL;
3780 }
3781 else
3782 ri->prefix[RIP_FILTER_OUT] = NULL;
3783}
3784
3785void
3786rip_distribute_update_interface (struct interface *ifp)
3787{
3788 struct distribute *dist;
3789
3790 dist = distribute_lookup (ifp->name);
3791 if (dist)
3792 rip_distribute_update (dist);
3793}
3794
3795/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003796/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003797void
paul02ff83c2004-06-11 11:27:03 +00003798rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003799{
3800 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003801 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003802
paul1eb8ef22005-04-07 07:30:20 +00003803 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3804 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003805}
paul11dde9c2004-05-31 14:00:00 +00003806/* ARGSUSED */
3807void
3808rip_distribute_update_all_wrapper(struct access_list *notused)
3809{
paul02ff83c2004-06-11 11:27:03 +00003810 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003811}
paul718e3742002-12-13 20:15:29 +00003812
3813/* Delete all added rip route. */
3814void
3815rip_clean ()
3816{
3817 int i;
3818 struct route_node *rp;
3819 struct rip_info *rinfo;
3820
3821 if (rip)
3822 {
3823 /* Clear RIP routes */
3824 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3825 if ((rinfo = rp->info) != NULL)
3826 {
3827 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3828 rinfo->sub_type == RIP_ROUTE_RTE)
3829 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3830 &rinfo->nexthop, rinfo->metric);
3831
3832 RIP_TIMER_OFF (rinfo->t_timeout);
3833 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3834
3835 rp->info = NULL;
3836 route_unlock_node (rp);
3837
3838 rip_info_free (rinfo);
3839 }
3840
3841 /* Cancel RIP related timers. */
3842 RIP_TIMER_OFF (rip->t_update);
3843 RIP_TIMER_OFF (rip->t_triggered_update);
3844 RIP_TIMER_OFF (rip->t_triggered_interval);
3845
3846 /* Cancel read thread. */
3847 if (rip->t_read)
3848 {
3849 thread_cancel (rip->t_read);
3850 rip->t_read = NULL;
3851 }
3852
3853 /* Close RIP socket. */
3854 if (rip->sock >= 0)
3855 {
3856 close (rip->sock);
3857 rip->sock = -1;
3858 }
3859
3860 /* Static RIP route configuration. */
3861 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3862 if (rp->info)
3863 {
3864 rp->info = NULL;
3865 route_unlock_node (rp);
3866 }
3867
3868 /* RIP neighbor configuration. */
3869 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3870 if (rp->info)
3871 {
3872 rp->info = NULL;
3873 route_unlock_node (rp);
3874 }
3875
3876 /* Redistribute related clear. */
3877 if (rip->default_information_route_map)
3878 free (rip->default_information_route_map);
3879
3880 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3881 if (rip->route_map[i].name)
3882 free (rip->route_map[i].name);
3883
3884 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3885 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3886 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3887
3888 XFREE (MTYPE_RIP, rip);
3889 rip = NULL;
3890 }
3891
3892 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003893 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003894 rip_offset_clean ();
3895 rip_interface_clean ();
3896 rip_distance_reset ();
3897 rip_redistribute_clean ();
3898}
3899
3900/* Reset all values to the default settings. */
3901void
3902rip_reset ()
3903{
3904 /* Reset global counters. */
3905 rip_global_route_changes = 0;
3906 rip_global_queries = 0;
3907
3908 /* Call ripd related reset functions. */
3909 rip_debug_reset ();
3910 rip_route_map_reset ();
3911
3912 /* Call library reset functions. */
3913 vty_reset ();
3914 access_list_reset ();
3915 prefix_list_reset ();
3916
3917 distribute_list_reset ();
3918
3919 rip_interface_reset ();
3920 rip_distance_reset ();
3921
3922 rip_zclient_reset ();
3923}
3924
hasso16705132003-05-25 14:49:19 +00003925void
3926rip_if_rmap_update (struct if_rmap *if_rmap)
3927{
3928 struct interface *ifp;
3929 struct rip_interface *ri;
3930 struct route_map *rmap;
3931
3932 ifp = if_lookup_by_name (if_rmap->ifname);
3933 if (ifp == NULL)
3934 return;
3935
3936 ri = ifp->info;
3937
3938 if (if_rmap->routemap[IF_RMAP_IN])
3939 {
3940 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3941 if (rmap)
3942 ri->routemap[IF_RMAP_IN] = rmap;
3943 else
3944 ri->routemap[IF_RMAP_IN] = NULL;
3945 }
3946 else
3947 ri->routemap[RIP_FILTER_IN] = NULL;
3948
3949 if (if_rmap->routemap[IF_RMAP_OUT])
3950 {
3951 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3952 if (rmap)
3953 ri->routemap[IF_RMAP_OUT] = rmap;
3954 else
3955 ri->routemap[IF_RMAP_OUT] = NULL;
3956 }
3957 else
3958 ri->routemap[RIP_FILTER_OUT] = NULL;
3959}
3960
3961void
3962rip_if_rmap_update_interface (struct interface *ifp)
3963{
3964 struct if_rmap *if_rmap;
3965
3966 if_rmap = if_rmap_lookup (ifp->name);
3967 if (if_rmap)
3968 rip_if_rmap_update (if_rmap);
3969}
3970
3971void
3972rip_routemap_update_redistribute (void)
3973{
3974 int i;
3975
3976 if (rip)
3977 {
3978 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3979 {
3980 if (rip->route_map[i].name)
3981 rip->route_map[i].map =
3982 route_map_lookup_by_name (rip->route_map[i].name);
3983 }
3984 }
3985}
3986
paul11dde9c2004-05-31 14:00:00 +00003987/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003988void
hasso98b718a2004-10-11 12:57:57 +00003989rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003990{
3991 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003992 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003993
paul1eb8ef22005-04-07 07:30:20 +00003994 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3995 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003996
3997 rip_routemap_update_redistribute ();
3998}
3999
paul718e3742002-12-13 20:15:29 +00004000/* Allocate new rip structure and set default value. */
4001void
4002rip_init ()
4003{
4004 /* Randomize for triggered update random(). */
4005 srand (time (NULL));
4006
4007 /* Install top nodes. */
4008 install_node (&rip_node, config_write_rip);
4009
4010 /* Install rip commands. */
4011 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004012 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004013 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004014 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004015 install_element (CONFIG_NODE, &router_rip_cmd);
4016 install_element (CONFIG_NODE, &no_router_rip_cmd);
4017
4018 install_default (RIP_NODE);
4019 install_element (RIP_NODE, &rip_version_cmd);
4020 install_element (RIP_NODE, &no_rip_version_cmd);
4021 install_element (RIP_NODE, &no_rip_version_val_cmd);
4022 install_element (RIP_NODE, &rip_default_metric_cmd);
4023 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4024 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4025 install_element (RIP_NODE, &rip_timers_cmd);
4026 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00004027 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00004028 install_element (RIP_NODE, &rip_route_cmd);
4029 install_element (RIP_NODE, &no_rip_route_cmd);
4030 install_element (RIP_NODE, &rip_distance_cmd);
4031 install_element (RIP_NODE, &no_rip_distance_cmd);
4032 install_element (RIP_NODE, &rip_distance_source_cmd);
4033 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4034 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4035 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4036
4037 /* Debug related init. */
4038 rip_debug_init ();
4039
paul718e3742002-12-13 20:15:29 +00004040 /* SNMP init. */
4041#ifdef HAVE_SNMP
4042 rip_snmp_init ();
4043#endif /* HAVE_SNMP */
4044
4045 /* Access list install. */
4046 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004047 access_list_add_hook (rip_distribute_update_all_wrapper);
4048 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004049
4050 /* Prefix list initialize.*/
4051 prefix_list_init ();
4052 prefix_list_add_hook (rip_distribute_update_all);
4053 prefix_list_delete_hook (rip_distribute_update_all);
4054
4055 /* Distribute list install. */
4056 distribute_list_init (RIP_NODE);
4057 distribute_list_add_hook (rip_distribute_update);
4058 distribute_list_delete_hook (rip_distribute_update);
4059
hasso16705132003-05-25 14:49:19 +00004060 /* Route-map */
4061 rip_route_map_init ();
4062 rip_offset_init ();
4063
4064 route_map_add_hook (rip_routemap_update);
4065 route_map_delete_hook (rip_routemap_update);
4066
4067 if_rmap_init (RIP_NODE);
4068 if_rmap_hook_add (rip_if_rmap_update);
4069 if_rmap_hook_delete (rip_if_rmap_update);
4070
paul718e3742002-12-13 20:15:29 +00004071 /* Distance control. */
4072 rip_distance_table = route_table_init ();
4073}