blob: 13cf9b9bdde7ee2795fb7772b7237e2de32420af [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};
88
89/* Each route type's strings and default preference. */
90struct
91{
92 int key;
hasso8a676be2004-10-08 06:36:38 +000093 const char *str;
94 const char *str_long;
paul718e3742002-12-13 20:15:29 +000095} route_info[] =
96{
97 { ZEBRA_ROUTE_SYSTEM, "X", "system"},
98 { ZEBRA_ROUTE_KERNEL, "K", "kernel"},
99 { ZEBRA_ROUTE_CONNECT, "C", "connected"},
100 { ZEBRA_ROUTE_STATIC, "S", "static"},
101 { ZEBRA_ROUTE_RIP, "R", "rip"},
102 { ZEBRA_ROUTE_RIPNG, "R", "ripng"},
103 { ZEBRA_ROUTE_OSPF, "O", "ospf"},
104 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"},
hasso8a676be2004-10-08 06:36:38 +0000105 { ZEBRA_ROUTE_ISIS, "I", "isis"},
paul718e3742002-12-13 20:15:29 +0000106 { ZEBRA_ROUTE_BGP, "B", "bgp"}
107};
108
109/* Utility function to set boradcast option to the socket. */
110int
111sockopt_broadcast (int sock)
112{
113 int ret;
114 int on = 1;
115
116 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
117 if (ret < 0)
118 {
119 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
120 return -1;
121 }
122 return 0;
123}
124
125int
126rip_route_rte (struct rip_info *rinfo)
127{
128 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
129}
130
131struct rip_info *
132rip_info_new ()
133{
134 struct rip_info *new;
135
136 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
137 memset (new, 0, sizeof (struct rip_info));
138 return new;
139}
140
141void
142rip_info_free (struct rip_info *rinfo)
143{
144 XFREE (MTYPE_RIP_INFO, rinfo);
145}
146
147/* RIP route garbage collect timer. */
148int
149rip_garbage_collect (struct thread *t)
150{
151 struct rip_info *rinfo;
152 struct route_node *rp;
153
154 rinfo = THREAD_ARG (t);
155 rinfo->t_garbage_collect = NULL;
156
157 /* Off timeout timer. */
158 RIP_TIMER_OFF (rinfo->t_timeout);
159
160 /* Get route_node pointer. */
161 rp = rinfo->rp;
162
163 /* Unlock route_node. */
164 rp->info = NULL;
165 route_unlock_node (rp);
166
167 /* Free RIP routing information. */
168 rip_info_free (rinfo);
169
170 return 0;
171}
172
173/* Timeout RIP routes. */
174int
175rip_timeout (struct thread *t)
176{
177 struct rip_info *rinfo;
178 struct route_node *rn;
179
180 rinfo = THREAD_ARG (t);
181 rinfo->t_timeout = NULL;
182
183 rn = rinfo->rp;
184
185 /* - The garbage-collection timer is set for 120 seconds. */
186 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
187 rip->garbage_time);
188
189 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
190 rinfo->metric);
191 /* - The metric for the route is set to 16 (infinity). This causes
192 the route to be removed from service. */
193 rinfo->metric = RIP_METRIC_INFINITY;
194 rinfo->flags &= ~RIP_RTF_FIB;
195
196 /* - The route change flag is to indicate that this entry has been
197 changed. */
198 rinfo->flags |= RIP_RTF_CHANGED;
199
200 /* - The output process is signalled to trigger a response. */
201 rip_event (RIP_TRIGGERED_UPDATE, 0);
202
203 return 0;
204}
205
206void
207rip_timeout_update (struct rip_info *rinfo)
208{
209 if (rinfo->metric != RIP_METRIC_INFINITY)
210 {
211 RIP_TIMER_OFF (rinfo->t_timeout);
212 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
213 }
214}
215
216int
217rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
218{
219 struct distribute *dist;
220 struct access_list *alist;
221 struct prefix_list *plist;
222
223 /* Input distribute-list filtering. */
224 if (ri->list[RIP_FILTER_IN])
225 {
226 if (access_list_apply (ri->list[RIP_FILTER_IN],
227 (struct prefix *) p) == FILTER_DENY)
228 {
229 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000230 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000231 inet_ntoa (p->prefix), p->prefixlen);
232 return -1;
233 }
234 }
235 if (ri->prefix[RIP_FILTER_IN])
236 {
237 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
238 (struct prefix *) p) == PREFIX_DENY)
239 {
240 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000241 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000242 inet_ntoa (p->prefix), p->prefixlen);
243 return -1;
244 }
245 }
246
247 /* All interface filter check. */
248 dist = distribute_lookup (NULL);
249 if (dist)
250 {
251 if (dist->list[DISTRIBUTE_IN])
252 {
253 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
254
255 if (alist)
256 {
257 if (access_list_apply (alist,
258 (struct prefix *) p) == FILTER_DENY)
259 {
260 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000261 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000262 inet_ntoa (p->prefix), p->prefixlen);
263 return -1;
264 }
265 }
266 }
267 if (dist->prefix[DISTRIBUTE_IN])
268 {
269 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
270
271 if (plist)
272 {
273 if (prefix_list_apply (plist,
274 (struct prefix *) p) == PREFIX_DENY)
275 {
276 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000277 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000278 inet_ntoa (p->prefix), p->prefixlen);
279 return -1;
280 }
281 }
282 }
283 }
284 return 0;
285}
286
287int
288rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
289{
290 struct distribute *dist;
291 struct access_list *alist;
292 struct prefix_list *plist;
293
294 if (ri->list[RIP_FILTER_OUT])
295 {
296 if (access_list_apply (ri->list[RIP_FILTER_OUT],
297 (struct prefix *) p) == FILTER_DENY)
298 {
299 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000300 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000301 inet_ntoa (p->prefix), p->prefixlen);
302 return -1;
303 }
304 }
305 if (ri->prefix[RIP_FILTER_OUT])
306 {
307 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
308 (struct prefix *) p) == PREFIX_DENY)
309 {
310 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000311 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000312 inet_ntoa (p->prefix), p->prefixlen);
313 return -1;
314 }
315 }
316
317 /* All interface filter check. */
318 dist = distribute_lookup (NULL);
319 if (dist)
320 {
321 if (dist->list[DISTRIBUTE_OUT])
322 {
323 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
324
325 if (alist)
326 {
327 if (access_list_apply (alist,
328 (struct prefix *) p) == FILTER_DENY)
329 {
330 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000331 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000332 inet_ntoa (p->prefix), p->prefixlen);
333 return -1;
334 }
335 }
336 }
337 if (dist->prefix[DISTRIBUTE_OUT])
338 {
339 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
340
341 if (plist)
342 {
343 if (prefix_list_apply (plist,
344 (struct prefix *) p) == PREFIX_DENY)
345 {
346 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000347 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000348 inet_ntoa (p->prefix), p->prefixlen);
349 return -1;
350 }
351 }
352 }
353 }
354 return 0;
355}
356
357/* Check nexthop address validity. */
358static int
359rip_nexthop_check (struct in_addr *addr)
360{
hasso52dc7ee2004-09-23 19:18:23 +0000361 struct listnode *node;
362 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000363 struct interface *ifp;
364 struct connected *ifc;
365 struct prefix *p;
366
367 /* If nexthop address matches local configured address then it is
368 invalid nexthop. */
paul1eb8ef22005-04-07 07:30:20 +0000369 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000370 {
paul1eb8ef22005-04-07 07:30:20 +0000371 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000372 {
paul718e3742002-12-13 20:15:29 +0000373 p = ifc->address;
374
375 if (p->family == AF_INET
376 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
377 return -1;
378 }
379 }
380 return 0;
381}
382
383/* RIP add route to routing table. */
384void
385rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000386 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000387{
388 int ret;
389 struct prefix_ipv4 p;
390 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000391 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000392 struct rip_interface *ri;
393 struct in_addr *nexthop;
394 u_char oldmetric;
395 int same = 0;
vincentfbf5d032005-09-29 11:25:50 +0000396 int route_reuse = 0;
397 unsigned char old_dist, new_dist;
paul718e3742002-12-13 20:15:29 +0000398
399 /* Make prefix structure. */
400 memset (&p, 0, sizeof (struct prefix_ipv4));
401 p.family = AF_INET;
402 p.prefix = rte->prefix;
403 p.prefixlen = ip_masklen (rte->mask);
404
405 /* Make sure mask is applied. */
406 apply_mask_ipv4 (&p);
407
408 /* Apply input filters. */
409 ri = ifp->info;
410
411 ret = rip_incoming_filter (&p, ri);
412 if (ret < 0)
413 return;
414
hasso16705132003-05-25 14:49:19 +0000415 /* Modify entry according to the interface routemap. */
416 if (ri->routemap[RIP_FILTER_IN])
417 {
418 int ret;
419 struct rip_info newinfo;
420
421 memset (&newinfo, 0, sizeof (newinfo));
422 newinfo.type = ZEBRA_ROUTE_RIP;
423 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000424 newinfo.nexthop = rte->nexthop;
425 newinfo.from = from->sin_addr;
426 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000427 newinfo.metric = rte->metric;
428 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000429 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000430
431 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000432 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
433 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000434
435 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000436 {
437 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000438 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000439 inet_ntoa (p.prefix), p.prefixlen);
440 return;
441 }
hasso16705132003-05-25 14:49:19 +0000442
443 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000444 rte->nexthop = newinfo.nexthop_out;
445 rte->tag = htons (newinfo.tag_out); /* XXX */
446 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000447 }
448
paul718e3742002-12-13 20:15:29 +0000449 /* Once the entry has been validated, update the metric by
450 adding the cost of the network on wich the message
451 arrived. If the result is greater than infinity, use infinity
452 (RFC2453 Sec. 3.9.2) */
453 /* Zebra ripd can handle offset-list in. */
454 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
455
456 /* If offset-list does not modify the metric use interface's
457 metric. */
paula87552c2004-05-03 20:00:17 +0000458 if (!ret)
paul718e3742002-12-13 20:15:29 +0000459 rte->metric += ifp->metric;
460
461 if (rte->metric > RIP_METRIC_INFINITY)
462 rte->metric = RIP_METRIC_INFINITY;
463
464 /* Set nexthop pointer. */
465 if (rte->nexthop.s_addr == 0)
466 nexthop = &from->sin_addr;
467 else
468 nexthop = &rte->nexthop;
469
hasso16705132003-05-25 14:49:19 +0000470 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000471 if (rip_nexthop_check (nexthop) < 0)
472 {
473 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000474 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000475 return;
476 }
477
478 /* Get index for the prefix. */
479 rp = route_node_get (rip->table, (struct prefix *) &p);
480
481 /* Check to see whether there is already RIP route on the table. */
482 rinfo = rp->info;
483
484 if (rinfo)
485 {
paul718e3742002-12-13 20:15:29 +0000486 /* Local static route. */
487 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000488 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
489 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
490 && rinfo->metric != RIP_METRIC_INFINITY)
vincentfbf5d032005-09-29 11:25:50 +0000491 {
492 route_unlock_node (rp);
493 return;
494 }
495
496 /* Redistributed route check. */
497 if (rinfo->type != ZEBRA_ROUTE_RIP
498 && rinfo->metric != RIP_METRIC_INFINITY)
499 {
500 /* Fill in a minimaly temporary rip_info structure, for a future
501 rip_distance_apply() use) */
502 memset (&rinfotmp, 0, sizeof (rinfotmp));
503 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
504 rinfotmp.rp = rinfo->rp;
505 new_dist = rip_distance_apply (&rinfotmp);
506 new_dist = new_dist ? new_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
507 old_dist = rinfo->distance;
508 old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
509 /* If imported route does not have STRICT precedence,
510 mark it as a ghost */
511 if (new_dist > old_dist
512 || rte->metric == RIP_METRIC_INFINITY)
513 {
514 route_unlock_node (rp);
515 return;
516 }
517 else
518 {
519 RIP_TIMER_OFF (rinfo->t_timeout);
520 RIP_TIMER_OFF (rinfo->t_garbage_collect);
521
522 rp->info = NULL;
523 if (rip_route_rte (rinfo))
524 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
525 &rinfo->nexthop, rinfo->metric);
526 rip_info_free (rinfo);
527 rinfo = NULL;
528 route_reuse = 1;
529 }
530 }
paul718e3742002-12-13 20:15:29 +0000531 }
paula87552c2004-05-03 20:00:17 +0000532
533 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000534 {
535 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000536 for the destination prefix. If there is no such route, add
537 this route to the routing table, unless the metric is
538 infinity (there is no point in adding a route which
539 unusable). */
paul718e3742002-12-13 20:15:29 +0000540 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000541 {
542 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000543
paula87552c2004-05-03 20:00:17 +0000544 /* - Setting the destination prefix and length to those in
545 the RTE. */
546 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000547
paula87552c2004-05-03 20:00:17 +0000548 /* - Setting the metric to the newly calculated metric (as
549 described above). */
550 rinfo->metric = rte->metric;
551 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000552
paula87552c2004-05-03 20:00:17 +0000553 /* - Set the next hop address to be the address of the router
554 from which the datagram came or the next hop address
555 specified by a next hop RTE. */
556 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
557 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
558 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000559
paula87552c2004-05-03 20:00:17 +0000560 /* - Initialize the timeout for the route. If the
561 garbage-collection timer is running for this route, stop it
562 (see section 2.3 for a discussion of the timers). */
563 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000564
paula87552c2004-05-03 20:00:17 +0000565 /* - Set the route change flag. */
566 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000567
paula87552c2004-05-03 20:00:17 +0000568 /* - Signal the output process to trigger an update (see section
569 2.5). */
570 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000571
paula87552c2004-05-03 20:00:17 +0000572 /* Finally, route goes into the kernel. */
573 rinfo->type = ZEBRA_ROUTE_RIP;
574 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000575
paula87552c2004-05-03 20:00:17 +0000576 /* Set distance value. */
577 rinfo->distance = rip_distance_apply (rinfo);
578
579 rp->info = rinfo;
580 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
581 rinfo->distance);
582 rinfo->flags |= RIP_RTF_FIB;
583 }
vincentfbf5d032005-09-29 11:25:50 +0000584
585 /* Unlock temporary lock, i.e. same behaviour */
586 if (route_reuse)
587 route_unlock_node (rp);
paul718e3742002-12-13 20:15:29 +0000588 }
589 else
590 {
591 /* Route is there but we are not sure the route is RIP or not. */
592 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000593
paul718e3742002-12-13 20:15:29 +0000594 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000595 to the address of the router from which the datagram came.
596 If this datagram is from the same router as the existing
597 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000598 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000599 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000600
601 if (same)
paula87552c2004-05-03 20:00:17 +0000602 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000603
paulb94f9db2004-05-01 20:45:38 +0000604
605 /* Fill in a minimaly temporary rip_info structure, for a future
606 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000607 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000608 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000609 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000610
611
paul718e3742002-12-13 20:15:29 +0000612 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000613 router as the existing route, and the new metric is different
614 than the old one; or, if the new metric is lower than the old
615 one, or if the tag has been changed; or if there is a route
616 with a lower administrave distance; or an update of the
617 distance on the actual route; do the following actions: */
618 if ((same && rinfo->metric != rte->metric)
619 || (rte->metric < rinfo->metric)
620 || ((same)
621 && (rinfo->metric == rte->metric)
622 && ntohs (rte->tag) != rinfo->tag)
623 || (rinfo->distance > rip_distance_apply (&rinfotmp))
624 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
625 {
626 /* - Adopt the route from the datagram. That is, put the
627 new metric in, and adjust the next hop address (if
628 necessary). */
629 oldmetric = rinfo->metric;
630 rinfo->metric = rte->metric;
631 rinfo->tag = ntohs (rte->tag);
632 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
633 rinfo->ifindex = ifp->ifindex;
634 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000635
paula87552c2004-05-03 20:00:17 +0000636 /* Should a new route to this network be established
637 while the garbage-collection timer is running, the
638 new route will replace the one that is about to be
639 deleted. In this case the garbage-collection timer
640 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000641
paula87552c2004-05-03 20:00:17 +0000642 if (oldmetric == RIP_METRIC_INFINITY &&
643 rinfo->metric < RIP_METRIC_INFINITY)
644 {
645 rinfo->type = ZEBRA_ROUTE_RIP;
646 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000647
paula87552c2004-05-03 20:00:17 +0000648 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000649
paula87552c2004-05-03 20:00:17 +0000650 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
651 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000652
paula87552c2004-05-03 20:00:17 +0000653 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
654 rinfo->distance);
655 rinfo->flags |= RIP_RTF_FIB;
656 }
paul718e3742002-12-13 20:15:29 +0000657
paula87552c2004-05-03 20:00:17 +0000658 /* Update nexthop and/or metric value. */
659 if (oldmetric != RIP_METRIC_INFINITY)
660 {
661 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
662 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
663 rinfo->distance);
664 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000665
paula87552c2004-05-03 20:00:17 +0000666 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
667 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
668 }
paul718e3742002-12-13 20:15:29 +0000669
paula87552c2004-05-03 20:00:17 +0000670 /* - Set the route change flag and signal the output process
671 to trigger an update. */
672 rinfo->flags |= RIP_RTF_CHANGED;
673 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000674
paula87552c2004-05-03 20:00:17 +0000675 /* - If the new metric is infinity, start the deletion
676 process (described above); */
677 if (rinfo->metric == RIP_METRIC_INFINITY)
678 {
679 /* If the new metric is infinity, the deletion process
680 begins for the route, which is no longer used for
681 routing packets. Note that the deletion process is
682 started only when the metric is first set to
683 infinity. If the metric was already infinity, then a
684 new deletion process is not started. */
685 if (oldmetric != RIP_METRIC_INFINITY)
686 {
687 /* - The garbage-collection timer is set for 120 seconds. */
688 RIP_TIMER_ON (rinfo->t_garbage_collect,
689 rip_garbage_collect, rip->garbage_time);
690 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000691
paula87552c2004-05-03 20:00:17 +0000692 /* - The metric for the route is set to 16
693 (infinity). This causes the route to be removed
694 from service. */
695 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
696 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000697
paula87552c2004-05-03 20:00:17 +0000698 /* - The route change flag is to indicate that this
699 entry has been changed. */
700 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000701 response. */
paula87552c2004-05-03 20:00:17 +0000702 ; /* Above processes are already done previously. */
703 }
704 }
705 else
706 {
707 /* otherwise, re-initialize the timeout. */
708 rip_timeout_update (rinfo);
709 }
710 }
paul718e3742002-12-13 20:15:29 +0000711 /* Unlock tempolary lock of the route. */
712 route_unlock_node (rp);
713 }
714}
715
716/* Dump RIP packet */
717void
hasso8a676be2004-10-08 06:36:38 +0000718rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000719{
720 caddr_t lim;
721 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000722 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000723 char pbuf[BUFSIZ], nbuf[BUFSIZ];
724 u_char netmask = 0;
725 u_char *p;
726
727 /* Set command string. */
728 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
729 command_str = lookup (rip_msg, packet->command);
730 else
731 command_str = "unknown";
732
733 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000734 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000735 sndrcv, command_str, packet->version, size);
736
737 /* Dump each routing table entry. */
738 rte = packet->rte;
739
740 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
741 {
742 if (packet->version == RIPv2)
743 {
744 netmask = ip_masklen (rte->mask);
745
paulca5e5162004-06-06 22:06:33 +0000746 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000747 {
paulca5e5162004-06-06 22:06:33 +0000748 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000749 {
750 p = (u_char *)&rte->prefix;
751
ajs5d6c3772004-12-08 19:24:06 +0000752 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000753 ntohs (rte->family), ntohs (rte->tag), p);
754 }
paulca5e5162004-06-06 22:06:33 +0000755 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000756 {
757 struct rip_md5_info *md5;
758
759 md5 = (struct rip_md5_info *) &packet->rte;
760
ajs5d6c3772004-12-08 19:24:06 +0000761 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000762 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000763 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000764 " Auth Data len %d",
765 ntohs (md5->packet_len), md5->keyid,
766 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000767 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000768 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000769 }
paulca5e5162004-06-06 22:06:33 +0000770 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000771 {
772 p = (u_char *)&rte->prefix;
773
ajs5d6c3772004-12-08 19:24:06 +0000774 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000775 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000776 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000777 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000778 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
779 p[7], p[9], p[10], p[11], p[12], p[13],
780 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000781 }
782 else
783 {
ajs5d6c3772004-12-08 19:24:06 +0000784 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000785 ntohs (rte->family), ntohs (rte->tag));
786 }
787 }
788 else
ajs5d6c3772004-12-08 19:24:06 +0000789 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000790 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
791 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
792 BUFSIZ), ntohs (rte->family),
793 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000794 }
795 else
796 {
ajs5d6c3772004-12-08 19:24:06 +0000797 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000798 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
799 ntohs (rte->family), ntohs (rte->tag),
800 (u_long)ntohl (rte->metric));
801 }
802 }
803}
804
805/* Check if the destination address is valid (unicast; not net 0
806 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
807 check net 0 because we accept default route. */
808int
809rip_destination_check (struct in_addr addr)
810{
811 u_int32_t destination;
812
813 /* Convert to host byte order. */
814 destination = ntohl (addr.s_addr);
815
816 if (IPV4_NET127 (destination))
817 return 0;
818
819 /* Net 0 may match to the default route. */
820 if (IPV4_NET0 (destination) && destination != 0)
821 return 0;
822
823 /* Unicast address must belong to class A, B, C. */
824 if (IN_CLASSA (destination))
825 return 1;
826 if (IN_CLASSB (destination))
827 return 1;
828 if (IN_CLASSC (destination))
829 return 1;
830
831 return 0;
832}
833
834/* RIP version 2 authentication. */
835int
836rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
837 struct interface *ifp)
838{
839 struct rip_interface *ri;
840 char *auth_str;
841
842 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000843 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000844 inet_ntoa (from->sin_addr));
845
846 ri = ifp->info;
847
848 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000849 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000850 return 0;
851
852 /* Simple password authentication. */
853 if (ri->auth_str)
854 {
855 auth_str = (char *) &rte->prefix;
856
857 if (strncmp (auth_str, ri->auth_str, 16) == 0)
858 return 1;
859 }
860 if (ri->key_chain)
861 {
862 struct keychain *keychain;
863 struct key *key;
864
865 keychain = keychain_lookup (ri->key_chain);
866 if (keychain == NULL)
867 return 0;
868
869 key = key_match_for_accept (keychain, (char *) &rte->prefix);
870 if (key)
871 return 1;
872 }
873 return 0;
874}
875
876/* RIP version 2 authentication with MD5. */
877int
878rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000879 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000880{
881 struct rip_interface *ri;
882 struct rip_md5_info *md5;
883 struct rip_md5_data *md5data;
884 struct keychain *keychain;
885 struct key *key;
vincentc1a03d42005-09-28 15:47:44 +0000886 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000887 u_char pdigest[RIP_AUTH_MD5_SIZE];
888 u_char digest[RIP_AUTH_MD5_SIZE];
889 u_int16_t packet_len;
890 char *auth_str = NULL;
891
892 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000893 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000894 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000895
896 ri = ifp->info;
897 md5 = (struct rip_md5_info *) &packet->rte;
898
899 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000900 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000901 return 0;
902
paulca5e5162004-06-06 22:06:33 +0000903 /* If the authentication length is less than 16, then it must be wrong for
904 * any interpretation of rfc2082. Some implementations also interpret
905 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000906 */
paulca5e5162004-06-06 22:06:33 +0000907 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
908 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000909 {
910 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000911 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000912 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000913 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000914 }
paul718e3742002-12-13 20:15:29 +0000915
paulca5e5162004-06-06 22:06:33 +0000916 /* grab and verify check packet length */
917 packet_len = ntohs (md5->packet_len);
918
919 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
920 {
921 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000922 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000923 "greater than received length %d!",
924 md5->packet_len, length);
925 return 0;
926 }
927
928 /* retrieve authentication data */
929 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
930
paul718e3742002-12-13 20:15:29 +0000931 if (ri->key_chain)
932 {
933 keychain = keychain_lookup (ri->key_chain);
934 if (keychain == NULL)
935 return 0;
936
937 key = key_lookup_for_accept (keychain, md5->keyid);
938 if (key == NULL)
939 return 0;
940
941 auth_str = key->string;
942 }
943
944 if (ri->auth_str)
945 auth_str = ri->auth_str;
946
947 if (! auth_str)
948 return 0;
949
950 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000951
952 /* Save digest to pdigest. */
953 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
954
955 /* Overwrite digest by my secret. */
956 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000957 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000958
vincentc1a03d42005-09-28 15:47:44 +0000959 memset (&ctx, 0, sizeof(ctx));
960 MD5Init(&ctx);
961 MD5Update(&ctx, packet, packet_len + md5->auth_len);
962 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000963
964 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
965 return packet_len;
966 else
967 return 0;
968}
969
paulb14ee002005-02-04 23:42:41 +0000970/* Pick correct auth string for sends, prepare auth_str buffer for use.
971 * (left justified and padded).
972 *
973 * presumes one of ri or key is valid, and that the auth strings they point
974 * to are nul terminated. If neither are present, auth_str will be fully
975 * zero padded.
976 *
977 */
978static void
979rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
980 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000981{
paulb14ee002005-02-04 23:42:41 +0000982 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000983
paulb14ee002005-02-04 23:42:41 +0000984 memset (auth_str, 0, len);
985 if (key && key->string)
986 strncpy (auth_str, key->string, len);
987 else if (ri->auth_str)
988 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000989
paulb14ee002005-02-04 23:42:41 +0000990 return;
991}
paul718e3742002-12-13 20:15:29 +0000992
paulb14ee002005-02-04 23:42:41 +0000993/* Write RIPv2 simple password authentication information
994 *
995 * auth_str is presumed to be 2 bytes and correctly prepared
996 * (left justified and zero padded).
997 */
998static void
999rip_auth_simple_write (struct stream *s, char *auth_str, int len)
1000{
1001 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00001002
paulb14ee002005-02-04 23:42:41 +00001003 stream_putw (s, RIP_FAMILY_AUTH);
1004 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1005 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
1006
1007 return;
1008}
1009
1010/* write RIPv2 MD5 "authentication header"
1011 * (uses the auth key data field)
1012 *
1013 * Digest offset field is set to 0.
1014 *
1015 * returns: offset of the digest offset field, which must be set when
1016 * length to the auth-data MD5 digest is known.
1017 */
1018static size_t
1019rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
1020 struct key *key)
1021{
1022 size_t len = 0;
1023
1024 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +00001025
1026 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +00001027 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00001028 stream_putw (s, RIP_AUTH_MD5);
1029
paulb14ee002005-02-04 23:42:41 +00001030 /* MD5 AH digest offset field.
1031 *
1032 * Set to placeholder value here, to true value when RIP-2 Packet length
1033 * is known. Actual value is set in .....().
1034 */
paul9985f832005-02-09 15:51:56 +00001035 len = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +00001036 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +00001037
1038 /* Key ID. */
1039 if (key)
1040 stream_putc (s, key->index % 256);
1041 else
1042 stream_putc (s, 1);
1043
paulca5e5162004-06-06 22:06:33 +00001044 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1045 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1046 * to be configurable.
1047 */
1048 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001049
1050 /* Sequence Number (non-decreasing). */
1051 /* RFC2080: The value used in the sequence number is
1052 arbitrary, but two suggestions are the time of the
1053 message's creation or a simple message counter. */
1054 stream_putl (s, time (NULL));
1055
1056 /* Reserved field must be zero. */
1057 stream_putl (s, 0);
1058 stream_putl (s, 0);
1059
paulb14ee002005-02-04 23:42:41 +00001060 return len;
1061}
paul718e3742002-12-13 20:15:29 +00001062
paulb14ee002005-02-04 23:42:41 +00001063/* If authentication is in used, write the appropriate header
1064 * returns stream offset to which length must later be written
1065 * or 0 if this is not required
1066 */
1067static size_t
1068rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1069 struct key *key, char *auth_str, int len)
1070{
1071 assert (ri->auth_type != RIP_NO_AUTH);
1072
1073 switch (ri->auth_type)
1074 {
1075 case RIP_AUTH_SIMPLE_PASSWORD:
1076 rip_auth_prepare_str_send (ri, key, auth_str, len);
1077 rip_auth_simple_write (s, auth_str, len);
1078 return 0;
1079 case RIP_AUTH_MD5:
1080 return rip_auth_md5_ah_write (s, ri, key);
1081 }
1082 assert (1);
1083}
1084
1085/* Write RIPv2 MD5 authentication data trailer */
1086static void
1087rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1088 char *auth_str, int authlen)
1089{
1090 unsigned long len;
vincentc1a03d42005-09-28 15:47:44 +00001091 MD5_CTX ctx;
paulb14ee002005-02-04 23:42:41 +00001092 unsigned char digest[RIP_AUTH_MD5_SIZE];
1093
1094 /* Make it sure this interface is configured as MD5
1095 authentication. */
1096 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1097 assert (doff > 0);
1098
1099 /* Get packet length. */
1100 len = stream_get_endp(s);
1101
1102 /* Check packet length. */
1103 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1104 {
1105 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1106 return;
1107 }
1108
1109 /* Set the digest offset length in the header */
1110 stream_putw_at (s, doff, len);
1111
paul718e3742002-12-13 20:15:29 +00001112 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001113 stream_putw (s, RIP_FAMILY_AUTH);
1114 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001115
1116 /* Generate a digest for the RIP packet. */
vincentc1a03d42005-09-28 15:47:44 +00001117 memset(&ctx, 0, sizeof(ctx));
1118 MD5Init(&ctx);
1119 MD5Update(&ctx, s->data, s->endp);
1120 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1121 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +00001122
1123 /* Copy the digest to the packet. */
1124 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1125}
1126
1127/* RIP routing information. */
1128void
1129rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001130 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001131{
1132 caddr_t lim;
1133 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001134 struct prefix_ipv4 ifaddr;
1135 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001136 int subnetted;
paul718e3742002-12-13 20:15:29 +00001137
paul727d1042002-12-13 20:50:29 +00001138 /* We don't know yet. */
1139 subnetted = -1;
1140
paul718e3742002-12-13 20:15:29 +00001141 /* The Response must be ignored if it is not from the RIP
1142 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001143 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001144 {
1145 zlog_info ("response doesn't come from RIP port: %d",
1146 from->sin_port);
1147 rip_peer_bad_packet (from);
1148 return;
1149 }
1150
1151 /* The datagram's IPv4 source address should be checked to see
1152 whether the datagram is from a valid neighbor; the source of the
1153 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001154 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001155 {
1156 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1157 inet_ntoa (from->sin_addr));
1158 rip_peer_bad_packet (from);
1159 return;
1160 }
1161
1162 /* It is also worth checking to see whether the response is from one
1163 of the router's own addresses. */
1164
1165 ; /* Alredy done in rip_read () */
1166
1167 /* Update RIP peer. */
1168 rip_peer_update (from, packet->version);
1169
1170 /* Set RTE pointer. */
1171 rte = packet->rte;
1172
1173 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1174 {
1175 /* RIPv2 authentication check. */
1176 /* If the Address Family Identifier of the first (and only the
1177 first) entry in the message is 0xFFFF, then the remainder of
1178 the entry contains the authentication. */
1179 /* If the packet gets here it means authentication enabled */
1180 /* Check is done in rip_read(). So, just skipping it */
1181 if (packet->version == RIPv2 &&
1182 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001183 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001184 continue;
1185
paulca5e5162004-06-06 22:06:33 +00001186 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001187 {
1188 /* Address family check. RIP only supports AF_INET. */
1189 zlog_info ("Unsupported family %d from %s.",
1190 ntohs (rte->family), inet_ntoa (from->sin_addr));
1191 continue;
1192 }
1193
1194 /* - is the destination address valid (e.g., unicast; not net 0
1195 or 127) */
1196 if (! rip_destination_check (rte->prefix))
1197 {
1198 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1199 rip_peer_bad_route (from);
1200 continue;
1201 }
1202
1203 /* Convert metric value to host byte order. */
1204 rte->metric = ntohl (rte->metric);
1205
1206 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1207 if (! (rte->metric >= 1 && rte->metric <= 16))
1208 {
1209 zlog_info ("Route's metric is not in the 1-16 range.");
1210 rip_peer_bad_route (from);
1211 continue;
1212 }
1213
1214 /* RIPv1 does not have nexthop value. */
1215 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1216 {
1217 zlog_info ("RIPv1 packet with nexthop value %s",
1218 inet_ntoa (rte->nexthop));
1219 rip_peer_bad_route (from);
1220 continue;
1221 }
1222
1223 /* That is, if the provided information is ignored, a possibly
1224 sub-optimal, but absolutely valid, route may be taken. If
1225 the received Next Hop is not directly reachable, it should be
1226 treated as 0.0.0.0. */
1227 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1228 {
1229 u_int32_t addrval;
1230
1231 /* Multicast address check. */
1232 addrval = ntohl (rte->nexthop.s_addr);
1233 if (IN_CLASSD (addrval))
1234 {
1235 zlog_info ("Nexthop %s is multicast address, skip this rte",
1236 inet_ntoa (rte->nexthop));
1237 continue;
1238 }
1239
1240 if (! if_lookup_address (rte->nexthop))
1241 {
1242 struct route_node *rn;
1243 struct rip_info *rinfo;
1244
1245 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1246
1247 if (rn)
1248 {
1249 rinfo = rn->info;
1250
1251 if (rinfo->type == ZEBRA_ROUTE_RIP
1252 && rinfo->sub_type == RIP_ROUTE_RTE)
1253 {
1254 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001255 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 +00001256 rte->nexthop = rinfo->from;
1257 }
1258 else
1259 {
1260 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001261 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 +00001262 rte->nexthop.s_addr = 0;
1263 }
1264
1265 route_unlock_node (rn);
1266 }
1267 else
1268 {
1269 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001270 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 +00001271 rte->nexthop.s_addr = 0;
1272 }
1273
1274 }
1275 }
1276
1277 /* For RIPv1, there won't be a valid netmask.
1278
1279 This is a best guess at the masks. If everyone was using old
1280 Ciscos before the 'ip subnet zero' option, it would be almost
1281 right too :-)
1282
1283 Cisco summarize ripv1 advertisments to the classful boundary
1284 (/16 for class B's) except when the RIP packet does to inside
1285 the classful network in question. */
1286
1287 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1288 || (packet->version == RIPv2
1289 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1290 {
1291 u_int32_t destination;
1292
paul727d1042002-12-13 20:50:29 +00001293 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001294 {
1295 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1296 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1297 apply_classful_mask_ipv4 (&ifaddrclass);
1298 subnetted = 0;
1299 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1300 subnetted = 1;
1301 }
paul727d1042002-12-13 20:50:29 +00001302
paul718e3742002-12-13 20:15:29 +00001303 destination = ntohl (rte->prefix.s_addr);
1304
paul727d1042002-12-13 20:50:29 +00001305 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001306 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001307 else if (IN_CLASSB (destination))
1308 masklen2ip (16, &rte->mask);
1309 else if (IN_CLASSC (destination))
1310 masklen2ip (24, &rte->mask);
1311
1312 if (subnetted == 1)
1313 masklen2ip (ifaddrclass.prefixlen,
1314 (struct in_addr *) &destination);
1315 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1316 ifaddrclass.prefix.s_addr))
1317 {
1318 masklen2ip (ifaddr.prefixlen, &rte->mask);
1319 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1320 masklen2ip (32, &rte->mask);
1321 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001322 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001323 }
1324 else
1325 {
1326 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1327 continue;
1328 }
1329
1330 if (IS_RIP_DEBUG_EVENT)
1331 {
ajs5d6c3772004-12-08 19:24:06 +00001332 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1333 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001334 }
1335 }
1336
1337 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1338 ignore the entry. */
1339 if ((packet->version == RIPv2)
1340 && (rte->mask.s_addr != 0)
1341 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1342 {
1343 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1344 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1345 rip_peer_bad_route (from);
1346 continue;
1347 }
1348
1349 /* Default route's netmask is ignored. */
1350 if (packet->version == RIPv2
1351 && (rte->prefix.s_addr == 0)
1352 && (rte->mask.s_addr != 0))
1353 {
1354 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001355 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001356 rte->mask.s_addr = 0;
1357 }
1358
1359 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001360 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001361 }
1362}
1363
paula4e987e2005-06-03 17:46:49 +00001364/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001365static int
paul2c61ae32005-08-16 15:22:14 +00001366rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001367{
1368 int ret;
1369 int sock;
1370 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001371
paul2c61ae32005-08-16 15:22:14 +00001372 memset (&addr, 0, sizeof (struct sockaddr_in));
1373
1374 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001375 {
paulf69bd9d2005-06-03 18:01:50 +00001376 addr.sin_family = AF_INET;
1377 addr.sin_addr.s_addr = INADDR_ANY;
paul2c61ae32005-08-16 15:22:14 +00001378#ifdef HAVE_SINLEN
1379 addr.sin_len = sizeof (struct sockaddr_in);
1380#endif /* HAVE_SINLEN */
paulf69bd9d2005-06-03 18:01:50 +00001381 }
1382
paul2c61ae32005-08-16 15:22:14 +00001383 /* sending port must always be the RIP port */
1384 addr.sin_port = htons (RIP_PORT_DEFAULT);
1385
paula4e987e2005-06-03 17:46:49 +00001386 /* Make datagram socket. */
1387 sock = socket (AF_INET, SOCK_DGRAM, 0);
1388 if (sock < 0)
1389 {
1390 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1391 exit (1);
1392 }
1393
1394 sockopt_broadcast (sock);
1395 sockopt_reuseaddr (sock);
1396 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001397#ifdef RIP_RECVMSG
1398 setsockopt_pktinfo (sock);
1399#endif /* RIP_RECVMSG */
1400
1401 if (ripd_privs.change (ZPRIVS_RAISE))
1402 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001403 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1404 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1405
paula4e987e2005-06-03 17:46:49 +00001406 {
1407 int save_errno = errno;
1408 if (ripd_privs.change (ZPRIVS_LOWER))
1409 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001410
1411 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1412 sock, inet_ntoa(addr.sin_addr),
1413 (int) ntohs(addr.sin_port),
1414 safe_strerror(save_errno));
1415
paulf69bd9d2005-06-03 18:01:50 +00001416 close (sock);
paula4e987e2005-06-03 17:46:49 +00001417 return ret;
1418 }
paulf69bd9d2005-06-03 18:01:50 +00001419
paula4e987e2005-06-03 17:46:49 +00001420 if (ripd_privs.change (ZPRIVS_LOWER))
1421 zlog_err ("rip_create_socket: could not lower privs");
1422
1423 return sock;
1424}
1425
paulc49ad8f2004-10-22 10:27:28 +00001426/* RIP packet send to destination address, on interface denoted by
1427 * by connected argument. NULL to argument denotes destination should be
1428 * should be RIP multicast group
1429 */
paul718e3742002-12-13 20:15:29 +00001430int
paulc49ad8f2004-10-22 10:27:28 +00001431rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1432 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001433{
paul931cd542004-01-23 15:31:42 +00001434 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001435 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001436
1437 assert (ifc != NULL);
1438
paul931cd542004-01-23 15:31:42 +00001439 if (IS_RIP_DEBUG_PACKET)
1440 {
paulf69bd9d2005-06-03 18:01:50 +00001441#define ADDRESS_SIZE 20
1442 char dst[ADDRESS_SIZE];
1443 dst[ADDRESS_SIZE - 1] = '\0';
1444
paul931cd542004-01-23 15:31:42 +00001445 if (to)
1446 {
paulf69bd9d2005-06-03 18:01:50 +00001447 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001448 }
1449 else
1450 {
1451 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001452 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001453 }
paulf69bd9d2005-06-03 18:01:50 +00001454#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001455 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001456 inet_ntoa(ifc->address->u.prefix4),
1457 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001458 }
paulf69bd9d2005-06-03 18:01:50 +00001459
paulc49ad8f2004-10-22 10:27:28 +00001460 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001461 {
1462 /*
1463 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1464 * with multiple addresses on the same subnet: the first address
1465 * on the subnet is configured "primary", and all subsequent addresses
1466 * on that subnet are treated as "secondary" addresses.
1467 * In order to avoid routing-table bloat on other rip listeners,
1468 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1469 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1470 * flag is set, we would end up sending a packet for a "secondary"
1471 * source address on non-linux systems.
1472 */
1473 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001474 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001475 return 0;
1476 }
1477
paul718e3742002-12-13 20:15:29 +00001478 /* Make destination address. */
1479 memset (&sin, 0, sizeof (struct sockaddr_in));
1480 sin.sin_family = AF_INET;
1481#ifdef HAVE_SIN_LEN
1482 sin.sin_len = sizeof (struct sockaddr_in);
1483#endif /* HAVE_SIN_LEN */
1484
1485 /* When destination is specified, use it's port and address. */
1486 if (to)
1487 {
paul718e3742002-12-13 20:15:29 +00001488 sin.sin_port = to->sin_port;
1489 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001490 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001491 }
1492 else
1493 {
paul2c61ae32005-08-16 15:22:14 +00001494 struct sockaddr_in from;
1495
paul718e3742002-12-13 20:15:29 +00001496 sin.sin_port = htons (RIP_PORT_DEFAULT);
1497 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001498
1499 /* multicast send should bind to local interface address */
1500 from.sin_family = AF_INET;
1501 from.sin_port = htons (RIP_PORT_DEFAULT);
1502 from.sin_addr = ifc->address->u.prefix4;
1503#ifdef HAVE_SIN_LEN
1504 from.sin_len = sizeof (struct sockaddr_in);
1505#endif /* HAVE_SIN_LEN */
1506
paul931cd542004-01-23 15:31:42 +00001507 /*
1508 * we have to open a new socket for each packet because this
1509 * is the most portable way to bind to a different source
1510 * ipv4 address for each packet.
1511 */
paul2c61ae32005-08-16 15:22:14 +00001512 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001513 {
paulf69bd9d2005-06-03 18:01:50 +00001514 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001515 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001516 }
paulc49ad8f2004-10-22 10:27:28 +00001517 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001518 }
1519
paul931cd542004-01-23 15:31:42 +00001520 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001521 sizeof (struct sockaddr_in));
1522
1523 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001524 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001525 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001526
1527 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001528 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001529
paul931cd542004-01-23 15:31:42 +00001530 if (!to)
1531 close(send_sock);
1532
paul718e3742002-12-13 20:15:29 +00001533 return ret;
1534}
1535
1536/* Add redistributed route to RIP table. */
1537void
1538rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
vincentfbf5d032005-09-29 11:25:50 +00001539 unsigned int ifindex, struct in_addr *nexthop,
1540 unsigned int metric, unsigned char distance)
paul718e3742002-12-13 20:15:29 +00001541{
1542 int ret;
1543 struct route_node *rp;
1544 struct rip_info *rinfo;
1545
1546 /* Redistribute route */
1547 ret = rip_destination_check (p->prefix);
1548 if (! ret)
1549 return;
1550
1551 rp = route_node_get (rip->table, (struct prefix *) p);
1552
1553 rinfo = rp->info;
1554
1555 if (rinfo)
1556 {
1557 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1558 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1559 && rinfo->metric != RIP_METRIC_INFINITY)
1560 {
1561 route_unlock_node (rp);
1562 return;
1563 }
1564
1565 /* Manually configured RIP route check. */
1566 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001567 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1568 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001569 {
hasso16705132003-05-25 14:49:19 +00001570 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1571 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001572 {
1573 route_unlock_node (rp);
1574 return;
1575 }
1576 }
1577
1578 RIP_TIMER_OFF (rinfo->t_timeout);
1579 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1580
1581 if (rip_route_rte (rinfo))
1582 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1583 rinfo->metric);
1584 rp->info = NULL;
1585 rip_info_free (rinfo);
1586
1587 route_unlock_node (rp);
1588 }
1589
1590 rinfo = rip_info_new ();
1591
1592 rinfo->type = type;
1593 rinfo->sub_type = sub_type;
1594 rinfo->ifindex = ifindex;
1595 rinfo->metric = 1;
vincentfbf5d032005-09-29 11:25:50 +00001596 rinfo->external_metric = metric;
1597 rinfo->distance = distance;
paul718e3742002-12-13 20:15:29 +00001598 rinfo->rp = rp;
1599
1600 if (nexthop)
1601 rinfo->nexthop = *nexthop;
1602
1603 rinfo->flags |= RIP_RTF_FIB;
1604 rp->info = rinfo;
1605
1606 rinfo->flags |= RIP_RTF_CHANGED;
1607
hasso16705132003-05-25 14:49:19 +00001608 if (IS_RIP_DEBUG_EVENT) {
1609 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001610 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001611 inet_ntoa(p->prefix), p->prefixlen,
1612 ifindex2ifname(ifindex));
1613 else
ajs5d6c3772004-12-08 19:24:06 +00001614 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001615 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1616 ifindex2ifname(ifindex));
1617 }
1618
1619
paul718e3742002-12-13 20:15:29 +00001620 rip_event (RIP_TRIGGERED_UPDATE, 0);
1621}
1622
1623/* Delete redistributed route from RIP table. */
1624void
1625rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1626 unsigned int ifindex)
1627{
1628 int ret;
1629 struct route_node *rp;
1630 struct rip_info *rinfo;
1631
1632 ret = rip_destination_check (p->prefix);
1633 if (! ret)
1634 return;
1635
1636 rp = route_node_lookup (rip->table, (struct prefix *) p);
1637 if (rp)
1638 {
1639 rinfo = rp->info;
1640
1641 if (rinfo != NULL
1642 && rinfo->type == type
1643 && rinfo->sub_type == sub_type
1644 && rinfo->ifindex == ifindex)
1645 {
1646 /* Perform poisoned reverse. */
1647 rinfo->metric = RIP_METRIC_INFINITY;
1648 RIP_TIMER_ON (rinfo->t_garbage_collect,
1649 rip_garbage_collect, rip->garbage_time);
1650 RIP_TIMER_OFF (rinfo->t_timeout);
1651 rinfo->flags |= RIP_RTF_CHANGED;
1652
hasso16705132003-05-25 14:49:19 +00001653 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001654 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001655 inet_ntoa(p->prefix), p->prefixlen,
1656 ifindex2ifname(ifindex));
1657
paul718e3742002-12-13 20:15:29 +00001658 rip_event (RIP_TRIGGERED_UPDATE, 0);
1659 }
1660 }
1661}
1662
1663/* Response to request called from rip_read ().*/
1664void
1665rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001666 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001667{
1668 caddr_t lim;
1669 struct rte *rte;
1670 struct prefix_ipv4 p;
1671 struct route_node *rp;
1672 struct rip_info *rinfo;
1673 struct rip_interface *ri;
1674
hasso16705132003-05-25 14:49:19 +00001675 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001676 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001677 return;
1678
hasso429a0f82004-02-22 23:42:22 +00001679 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001680 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001681 if (! ri->running)
1682 return;
paul718e3742002-12-13 20:15:29 +00001683
1684 /* When passive interface is specified, suppress responses */
1685 if (ri->passive)
1686 return;
paulc49ad8f2004-10-22 10:27:28 +00001687
paul718e3742002-12-13 20:15:29 +00001688 /* RIP peer update. */
1689 rip_peer_update (from, packet->version);
1690
1691 lim = ((caddr_t) packet) + size;
1692 rte = packet->rte;
1693
1694 /* The Request is processed entry by entry. If there are no
1695 entries, no response is given. */
1696 if (lim == (caddr_t) rte)
1697 return;
1698
1699 /* There is one special case. If there is exactly one entry in the
1700 request, and it has an address family identifier of zero and a
1701 metric of infinity (i.e., 16), then this is a request to send the
1702 entire routing table. */
1703 if (lim == ((caddr_t) (rte + 1)) &&
1704 ntohs (rte->family) == 0 &&
1705 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1706 {
paulcc1131a2003-10-15 23:20:17 +00001707 struct prefix_ipv4 saddr;
1708
1709 /* saddr will be used for determining which routes to split-horizon.
1710 Since the source address we'll pick will be on the same subnet as the
1711 destination, for the purpose of split-horizoning, we'll
1712 pretend that "from" is our source address. */
1713 saddr.family = AF_INET;
1714 saddr.prefixlen = IPV4_MAX_BITLEN;
1715 saddr.prefix = from->sin_addr;
1716
paul718e3742002-12-13 20:15:29 +00001717 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001718 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001719 }
1720 else
1721 {
1722 /* Examine the list of RTEs in the Request one by one. For each
1723 entry, look up the destination in the router's routing
1724 database and, if there is a route, put that route's metric in
1725 the metric field of the RTE. If there is no explicit route
1726 to the specified destination, put infinity in the metric
1727 field. Once all the entries have been filled in, change the
1728 command from Request to Response and send the datagram back
1729 to the requestor. */
1730 p.family = AF_INET;
1731
1732 for (; ((caddr_t) rte) < lim; rte++)
1733 {
1734 p.prefix = rte->prefix;
1735 p.prefixlen = ip_masklen (rte->mask);
1736 apply_mask_ipv4 (&p);
1737
1738 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1739 if (rp)
1740 {
1741 rinfo = rp->info;
1742 rte->metric = htonl (rinfo->metric);
1743 route_unlock_node (rp);
1744 }
1745 else
1746 rte->metric = htonl (RIP_METRIC_INFINITY);
1747 }
1748 packet->command = RIP_RESPONSE;
1749
paulc49ad8f2004-10-22 10:27:28 +00001750 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001751 }
1752 rip_global_queries++;
1753}
1754
1755#if RIP_RECVMSG
1756/* Set IPv6 packet info to the socket. */
1757static int
1758setsockopt_pktinfo (int sock)
1759{
1760 int ret;
1761 int val = 1;
1762
1763 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1764 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001765 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001766 return ret;
1767}
1768
1769/* Read RIP packet by recvmsg function. */
1770int
1771rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1772 int *ifindex)
1773{
1774 int ret;
1775 struct msghdr msg;
1776 struct iovec iov;
1777 struct cmsghdr *ptr;
1778 char adata[1024];
1779
1780 msg.msg_name = (void *) from;
1781 msg.msg_namelen = sizeof (struct sockaddr_in);
1782 msg.msg_iov = &iov;
1783 msg.msg_iovlen = 1;
1784 msg.msg_control = (void *) adata;
1785 msg.msg_controllen = sizeof adata;
1786 iov.iov_base = buf;
1787 iov.iov_len = size;
1788
1789 ret = recvmsg (sock, &msg, 0);
1790 if (ret < 0)
1791 return ret;
1792
ajsb99760a2005-01-04 16:24:43 +00001793 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001794 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1795 {
1796 struct in_pktinfo *pktinfo;
1797 int i;
1798
1799 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1800 i = pktinfo->ipi_ifindex;
1801 }
1802 return ret;
1803}
1804
1805/* RIP packet read function. */
1806int
1807rip_read_new (struct thread *t)
1808{
1809 int ret;
1810 int sock;
1811 char buf[RIP_PACKET_MAXSIZ];
1812 struct sockaddr_in from;
1813 unsigned int ifindex;
1814
1815 /* Fetch socket then register myself. */
1816 sock = THREAD_FD (t);
1817 rip_event (RIP_READ, sock);
1818
1819 /* Read RIP packet. */
1820 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1821 if (ret < 0)
1822 {
ajs6099b3b2004-11-20 02:06:59 +00001823 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001824 return ret;
1825 }
1826
1827 return ret;
1828}
1829#endif /* RIP_RECVMSG */
1830
1831/* First entry point of RIP packet. */
1832int
1833rip_read (struct thread *t)
1834{
1835 int sock;
1836 int ret;
1837 int rtenum;
1838 union rip_buf rip_buf;
1839 struct rip_packet *packet;
1840 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001841 int len;
1842 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001843 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001844 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001845 struct rip_interface *ri;
1846
1847 /* Fetch socket then register myself. */
1848 sock = THREAD_FD (t);
1849 rip->t_read = NULL;
1850
1851 /* Add myself to tne next event */
1852 rip_event (RIP_READ, sock);
1853
1854 /* RIPd manages only IPv4. */
1855 memset (&from, 0, sizeof (struct sockaddr_in));
1856 fromlen = sizeof (struct sockaddr_in);
1857
1858 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1859 (struct sockaddr *) &from, &fromlen);
1860 if (len < 0)
1861 {
ajs6099b3b2004-11-20 02:06:59 +00001862 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001863 return len;
1864 }
1865
1866 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001867 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001868 {
1869 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001870 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001871 return -1;
1872 }
1873
1874 /* Which interface is this packet comes from. */
1875 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001876
paul718e3742002-12-13 20:15:29 +00001877 /* RIP packet received */
1878 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001879 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001880 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1881 ifp ? ifp->name : "unknown");
1882
1883 /* If this packet come from unknown interface, ignore it. */
1884 if (ifp == NULL)
1885 {
ajs766a0ca2004-12-15 14:55:51 +00001886 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1887 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001888 return -1;
1889 }
1890
1891 ifc = connected_lookup_address (ifp, from.sin_addr);
1892
1893 if (ifc == NULL)
1894 {
ajs766a0ca2004-12-15 14:55:51 +00001895 zlog_info ("rip_read: cannot find connected address for packet from %s "
1896 "port %d on interface %s",
1897 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001898 return -1;
1899 }
1900
1901 /* Packet length check. */
1902 if (len < RIP_PACKET_MINSIZ)
1903 {
1904 zlog_warn ("packet size %d is smaller than minimum size %d",
1905 len, RIP_PACKET_MINSIZ);
1906 rip_peer_bad_packet (&from);
1907 return len;
1908 }
1909 if (len > RIP_PACKET_MAXSIZ)
1910 {
1911 zlog_warn ("packet size %d is larger than max size %d",
1912 len, RIP_PACKET_MAXSIZ);
1913 rip_peer_bad_packet (&from);
1914 return len;
1915 }
1916
1917 /* Packet alignment check. */
1918 if ((len - RIP_PACKET_MINSIZ) % 20)
1919 {
1920 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1921 rip_peer_bad_packet (&from);
1922 return len;
1923 }
1924
1925 /* Set RTE number. */
1926 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1927
1928 /* For easy to handle. */
1929 packet = &rip_buf.rip_packet;
1930
1931 /* RIP version check. */
1932 if (packet->version == 0)
1933 {
1934 zlog_info ("version 0 with command %d received.", packet->command);
1935 rip_peer_bad_packet (&from);
1936 return -1;
1937 }
1938
1939 /* Dump RIP packet. */
1940 if (IS_RIP_DEBUG_RECV)
1941 rip_packet_dump (packet, len, "RECV");
1942
1943 /* RIP version adjust. This code should rethink now. RFC1058 says
1944 that "Version 1 implementations are to ignore this extra data and
1945 process only the fields specified in this document.". So RIPv3
1946 packet should be treated as RIPv1 ignoring must be zero field. */
1947 if (packet->version > RIPv2)
1948 packet->version = RIPv2;
1949
1950 /* Is RIP running or is this RIP neighbor ?*/
1951 ri = ifp->info;
1952 if (! ri->running && ! rip_neighbor_lookup (&from))
1953 {
1954 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001955 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001956 rip_peer_bad_packet (&from);
1957 return -1;
1958 }
1959
1960 /* RIP Version check. */
1961 if (packet->command == RIP_RESPONSE)
1962 {
paulf38a4712003-06-07 01:10:00 +00001963 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1964 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001965 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001966 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001967 {
1968 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001969 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001970 packet->version);
1971 rip_peer_bad_packet (&from);
1972 return -1;
1973 }
1974 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001975 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001976 {
1977 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001978 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001979 packet->version);
1980 rip_peer_bad_packet (&from);
1981 return -1;
1982 }
paul718e3742002-12-13 20:15:29 +00001983 }
1984
1985 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1986 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1987 accepted; authenticated RIP-2 messages shall be discarded. */
1988
1989 if ((ri->auth_type == RIP_NO_AUTH)
1990 && rtenum
paulca5e5162004-06-06 22:06:33 +00001991 && (packet->version == RIPv2)
1992 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001993 {
1994 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001995 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001996 packet->version);
1997 rip_peer_bad_packet (&from);
1998 return -1;
1999 }
2000
2001 /* If the router is configured to authenticate RIP-2 messages, then
2002 RIP-1 messages and RIP-2 messages which pass authentication
2003 testing shall be accepted; unauthenticated and failed
2004 authentication RIP-2 messages shall be discarded. For maximum
2005 security, RIP-1 messages should be ignored when authentication is
2006 in use (see section 4.1); otherwise, the routing information from
2007 authenticated messages will be propagated by RIP-1 routers in an
2008 unauthenticated manner. */
2009
2010 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00002011 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00002012 {
2013 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00002014 if (packet->version == RIPv1
2015 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00002016 {
2017 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002018 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002019 ("packet RIPv%d is dropped because authentication enabled",
2020 packet->version);
paul718e3742002-12-13 20:15:29 +00002021 rip_peer_bad_packet (&from);
2022 return -1;
2023 }
2024
2025 /* Check RIPv2 authentication. */
2026 if (packet->version == RIPv2)
2027 {
paulca5e5162004-06-06 22:06:33 +00002028 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00002029 {
paulca5e5162004-06-06 22:06:33 +00002030 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00002031 {
2032 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2033 if (! ret)
2034 {
2035 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002036 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002037 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00002038 rip_peer_bad_packet (&from);
2039 return -1;
2040 }
2041 else
2042 {
2043 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002044 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002045 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002046 }
2047 }
paulca5e5162004-06-06 22:06:33 +00002048 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002049 {
paulca5e5162004-06-06 22:06:33 +00002050 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002051 if (! ret)
2052 {
2053 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002054 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002055 rip_peer_bad_packet (&from);
2056 return -1;
2057 }
2058 else
2059 {
2060 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002061 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002062 }
2063 /* Reset RIP packet length to trim MD5 data. */
2064 len = ret;
2065 }
2066 else
2067 {
2068 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002069 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002070 ntohs (packet->rte->tag));
2071 rip_peer_bad_packet (&from);
2072 return -1;
2073 }
2074 }
2075 else
2076 {
2077 /* There is no authentication in the packet. */
2078 if (ri->auth_str || ri->key_chain)
2079 {
2080 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002081 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002082 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002083 rip_peer_bad_packet (&from);
2084 return -1;
2085 }
2086 }
2087 }
2088 }
2089
2090 /* Process each command. */
2091 switch (packet->command)
2092 {
2093 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002094 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002095 break;
2096 case RIP_REQUEST:
2097 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002098 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002099 break;
2100 case RIP_TRACEON:
2101 case RIP_TRACEOFF:
2102 zlog_info ("Obsolete command %s received, please sent it to routed",
2103 lookup (rip_msg, packet->command));
2104 rip_peer_bad_packet (&from);
2105 break;
2106 case RIP_POLL_ENTRY:
2107 zlog_info ("Obsolete command %s received",
2108 lookup (rip_msg, packet->command));
2109 rip_peer_bad_packet (&from);
2110 break;
2111 default:
2112 zlog_info ("Unknown RIP command %d received", packet->command);
2113 rip_peer_bad_packet (&from);
2114 break;
2115 }
2116
2117 return len;
2118}
2119
paul718e3742002-12-13 20:15:29 +00002120/* Write routing table entry to the stream and return next index of
2121 the routing table entry in the stream. */
2122int
2123rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002124 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002125{
2126 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002127
2128 /* Write routing table entry. */
2129 if (version == RIPv1)
2130 {
2131 stream_putw (s, AF_INET);
2132 stream_putw (s, 0);
2133 stream_put_ipv4 (s, p->prefix.s_addr);
2134 stream_put_ipv4 (s, 0);
2135 stream_put_ipv4 (s, 0);
2136 stream_putl (s, rinfo->metric_out);
2137 }
2138 else
2139 {
2140 masklen2ip (p->prefixlen, &mask);
2141
2142 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002143 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002144 stream_put_ipv4 (s, p->prefix.s_addr);
2145 stream_put_ipv4 (s, mask.s_addr);
2146 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2147 stream_putl (s, rinfo->metric_out);
2148 }
2149
2150 return ++num;
2151}
2152
2153/* Send update to the ifp or spcified neighbor. */
2154void
paulc49ad8f2004-10-22 10:27:28 +00002155rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2156 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002157{
2158 int ret;
2159 struct stream *s;
2160 struct route_node *rp;
2161 struct rip_info *rinfo;
2162 struct rip_interface *ri;
2163 struct prefix_ipv4 *p;
2164 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002165 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002166 struct key *key = NULL;
2167 /* this might need to made dynamic if RIP ever supported auth methods
2168 with larger key string sizes */
2169 char auth_str[RIP_AUTH_SIMPLE_SIZE];
2170 size_t doff; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002171 int num = 0;
paul718e3742002-12-13 20:15:29 +00002172 int rtemax;
paul01d09082003-06-08 21:22:18 +00002173 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002174
2175 /* Logging output event. */
2176 if (IS_RIP_DEBUG_EVENT)
2177 {
2178 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002179 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002180 else
ajs5d6c3772004-12-08 19:24:06 +00002181 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002182 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002183 }
2184
2185 /* Set output stream. */
2186 s = rip->obuf;
2187
2188 /* Reset stream and RTE counter. */
2189 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002190 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2191
2192 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002193 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002194
2195 /* If output interface is in simple password authentication mode, we
2196 need space for authentication data. */
2197 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2198 rtemax -= 1;
2199
2200 /* If output interface is in MD5 authentication mode, we need space
2201 for authentication header and data. */
2202 if (ri->auth_type == RIP_AUTH_MD5)
2203 rtemax -= 2;
2204
2205 /* If output interface is in simple password authentication mode
2206 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002207 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002208 {
2209 if (ri->key_chain)
2210 {
2211 struct keychain *keychain;
2212
2213 keychain = keychain_lookup (ri->key_chain);
2214 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002215 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002216 }
paulb14ee002005-02-04 23:42:41 +00002217 /* to be passed to auth functions later */
2218 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002219 }
2220
paul727d1042002-12-13 20:50:29 +00002221 if (version == RIPv1)
2222 {
paulc49ad8f2004-10-22 10:27:28 +00002223 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002224 apply_classful_mask_ipv4 (&ifaddrclass);
2225 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002226 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002227 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002228 }
2229
paul718e3742002-12-13 20:15:29 +00002230 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2231 if ((rinfo = rp->info) != NULL)
2232 {
paul727d1042002-12-13 20:50:29 +00002233 /* For RIPv1, if we are subnetted, output subnets in our network */
2234 /* that have the same mask as the output "interface". For other */
2235 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002236
2237 if (version == RIPv1)
2238 {
paul727d1042002-12-13 20:50:29 +00002239 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002240
2241 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002242 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002243 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002244
paul727d1042002-12-13 20:50:29 +00002245 if (subnetted &&
2246 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2247 {
paulc49ad8f2004-10-22 10:27:28 +00002248 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002249 (rp->p.prefixlen != 32))
2250 continue;
2251 }
2252 else
2253 {
2254 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2255 apply_classful_mask_ipv4(&classfull);
2256 if (rp->p.u.prefix4.s_addr != 0 &&
2257 classfull.prefixlen != rp->p.prefixlen)
2258 continue;
2259 }
paul718e3742002-12-13 20:15:29 +00002260 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002261 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002262 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002263 }
2264 else
2265 p = (struct prefix_ipv4 *) &rp->p;
2266
2267 /* Apply output filters. */
2268 ret = rip_outgoing_filter (p, ri);
2269 if (ret < 0)
2270 continue;
2271
2272 /* Changed route only output. */
2273 if (route_type == rip_changed_route &&
2274 (! (rinfo->flags & RIP_RTF_CHANGED)))
2275 continue;
2276
2277 /* Split horizon. */
2278 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002279 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002280 {
paul42d14d92003-11-17 09:15:18 +00002281 /*
2282 * We perform split horizon for RIP and connected route.
2283 * For rip routes, we want to suppress the route if we would
2284 * end up sending the route back on the interface that we
2285 * learned it from, with a higher metric. For connected routes,
2286 * we suppress the route if the prefix is a subset of the
2287 * source address that we are going to use for the packet
2288 * (in order to handle the case when multiple subnets are
2289 * configured on the same interface).
2290 */
2291 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002292 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002293 continue;
2294 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002295 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002296 continue;
2297 }
2298
2299 /* Preparation for route-map. */
2300 rinfo->metric_set = 0;
2301 rinfo->nexthop_out.s_addr = 0;
2302 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002303 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002304 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002305
hasso16705132003-05-25 14:49:19 +00002306 /* In order to avoid some local loops,
2307 * if the RIP route has a nexthop via this interface, keep the nexthop,
2308 * otherwise set it to 0. The nexthop should not be propagated
2309 * beyond the local broadcast/multicast area in order
2310 * to avoid an IGP multi-level recursive look-up.
2311 * see (4.4)
2312 */
paulc49ad8f2004-10-22 10:27:28 +00002313 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002314 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002315
2316 /* Interface route-map */
2317 if (ri->routemap[RIP_FILTER_OUT])
2318 {
2319 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2320 (struct prefix *) p, RMAP_RIP,
2321 rinfo);
2322
2323 if (ret == RMAP_DENYMATCH)
2324 {
2325 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002326 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002327 inet_ntoa (p->prefix), p->prefixlen);
2328 continue;
2329 }
2330 }
paul718e3742002-12-13 20:15:29 +00002331
hasso16705132003-05-25 14:49:19 +00002332 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002333 if (rip->route_map[rinfo->type].name
2334 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2335 {
2336 ret = route_map_apply (rip->route_map[rinfo->type].map,
2337 (struct prefix *)p, RMAP_RIP, rinfo);
2338
2339 if (ret == RMAP_DENYMATCH)
2340 {
2341 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002342 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002343 inet_ntoa (p->prefix), p->prefixlen);
2344 continue;
2345 }
2346 }
2347
2348 /* When route-map does not set metric. */
2349 if (! rinfo->metric_set)
2350 {
2351 /* If redistribute metric is set. */
2352 if (rip->route_map[rinfo->type].metric_config
2353 && rinfo->metric != RIP_METRIC_INFINITY)
2354 {
2355 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2356 }
2357 else
2358 {
2359 /* If the route is not connected or localy generated
2360 one, use default-metric value*/
2361 if (rinfo->type != ZEBRA_ROUTE_RIP
2362 && rinfo->type != ZEBRA_ROUTE_CONNECT
2363 && rinfo->metric != RIP_METRIC_INFINITY)
2364 rinfo->metric_out = rip->default_metric;
2365 }
2366 }
2367
2368 /* Apply offset-list */
2369 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002370 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002371
2372 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2373 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002374
2375 /* Perform split-horizon with poisoned reverse
2376 * for RIP and connected routes.
2377 **/
2378 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002379 /*
2380 * We perform split horizon for RIP and connected route.
2381 * For rip routes, we want to suppress the route if we would
2382 * end up sending the route back on the interface that we
2383 * learned it from, with a higher metric. For connected routes,
2384 * we suppress the route if the prefix is a subset of the
2385 * source address that we are going to use for the packet
2386 * (in order to handle the case when multiple subnets are
2387 * configured on the same interface).
2388 */
2389 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002390 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002391 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002392 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002393 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002394 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002395 }
paulb14ee002005-02-04 23:42:41 +00002396
2397 /* Prepare preamble, auth headers, if needs be */
2398 if (num == 0)
2399 {
2400 stream_putc (s, RIP_RESPONSE);
2401 stream_putc (s, version);
2402 stream_putw (s, 0);
2403
paul0cb8a012005-05-29 11:27:24 +00002404 /* auth header for !v1 && !no_auth */
2405 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002406 doff = rip_auth_header_write (s, ri, key, auth_str,
2407 RIP_AUTH_SIMPLE_SIZE);
2408 }
2409
paul718e3742002-12-13 20:15:29 +00002410 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002411 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002412 if (num == rtemax)
2413 {
2414 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002415 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002416
2417 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002418 to, ifc);
paul718e3742002-12-13 20:15:29 +00002419
2420 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2421 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2422 stream_get_endp(s), "SEND");
2423 num = 0;
2424 stream_reset (s);
2425 }
2426 }
2427
2428 /* Flush unwritten RTE. */
2429 if (num != 0)
2430 {
2431 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002432 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002433
paulc49ad8f2004-10-22 10:27:28 +00002434 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002435
2436 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2437 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2438 stream_get_endp (s), "SEND");
2439 num = 0;
2440 stream_reset (s);
2441 }
2442
2443 /* Statistics updates. */
2444 ri->sent_updates++;
2445}
2446
2447/* Send RIP packet to the interface. */
2448void
paulc49ad8f2004-10-22 10:27:28 +00002449rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002450{
paul718e3742002-12-13 20:15:29 +00002451 struct sockaddr_in to;
2452
2453 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002454 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002455 {
2456 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002457 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002458
paulc49ad8f2004-10-22 10:27:28 +00002459 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002460 return;
2461 }
paulc49ad8f2004-10-22 10:27:28 +00002462
paul718e3742002-12-13 20:15:29 +00002463 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002464 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002465 {
paulc49ad8f2004-10-22 10:27:28 +00002466 if (ifc->address->family == AF_INET)
2467 {
2468 /* Destination address and port setting. */
2469 memset (&to, 0, sizeof (struct sockaddr_in));
2470 if (ifc->destination)
2471 /* use specified broadcast or point-to-point destination addr */
2472 to.sin_addr = ifc->destination->u.prefix4;
2473 else
2474 /* calculate the appropriate broadcast address */
2475 to.sin_addr.s_addr =
2476 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2477 ifc->address->prefixlen);
2478 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002479
paulc49ad8f2004-10-22 10:27:28 +00002480 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002481 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002482 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2483 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002484
paulc49ad8f2004-10-22 10:27:28 +00002485 rip_output_process (ifc, &to, route_type, version);
2486 }
paul718e3742002-12-13 20:15:29 +00002487 }
2488}
2489
2490/* Update send to all interface and neighbor. */
2491void
2492rip_update_process (int route_type)
2493{
paul1eb8ef22005-04-07 07:30:20 +00002494 struct listnode *node;
2495 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002496 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002497 struct interface *ifp;
2498 struct rip_interface *ri;
2499 struct route_node *rp;
2500 struct sockaddr_in to;
2501 struct prefix_ipv4 *p;
2502
2503 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002504 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002505 {
paul718e3742002-12-13 20:15:29 +00002506 if (if_is_loopback (ifp))
2507 continue;
2508
paul2e3b2e42002-12-13 21:03:13 +00002509 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002510 continue;
2511
2512 /* Fetch RIP interface information. */
2513 ri = ifp->info;
2514
2515 /* When passive interface is specified, suppress announce to the
2516 interface. */
2517 if (ri->passive)
2518 continue;
2519
2520 if (ri->running)
2521 {
2522 if (IS_RIP_DEBUG_EVENT)
2523 {
2524 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002525 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002526 ifp->name, ifp->ifindex);
2527 else
ajs5d6c3772004-12-08 19:24:06 +00002528 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002529 ifp->ifindex);
2530 }
2531
paulcc1131a2003-10-15 23:20:17 +00002532 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002533 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002534 {
2535 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002536 int done = 0;
2537 /*
2538 * If there is no version configuration in the interface,
2539 * use rip's version setting.
2540 */
paulf38a4712003-06-07 01:10:00 +00002541 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2542 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002543
2544 ifaddr = (struct prefix_ipv4 *) connected->address;
2545
2546 if (ifaddr->family != AF_INET)
2547 continue;
2548
paul931cd542004-01-23 15:31:42 +00002549 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002550 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002551 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002552 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002553 done = 1;
2554 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2555 break;
2556
paulf38a4712003-06-07 01:10:00 +00002557 }
paul718e3742002-12-13 20:15:29 +00002558 }
2559 }
2560
2561 /* RIP send updates to each neighbor. */
2562 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2563 if (rp->info != NULL)
2564 {
2565 p = (struct prefix_ipv4 *) &rp->p;
2566
2567 ifp = if_lookup_address (p->prefix);
2568 if (! ifp)
2569 {
paulc49ad8f2004-10-22 10:27:28 +00002570 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002571 inet_ntoa (p->prefix));
2572 continue;
2573 }
paulc49ad8f2004-10-22 10:27:28 +00002574
2575 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2576 {
2577 zlog_warn ("Neighbor %s doesnt have connected network",
2578 inet_ntoa (p->prefix));
2579 continue;
2580 }
2581
paul718e3742002-12-13 20:15:29 +00002582 /* Set destination address and port */
2583 memset (&to, 0, sizeof (struct sockaddr_in));
2584 to.sin_addr = p->prefix;
2585 to.sin_port = htons (RIP_PORT_DEFAULT);
2586
2587 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002588 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002589 }
2590}
2591
2592/* RIP's periodical timer. */
2593int
2594rip_update (struct thread *t)
2595{
2596 /* Clear timer pointer. */
2597 rip->t_update = NULL;
2598
2599 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002600 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002601
2602 /* Process update output. */
2603 rip_update_process (rip_all_route);
2604
2605 /* Triggered updates may be suppressed if a regular update is due by
2606 the time the triggered update would be sent. */
2607 if (rip->t_triggered_interval)
2608 {
2609 thread_cancel (rip->t_triggered_interval);
2610 rip->t_triggered_interval = NULL;
2611 }
2612 rip->trigger = 0;
2613
2614 /* Register myself. */
2615 rip_event (RIP_UPDATE_EVENT, 0);
2616
2617 return 0;
2618}
2619
2620/* Walk down the RIP routing table then clear changed flag. */
2621void
2622rip_clear_changed_flag ()
2623{
2624 struct route_node *rp;
2625 struct rip_info *rinfo;
2626
2627 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2628 if ((rinfo = rp->info) != NULL)
2629 if (rinfo->flags & RIP_RTF_CHANGED)
2630 rinfo->flags &= ~RIP_RTF_CHANGED;
2631}
2632
2633/* Triggered update interval timer. */
2634int
2635rip_triggered_interval (struct thread *t)
2636{
2637 int rip_triggered_update (struct thread *);
2638
2639 rip->t_triggered_interval = NULL;
2640
2641 if (rip->trigger)
2642 {
2643 rip->trigger = 0;
2644 rip_triggered_update (t);
2645 }
2646 return 0;
2647}
2648
2649/* Execute triggered update. */
2650int
2651rip_triggered_update (struct thread *t)
2652{
2653 int interval;
2654
2655 /* Clear thred pointer. */
2656 rip->t_triggered_update = NULL;
2657
2658 /* Cancel interval timer. */
2659 if (rip->t_triggered_interval)
2660 {
2661 thread_cancel (rip->t_triggered_interval);
2662 rip->t_triggered_interval = NULL;
2663 }
2664 rip->trigger = 0;
2665
2666 /* Logging triggered update. */
2667 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002668 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002669
2670 /* Split Horizon processing is done when generating triggered
2671 updates as well as normal updates (see section 2.6). */
2672 rip_update_process (rip_changed_route);
2673
2674 /* Once all of the triggered updates have been generated, the route
2675 change flags should be cleared. */
2676 rip_clear_changed_flag ();
2677
2678 /* After a triggered update is sent, a timer should be set for a
2679 random interval between 1 and 5 seconds. If other changes that
2680 would trigger updates occur before the timer expires, a single
2681 update is triggered when the timer expires. */
2682 interval = (random () % 5) + 1;
2683
2684 rip->t_triggered_interval =
2685 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2686
2687 return 0;
2688}
2689
2690/* Withdraw redistributed route. */
2691void
2692rip_redistribute_withdraw (int type)
2693{
2694 struct route_node *rp;
2695 struct rip_info *rinfo;
2696
2697 if (!rip)
2698 return;
2699
2700 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2701 if ((rinfo = rp->info) != NULL)
2702 {
2703 if (rinfo->type == type
2704 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2705 {
2706 /* Perform poisoned reverse. */
2707 rinfo->metric = RIP_METRIC_INFINITY;
2708 RIP_TIMER_ON (rinfo->t_garbage_collect,
2709 rip_garbage_collect, rip->garbage_time);
2710 RIP_TIMER_OFF (rinfo->t_timeout);
2711 rinfo->flags |= RIP_RTF_CHANGED;
2712
hasso16705132003-05-25 14:49:19 +00002713 if (IS_RIP_DEBUG_EVENT) {
2714 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2715
ajs5d6c3772004-12-08 19:24:06 +00002716 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002717 inet_ntoa(p->prefix), p->prefixlen,
2718 ifindex2ifname(rinfo->ifindex));
2719 }
2720
paul718e3742002-12-13 20:15:29 +00002721 rip_event (RIP_TRIGGERED_UPDATE, 0);
2722 }
2723 }
2724}
2725
2726/* Create new RIP instance and set it to global variable. */
2727int
2728rip_create ()
2729{
2730 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2731 memset (rip, 0, sizeof (struct rip));
2732
2733 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002734 rip->version_send = RI_RIP_VERSION_2;
2735 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002736 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2737 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2738 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2739 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2740
2741 /* Initialize RIP routig table. */
2742 rip->table = route_table_init ();
2743 rip->route = route_table_init ();
2744 rip->neighbor = route_table_init ();
2745
2746 /* Make output stream. */
2747 rip->obuf = stream_new (1500);
2748
2749 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002750 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002751 if (rip->sock < 0)
2752 return rip->sock;
2753
2754 /* Create read and timer thread. */
2755 rip_event (RIP_READ, rip->sock);
2756 rip_event (RIP_UPDATE_EVENT, 1);
2757
2758 return 0;
2759}
2760
2761/* Sned RIP request to the destination. */
2762int
2763rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002764 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002765{
2766 struct rte *rte;
2767 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002768 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002769
2770 memset (&rip_packet, 0, sizeof (rip_packet));
2771
2772 rip_packet.command = RIP_REQUEST;
2773 rip_packet.version = version;
2774 rte = rip_packet.rte;
2775 rte->metric = htonl (RIP_METRIC_INFINITY);
2776
paul931cd542004-01-23 15:31:42 +00002777 if (connected)
2778 {
2779 /*
2780 * connected is only sent for ripv1 case, or when
2781 * interface does not support multicast. Caller loops
2782 * over each connected address for this case.
2783 */
paul11dde9c2004-05-31 14:00:00 +00002784 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002785 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002786 return -1;
2787 else
2788 return sizeof (rip_packet);
2789 }
2790
paulcc1131a2003-10-15 23:20:17 +00002791 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002792 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002793 {
2794 struct prefix_ipv4 *p;
2795
2796 p = (struct prefix_ipv4 *) connected->address;
2797
2798 if (p->family != AF_INET)
2799 continue;
2800
paul11dde9c2004-05-31 14:00:00 +00002801 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002802 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002803 return -1;
2804 }
2805 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002806}
2807
2808int
2809rip_update_jitter (unsigned long time)
2810{
paul239389b2004-05-05 14:09:37 +00002811#define JITTER_BOUND 4
2812 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2813 Given that, we cannot let time be less than JITTER_BOUND seconds.
2814 The RIPv2 RFC says jitter should be small compared to
2815 update_time. We consider 1/JITTER_BOUND to be small.
2816 */
2817
2818 int jitter_input = time;
2819 int jitter;
2820
2821 if (jitter_input < JITTER_BOUND)
2822 jitter_input = JITTER_BOUND;
2823
2824 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2825
2826 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002827}
2828
2829void
2830rip_event (enum rip_event event, int sock)
2831{
2832 int jitter = 0;
2833
2834 switch (event)
2835 {
2836 case RIP_READ:
2837 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2838 break;
2839 case RIP_UPDATE_EVENT:
2840 if (rip->t_update)
2841 {
2842 thread_cancel (rip->t_update);
2843 rip->t_update = NULL;
2844 }
2845 jitter = rip_update_jitter (rip->update_time);
2846 rip->t_update =
2847 thread_add_timer (master, rip_update, NULL,
2848 sock ? 2 : rip->update_time + jitter);
2849 break;
2850 case RIP_TRIGGERED_UPDATE:
2851 if (rip->t_triggered_interval)
2852 rip->trigger = 1;
2853 else if (! rip->t_triggered_update)
2854 rip->t_triggered_update =
2855 thread_add_event (master, rip_triggered_update, NULL, 0);
2856 break;
2857 default:
2858 break;
2859 }
2860}
2861
2862DEFUN (router_rip,
2863 router_rip_cmd,
2864 "router rip",
2865 "Enable a routing process\n"
2866 "Routing Information Protocol (RIP)\n")
2867{
2868 int ret;
2869
2870 /* If rip is not enabled before. */
2871 if (! rip)
2872 {
2873 ret = rip_create ();
2874 if (ret < 0)
2875 {
2876 zlog_info ("Can't create RIP");
2877 return CMD_WARNING;
2878 }
2879 }
2880 vty->node = RIP_NODE;
2881 vty->index = rip;
2882
2883 return CMD_SUCCESS;
2884}
2885
2886DEFUN (no_router_rip,
2887 no_router_rip_cmd,
2888 "no router rip",
2889 NO_STR
2890 "Enable a routing process\n"
2891 "Routing Information Protocol (RIP)\n")
2892{
2893 if (rip)
2894 rip_clean ();
2895 return CMD_SUCCESS;
2896}
2897
2898DEFUN (rip_version,
2899 rip_version_cmd,
2900 "version <1-2>",
2901 "Set routing protocol version\n"
2902 "version\n")
2903{
2904 int version;
2905
2906 version = atoi (argv[0]);
2907 if (version != RIPv1 && version != RIPv2)
2908 {
2909 vty_out (vty, "invalid rip version %d%s", version,
2910 VTY_NEWLINE);
2911 return CMD_WARNING;
2912 }
paulf38a4712003-06-07 01:10:00 +00002913 rip->version_send = version;
2914 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002915
2916 return CMD_SUCCESS;
2917}
2918
2919DEFUN (no_rip_version,
2920 no_rip_version_cmd,
2921 "no version",
2922 NO_STR
2923 "Set routing protocol version\n")
2924{
2925 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002926 rip->version_send = RI_RIP_VERSION_2;
2927 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002928
2929 return CMD_SUCCESS;
2930}
2931
2932ALIAS (no_rip_version,
2933 no_rip_version_val_cmd,
2934 "no version <1-2>",
2935 NO_STR
2936 "Set routing protocol version\n"
2937 "version\n")
2938
2939DEFUN (rip_route,
2940 rip_route_cmd,
2941 "route A.B.C.D/M",
2942 "RIP static route configuration\n"
2943 "IP prefix <network>/<length>\n")
2944{
2945 int ret;
2946 struct prefix_ipv4 p;
2947 struct route_node *node;
2948
2949 ret = str2prefix_ipv4 (argv[0], &p);
2950 if (ret < 0)
2951 {
2952 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2953 return CMD_WARNING;
2954 }
2955 apply_mask_ipv4 (&p);
2956
2957 /* For router rip configuration. */
2958 node = route_node_get (rip->route, (struct prefix *) &p);
2959
2960 if (node->info)
2961 {
2962 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2963 route_unlock_node (node);
2964 return CMD_WARNING;
2965 }
2966
hasso8a676be2004-10-08 06:36:38 +00002967 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002968
vincentfbf5d032005-09-29 11:25:50 +00002969 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
paul718e3742002-12-13 20:15:29 +00002970
2971 return CMD_SUCCESS;
2972}
2973
2974DEFUN (no_rip_route,
2975 no_rip_route_cmd,
2976 "no route A.B.C.D/M",
2977 NO_STR
2978 "RIP static route configuration\n"
2979 "IP prefix <network>/<length>\n")
2980{
2981 int ret;
2982 struct prefix_ipv4 p;
2983 struct route_node *node;
2984
2985 ret = str2prefix_ipv4 (argv[0], &p);
2986 if (ret < 0)
2987 {
2988 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2989 return CMD_WARNING;
2990 }
2991 apply_mask_ipv4 (&p);
2992
2993 /* For router rip configuration. */
2994 node = route_node_lookup (rip->route, (struct prefix *) &p);
2995 if (! node)
2996 {
2997 vty_out (vty, "Can't find route %s.%s", argv[0],
2998 VTY_NEWLINE);
2999 return CMD_WARNING;
3000 }
3001
3002 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
3003 route_unlock_node (node);
3004
3005 node->info = NULL;
3006 route_unlock_node (node);
3007
3008 return CMD_SUCCESS;
3009}
3010
3011void
3012rip_update_default_metric ()
3013{
3014 struct route_node *np;
3015 struct rip_info *rinfo;
3016
3017 for (np = route_top (rip->table); np; np = route_next (np))
3018 if ((rinfo = np->info) != NULL)
3019 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3020 rinfo->metric = rip->default_metric;
3021}
3022
3023DEFUN (rip_default_metric,
3024 rip_default_metric_cmd,
3025 "default-metric <1-16>",
3026 "Set a metric of redistribute routes\n"
3027 "Default metric\n")
3028{
3029 if (rip)
3030 {
3031 rip->default_metric = atoi (argv[0]);
3032 /* rip_update_default_metric (); */
3033 }
3034 return CMD_SUCCESS;
3035}
3036
3037DEFUN (no_rip_default_metric,
3038 no_rip_default_metric_cmd,
3039 "no default-metric",
3040 NO_STR
3041 "Set a metric of redistribute routes\n"
3042 "Default metric\n")
3043{
3044 if (rip)
3045 {
3046 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3047 /* rip_update_default_metric (); */
3048 }
3049 return CMD_SUCCESS;
3050}
3051
3052ALIAS (no_rip_default_metric,
3053 no_rip_default_metric_val_cmd,
3054 "no default-metric <1-16>",
3055 NO_STR
3056 "Set a metric of redistribute routes\n"
3057 "Default metric\n")
3058
3059DEFUN (rip_timers,
3060 rip_timers_cmd,
3061 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3062 "Adjust routing timers\n"
3063 "Basic routing protocol update timers\n"
3064 "Routing table update timer value in second. Default is 30.\n"
3065 "Routing information timeout timer. Default is 180.\n"
3066 "Garbage collection timer. Default is 120.\n")
3067{
3068 unsigned long update;
3069 unsigned long timeout;
3070 unsigned long garbage;
3071 char *endptr = NULL;
3072 unsigned long RIP_TIMER_MAX = 2147483647;
3073 unsigned long RIP_TIMER_MIN = 5;
3074
3075 update = strtoul (argv[0], &endptr, 10);
3076 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3077 {
3078 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3079 return CMD_WARNING;
3080 }
3081
3082 timeout = strtoul (argv[1], &endptr, 10);
3083 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3084 {
3085 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3086 return CMD_WARNING;
3087 }
3088
3089 garbage = strtoul (argv[2], &endptr, 10);
3090 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3091 {
3092 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3093 return CMD_WARNING;
3094 }
3095
3096 /* Set each timer value. */
3097 rip->update_time = update;
3098 rip->timeout_time = timeout;
3099 rip->garbage_time = garbage;
3100
3101 /* Reset update timer thread. */
3102 rip_event (RIP_UPDATE_EVENT, 0);
3103
3104 return CMD_SUCCESS;
3105}
3106
3107DEFUN (no_rip_timers,
3108 no_rip_timers_cmd,
3109 "no timers basic",
3110 NO_STR
3111 "Adjust routing timers\n"
3112 "Basic routing protocol update timers\n")
3113{
3114 /* Set each timer value to the default. */
3115 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3116 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3117 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3118
3119 /* Reset update timer thread. */
3120 rip_event (RIP_UPDATE_EVENT, 0);
3121
3122 return CMD_SUCCESS;
3123}
hasso16705132003-05-25 14:49:19 +00003124
3125ALIAS (no_rip_timers,
3126 no_rip_timers_val_cmd,
3127 "no timers basic <0-65535> <0-65535> <0-65535>",
3128 NO_STR
3129 "Adjust routing timers\n"
3130 "Basic routing protocol update timers\n"
3131 "Routing table update timer value in second. Default is 30.\n"
3132 "Routing information timeout timer. Default is 180.\n"
3133 "Garbage collection timer. Default is 120.\n")
3134
paul718e3742002-12-13 20:15:29 +00003135
3136struct route_table *rip_distance_table;
3137
3138struct rip_distance
3139{
3140 /* Distance value for the IP source prefix. */
3141 u_char distance;
3142
3143 /* Name of the access-list to be matched. */
3144 char *access_list;
3145};
3146
3147struct rip_distance *
3148rip_distance_new ()
3149{
3150 struct rip_distance *new;
3151 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3152 memset (new, 0, sizeof (struct rip_distance));
3153 return new;
3154}
3155
3156void
3157rip_distance_free (struct rip_distance *rdistance)
3158{
3159 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3160}
3161
3162int
hasso98b718a2004-10-11 12:57:57 +00003163rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3164 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003165{
3166 int ret;
3167 struct prefix_ipv4 p;
3168 u_char distance;
3169 struct route_node *rn;
3170 struct rip_distance *rdistance;
3171
3172 ret = str2prefix_ipv4 (ip_str, &p);
3173 if (ret == 0)
3174 {
3175 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3176 return CMD_WARNING;
3177 }
3178
3179 distance = atoi (distance_str);
3180
3181 /* Get RIP distance node. */
3182 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3183 if (rn->info)
3184 {
3185 rdistance = rn->info;
3186 route_unlock_node (rn);
3187 }
3188 else
3189 {
3190 rdistance = rip_distance_new ();
3191 rn->info = rdistance;
3192 }
3193
3194 /* Set distance value. */
3195 rdistance->distance = distance;
3196
3197 /* Reset access-list configuration. */
3198 if (rdistance->access_list)
3199 {
3200 free (rdistance->access_list);
3201 rdistance->access_list = NULL;
3202 }
3203 if (access_list_str)
3204 rdistance->access_list = strdup (access_list_str);
3205
3206 return CMD_SUCCESS;
3207}
3208
3209int
hasso98b718a2004-10-11 12:57:57 +00003210rip_distance_unset (struct vty *vty, const char *distance_str,
3211 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003212{
3213 int ret;
3214 struct prefix_ipv4 p;
3215 u_char distance;
3216 struct route_node *rn;
3217 struct rip_distance *rdistance;
3218
3219 ret = str2prefix_ipv4 (ip_str, &p);
3220 if (ret == 0)
3221 {
3222 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3223 return CMD_WARNING;
3224 }
3225
3226 distance = atoi (distance_str);
3227
3228 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3229 if (! rn)
3230 {
3231 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3232 return CMD_WARNING;
3233 }
3234
3235 rdistance = rn->info;
3236
3237 if (rdistance->access_list)
3238 free (rdistance->access_list);
3239 rip_distance_free (rdistance);
3240
3241 rn->info = NULL;
3242 route_unlock_node (rn);
3243 route_unlock_node (rn);
3244
3245 return CMD_SUCCESS;
3246}
3247
3248void
3249rip_distance_reset ()
3250{
3251 struct route_node *rn;
3252 struct rip_distance *rdistance;
3253
3254 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3255 if ((rdistance = rn->info) != NULL)
3256 {
3257 if (rdistance->access_list)
3258 free (rdistance->access_list);
3259 rip_distance_free (rdistance);
3260 rn->info = NULL;
3261 route_unlock_node (rn);
3262 }
3263}
3264
3265/* Apply RIP information to distance method. */
3266u_char
3267rip_distance_apply (struct rip_info *rinfo)
3268{
3269 struct route_node *rn;
3270 struct prefix_ipv4 p;
3271 struct rip_distance *rdistance;
3272 struct access_list *alist;
3273
3274 if (! rip)
3275 return 0;
3276
3277 memset (&p, 0, sizeof (struct prefix_ipv4));
3278 p.family = AF_INET;
3279 p.prefix = rinfo->from;
3280 p.prefixlen = IPV4_MAX_BITLEN;
3281
3282 /* Check source address. */
3283 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3284 if (rn)
3285 {
3286 rdistance = rn->info;
3287 route_unlock_node (rn);
3288
3289 if (rdistance->access_list)
3290 {
3291 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3292 if (alist == NULL)
3293 return 0;
3294 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3295 return 0;
3296
3297 return rdistance->distance;
3298 }
3299 else
3300 return rdistance->distance;
3301 }
3302
3303 if (rip->distance)
3304 return rip->distance;
3305
3306 return 0;
3307}
3308
3309void
3310rip_distance_show (struct vty *vty)
3311{
3312 struct route_node *rn;
3313 struct rip_distance *rdistance;
3314 int header = 1;
3315 char buf[BUFSIZ];
3316
3317 vty_out (vty, " Distance: (default is %d)%s",
3318 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3319 VTY_NEWLINE);
3320
3321 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3322 if ((rdistance = rn->info) != NULL)
3323 {
3324 if (header)
3325 {
3326 vty_out (vty, " Address Distance List%s",
3327 VTY_NEWLINE);
3328 header = 0;
3329 }
3330 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3331 vty_out (vty, " %-20s %4d %s%s",
3332 buf, rdistance->distance,
3333 rdistance->access_list ? rdistance->access_list : "",
3334 VTY_NEWLINE);
3335 }
3336}
3337
3338DEFUN (rip_distance,
3339 rip_distance_cmd,
3340 "distance <1-255>",
3341 "Administrative distance\n"
3342 "Distance value\n")
3343{
3344 rip->distance = atoi (argv[0]);
3345 return CMD_SUCCESS;
3346}
3347
3348DEFUN (no_rip_distance,
3349 no_rip_distance_cmd,
3350 "no distance <1-255>",
3351 NO_STR
3352 "Administrative distance\n"
3353 "Distance value\n")
3354{
3355 rip->distance = 0;
3356 return CMD_SUCCESS;
3357}
3358
3359DEFUN (rip_distance_source,
3360 rip_distance_source_cmd,
3361 "distance <1-255> A.B.C.D/M",
3362 "Administrative distance\n"
3363 "Distance value\n"
3364 "IP source prefix\n")
3365{
3366 rip_distance_set (vty, argv[0], argv[1], NULL);
3367 return CMD_SUCCESS;
3368}
3369
3370DEFUN (no_rip_distance_source,
3371 no_rip_distance_source_cmd,
3372 "no distance <1-255> A.B.C.D/M",
3373 NO_STR
3374 "Administrative distance\n"
3375 "Distance value\n"
3376 "IP source prefix\n")
3377{
3378 rip_distance_unset (vty, argv[0], argv[1], NULL);
3379 return CMD_SUCCESS;
3380}
3381
3382DEFUN (rip_distance_source_access_list,
3383 rip_distance_source_access_list_cmd,
3384 "distance <1-255> A.B.C.D/M WORD",
3385 "Administrative distance\n"
3386 "Distance value\n"
3387 "IP source prefix\n"
3388 "Access list name\n")
3389{
3390 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3391 return CMD_SUCCESS;
3392}
3393
3394DEFUN (no_rip_distance_source_access_list,
3395 no_rip_distance_source_access_list_cmd,
3396 "no distance <1-255> A.B.C.D/M WORD",
3397 NO_STR
3398 "Administrative distance\n"
3399 "Distance value\n"
3400 "IP source prefix\n"
3401 "Access list name\n")
3402{
3403 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3404 return CMD_SUCCESS;
3405}
3406
3407/* Print out routes update time. */
3408void
3409rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3410{
3411 struct timeval timer_now;
3412 time_t clock;
3413 struct tm *tm;
3414#define TIME_BUF 25
3415 char timebuf [TIME_BUF];
3416 struct thread *thread;
3417
3418 gettimeofday (&timer_now, NULL);
3419
3420 if ((thread = rinfo->t_timeout) != NULL)
3421 {
3422 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3423 tm = gmtime (&clock);
3424 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3425 vty_out (vty, "%5s", timebuf);
3426 }
3427 else if ((thread = rinfo->t_garbage_collect) != NULL)
3428 {
3429 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3430 tm = gmtime (&clock);
3431 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3432 vty_out (vty, "%5s", timebuf);
3433 }
3434}
3435
hasso8a676be2004-10-08 06:36:38 +00003436const char *
paul718e3742002-12-13 20:15:29 +00003437rip_route_type_print (int sub_type)
3438{
3439 switch (sub_type)
3440 {
3441 case RIP_ROUTE_RTE:
3442 return "n";
3443 case RIP_ROUTE_STATIC:
3444 return "s";
3445 case RIP_ROUTE_DEFAULT:
3446 return "d";
3447 case RIP_ROUTE_REDISTRIBUTE:
3448 return "r";
3449 case RIP_ROUTE_INTERFACE:
3450 return "i";
3451 default:
3452 return "?";
3453 }
3454}
3455
3456DEFUN (show_ip_rip,
3457 show_ip_rip_cmd,
3458 "show ip rip",
3459 SHOW_STR
3460 IP_STR
3461 "Show RIP routes\n")
3462{
3463 struct route_node *np;
3464 struct rip_info *rinfo;
3465
3466 if (! rip)
3467 return CMD_SUCCESS;
3468
hasso16705132003-05-25 14:49:19 +00003469 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3470 "Sub-codes:%s"
3471 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003472 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003473 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003474 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003475
3476 for (np = route_top (rip->table); np; np = route_next (np))
3477 if ((rinfo = np->info) != NULL)
3478 {
3479 int len;
3480
3481 len = vty_out (vty, "%s(%s) %s/%d",
3482 /* np->lock, For debugging. */
3483 route_info[rinfo->type].str,
3484 rip_route_type_print (rinfo->sub_type),
3485 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3486
hassoa1455d82004-03-03 19:36:24 +00003487 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003488
3489 if (len > 0)
3490 vty_out (vty, "%*s", len, " ");
3491
3492 if (rinfo->nexthop.s_addr)
3493 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3494 rinfo->metric);
3495 else
3496 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3497
3498 /* Route which exist in kernel routing table. */
3499 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3500 (rinfo->sub_type == RIP_ROUTE_RTE))
3501 {
3502 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003503 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003504 rip_vty_out_uptime (vty, rinfo);
3505 }
3506 else if (rinfo->metric == RIP_METRIC_INFINITY)
3507 {
3508 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003509 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003510 rip_vty_out_uptime (vty, rinfo);
3511 }
3512 else
hasso16705132003-05-25 14:49:19 +00003513 {
vincentfbf5d032005-09-29 11:25:50 +00003514 if (rinfo->external_metric)
3515 {
3516 len = vty_out (vty, "self (%s:%d)",
3517 route_info[rinfo->type].str_long,
3518 rinfo->external_metric);
3519 len = 16 - len;
3520 if (len > 0)
3521 vty_out (vty, "%*s", len, " ");
3522 }
3523 else
3524 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003525 vty_out (vty, "%3d", rinfo->tag);
3526 }
paul718e3742002-12-13 20:15:29 +00003527
3528 vty_out (vty, "%s", VTY_NEWLINE);
3529 }
3530 return CMD_SUCCESS;
3531}
3532
3533/* Return next event time. */
3534int
3535rip_next_thread_timer (struct thread *thread)
3536{
3537 struct timeval timer_now;
3538
3539 gettimeofday (&timer_now, NULL);
3540
3541 return thread->u.sands.tv_sec - timer_now.tv_sec;
3542}
3543
hasso16705132003-05-25 14:49:19 +00003544/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3545DEFUN (show_ip_rip_status,
3546 show_ip_rip_status_cmd,
3547 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003548 SHOW_STR
3549 IP_STR
hasso16705132003-05-25 14:49:19 +00003550 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003551 "IP routing protocol process parameters and statistics\n")
3552{
hasso52dc7ee2004-09-23 19:18:23 +00003553 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003554 struct interface *ifp;
3555 struct rip_interface *ri;
3556 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003557 const char *send_version;
3558 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003559
3560 if (! rip)
3561 return CMD_SUCCESS;
3562
3563 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3564 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3565 rip->update_time);
3566 vty_out (vty, " next due in %d seconds%s",
3567 rip_next_thread_timer (rip->t_update),
3568 VTY_NEWLINE);
3569 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3570 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3571 VTY_NEWLINE);
3572
3573 /* Filtering status show. */
3574 config_show_distribute (vty);
3575
3576 /* Default metric information. */
3577 vty_out (vty, " Default redistribution metric is %d%s",
3578 rip->default_metric, VTY_NEWLINE);
3579
3580 /* Redistribute information. */
3581 vty_out (vty, " Redistributing:");
3582 config_write_rip_redistribute (vty, 0);
3583 vty_out (vty, "%s", VTY_NEWLINE);
3584
paulf38a4712003-06-07 01:10:00 +00003585 vty_out (vty, " Default version control: send version %s,",
3586 lookup(ri_version_msg,rip->version_send));
3587 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3588 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3589 else
3590 vty_out (vty, " receive version %s %s",
3591 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003592
3593 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3594
paul1eb8ef22005-04-07 07:30:20 +00003595 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003596 {
paul718e3742002-12-13 20:15:29 +00003597 ri = ifp->info;
3598
3599 if (ri->enable_network || ri->enable_interface)
3600 {
3601 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003602 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003603 else
3604 send_version = lookup (ri_version_msg, ri->ri_send);
3605
3606 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003607 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003608 else
3609 receive_version = lookup (ri_version_msg, ri->ri_receive);
3610
3611 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3612 send_version,
3613 receive_version,
3614 ri->key_chain ? ri->key_chain : "",
3615 VTY_NEWLINE);
3616 }
3617 }
3618
3619 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3620 config_write_rip_network (vty, 0);
3621
paul4aaff3f2003-06-07 01:04:45 +00003622 {
3623 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003624 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003625 {
paul4aaff3f2003-06-07 01:04:45 +00003626 ri = ifp->info;
3627
3628 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3629 {
3630 if (!found_passive)
3631 {
3632 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3633 found_passive = 1;
3634 }
3635 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3636 }
3637 }
3638 }
3639
paul718e3742002-12-13 20:15:29 +00003640 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3641 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3642 rip_peer_display (vty);
3643
3644 rip_distance_show (vty);
3645
3646 return CMD_SUCCESS;
3647}
3648
3649/* RIP configuration write function. */
3650int
3651config_write_rip (struct vty *vty)
3652{
3653 int write = 0;
3654 struct route_node *rn;
3655 struct rip_distance *rdistance;
3656
3657 if (rip)
3658 {
3659 /* Router RIP statement. */
3660 vty_out (vty, "router rip%s", VTY_NEWLINE);
3661 write++;
3662
3663 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003664 if (rip->version_send != RI_RIP_VERSION_2
3665 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3666 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003667 VTY_NEWLINE);
3668
3669 /* RIP timer configuration. */
3670 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3671 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3672 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3673 vty_out (vty, " timers basic %lu %lu %lu%s",
3674 rip->update_time,
3675 rip->timeout_time,
3676 rip->garbage_time,
3677 VTY_NEWLINE);
3678
3679 /* Default information configuration. */
3680 if (rip->default_information)
3681 {
3682 if (rip->default_information_route_map)
3683 vty_out (vty, " default-information originate route-map %s%s",
3684 rip->default_information_route_map, VTY_NEWLINE);
3685 else
3686 vty_out (vty, " default-information originate%s",
3687 VTY_NEWLINE);
3688 }
3689
3690 /* Redistribute configuration. */
3691 config_write_rip_redistribute (vty, 1);
3692
3693 /* RIP offset-list configuration. */
3694 config_write_rip_offset_list (vty);
3695
3696 /* RIP enabled network and interface configuration. */
3697 config_write_rip_network (vty, 1);
3698
3699 /* RIP default metric configuration */
3700 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3701 vty_out (vty, " default-metric %d%s",
3702 rip->default_metric, VTY_NEWLINE);
3703
3704 /* Distribute configuration. */
3705 write += config_write_distribute (vty);
3706
hasso16705132003-05-25 14:49:19 +00003707 /* Interface routemap configuration */
3708 write += config_write_if_rmap (vty);
3709
paul718e3742002-12-13 20:15:29 +00003710 /* Distance configuration. */
3711 if (rip->distance)
3712 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3713
3714 /* RIP source IP prefix distance configuration. */
3715 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3716 if ((rdistance = rn->info) != NULL)
3717 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3718 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3719 rdistance->access_list ? rdistance->access_list : "",
3720 VTY_NEWLINE);
3721
3722 /* RIP static route configuration. */
3723 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3724 if (rn->info)
3725 vty_out (vty, " route %s/%d%s",
3726 inet_ntoa (rn->p.u.prefix4),
3727 rn->p.prefixlen,
3728 VTY_NEWLINE);
3729
3730 }
3731 return write;
3732}
3733
3734/* RIP node structure. */
3735struct cmd_node rip_node =
3736{
3737 RIP_NODE,
3738 "%s(config-router)# ",
3739 1
3740};
3741
3742/* Distribute-list update functions. */
3743void
3744rip_distribute_update (struct distribute *dist)
3745{
3746 struct interface *ifp;
3747 struct rip_interface *ri;
3748 struct access_list *alist;
3749 struct prefix_list *plist;
3750
3751 if (! dist->ifname)
3752 return;
3753
3754 ifp = if_lookup_by_name (dist->ifname);
3755 if (ifp == NULL)
3756 return;
3757
3758 ri = ifp->info;
3759
3760 if (dist->list[DISTRIBUTE_IN])
3761 {
3762 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3763 if (alist)
3764 ri->list[RIP_FILTER_IN] = alist;
3765 else
3766 ri->list[RIP_FILTER_IN] = NULL;
3767 }
3768 else
3769 ri->list[RIP_FILTER_IN] = NULL;
3770
3771 if (dist->list[DISTRIBUTE_OUT])
3772 {
3773 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3774 if (alist)
3775 ri->list[RIP_FILTER_OUT] = alist;
3776 else
3777 ri->list[RIP_FILTER_OUT] = NULL;
3778 }
3779 else
3780 ri->list[RIP_FILTER_OUT] = NULL;
3781
3782 if (dist->prefix[DISTRIBUTE_IN])
3783 {
3784 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3785 if (plist)
3786 ri->prefix[RIP_FILTER_IN] = plist;
3787 else
3788 ri->prefix[RIP_FILTER_IN] = NULL;
3789 }
3790 else
3791 ri->prefix[RIP_FILTER_IN] = NULL;
3792
3793 if (dist->prefix[DISTRIBUTE_OUT])
3794 {
3795 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3796 if (plist)
3797 ri->prefix[RIP_FILTER_OUT] = plist;
3798 else
3799 ri->prefix[RIP_FILTER_OUT] = NULL;
3800 }
3801 else
3802 ri->prefix[RIP_FILTER_OUT] = NULL;
3803}
3804
3805void
3806rip_distribute_update_interface (struct interface *ifp)
3807{
3808 struct distribute *dist;
3809
3810 dist = distribute_lookup (ifp->name);
3811 if (dist)
3812 rip_distribute_update (dist);
3813}
3814
3815/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003816/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003817void
paul02ff83c2004-06-11 11:27:03 +00003818rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003819{
3820 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003821 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003822
paul1eb8ef22005-04-07 07:30:20 +00003823 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3824 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003825}
paul11dde9c2004-05-31 14:00:00 +00003826/* ARGSUSED */
3827void
3828rip_distribute_update_all_wrapper(struct access_list *notused)
3829{
paul02ff83c2004-06-11 11:27:03 +00003830 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003831}
paul718e3742002-12-13 20:15:29 +00003832
3833/* Delete all added rip route. */
3834void
3835rip_clean ()
3836{
3837 int i;
3838 struct route_node *rp;
3839 struct rip_info *rinfo;
3840
3841 if (rip)
3842 {
3843 /* Clear RIP routes */
3844 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3845 if ((rinfo = rp->info) != NULL)
3846 {
3847 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3848 rinfo->sub_type == RIP_ROUTE_RTE)
3849 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3850 &rinfo->nexthop, rinfo->metric);
3851
3852 RIP_TIMER_OFF (rinfo->t_timeout);
3853 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3854
3855 rp->info = NULL;
3856 route_unlock_node (rp);
3857
3858 rip_info_free (rinfo);
3859 }
3860
3861 /* Cancel RIP related timers. */
3862 RIP_TIMER_OFF (rip->t_update);
3863 RIP_TIMER_OFF (rip->t_triggered_update);
3864 RIP_TIMER_OFF (rip->t_triggered_interval);
3865
3866 /* Cancel read thread. */
3867 if (rip->t_read)
3868 {
3869 thread_cancel (rip->t_read);
3870 rip->t_read = NULL;
3871 }
3872
3873 /* Close RIP socket. */
3874 if (rip->sock >= 0)
3875 {
3876 close (rip->sock);
3877 rip->sock = -1;
3878 }
3879
3880 /* Static RIP route configuration. */
3881 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3882 if (rp->info)
3883 {
3884 rp->info = NULL;
3885 route_unlock_node (rp);
3886 }
3887
3888 /* RIP neighbor configuration. */
3889 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3890 if (rp->info)
3891 {
3892 rp->info = NULL;
3893 route_unlock_node (rp);
3894 }
3895
3896 /* Redistribute related clear. */
3897 if (rip->default_information_route_map)
3898 free (rip->default_information_route_map);
3899
3900 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3901 if (rip->route_map[i].name)
3902 free (rip->route_map[i].name);
3903
3904 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3905 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3906 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3907
3908 XFREE (MTYPE_RIP, rip);
3909 rip = NULL;
3910 }
3911
3912 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003913 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003914 rip_offset_clean ();
3915 rip_interface_clean ();
3916 rip_distance_reset ();
3917 rip_redistribute_clean ();
3918}
3919
3920/* Reset all values to the default settings. */
3921void
3922rip_reset ()
3923{
3924 /* Reset global counters. */
3925 rip_global_route_changes = 0;
3926 rip_global_queries = 0;
3927
3928 /* Call ripd related reset functions. */
3929 rip_debug_reset ();
3930 rip_route_map_reset ();
3931
3932 /* Call library reset functions. */
3933 vty_reset ();
3934 access_list_reset ();
3935 prefix_list_reset ();
3936
3937 distribute_list_reset ();
3938
3939 rip_interface_reset ();
3940 rip_distance_reset ();
3941
3942 rip_zclient_reset ();
3943}
3944
hasso16705132003-05-25 14:49:19 +00003945void
3946rip_if_rmap_update (struct if_rmap *if_rmap)
3947{
3948 struct interface *ifp;
3949 struct rip_interface *ri;
3950 struct route_map *rmap;
3951
3952 ifp = if_lookup_by_name (if_rmap->ifname);
3953 if (ifp == NULL)
3954 return;
3955
3956 ri = ifp->info;
3957
3958 if (if_rmap->routemap[IF_RMAP_IN])
3959 {
3960 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3961 if (rmap)
3962 ri->routemap[IF_RMAP_IN] = rmap;
3963 else
3964 ri->routemap[IF_RMAP_IN] = NULL;
3965 }
3966 else
3967 ri->routemap[RIP_FILTER_IN] = NULL;
3968
3969 if (if_rmap->routemap[IF_RMAP_OUT])
3970 {
3971 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3972 if (rmap)
3973 ri->routemap[IF_RMAP_OUT] = rmap;
3974 else
3975 ri->routemap[IF_RMAP_OUT] = NULL;
3976 }
3977 else
3978 ri->routemap[RIP_FILTER_OUT] = NULL;
3979}
3980
3981void
3982rip_if_rmap_update_interface (struct interface *ifp)
3983{
3984 struct if_rmap *if_rmap;
3985
3986 if_rmap = if_rmap_lookup (ifp->name);
3987 if (if_rmap)
3988 rip_if_rmap_update (if_rmap);
3989}
3990
3991void
3992rip_routemap_update_redistribute (void)
3993{
3994 int i;
3995
3996 if (rip)
3997 {
3998 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3999 {
4000 if (rip->route_map[i].name)
4001 rip->route_map[i].map =
4002 route_map_lookup_by_name (rip->route_map[i].name);
4003 }
4004 }
4005}
4006
paul11dde9c2004-05-31 14:00:00 +00004007/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00004008void
hasso98b718a2004-10-11 12:57:57 +00004009rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00004010{
4011 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00004012 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00004013
paul1eb8ef22005-04-07 07:30:20 +00004014 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
4015 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00004016
4017 rip_routemap_update_redistribute ();
4018}
4019
paul718e3742002-12-13 20:15:29 +00004020/* Allocate new rip structure and set default value. */
4021void
4022rip_init ()
4023{
4024 /* Randomize for triggered update random(). */
4025 srand (time (NULL));
4026
4027 /* Install top nodes. */
4028 install_node (&rip_node, config_write_rip);
4029
4030 /* Install rip commands. */
4031 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004032 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004033 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004034 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004035 install_element (CONFIG_NODE, &router_rip_cmd);
4036 install_element (CONFIG_NODE, &no_router_rip_cmd);
4037
4038 install_default (RIP_NODE);
4039 install_element (RIP_NODE, &rip_version_cmd);
4040 install_element (RIP_NODE, &no_rip_version_cmd);
4041 install_element (RIP_NODE, &no_rip_version_val_cmd);
4042 install_element (RIP_NODE, &rip_default_metric_cmd);
4043 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4044 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4045 install_element (RIP_NODE, &rip_timers_cmd);
4046 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00004047 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00004048 install_element (RIP_NODE, &rip_route_cmd);
4049 install_element (RIP_NODE, &no_rip_route_cmd);
4050 install_element (RIP_NODE, &rip_distance_cmd);
4051 install_element (RIP_NODE, &no_rip_distance_cmd);
4052 install_element (RIP_NODE, &rip_distance_source_cmd);
4053 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4054 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4055 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4056
4057 /* Debug related init. */
4058 rip_debug_init ();
4059
paul718e3742002-12-13 20:15:29 +00004060 /* SNMP init. */
4061#ifdef HAVE_SNMP
4062 rip_snmp_init ();
4063#endif /* HAVE_SNMP */
4064
4065 /* Access list install. */
4066 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004067 access_list_add_hook (rip_distribute_update_all_wrapper);
4068 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004069
4070 /* Prefix list initialize.*/
4071 prefix_list_init ();
4072 prefix_list_add_hook (rip_distribute_update_all);
4073 prefix_list_delete_hook (rip_distribute_update_all);
4074
4075 /* Distribute list install. */
4076 distribute_list_init (RIP_NODE);
4077 distribute_list_add_hook (rip_distribute_update);
4078 distribute_list_delete_hook (rip_distribute_update);
4079
hasso16705132003-05-25 14:49:19 +00004080 /* Route-map */
4081 rip_route_map_init ();
4082 rip_offset_init ();
4083
4084 route_map_add_hook (rip_routemap_update);
4085 route_map_delete_hook (rip_routemap_update);
4086
4087 if_rmap_init (RIP_NODE);
4088 if_rmap_hook_add (rip_if_rmap_update);
4089 if_rmap_hook_delete (rip_if_rmap_update);
4090
paul718e3742002-12-13 20:15:29 +00004091 /* Distance control. */
4092 rip_distance_table = route_table_init ();
4093}