blob: 5fbb349219342bc0093752aad7ae46c3a284e4c9 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "if.h"
25#include "command.h"
26#include "prefix.h"
27#include "table.h"
28#include "thread.h"
29#include "memory.h"
30#include "log.h"
31#include "stream.h"
32#include "filter.h"
33#include "sockunion.h"
34#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000035#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000036#include "plist.h"
37#include "distribute.h"
38#include "md5-gnu.h"
39#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000040#include "privs.h"
paul718e3742002-12-13 20:15:29 +000041
42#include "ripd/ripd.h"
43#include "ripd/rip_debug.h"
44
paul0b3acf42004-09-17 08:39:08 +000045/* UDP receive buffer size */
46#define RIP_UDP_RCV_BUF 41600
47
48/* privileges global */
pauledd7c242003-06-04 13:59:38 +000049extern struct zebra_privs_t ripd_privs;
50
paul718e3742002-12-13 20:15:29 +000051/* RIP Structure. */
52struct rip *rip = NULL;
53
54/* RIP neighbor address table. */
55struct route_table *rip_neighbor_table;
56
57/* RIP route changes. */
58long rip_global_route_changes = 0;
59
60/* RIP queries. */
61long rip_global_queries = 0;
62
63/* Prototypes. */
64void rip_event (enum rip_event, int);
65
paul727d1042002-12-13 20:50:29 +000066void rip_output_process (struct interface *, struct prefix *,
paulcc1131a2003-10-15 23:20:17 +000067 struct sockaddr_in *, int, u_char,
paul931cd542004-01-23 15:31:42 +000068 struct connected *, struct prefix_ipv4 *);
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;
93 char *str;
94 char *str_long;
95} 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"},
105 { ZEBRA_ROUTE_BGP, "B", "bgp"}
106};
107
108/* Utility function to set boradcast option to the socket. */
109int
110sockopt_broadcast (int sock)
111{
112 int ret;
113 int on = 1;
114
115 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
116 if (ret < 0)
117 {
118 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
119 return -1;
120 }
121 return 0;
122}
123
124int
125rip_route_rte (struct rip_info *rinfo)
126{
127 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
128}
129
130struct rip_info *
131rip_info_new ()
132{
133 struct rip_info *new;
134
135 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
136 memset (new, 0, sizeof (struct rip_info));
137 return new;
138}
139
140void
141rip_info_free (struct rip_info *rinfo)
142{
143 XFREE (MTYPE_RIP_INFO, rinfo);
144}
145
146/* RIP route garbage collect timer. */
147int
148rip_garbage_collect (struct thread *t)
149{
150 struct rip_info *rinfo;
151 struct route_node *rp;
152
153 rinfo = THREAD_ARG (t);
154 rinfo->t_garbage_collect = NULL;
155
156 /* Off timeout timer. */
157 RIP_TIMER_OFF (rinfo->t_timeout);
158
159 /* Get route_node pointer. */
160 rp = rinfo->rp;
161
162 /* Unlock route_node. */
163 rp->info = NULL;
164 route_unlock_node (rp);
165
166 /* Free RIP routing information. */
167 rip_info_free (rinfo);
168
169 return 0;
170}
171
172/* Timeout RIP routes. */
173int
174rip_timeout (struct thread *t)
175{
176 struct rip_info *rinfo;
177 struct route_node *rn;
178
179 rinfo = THREAD_ARG (t);
180 rinfo->t_timeout = NULL;
181
182 rn = rinfo->rp;
183
184 /* - The garbage-collection timer is set for 120 seconds. */
185 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
186 rip->garbage_time);
187
188 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
189 rinfo->metric);
190 /* - The metric for the route is set to 16 (infinity). This causes
191 the route to be removed from service. */
192 rinfo->metric = RIP_METRIC_INFINITY;
193 rinfo->flags &= ~RIP_RTF_FIB;
194
195 /* - The route change flag is to indicate that this entry has been
196 changed. */
197 rinfo->flags |= RIP_RTF_CHANGED;
198
199 /* - The output process is signalled to trigger a response. */
200 rip_event (RIP_TRIGGERED_UPDATE, 0);
201
202 return 0;
203}
204
205void
206rip_timeout_update (struct rip_info *rinfo)
207{
208 if (rinfo->metric != RIP_METRIC_INFINITY)
209 {
210 RIP_TIMER_OFF (rinfo->t_timeout);
211 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
212 }
213}
214
215int
216rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
217{
218 struct distribute *dist;
219 struct access_list *alist;
220 struct prefix_list *plist;
221
222 /* Input distribute-list filtering. */
223 if (ri->list[RIP_FILTER_IN])
224 {
225 if (access_list_apply (ri->list[RIP_FILTER_IN],
226 (struct prefix *) p) == FILTER_DENY)
227 {
228 if (IS_RIP_DEBUG_PACKET)
229 zlog_info ("%s/%d filtered by distribute in",
230 inet_ntoa (p->prefix), p->prefixlen);
231 return -1;
232 }
233 }
234 if (ri->prefix[RIP_FILTER_IN])
235 {
236 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
237 (struct prefix *) p) == PREFIX_DENY)
238 {
239 if (IS_RIP_DEBUG_PACKET)
240 zlog_info ("%s/%d filtered by prefix-list in",
241 inet_ntoa (p->prefix), p->prefixlen);
242 return -1;
243 }
244 }
245
246 /* All interface filter check. */
247 dist = distribute_lookup (NULL);
248 if (dist)
249 {
250 if (dist->list[DISTRIBUTE_IN])
251 {
252 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
253
254 if (alist)
255 {
256 if (access_list_apply (alist,
257 (struct prefix *) p) == FILTER_DENY)
258 {
259 if (IS_RIP_DEBUG_PACKET)
260 zlog_info ("%s/%d filtered by distribute in",
261 inet_ntoa (p->prefix), p->prefixlen);
262 return -1;
263 }
264 }
265 }
266 if (dist->prefix[DISTRIBUTE_IN])
267 {
268 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
269
270 if (plist)
271 {
272 if (prefix_list_apply (plist,
273 (struct prefix *) p) == PREFIX_DENY)
274 {
275 if (IS_RIP_DEBUG_PACKET)
276 zlog_info ("%s/%d filtered by prefix-list in",
277 inet_ntoa (p->prefix), p->prefixlen);
278 return -1;
279 }
280 }
281 }
282 }
283 return 0;
284}
285
286int
287rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
288{
289 struct distribute *dist;
290 struct access_list *alist;
291 struct prefix_list *plist;
292
293 if (ri->list[RIP_FILTER_OUT])
294 {
295 if (access_list_apply (ri->list[RIP_FILTER_OUT],
296 (struct prefix *) p) == FILTER_DENY)
297 {
298 if (IS_RIP_DEBUG_PACKET)
299 zlog_info ("%s/%d is filtered by distribute out",
300 inet_ntoa (p->prefix), p->prefixlen);
301 return -1;
302 }
303 }
304 if (ri->prefix[RIP_FILTER_OUT])
305 {
306 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
307 (struct prefix *) p) == PREFIX_DENY)
308 {
309 if (IS_RIP_DEBUG_PACKET)
310 zlog_info ("%s/%d is filtered by prefix-list out",
311 inet_ntoa (p->prefix), p->prefixlen);
312 return -1;
313 }
314 }
315
316 /* All interface filter check. */
317 dist = distribute_lookup (NULL);
318 if (dist)
319 {
320 if (dist->list[DISTRIBUTE_OUT])
321 {
322 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
323
324 if (alist)
325 {
326 if (access_list_apply (alist,
327 (struct prefix *) p) == FILTER_DENY)
328 {
329 if (IS_RIP_DEBUG_PACKET)
330 zlog_info ("%s/%d filtered by distribute out",
331 inet_ntoa (p->prefix), p->prefixlen);
332 return -1;
333 }
334 }
335 }
336 if (dist->prefix[DISTRIBUTE_OUT])
337 {
338 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
339
340 if (plist)
341 {
342 if (prefix_list_apply (plist,
343 (struct prefix *) p) == PREFIX_DENY)
344 {
345 if (IS_RIP_DEBUG_PACKET)
346 zlog_info ("%s/%d filtered by prefix-list out",
347 inet_ntoa (p->prefix), p->prefixlen);
348 return -1;
349 }
350 }
351 }
352 }
353 return 0;
354}
355
356/* Check nexthop address validity. */
357static int
358rip_nexthop_check (struct in_addr *addr)
359{
360 listnode node;
361 listnode cnode;
362 struct interface *ifp;
363 struct connected *ifc;
364 struct prefix *p;
365
366 /* If nexthop address matches local configured address then it is
367 invalid nexthop. */
368 for (node = listhead (iflist); node; nextnode (node))
369 {
370 ifp = getdata (node);
371
372 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
373 {
374 ifc = getdata (cnode);
375 p = ifc->address;
376
377 if (p->family == AF_INET
378 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
379 return -1;
380 }
381 }
382 return 0;
383}
384
385/* RIP add route to routing table. */
386void
387rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000388 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000389{
390 int ret;
391 struct prefix_ipv4 p;
392 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000393 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000394 struct rip_interface *ri;
395 struct in_addr *nexthop;
396 u_char oldmetric;
397 int same = 0;
398
399 /* Make prefix structure. */
400 memset (&p, 0, sizeof (struct prefix_ipv4));
401 p.family = AF_INET;
402 p.prefix = rte->prefix;
403 p.prefixlen = ip_masklen (rte->mask);
404
405 /* Make sure mask is applied. */
406 apply_mask_ipv4 (&p);
407
408 /* Apply input filters. */
409 ri = ifp->info;
410
411 ret = rip_incoming_filter (&p, ri);
412 if (ret < 0)
413 return;
414
hasso16705132003-05-25 14:49:19 +0000415 /* Modify entry according to the interface routemap. */
416 if (ri->routemap[RIP_FILTER_IN])
417 {
418 int ret;
419 struct rip_info newinfo;
420
421 memset (&newinfo, 0, sizeof (newinfo));
422 newinfo.type = ZEBRA_ROUTE_RIP;
423 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000424 newinfo.nexthop = rte->nexthop;
425 newinfo.from = from->sin_addr;
426 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000427 newinfo.metric = rte->metric;
428 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000429 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000430
431 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000432 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
433 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000434
435 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000436 {
437 if (IS_RIP_DEBUG_PACKET)
438 zlog_info ("RIP %s/%d is filtered by route-map in",
439 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)
paula87552c2004-05-03 20:00:17 +0000474 zlog_info ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000475 return;
476 }
477
478 /* Get index for the prefix. */
479 rp = route_node_get (rip->table, (struct prefix *) &p);
480
481 /* Check to see whether there is already RIP route on the table. */
482 rinfo = rp->info;
483
484 if (rinfo)
485 {
486 /* Redistributed route check. */
487 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000488 && rinfo->metric != RIP_METRIC_INFINITY)
489 return;
paul718e3742002-12-13 20:15:29 +0000490
491 /* Local static route. */
492 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000493 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
494 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
495 && rinfo->metric != RIP_METRIC_INFINITY)
496 return;
paul718e3742002-12-13 20:15:29 +0000497 }
paula87552c2004-05-03 20:00:17 +0000498
499 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000500 {
501 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000502 for the destination prefix. If there is no such route, add
503 this route to the routing table, unless the metric is
504 infinity (there is no point in adding a route which
505 unusable). */
paul718e3742002-12-13 20:15:29 +0000506 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000507 {
508 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000509
paula87552c2004-05-03 20:00:17 +0000510 /* - Setting the destination prefix and length to those in
511 the RTE. */
512 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000513
paula87552c2004-05-03 20:00:17 +0000514 /* - Setting the metric to the newly calculated metric (as
515 described above). */
516 rinfo->metric = rte->metric;
517 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000518
paula87552c2004-05-03 20:00:17 +0000519 /* - Set the next hop address to be the address of the router
520 from which the datagram came or the next hop address
521 specified by a next hop RTE. */
522 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
523 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
524 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000525
paula87552c2004-05-03 20:00:17 +0000526 /* - Initialize the timeout for the route. If the
527 garbage-collection timer is running for this route, stop it
528 (see section 2.3 for a discussion of the timers). */
529 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Set the route change flag. */
532 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000533
paula87552c2004-05-03 20:00:17 +0000534 /* - Signal the output process to trigger an update (see section
535 2.5). */
536 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000537
paula87552c2004-05-03 20:00:17 +0000538 /* Finally, route goes into the kernel. */
539 rinfo->type = ZEBRA_ROUTE_RIP;
540 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000541
paula87552c2004-05-03 20:00:17 +0000542 /* Set distance value. */
543 rinfo->distance = rip_distance_apply (rinfo);
544
545 rp->info = rinfo;
546 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
547 rinfo->distance);
548 rinfo->flags |= RIP_RTF_FIB;
549 }
paul718e3742002-12-13 20:15:29 +0000550 }
551 else
552 {
553 /* Route is there but we are not sure the route is RIP or not. */
554 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000555
paul718e3742002-12-13 20:15:29 +0000556 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000557 to the address of the router from which the datagram came.
558 If this datagram is from the same router as the existing
559 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000560 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000561 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000562
563 if (same)
paula87552c2004-05-03 20:00:17 +0000564 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000565
paulb94f9db2004-05-01 20:45:38 +0000566
567 /* Fill in a minimaly temporary rip_info structure, for a future
568 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000569 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000570 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000571 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000572
573
paul718e3742002-12-13 20:15:29 +0000574 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000575 router as the existing route, and the new metric is different
576 than the old one; or, if the new metric is lower than the old
577 one, or if the tag has been changed; or if there is a route
578 with a lower administrave distance; or an update of the
579 distance on the actual route; do the following actions: */
580 if ((same && rinfo->metric != rte->metric)
581 || (rte->metric < rinfo->metric)
582 || ((same)
583 && (rinfo->metric == rte->metric)
584 && ntohs (rte->tag) != rinfo->tag)
585 || (rinfo->distance > rip_distance_apply (&rinfotmp))
586 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
587 {
588 /* - Adopt the route from the datagram. That is, put the
589 new metric in, and adjust the next hop address (if
590 necessary). */
591 oldmetric = rinfo->metric;
592 rinfo->metric = rte->metric;
593 rinfo->tag = ntohs (rte->tag);
594 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
595 rinfo->ifindex = ifp->ifindex;
596 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000597
paula87552c2004-05-03 20:00:17 +0000598 /* Should a new route to this network be established
599 while the garbage-collection timer is running, the
600 new route will replace the one that is about to be
601 deleted. In this case the garbage-collection timer
602 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000603
paula87552c2004-05-03 20:00:17 +0000604 if (oldmetric == RIP_METRIC_INFINITY &&
605 rinfo->metric < RIP_METRIC_INFINITY)
606 {
607 rinfo->type = ZEBRA_ROUTE_RIP;
608 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000609
paula87552c2004-05-03 20:00:17 +0000610 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
613 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000614
paula87552c2004-05-03 20:00:17 +0000615 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
616 rinfo->distance);
617 rinfo->flags |= RIP_RTF_FIB;
618 }
paul718e3742002-12-13 20:15:29 +0000619
paula87552c2004-05-03 20:00:17 +0000620 /* Update nexthop and/or metric value. */
621 if (oldmetric != RIP_METRIC_INFINITY)
622 {
623 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
624 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
625 rinfo->distance);
626 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000627
paula87552c2004-05-03 20:00:17 +0000628 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
629 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
630 }
paul718e3742002-12-13 20:15:29 +0000631
paula87552c2004-05-03 20:00:17 +0000632 /* - Set the route change flag and signal the output process
633 to trigger an update. */
634 rinfo->flags |= RIP_RTF_CHANGED;
635 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000636
paula87552c2004-05-03 20:00:17 +0000637 /* - If the new metric is infinity, start the deletion
638 process (described above); */
639 if (rinfo->metric == RIP_METRIC_INFINITY)
640 {
641 /* If the new metric is infinity, the deletion process
642 begins for the route, which is no longer used for
643 routing packets. Note that the deletion process is
644 started only when the metric is first set to
645 infinity. If the metric was already infinity, then a
646 new deletion process is not started. */
647 if (oldmetric != RIP_METRIC_INFINITY)
648 {
649 /* - The garbage-collection timer is set for 120 seconds. */
650 RIP_TIMER_ON (rinfo->t_garbage_collect,
651 rip_garbage_collect, rip->garbage_time);
652 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000653
paula87552c2004-05-03 20:00:17 +0000654 /* - The metric for the route is set to 16
655 (infinity). This causes the route to be removed
656 from service. */
657 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
658 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000659
paula87552c2004-05-03 20:00:17 +0000660 /* - The route change flag is to indicate that this
661 entry has been changed. */
662 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000663 response. */
paula87552c2004-05-03 20:00:17 +0000664 ; /* Above processes are already done previously. */
665 }
666 }
667 else
668 {
669 /* otherwise, re-initialize the timeout. */
670 rip_timeout_update (rinfo);
671 }
672 }
paul718e3742002-12-13 20:15:29 +0000673 /* Unlock tempolary lock of the route. */
674 route_unlock_node (rp);
675 }
676}
677
678/* Dump RIP packet */
679void
680rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)
681{
682 caddr_t lim;
683 struct rte *rte;
684 char *command_str;
685 char pbuf[BUFSIZ], nbuf[BUFSIZ];
686 u_char netmask = 0;
687 u_char *p;
688
689 /* Set command string. */
690 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
691 command_str = lookup (rip_msg, packet->command);
692 else
693 command_str = "unknown";
694
695 /* Dump packet header. */
696 zlog_info ("%s %s version %d packet size %d",
697 sndrcv, command_str, packet->version, size);
698
699 /* Dump each routing table entry. */
700 rte = packet->rte;
701
702 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
703 {
704 if (packet->version == RIPv2)
705 {
706 netmask = ip_masklen (rte->mask);
707
paulca5e5162004-06-06 22:06:33 +0000708 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000709 {
paulca5e5162004-06-06 22:06:33 +0000710 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000711 {
712 p = (u_char *)&rte->prefix;
713
714 zlog_info (" family 0x%X type %d auth string: %s",
715 ntohs (rte->family), ntohs (rte->tag), p);
716 }
paulca5e5162004-06-06 22:06:33 +0000717 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000718 {
719 struct rip_md5_info *md5;
720
721 md5 = (struct rip_md5_info *) &packet->rte;
722
723 zlog_info (" family 0x%X type %d (MD5 authentication)",
724 ntohs (md5->family), ntohs (md5->type));
725 zlog_info (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000726 " Auth Data len %d",
727 ntohs (md5->packet_len), md5->keyid,
728 md5->auth_len);
729 zlog_info (" Sequence Number %ld",
730 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000731 }
paulca5e5162004-06-06 22:06:33 +0000732 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000733 {
734 p = (u_char *)&rte->prefix;
735
736 zlog_info (" family 0x%X type %d (MD5 data)",
737 ntohs (rte->family), ntohs (rte->tag));
738 zlog_info (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
739 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000740 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
741 p[7], p[9], p[10], p[11], p[12], p[13],
742 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000743 }
744 else
745 {
746 zlog_info (" family 0x%X type %d (Unknown auth type)",
747 ntohs (rte->family), ntohs (rte->tag));
748 }
749 }
750 else
751 zlog_info (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000752 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
753 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
754 BUFSIZ), ntohs (rte->family),
755 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000756 }
757 else
758 {
759 zlog_info (" %s family %d tag %d metric %ld",
760 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
761 ntohs (rte->family), ntohs (rte->tag),
762 (u_long)ntohl (rte->metric));
763 }
764 }
765}
766
767/* Check if the destination address is valid (unicast; not net 0
768 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
769 check net 0 because we accept default route. */
770int
771rip_destination_check (struct in_addr addr)
772{
773 u_int32_t destination;
774
775 /* Convert to host byte order. */
776 destination = ntohl (addr.s_addr);
777
778 if (IPV4_NET127 (destination))
779 return 0;
780
781 /* Net 0 may match to the default route. */
782 if (IPV4_NET0 (destination) && destination != 0)
783 return 0;
784
785 /* Unicast address must belong to class A, B, C. */
786 if (IN_CLASSA (destination))
787 return 1;
788 if (IN_CLASSB (destination))
789 return 1;
790 if (IN_CLASSC (destination))
791 return 1;
792
793 return 0;
794}
795
796/* RIP version 2 authentication. */
797int
798rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
799 struct interface *ifp)
800{
801 struct rip_interface *ri;
802 char *auth_str;
803
804 if (IS_RIP_DEBUG_EVENT)
805 zlog_info ("RIPv2 simple password authentication from %s",
806 inet_ntoa (from->sin_addr));
807
808 ri = ifp->info;
809
810 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000811 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000812 return 0;
813
814 /* Simple password authentication. */
815 if (ri->auth_str)
816 {
817 auth_str = (char *) &rte->prefix;
818
819 if (strncmp (auth_str, ri->auth_str, 16) == 0)
820 return 1;
821 }
822 if (ri->key_chain)
823 {
824 struct keychain *keychain;
825 struct key *key;
826
827 keychain = keychain_lookup (ri->key_chain);
828 if (keychain == NULL)
829 return 0;
830
831 key = key_match_for_accept (keychain, (char *) &rte->prefix);
832 if (key)
833 return 1;
834 }
835 return 0;
836}
837
838/* RIP version 2 authentication with MD5. */
839int
840rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000841 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
843 struct rip_interface *ri;
844 struct rip_md5_info *md5;
845 struct rip_md5_data *md5data;
846 struct keychain *keychain;
847 struct key *key;
848 struct md5_ctx ctx;
849 u_char pdigest[RIP_AUTH_MD5_SIZE];
850 u_char digest[RIP_AUTH_MD5_SIZE];
851 u_int16_t packet_len;
852 char *auth_str = NULL;
853
854 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000855 zlog_info ("RIPv2 MD5 authentication from %s",
856 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000857
858 ri = ifp->info;
859 md5 = (struct rip_md5_info *) &packet->rte;
860
861 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000862 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000863 return 0;
864
paulca5e5162004-06-06 22:06:33 +0000865 /* If the authentication length is less than 16, then it must be wrong for
866 * any interpretation of rfc2082. Some implementations also interpret
867 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000868 */
paulca5e5162004-06-06 22:06:33 +0000869 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
870 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000871 {
872 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000873 zlog_warn ("RIPv2 MD5 authentication, strange authentication "
874 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000875 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000876 }
paul718e3742002-12-13 20:15:29 +0000877
paulca5e5162004-06-06 22:06:33 +0000878 /* grab and verify check packet length */
879 packet_len = ntohs (md5->packet_len);
880
881 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
882 {
883 if (IS_RIP_DEBUG_EVENT)
884 zlog_warn ("RIPv2 MD5 authentication, packet length field %d "
885 "greater than received length %d!",
886 md5->packet_len, length);
887 return 0;
888 }
889
890 /* retrieve authentication data */
891 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
892
paul718e3742002-12-13 20:15:29 +0000893 if (ri->key_chain)
894 {
895 keychain = keychain_lookup (ri->key_chain);
896 if (keychain == NULL)
897 return 0;
898
899 key = key_lookup_for_accept (keychain, md5->keyid);
900 if (key == NULL)
901 return 0;
902
903 auth_str = key->string;
904 }
905
906 if (ri->auth_str)
907 auth_str = ri->auth_str;
908
909 if (! auth_str)
910 return 0;
911
912 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000913
914 /* Save digest to pdigest. */
915 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
916
917 /* Overwrite digest by my secret. */
918 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000919 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000920
921 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000922 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000923 &ctx);
paul718e3742002-12-13 20:15:29 +0000924 md5_finish_ctx (&ctx, digest);
925
926 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
927 return packet_len;
928 else
929 return 0;
930}
931
932void
933rip_auth_md5_set (struct stream *s, struct interface *ifp)
934{
935 struct rip_interface *ri;
936 struct keychain *keychain = NULL;
937 struct key *key = NULL;
938 unsigned long len;
939 struct md5_ctx ctx;
940 unsigned char secret[RIP_AUTH_MD5_SIZE];
941 unsigned char digest[RIP_AUTH_MD5_SIZE];
942 char *auth_str = NULL;
943
944 ri = ifp->info;
945
946 /* Make it sure this interface is configured as MD5
947 authentication. */
948 if (ri->auth_type != RIP_AUTH_MD5)
949 return;
950
951 /* Lookup key chain. */
952 if (ri->key_chain)
953 {
954 keychain = keychain_lookup (ri->key_chain);
955 if (keychain == NULL)
956 return;
957
958 /* Lookup key. */
959 key = key_lookup_for_send (keychain);
960 if (key == NULL)
961 return;
962
963 auth_str = key->string;
964 }
965
966 if (ri->auth_str)
967 auth_str = ri->auth_str;
968
969 if (! auth_str)
970 return;
971
972 /* Get packet length. */
973 len = s->putp;
974
975 /* Check packet length. */
976 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
977 {
978 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
979 return;
980 }
981
982 /* Move RTE. */
983 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
984 s->data + RIP_HEADER_SIZE,
985 len - RIP_HEADER_SIZE);
986
987 /* Set pointer to authentication header. */
988 stream_set_putp (s, RIP_HEADER_SIZE);
989 len += RIP_RTE_SIZE;
990
991 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000992 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000993 stream_putw (s, RIP_AUTH_MD5);
994
995 /* RIP-2 Packet length. Actual value is filled in
996 rip_auth_md5_set(). */
997 stream_putw (s, len);
998
999 /* Key ID. */
1000 if (key)
1001 stream_putc (s, key->index % 256);
1002 else
1003 stream_putc (s, 1);
1004
paulca5e5162004-06-06 22:06:33 +00001005 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1006 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1007 * to be configurable.
1008 */
1009 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001010
1011 /* Sequence Number (non-decreasing). */
1012 /* RFC2080: The value used in the sequence number is
1013 arbitrary, but two suggestions are the time of the
1014 message's creation or a simple message counter. */
1015 stream_putl (s, time (NULL));
1016
1017 /* Reserved field must be zero. */
1018 stream_putl (s, 0);
1019 stream_putl (s, 0);
1020
1021 /* Set pointer to authentication data. */
1022 stream_set_putp (s, len);
1023
1024 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001025 stream_putw (s, RIP_FAMILY_AUTH);
1026 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001027
1028 /* Generate a digest for the RIP packet. */
1029 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001030 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001031 md5_init_ctx (&ctx);
1032 md5_process_bytes (s->data, s->endp, &ctx);
1033 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1034 md5_finish_ctx (&ctx, digest);
1035
1036 /* Copy the digest to the packet. */
1037 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1038}
1039
1040/* RIP routing information. */
1041void
1042rip_response_process (struct rip_packet *packet, int size,
1043 struct sockaddr_in *from, struct interface *ifp)
1044{
1045 caddr_t lim;
1046 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001047 struct prefix_ipv4 ifaddr;
1048 struct prefix_ipv4 ifaddrclass;
1049 struct connected *c;
1050 int subnetted;
paul718e3742002-12-13 20:15:29 +00001051
paul727d1042002-12-13 20:50:29 +00001052 /* We don't know yet. */
1053 subnetted = -1;
1054
paul718e3742002-12-13 20:15:29 +00001055 /* The Response must be ignored if it is not from the RIP
1056 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001057 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001058 {
1059 zlog_info ("response doesn't come from RIP port: %d",
1060 from->sin_port);
1061 rip_peer_bad_packet (from);
1062 return;
1063 }
1064
1065 /* The datagram's IPv4 source address should be checked to see
1066 whether the datagram is from a valid neighbor; the source of the
1067 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001068 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001069 {
1070 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1071 inet_ntoa (from->sin_addr));
1072 rip_peer_bad_packet (from);
1073 return;
1074 }
1075
1076 /* It is also worth checking to see whether the response is from one
1077 of the router's own addresses. */
1078
1079 ; /* Alredy done in rip_read () */
1080
1081 /* Update RIP peer. */
1082 rip_peer_update (from, packet->version);
1083
1084 /* Set RTE pointer. */
1085 rte = packet->rte;
1086
1087 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1088 {
1089 /* RIPv2 authentication check. */
1090 /* If the Address Family Identifier of the first (and only the
1091 first) entry in the message is 0xFFFF, then the remainder of
1092 the entry contains the authentication. */
1093 /* If the packet gets here it means authentication enabled */
1094 /* Check is done in rip_read(). So, just skipping it */
1095 if (packet->version == RIPv2 &&
1096 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001097 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001098 continue;
1099
paulca5e5162004-06-06 22:06:33 +00001100 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001101 {
1102 /* Address family check. RIP only supports AF_INET. */
1103 zlog_info ("Unsupported family %d from %s.",
1104 ntohs (rte->family), inet_ntoa (from->sin_addr));
1105 continue;
1106 }
1107
1108 /* - is the destination address valid (e.g., unicast; not net 0
1109 or 127) */
1110 if (! rip_destination_check (rte->prefix))
1111 {
1112 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1113 rip_peer_bad_route (from);
1114 continue;
1115 }
1116
1117 /* Convert metric value to host byte order. */
1118 rte->metric = ntohl (rte->metric);
1119
1120 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1121 if (! (rte->metric >= 1 && rte->metric <= 16))
1122 {
1123 zlog_info ("Route's metric is not in the 1-16 range.");
1124 rip_peer_bad_route (from);
1125 continue;
1126 }
1127
1128 /* RIPv1 does not have nexthop value. */
1129 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1130 {
1131 zlog_info ("RIPv1 packet with nexthop value %s",
1132 inet_ntoa (rte->nexthop));
1133 rip_peer_bad_route (from);
1134 continue;
1135 }
1136
1137 /* That is, if the provided information is ignored, a possibly
1138 sub-optimal, but absolutely valid, route may be taken. If
1139 the received Next Hop is not directly reachable, it should be
1140 treated as 0.0.0.0. */
1141 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1142 {
1143 u_int32_t addrval;
1144
1145 /* Multicast address check. */
1146 addrval = ntohl (rte->nexthop.s_addr);
1147 if (IN_CLASSD (addrval))
1148 {
1149 zlog_info ("Nexthop %s is multicast address, skip this rte",
1150 inet_ntoa (rte->nexthop));
1151 continue;
1152 }
1153
1154 if (! if_lookup_address (rte->nexthop))
1155 {
1156 struct route_node *rn;
1157 struct rip_info *rinfo;
1158
1159 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1160
1161 if (rn)
1162 {
1163 rinfo = rn->info;
1164
1165 if (rinfo->type == ZEBRA_ROUTE_RIP
1166 && rinfo->sub_type == RIP_ROUTE_RTE)
1167 {
1168 if (IS_RIP_DEBUG_EVENT)
1169 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1170 rte->nexthop = rinfo->from;
1171 }
1172 else
1173 {
1174 if (IS_RIP_DEBUG_EVENT)
1175 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1176 rte->nexthop.s_addr = 0;
1177 }
1178
1179 route_unlock_node (rn);
1180 }
1181 else
1182 {
1183 if (IS_RIP_DEBUG_EVENT)
1184 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1185 rte->nexthop.s_addr = 0;
1186 }
1187
1188 }
1189 }
1190
1191 /* For RIPv1, there won't be a valid netmask.
1192
1193 This is a best guess at the masks. If everyone was using old
1194 Ciscos before the 'ip subnet zero' option, it would be almost
1195 right too :-)
1196
1197 Cisco summarize ripv1 advertisments to the classful boundary
1198 (/16 for class B's) except when the RIP packet does to inside
1199 the classful network in question. */
1200
1201 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1202 || (packet->version == RIPv2
1203 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1204 {
1205 u_int32_t destination;
1206
paul727d1042002-12-13 20:50:29 +00001207 if (subnetted == -1)
1208 {
1209 c = connected_lookup_address (ifp, from->sin_addr);
1210 if (c != NULL)
1211 {
1212 memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
1213 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1214 apply_classful_mask_ipv4 (&ifaddrclass);
1215 subnetted = 0;
1216 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1217 subnetted = 1;
1218 }
1219 }
1220
paul718e3742002-12-13 20:15:29 +00001221 destination = ntohl (rte->prefix.s_addr);
1222
paul727d1042002-12-13 20:50:29 +00001223 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001224 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001225 else if (IN_CLASSB (destination))
1226 masklen2ip (16, &rte->mask);
1227 else if (IN_CLASSC (destination))
1228 masklen2ip (24, &rte->mask);
1229
1230 if (subnetted == 1)
1231 masklen2ip (ifaddrclass.prefixlen,
1232 (struct in_addr *) &destination);
1233 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1234 ifaddrclass.prefix.s_addr))
1235 {
1236 masklen2ip (ifaddr.prefixlen, &rte->mask);
1237 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1238 masklen2ip (32, &rte->mask);
1239 if (IS_RIP_DEBUG_EVENT)
1240 zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
1241 }
1242 else
1243 {
1244 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1245 continue;
1246 }
1247
1248 if (IS_RIP_DEBUG_EVENT)
1249 {
1250 zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
1251 zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001252 }
1253 }
1254
1255 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1256 ignore the entry. */
1257 if ((packet->version == RIPv2)
1258 && (rte->mask.s_addr != 0)
1259 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1260 {
1261 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1262 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1263 rip_peer_bad_route (from);
1264 continue;
1265 }
1266
1267 /* Default route's netmask is ignored. */
1268 if (packet->version == RIPv2
1269 && (rte->prefix.s_addr == 0)
1270 && (rte->mask.s_addr != 0))
1271 {
1272 if (IS_RIP_DEBUG_EVENT)
1273 zlog_info ("Default route with non-zero netmask. Set zero to netmask");
1274 rte->mask.s_addr = 0;
1275 }
1276
1277 /* Routing table updates. */
1278 rip_rte_process (rte, from, ifp);
1279 }
1280}
1281
1282/* RIP packet send to destination address. */
1283int
paul11dde9c2004-05-31 14:00:00 +00001284rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
paul931cd542004-01-23 15:31:42 +00001285 struct interface *ifp, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00001286{
paul931cd542004-01-23 15:31:42 +00001287 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001288 struct sockaddr_in sin;
paul718e3742002-12-13 20:15:29 +00001289
paul931cd542004-01-23 15:31:42 +00001290 if (IS_RIP_DEBUG_PACKET)
1291 {
1292 char dst[20];
1293 if (to)
1294 {
1295 strcpy(dst, inet_ntoa(to->sin_addr));
1296 }
1297 else
1298 {
1299 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1300 strcpy(dst, inet_ntoa(sin.sin_addr));
1301 }
1302 zlog_info("rip_send_packet %s > %s (%s)",
hassoda9c9a22004-03-18 02:40:55 +00001303 (connected ? inet_ntoa(connected->address->u.prefix4) : ""),
1304 dst, ifp->name);
paul931cd542004-01-23 15:31:42 +00001305 }
hassoda9c9a22004-03-18 02:40:55 +00001306 if (connected && connected->flags & ZEBRA_IFA_SECONDARY)
paul931cd542004-01-23 15:31:42 +00001307 {
1308 /*
1309 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1310 * with multiple addresses on the same subnet: the first address
1311 * on the subnet is configured "primary", and all subsequent addresses
1312 * on that subnet are treated as "secondary" addresses.
1313 * In order to avoid routing-table bloat on other rip listeners,
1314 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1315 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1316 * flag is set, we would end up sending a packet for a "secondary"
1317 * source address on non-linux systems.
1318 */
1319 if (IS_RIP_DEBUG_PACKET)
1320 zlog_info("duplicate dropped");
1321 return 0;
1322 }
1323
paul718e3742002-12-13 20:15:29 +00001324 /* Make destination address. */
1325 memset (&sin, 0, sizeof (struct sockaddr_in));
1326 sin.sin_family = AF_INET;
1327#ifdef HAVE_SIN_LEN
1328 sin.sin_len = sizeof (struct sockaddr_in);
1329#endif /* HAVE_SIN_LEN */
1330
1331 /* When destination is specified, use it's port and address. */
1332 if (to)
1333 {
paul718e3742002-12-13 20:15:29 +00001334 sin.sin_port = to->sin_port;
1335 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001336 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001337 }
1338 else
1339 {
paul718e3742002-12-13 20:15:29 +00001340
1341 sin.sin_port = htons (RIP_PORT_DEFAULT);
1342 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1343
paul931cd542004-01-23 15:31:42 +00001344 /*
1345 * we have to open a new socket for each packet because this
1346 * is the most portable way to bind to a different source
1347 * ipv4 address for each packet.
1348 */
1349 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1350 if (send_sock < 0)
1351 {
1352 zlog_warn("rip_send_packet could not create socket %s",
1353 strerror(errno));
1354 return -1;
1355 }
1356 sockopt_broadcast (send_sock);
1357 sockopt_reuseaddr (send_sock);
1358 sockopt_reuseport (send_sock);
1359#ifdef RIP_RECVMSG
1360 setsockopt_pktinfo (send_sock);
1361#endif /* RIP_RECVMSG */
paul1a517862004-08-19 04:03:08 +00001362 rip_interface_multicast_set (send_sock, connected);
paul718e3742002-12-13 20:15:29 +00001363 }
1364
paul931cd542004-01-23 15:31:42 +00001365 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001366 sizeof (struct sockaddr_in));
1367
1368 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001369 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1370 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001371
1372 if (ret < 0)
1373 zlog_warn ("can't send packet : %s", strerror (errno));
1374
paul931cd542004-01-23 15:31:42 +00001375 if (!to)
1376 close(send_sock);
1377
paul718e3742002-12-13 20:15:29 +00001378 return ret;
1379}
1380
1381/* Add redistributed route to RIP table. */
1382void
1383rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1384 unsigned int ifindex, struct in_addr *nexthop)
1385{
1386 int ret;
1387 struct route_node *rp;
1388 struct rip_info *rinfo;
1389
1390 /* Redistribute route */
1391 ret = rip_destination_check (p->prefix);
1392 if (! ret)
1393 return;
1394
1395 rp = route_node_get (rip->table, (struct prefix *) p);
1396
1397 rinfo = rp->info;
1398
1399 if (rinfo)
1400 {
1401 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1402 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1403 && rinfo->metric != RIP_METRIC_INFINITY)
1404 {
1405 route_unlock_node (rp);
1406 return;
1407 }
1408
1409 /* Manually configured RIP route check. */
1410 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001411 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1412 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001413 {
hasso16705132003-05-25 14:49:19 +00001414 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1415 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001416 {
1417 route_unlock_node (rp);
1418 return;
1419 }
1420 }
1421
1422 RIP_TIMER_OFF (rinfo->t_timeout);
1423 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1424
1425 if (rip_route_rte (rinfo))
1426 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1427 rinfo->metric);
1428 rp->info = NULL;
1429 rip_info_free (rinfo);
1430
1431 route_unlock_node (rp);
1432 }
1433
1434 rinfo = rip_info_new ();
1435
1436 rinfo->type = type;
1437 rinfo->sub_type = sub_type;
1438 rinfo->ifindex = ifindex;
1439 rinfo->metric = 1;
1440 rinfo->rp = rp;
1441
1442 if (nexthop)
1443 rinfo->nexthop = *nexthop;
1444
1445 rinfo->flags |= RIP_RTF_FIB;
1446 rp->info = rinfo;
1447
1448 rinfo->flags |= RIP_RTF_CHANGED;
1449
hasso16705132003-05-25 14:49:19 +00001450 if (IS_RIP_DEBUG_EVENT) {
1451 if (!nexthop)
1452 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1453 inet_ntoa(p->prefix), p->prefixlen,
1454 ifindex2ifname(ifindex));
1455 else
1456 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1457 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1458 ifindex2ifname(ifindex));
1459 }
1460
1461
paul718e3742002-12-13 20:15:29 +00001462 rip_event (RIP_TRIGGERED_UPDATE, 0);
1463}
1464
1465/* Delete redistributed route from RIP table. */
1466void
1467rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1468 unsigned int ifindex)
1469{
1470 int ret;
1471 struct route_node *rp;
1472 struct rip_info *rinfo;
1473
1474 ret = rip_destination_check (p->prefix);
1475 if (! ret)
1476 return;
1477
1478 rp = route_node_lookup (rip->table, (struct prefix *) p);
1479 if (rp)
1480 {
1481 rinfo = rp->info;
1482
1483 if (rinfo != NULL
1484 && rinfo->type == type
1485 && rinfo->sub_type == sub_type
1486 && rinfo->ifindex == ifindex)
1487 {
1488 /* Perform poisoned reverse. */
1489 rinfo->metric = RIP_METRIC_INFINITY;
1490 RIP_TIMER_ON (rinfo->t_garbage_collect,
1491 rip_garbage_collect, rip->garbage_time);
1492 RIP_TIMER_OFF (rinfo->t_timeout);
1493 rinfo->flags |= RIP_RTF_CHANGED;
1494
hasso16705132003-05-25 14:49:19 +00001495 if (IS_RIP_DEBUG_EVENT)
1496 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1497 inet_ntoa(p->prefix), p->prefixlen,
1498 ifindex2ifname(ifindex));
1499
paul718e3742002-12-13 20:15:29 +00001500 rip_event (RIP_TRIGGERED_UPDATE, 0);
1501 }
1502 }
1503}
1504
1505/* Response to request called from rip_read ().*/
1506void
1507rip_request_process (struct rip_packet *packet, int size,
1508 struct sockaddr_in *from, struct interface *ifp)
1509{
1510 caddr_t lim;
1511 struct rte *rte;
1512 struct prefix_ipv4 p;
1513 struct route_node *rp;
1514 struct rip_info *rinfo;
1515 struct rip_interface *ri;
1516
hasso16705132003-05-25 14:49:19 +00001517 /* Does not reponse to the requests on the loopback interfaces */
1518 if (if_is_loopback (ifp))
1519 return;
1520
hasso429a0f82004-02-22 23:42:22 +00001521 /* Check RIP process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001522 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001523 if (! ri->running)
1524 return;
paul718e3742002-12-13 20:15:29 +00001525
1526 /* When passive interface is specified, suppress responses */
1527 if (ri->passive)
1528 return;
1529
1530 /* RIP peer update. */
1531 rip_peer_update (from, packet->version);
1532
1533 lim = ((caddr_t) packet) + size;
1534 rte = packet->rte;
1535
1536 /* The Request is processed entry by entry. If there are no
1537 entries, no response is given. */
1538 if (lim == (caddr_t) rte)
1539 return;
1540
1541 /* There is one special case. If there is exactly one entry in the
1542 request, and it has an address family identifier of zero and a
1543 metric of infinity (i.e., 16), then this is a request to send the
1544 entire routing table. */
1545 if (lim == ((caddr_t) (rte + 1)) &&
1546 ntohs (rte->family) == 0 &&
1547 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1548 {
paulcc1131a2003-10-15 23:20:17 +00001549 struct prefix_ipv4 saddr;
1550
1551 /* saddr will be used for determining which routes to split-horizon.
1552 Since the source address we'll pick will be on the same subnet as the
1553 destination, for the purpose of split-horizoning, we'll
1554 pretend that "from" is our source address. */
1555 saddr.family = AF_INET;
1556 saddr.prefixlen = IPV4_MAX_BITLEN;
1557 saddr.prefix = from->sin_addr;
1558
paul718e3742002-12-13 20:15:29 +00001559 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001560 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001561 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001562 }
1563 else
1564 {
1565 /* Examine the list of RTEs in the Request one by one. For each
1566 entry, look up the destination in the router's routing
1567 database and, if there is a route, put that route's metric in
1568 the metric field of the RTE. If there is no explicit route
1569 to the specified destination, put infinity in the metric
1570 field. Once all the entries have been filled in, change the
1571 command from Request to Response and send the datagram back
1572 to the requestor. */
1573 p.family = AF_INET;
1574
1575 for (; ((caddr_t) rte) < lim; rte++)
1576 {
1577 p.prefix = rte->prefix;
1578 p.prefixlen = ip_masklen (rte->mask);
1579 apply_mask_ipv4 (&p);
1580
1581 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1582 if (rp)
1583 {
1584 rinfo = rp->info;
1585 rte->metric = htonl (rinfo->metric);
1586 route_unlock_node (rp);
1587 }
1588 else
1589 rte->metric = htonl (RIP_METRIC_INFINITY);
1590 }
1591 packet->command = RIP_RESPONSE;
1592
paul11dde9c2004-05-31 14:00:00 +00001593 rip_send_packet ((u_char *)packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001594 }
1595 rip_global_queries++;
1596}
1597
1598#if RIP_RECVMSG
1599/* Set IPv6 packet info to the socket. */
1600static int
1601setsockopt_pktinfo (int sock)
1602{
1603 int ret;
1604 int val = 1;
1605
1606 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1607 if (ret < 0)
1608 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1609 return ret;
1610}
1611
1612/* Read RIP packet by recvmsg function. */
1613int
1614rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1615 int *ifindex)
1616{
1617 int ret;
1618 struct msghdr msg;
1619 struct iovec iov;
1620 struct cmsghdr *ptr;
1621 char adata[1024];
1622
1623 msg.msg_name = (void *) from;
1624 msg.msg_namelen = sizeof (struct sockaddr_in);
1625 msg.msg_iov = &iov;
1626 msg.msg_iovlen = 1;
1627 msg.msg_control = (void *) adata;
1628 msg.msg_controllen = sizeof adata;
1629 iov.iov_base = buf;
1630 iov.iov_len = size;
1631
1632 ret = recvmsg (sock, &msg, 0);
1633 if (ret < 0)
1634 return ret;
1635
1636 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1637 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1638 {
1639 struct in_pktinfo *pktinfo;
1640 int i;
1641
1642 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1643 i = pktinfo->ipi_ifindex;
1644 }
1645 return ret;
1646}
1647
1648/* RIP packet read function. */
1649int
1650rip_read_new (struct thread *t)
1651{
1652 int ret;
1653 int sock;
1654 char buf[RIP_PACKET_MAXSIZ];
1655 struct sockaddr_in from;
1656 unsigned int ifindex;
1657
1658 /* Fetch socket then register myself. */
1659 sock = THREAD_FD (t);
1660 rip_event (RIP_READ, sock);
1661
1662 /* Read RIP packet. */
1663 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1664 if (ret < 0)
1665 {
1666 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1667 return ret;
1668 }
1669
1670 return ret;
1671}
1672#endif /* RIP_RECVMSG */
1673
1674/* First entry point of RIP packet. */
1675int
1676rip_read (struct thread *t)
1677{
1678 int sock;
1679 int ret;
1680 int rtenum;
1681 union rip_buf rip_buf;
1682 struct rip_packet *packet;
1683 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001684 int len;
1685 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001686 struct interface *ifp;
1687 struct rip_interface *ri;
1688
1689 /* Fetch socket then register myself. */
1690 sock = THREAD_FD (t);
1691 rip->t_read = NULL;
1692
1693 /* Add myself to tne next event */
1694 rip_event (RIP_READ, sock);
1695
1696 /* RIPd manages only IPv4. */
1697 memset (&from, 0, sizeof (struct sockaddr_in));
1698 fromlen = sizeof (struct sockaddr_in);
1699
1700 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1701 (struct sockaddr *) &from, &fromlen);
1702 if (len < 0)
1703 {
1704 zlog_info ("recvfrom failed: %s", strerror (errno));
1705 return len;
1706 }
1707
1708 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001709 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001710 {
1711 if (IS_RIP_DEBUG_PACKET)
1712 zlog_warn ("ignore packet comes from myself");
1713 return -1;
1714 }
1715
1716 /* Which interface is this packet comes from. */
1717 ifp = if_lookup_address (from.sin_addr);
1718
1719 /* RIP packet received */
1720 if (IS_RIP_DEBUG_EVENT)
1721 zlog_info ("RECV packet from %s port %d on %s",
1722 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1723 ifp ? ifp->name : "unknown");
1724
1725 /* If this packet come from unknown interface, ignore it. */
1726 if (ifp == NULL)
1727 {
1728 zlog_info ("packet comes from unknown interface");
1729 return -1;
1730 }
1731
1732 /* Packet length check. */
1733 if (len < RIP_PACKET_MINSIZ)
1734 {
1735 zlog_warn ("packet size %d is smaller than minimum size %d",
1736 len, RIP_PACKET_MINSIZ);
1737 rip_peer_bad_packet (&from);
1738 return len;
1739 }
1740 if (len > RIP_PACKET_MAXSIZ)
1741 {
1742 zlog_warn ("packet size %d is larger than max size %d",
1743 len, RIP_PACKET_MAXSIZ);
1744 rip_peer_bad_packet (&from);
1745 return len;
1746 }
1747
1748 /* Packet alignment check. */
1749 if ((len - RIP_PACKET_MINSIZ) % 20)
1750 {
1751 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1752 rip_peer_bad_packet (&from);
1753 return len;
1754 }
1755
1756 /* Set RTE number. */
1757 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1758
1759 /* For easy to handle. */
1760 packet = &rip_buf.rip_packet;
1761
1762 /* RIP version check. */
1763 if (packet->version == 0)
1764 {
1765 zlog_info ("version 0 with command %d received.", packet->command);
1766 rip_peer_bad_packet (&from);
1767 return -1;
1768 }
1769
1770 /* Dump RIP packet. */
1771 if (IS_RIP_DEBUG_RECV)
1772 rip_packet_dump (packet, len, "RECV");
1773
1774 /* RIP version adjust. This code should rethink now. RFC1058 says
1775 that "Version 1 implementations are to ignore this extra data and
1776 process only the fields specified in this document.". So RIPv3
1777 packet should be treated as RIPv1 ignoring must be zero field. */
1778 if (packet->version > RIPv2)
1779 packet->version = RIPv2;
1780
1781 /* Is RIP running or is this RIP neighbor ?*/
1782 ri = ifp->info;
1783 if (! ri->running && ! rip_neighbor_lookup (&from))
1784 {
1785 if (IS_RIP_DEBUG_EVENT)
1786 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1787 rip_peer_bad_packet (&from);
1788 return -1;
1789 }
1790
1791 /* RIP Version check. */
1792 if (packet->command == RIP_RESPONSE)
1793 {
paulf38a4712003-06-07 01:10:00 +00001794 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1795 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001796 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001797 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001798 {
1799 if (IS_RIP_DEBUG_PACKET)
1800 zlog_warn (" packet's v%d doesn't fit to if version spec",
1801 packet->version);
1802 rip_peer_bad_packet (&from);
1803 return -1;
1804 }
1805 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001806 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001807 {
1808 if (IS_RIP_DEBUG_PACKET)
1809 zlog_warn (" packet's v%d doesn't fit to if version spec",
1810 packet->version);
1811 rip_peer_bad_packet (&from);
1812 return -1;
1813 }
paul718e3742002-12-13 20:15:29 +00001814 }
1815
1816 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1817 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1818 accepted; authenticated RIP-2 messages shall be discarded. */
1819
1820 if ((ri->auth_type == RIP_NO_AUTH)
1821 && rtenum
paulca5e5162004-06-06 22:06:33 +00001822 && (packet->version == RIPv2)
1823 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001824 {
1825 if (IS_RIP_DEBUG_EVENT)
1826 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1827 packet->version);
1828 rip_peer_bad_packet (&from);
1829 return -1;
1830 }
1831
1832 /* If the router is configured to authenticate RIP-2 messages, then
1833 RIP-1 messages and RIP-2 messages which pass authentication
1834 testing shall be accepted; unauthenticated and failed
1835 authentication RIP-2 messages shall be discarded. For maximum
1836 security, RIP-1 messages should be ignored when authentication is
1837 in use (see section 4.1); otherwise, the routing information from
1838 authenticated messages will be propagated by RIP-1 routers in an
1839 unauthenticated manner. */
1840
1841 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001842 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001843 {
1844 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001845 if (packet->version == RIPv1
1846 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001847 {
1848 if (IS_RIP_DEBUG_PACKET)
paulca5e5162004-06-06 22:06:33 +00001849 zlog_warn
1850 ("packet RIPv%d is dropped because authentication enabled",
1851 packet->version);
paul718e3742002-12-13 20:15:29 +00001852 rip_peer_bad_packet (&from);
1853 return -1;
1854 }
1855
1856 /* Check RIPv2 authentication. */
1857 if (packet->version == RIPv2)
1858 {
paulca5e5162004-06-06 22:06:33 +00001859 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001860 {
paulca5e5162004-06-06 22:06:33 +00001861 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001862 {
1863 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1864 if (! ret)
1865 {
1866 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001867 zlog_warn
1868 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001869 rip_peer_bad_packet (&from);
1870 return -1;
1871 }
1872 else
1873 {
1874 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001875 zlog_info
1876 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001877 }
1878 }
paulca5e5162004-06-06 22:06:33 +00001879 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001880 {
paulca5e5162004-06-06 22:06:33 +00001881 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001882 if (! ret)
1883 {
1884 if (IS_RIP_DEBUG_EVENT)
1885 zlog_warn ("RIPv2 MD5 authentication failed");
1886 rip_peer_bad_packet (&from);
1887 return -1;
1888 }
1889 else
1890 {
1891 if (IS_RIP_DEBUG_EVENT)
1892 zlog_info ("RIPv2 MD5 authentication success");
1893 }
1894 /* Reset RIP packet length to trim MD5 data. */
1895 len = ret;
1896 }
1897 else
1898 {
1899 if (IS_RIP_DEBUG_EVENT)
1900 zlog_warn ("Unknown authentication type %d",
1901 ntohs (packet->rte->tag));
1902 rip_peer_bad_packet (&from);
1903 return -1;
1904 }
1905 }
1906 else
1907 {
1908 /* There is no authentication in the packet. */
1909 if (ri->auth_str || ri->key_chain)
1910 {
1911 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001912 zlog_warn
1913 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001914 rip_peer_bad_packet (&from);
1915 return -1;
1916 }
1917 }
1918 }
1919 }
1920
1921 /* Process each command. */
1922 switch (packet->command)
1923 {
1924 case RIP_RESPONSE:
1925 rip_response_process (packet, len, &from, ifp);
1926 break;
1927 case RIP_REQUEST:
1928 case RIP_POLL:
1929 rip_request_process (packet, len, &from, ifp);
1930 break;
1931 case RIP_TRACEON:
1932 case RIP_TRACEOFF:
1933 zlog_info ("Obsolete command %s received, please sent it to routed",
1934 lookup (rip_msg, packet->command));
1935 rip_peer_bad_packet (&from);
1936 break;
1937 case RIP_POLL_ENTRY:
1938 zlog_info ("Obsolete command %s received",
1939 lookup (rip_msg, packet->command));
1940 rip_peer_bad_packet (&from);
1941 break;
1942 default:
1943 zlog_info ("Unknown RIP command %d received", packet->command);
1944 rip_peer_bad_packet (&from);
1945 break;
1946 }
1947
1948 return len;
1949}
1950
1951/* Make socket for RIP protocol. */
1952int
1953rip_create_socket ()
1954{
1955 int ret;
1956 int sock;
1957 struct sockaddr_in addr;
1958 struct servent *sp;
1959
1960 memset (&addr, 0, sizeof (struct sockaddr_in));
1961
1962 /* Set RIP port. */
1963 sp = getservbyname ("router", "udp");
1964 if (sp)
1965 addr.sin_port = sp->s_port;
1966 else
1967 addr.sin_port = htons (RIP_PORT_DEFAULT);
1968
1969 /* Address shoud be any address. */
1970 addr.sin_family = AF_INET;
1971 addr.sin_addr.s_addr = INADDR_ANY;
1972
1973 /* Make datagram socket. */
1974 sock = socket (AF_INET, SOCK_DGRAM, 0);
1975 if (sock < 0)
1976 {
1977 perror ("socket");
1978 exit (1);
1979 }
1980
1981 sockopt_broadcast (sock);
1982 sockopt_reuseaddr (sock);
1983 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00001984 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00001985#ifdef RIP_RECVMSG
1986 setsockopt_pktinfo (sock);
1987#endif /* RIP_RECVMSG */
1988
pauledd7c242003-06-04 13:59:38 +00001989 if (ripd_privs.change (ZPRIVS_RAISE))
1990 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001991 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1992 if (ret < 0)
1993 {
1994 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001995 if (ripd_privs.change (ZPRIVS_LOWER))
1996 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001997 return ret;
1998 }
pauledd7c242003-06-04 13:59:38 +00001999 if (ripd_privs.change (ZPRIVS_LOWER))
2000 zlog_err ("rip_create_socket: could not lower privs");
2001
paul718e3742002-12-13 20:15:29 +00002002 return sock;
2003}
2004
2005/* Write routing table entry to the stream and return next index of
2006 the routing table entry in the stream. */
2007int
2008rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2009 u_char version, struct rip_info *rinfo, struct interface *ifp)
2010{
2011 struct in_addr mask;
2012 struct rip_interface *ri;
2013
2014 /* RIP packet header. */
2015 if (num == 0)
2016 {
2017 stream_putc (s, RIP_RESPONSE);
2018 stream_putc (s, version);
2019 stream_putw (s, 0);
2020
2021 /* In case of we need RIPv2 authentication. */
2022 if (version == RIPv2 && ifp)
2023 {
2024 ri = ifp->info;
2025
2026 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2027 {
2028 if (ri->auth_str)
2029 {
paulca5e5162004-06-06 22:06:33 +00002030 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002031 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2032
2033 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002034 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002035 stream_set_putp (s, s->putp + 16);
2036
2037 num++;
2038 }
2039 if (ri->key_chain)
2040 {
2041 struct keychain *keychain;
2042 struct key *key;
2043
2044 keychain = keychain_lookup (ri->key_chain);
2045
2046 if (keychain)
2047 {
2048 key = key_lookup_for_send (keychain);
2049
2050 if (key)
2051 {
paulca5e5162004-06-06 22:06:33 +00002052 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002053 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2054
2055 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002056 strncpy ((char *)(s->data + s->putp),
2057 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002058 stream_set_putp (s, s->putp + 16);
2059
2060 num++;
2061 }
2062 }
2063 }
2064 }
2065 }
2066 }
2067
2068 /* Write routing table entry. */
2069 if (version == RIPv1)
2070 {
2071 stream_putw (s, AF_INET);
2072 stream_putw (s, 0);
2073 stream_put_ipv4 (s, p->prefix.s_addr);
2074 stream_put_ipv4 (s, 0);
2075 stream_put_ipv4 (s, 0);
2076 stream_putl (s, rinfo->metric_out);
2077 }
2078 else
2079 {
2080 masklen2ip (p->prefixlen, &mask);
2081
2082 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002083 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002084 stream_put_ipv4 (s, p->prefix.s_addr);
2085 stream_put_ipv4 (s, mask.s_addr);
2086 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2087 stream_putl (s, rinfo->metric_out);
2088 }
2089
2090 return ++num;
2091}
2092
2093/* Send update to the ifp or spcified neighbor. */
2094void
paul727d1042002-12-13 20:50:29 +00002095rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002096 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002097 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002098{
2099 int ret;
2100 struct stream *s;
2101 struct route_node *rp;
2102 struct rip_info *rinfo;
2103 struct rip_interface *ri;
2104 struct prefix_ipv4 *p;
2105 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002106 struct prefix_ipv4 ifaddrclass;
2107 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002108 int num;
2109 int rtemax;
paul01d09082003-06-08 21:22:18 +00002110 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002111
2112 /* Logging output event. */
2113 if (IS_RIP_DEBUG_EVENT)
2114 {
2115 if (to)
2116 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2117 else
2118 zlog_info ("update routes on interface %s ifindex %d",
2119 ifp->name, ifp->ifindex);
2120 }
2121
2122 /* Set output stream. */
2123 s = rip->obuf;
2124
2125 /* Reset stream and RTE counter. */
2126 stream_reset (s);
2127 num = 0;
2128 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2129
2130 /* Get RIP interface. */
2131 ri = ifp->info;
2132
2133 /* If output interface is in simple password authentication mode, we
2134 need space for authentication data. */
2135 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2136 rtemax -= 1;
2137
2138 /* If output interface is in MD5 authentication mode, we need space
2139 for authentication header and data. */
2140 if (ri->auth_type == RIP_AUTH_MD5)
2141 rtemax -= 2;
2142
2143 /* If output interface is in simple password authentication mode
2144 and string or keychain is specified we need space for auth. data */
2145 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2146 {
2147 if (ri->key_chain)
2148 {
2149 struct keychain *keychain;
2150
2151 keychain = keychain_lookup (ri->key_chain);
2152 if (keychain)
2153 if (key_lookup_for_send (keychain))
2154 rtemax -=1;
2155 }
2156 else
2157 if (ri->auth_str)
2158 rtemax -=1;
2159 }
2160
paul727d1042002-12-13 20:50:29 +00002161 if (version == RIPv1)
2162 {
2163 if (ifaddr == NULL)
2164 {
2165 c = connected_lookup_address (ifp, to->sin_addr);
2166 if (c != NULL)
2167 ifaddr = c->address;
2168 }
2169 if (ifaddr == NULL)
2170 {
2171 zlog_warn ("cannot find source address for packets to neighbor %s",
2172 inet_ntoa (to->sin_addr));
2173 return;
2174 }
2175 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2176 apply_classful_mask_ipv4 (&ifaddrclass);
2177 subnetted = 0;
2178 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002179 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002180 }
2181
paul718e3742002-12-13 20:15:29 +00002182 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2183 if ((rinfo = rp->info) != NULL)
2184 {
paul727d1042002-12-13 20:50:29 +00002185 /* For RIPv1, if we are subnetted, output subnets in our network */
2186 /* that have the same mask as the output "interface". For other */
2187 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002188
2189 if (version == RIPv1)
2190 {
paul727d1042002-12-13 20:50:29 +00002191 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002192
2193 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002194 zlog_info("RIPv1 mask check, %s/%d considered for output",
2195 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002196
paul727d1042002-12-13 20:50:29 +00002197 if (subnetted &&
2198 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2199 {
2200 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2201 (rp->p.prefixlen != 32))
2202 continue;
2203 }
2204 else
2205 {
2206 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2207 apply_classful_mask_ipv4(&classfull);
2208 if (rp->p.u.prefix4.s_addr != 0 &&
2209 classfull.prefixlen != rp->p.prefixlen)
2210 continue;
2211 }
paul718e3742002-12-13 20:15:29 +00002212 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002213 zlog_info("RIPv1 mask check, %s/%d made it through",
2214 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002215 }
2216 else
2217 p = (struct prefix_ipv4 *) &rp->p;
2218
2219 /* Apply output filters. */
2220 ret = rip_outgoing_filter (p, ri);
2221 if (ret < 0)
2222 continue;
2223
2224 /* Changed route only output. */
2225 if (route_type == rip_changed_route &&
2226 (! (rinfo->flags & RIP_RTF_CHANGED)))
2227 continue;
2228
2229 /* Split horizon. */
2230 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002231 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002232 {
paul42d14d92003-11-17 09:15:18 +00002233 /*
2234 * We perform split horizon for RIP and connected route.
2235 * For rip routes, we want to suppress the route if we would
2236 * end up sending the route back on the interface that we
2237 * learned it from, with a higher metric. For connected routes,
2238 * we suppress the route if the prefix is a subset of the
2239 * source address that we are going to use for the packet
2240 * (in order to handle the case when multiple subnets are
2241 * configured on the same interface).
2242 */
2243 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2244 rinfo->ifindex == ifp->ifindex)
2245 continue;
2246 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002247 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002248 continue;
2249 }
2250
2251 /* Preparation for route-map. */
2252 rinfo->metric_set = 0;
2253 rinfo->nexthop_out.s_addr = 0;
2254 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002255 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002256 rinfo->ifindex_out = ifp->ifindex;
2257
hasso16705132003-05-25 14:49:19 +00002258 /* In order to avoid some local loops,
2259 * if the RIP route has a nexthop via this interface, keep the nexthop,
2260 * otherwise set it to 0. The nexthop should not be propagated
2261 * beyond the local broadcast/multicast area in order
2262 * to avoid an IGP multi-level recursive look-up.
2263 * see (4.4)
2264 */
2265 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002266 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002267
2268 /* Interface route-map */
2269 if (ri->routemap[RIP_FILTER_OUT])
2270 {
2271 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2272 (struct prefix *) p, RMAP_RIP,
2273 rinfo);
2274
2275 if (ret == RMAP_DENYMATCH)
2276 {
2277 if (IS_RIP_DEBUG_PACKET)
2278 zlog_info ("RIP %s/%d is filtered by route-map out",
2279 inet_ntoa (p->prefix), p->prefixlen);
2280 continue;
2281 }
2282 }
paul718e3742002-12-13 20:15:29 +00002283
hasso16705132003-05-25 14:49:19 +00002284 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002285 if (rip->route_map[rinfo->type].name
2286 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2287 {
2288 ret = route_map_apply (rip->route_map[rinfo->type].map,
2289 (struct prefix *)p, RMAP_RIP, rinfo);
2290
2291 if (ret == RMAP_DENYMATCH)
2292 {
2293 if (IS_RIP_DEBUG_PACKET)
2294 zlog_info ("%s/%d is filtered by route-map",
2295 inet_ntoa (p->prefix), p->prefixlen);
2296 continue;
2297 }
2298 }
2299
2300 /* When route-map does not set metric. */
2301 if (! rinfo->metric_set)
2302 {
2303 /* If redistribute metric is set. */
2304 if (rip->route_map[rinfo->type].metric_config
2305 && rinfo->metric != RIP_METRIC_INFINITY)
2306 {
2307 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2308 }
2309 else
2310 {
2311 /* If the route is not connected or localy generated
2312 one, use default-metric value*/
2313 if (rinfo->type != ZEBRA_ROUTE_RIP
2314 && rinfo->type != ZEBRA_ROUTE_CONNECT
2315 && rinfo->metric != RIP_METRIC_INFINITY)
2316 rinfo->metric_out = rip->default_metric;
2317 }
2318 }
2319
2320 /* Apply offset-list */
2321 if (rinfo->metric != RIP_METRIC_INFINITY)
2322 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2323
2324 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2325 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002326
2327 /* Perform split-horizon with poisoned reverse
2328 * for RIP and connected routes.
2329 **/
2330 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002331 /*
2332 * We perform split horizon for RIP and connected route.
2333 * For rip routes, we want to suppress the route if we would
2334 * end up sending the route back on the interface that we
2335 * learned it from, with a higher metric. For connected routes,
2336 * we suppress the route if the prefix is a subset of the
2337 * source address that we are going to use for the packet
2338 * (in order to handle the case when multiple subnets are
2339 * configured on the same interface).
2340 */
2341 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002342 rinfo->ifindex == ifp->ifindex)
2343 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002344 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2345 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2346 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002347 }
2348
paul718e3742002-12-13 20:15:29 +00002349 /* Write RTE to the stream. */
2350 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2351 if (num == rtemax)
2352 {
2353 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2354 rip_auth_md5_set (s, ifp);
2355
2356 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002357 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002358
2359 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2360 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2361 stream_get_endp(s), "SEND");
2362 num = 0;
2363 stream_reset (s);
2364 }
2365 }
2366
2367 /* Flush unwritten RTE. */
2368 if (num != 0)
2369 {
2370 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2371 rip_auth_md5_set (s, ifp);
2372
paul931cd542004-01-23 15:31:42 +00002373 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2374 connected);
paul718e3742002-12-13 20:15:29 +00002375
2376 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2377 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2378 stream_get_endp (s), "SEND");
2379 num = 0;
2380 stream_reset (s);
2381 }
2382
2383 /* Statistics updates. */
2384 ri->sent_updates++;
2385}
2386
2387/* Send RIP packet to the interface. */
2388void
paulcc1131a2003-10-15 23:20:17 +00002389rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002390 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002391{
2392 struct prefix_ipv4 *p;
2393 struct connected *connected;
2394 listnode node;
2395 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002396 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002397
2398 /* When RIP version is 2 and multicast enable interface. */
2399 if (version == RIPv2 && if_is_multicast (ifp))
2400 {
2401 if (IS_RIP_DEBUG_EVENT)
2402 zlog_info ("multicast announce on %s ", ifp->name);
2403
hassocaa6f8a2004-03-03 19:48:48 +00002404 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002405 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002406 return;
2407 }
2408
2409 /* If we can't send multicast packet, send it with unicast. */
2410 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2411 {
2412 for (node = listhead (ifp->connected); node; nextnode (node))
2413 {
2414 connected = getdata (node);
2415
2416 /* Fetch broadcast address or poin-to-point destination
2417 address . */
2418 p = (struct prefix_ipv4 *) connected->destination;
2419
2420 if (p->family == AF_INET)
2421 {
2422 /* Destination address and port setting. */
2423 memset (&to, 0, sizeof (struct sockaddr_in));
2424 to.sin_addr = p->prefix;
2425 to.sin_port = htons (RIP_PORT_DEFAULT);
2426
2427 if (IS_RIP_DEBUG_EVENT)
2428 zlog_info ("%s announce to %s on %s",
2429 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2430 inet_ntoa (to.sin_addr), ifp->name);
2431
paul727d1042002-12-13 20:50:29 +00002432 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002433 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002434 }
2435 }
2436 }
2437}
2438
2439/* Update send to all interface and neighbor. */
2440void
2441rip_update_process (int route_type)
2442{
paulcc1131a2003-10-15 23:20:17 +00002443 listnode node, ifnode;
2444 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002445 struct interface *ifp;
2446 struct rip_interface *ri;
2447 struct route_node *rp;
2448 struct sockaddr_in to;
2449 struct prefix_ipv4 *p;
2450
2451 /* Send RIP update to each interface. */
2452 for (node = listhead (iflist); node; nextnode (node))
2453 {
2454 ifp = getdata (node);
2455
2456 if (if_is_loopback (ifp))
2457 continue;
2458
paul2e3b2e42002-12-13 21:03:13 +00002459 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002460 continue;
2461
2462 /* Fetch RIP interface information. */
2463 ri = ifp->info;
2464
2465 /* When passive interface is specified, suppress announce to the
2466 interface. */
2467 if (ri->passive)
2468 continue;
2469
2470 if (ri->running)
2471 {
2472 if (IS_RIP_DEBUG_EVENT)
2473 {
2474 if (ifp->name)
2475 zlog_info ("SEND UPDATE to %s ifindex %d",
2476 ifp->name, ifp->ifindex);
2477 else
2478 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2479 ifp->ifindex);
2480 }
2481
paulcc1131a2003-10-15 23:20:17 +00002482 /* send update on each connected network */
2483
2484 LIST_LOOP(ifp->connected, connected, ifnode)
2485 {
2486 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002487 int done = 0;
2488 /*
2489 * If there is no version configuration in the interface,
2490 * use rip's version setting.
2491 */
paulf38a4712003-06-07 01:10:00 +00002492 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2493 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002494
2495 ifaddr = (struct prefix_ipv4 *) connected->address;
2496
2497 if (ifaddr->family != AF_INET)
2498 continue;
2499
paul931cd542004-01-23 15:31:42 +00002500 if ((vsend & RIPv1) && !done)
2501 rip_update_interface (ifp, RIPv1, route_type, connected);
2502 if ((vsend & RIPv2) && if_is_multicast(ifp))
2503 rip_update_interface (ifp, RIPv2, route_type, connected);
2504 done = 1;
2505 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2506 break;
2507
paulf38a4712003-06-07 01:10:00 +00002508 }
paul718e3742002-12-13 20:15:29 +00002509 }
2510 }
2511
2512 /* RIP send updates to each neighbor. */
2513 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2514 if (rp->info != NULL)
2515 {
2516 p = (struct prefix_ipv4 *) &rp->p;
2517
2518 ifp = if_lookup_address (p->prefix);
2519 if (! ifp)
2520 {
2521 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2522 inet_ntoa (p->prefix));
2523 continue;
2524 }
2525
2526 /* Set destination address and port */
2527 memset (&to, 0, sizeof (struct sockaddr_in));
2528 to.sin_addr = p->prefix;
2529 to.sin_port = htons (RIP_PORT_DEFAULT);
2530
2531 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002532 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2533 NULL, p);
paul718e3742002-12-13 20:15:29 +00002534 }
2535}
2536
2537/* RIP's periodical timer. */
2538int
2539rip_update (struct thread *t)
2540{
2541 /* Clear timer pointer. */
2542 rip->t_update = NULL;
2543
2544 if (IS_RIP_DEBUG_EVENT)
2545 zlog_info ("update timer fire!");
2546
2547 /* Process update output. */
2548 rip_update_process (rip_all_route);
2549
2550 /* Triggered updates may be suppressed if a regular update is due by
2551 the time the triggered update would be sent. */
2552 if (rip->t_triggered_interval)
2553 {
2554 thread_cancel (rip->t_triggered_interval);
2555 rip->t_triggered_interval = NULL;
2556 }
2557 rip->trigger = 0;
2558
2559 /* Register myself. */
2560 rip_event (RIP_UPDATE_EVENT, 0);
2561
2562 return 0;
2563}
2564
2565/* Walk down the RIP routing table then clear changed flag. */
2566void
2567rip_clear_changed_flag ()
2568{
2569 struct route_node *rp;
2570 struct rip_info *rinfo;
2571
2572 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2573 if ((rinfo = rp->info) != NULL)
2574 if (rinfo->flags & RIP_RTF_CHANGED)
2575 rinfo->flags &= ~RIP_RTF_CHANGED;
2576}
2577
2578/* Triggered update interval timer. */
2579int
2580rip_triggered_interval (struct thread *t)
2581{
2582 int rip_triggered_update (struct thread *);
2583
2584 rip->t_triggered_interval = NULL;
2585
2586 if (rip->trigger)
2587 {
2588 rip->trigger = 0;
2589 rip_triggered_update (t);
2590 }
2591 return 0;
2592}
2593
2594/* Execute triggered update. */
2595int
2596rip_triggered_update (struct thread *t)
2597{
2598 int interval;
2599
2600 /* Clear thred pointer. */
2601 rip->t_triggered_update = NULL;
2602
2603 /* Cancel interval timer. */
2604 if (rip->t_triggered_interval)
2605 {
2606 thread_cancel (rip->t_triggered_interval);
2607 rip->t_triggered_interval = NULL;
2608 }
2609 rip->trigger = 0;
2610
2611 /* Logging triggered update. */
2612 if (IS_RIP_DEBUG_EVENT)
2613 zlog_info ("triggered update!");
2614
2615 /* Split Horizon processing is done when generating triggered
2616 updates as well as normal updates (see section 2.6). */
2617 rip_update_process (rip_changed_route);
2618
2619 /* Once all of the triggered updates have been generated, the route
2620 change flags should be cleared. */
2621 rip_clear_changed_flag ();
2622
2623 /* After a triggered update is sent, a timer should be set for a
2624 random interval between 1 and 5 seconds. If other changes that
2625 would trigger updates occur before the timer expires, a single
2626 update is triggered when the timer expires. */
2627 interval = (random () % 5) + 1;
2628
2629 rip->t_triggered_interval =
2630 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2631
2632 return 0;
2633}
2634
2635/* Withdraw redistributed route. */
2636void
2637rip_redistribute_withdraw (int type)
2638{
2639 struct route_node *rp;
2640 struct rip_info *rinfo;
2641
2642 if (!rip)
2643 return;
2644
2645 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2646 if ((rinfo = rp->info) != NULL)
2647 {
2648 if (rinfo->type == type
2649 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2650 {
2651 /* Perform poisoned reverse. */
2652 rinfo->metric = RIP_METRIC_INFINITY;
2653 RIP_TIMER_ON (rinfo->t_garbage_collect,
2654 rip_garbage_collect, rip->garbage_time);
2655 RIP_TIMER_OFF (rinfo->t_timeout);
2656 rinfo->flags |= RIP_RTF_CHANGED;
2657
hasso16705132003-05-25 14:49:19 +00002658 if (IS_RIP_DEBUG_EVENT) {
2659 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2660
2661 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2662 inet_ntoa(p->prefix), p->prefixlen,
2663 ifindex2ifname(rinfo->ifindex));
2664 }
2665
paul718e3742002-12-13 20:15:29 +00002666 rip_event (RIP_TRIGGERED_UPDATE, 0);
2667 }
2668 }
2669}
2670
2671/* Create new RIP instance and set it to global variable. */
2672int
2673rip_create ()
2674{
2675 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2676 memset (rip, 0, sizeof (struct rip));
2677
2678 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002679 rip->version_send = RI_RIP_VERSION_2;
2680 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002681 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2682 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2683 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2684 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2685
2686 /* Initialize RIP routig table. */
2687 rip->table = route_table_init ();
2688 rip->route = route_table_init ();
2689 rip->neighbor = route_table_init ();
2690
2691 /* Make output stream. */
2692 rip->obuf = stream_new (1500);
2693
2694 /* Make socket. */
2695 rip->sock = rip_create_socket ();
2696 if (rip->sock < 0)
2697 return rip->sock;
2698
2699 /* Create read and timer thread. */
2700 rip_event (RIP_READ, rip->sock);
2701 rip_event (RIP_UPDATE_EVENT, 1);
2702
2703 return 0;
2704}
2705
2706/* Sned RIP request to the destination. */
2707int
2708rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002709 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002710{
2711 struct rte *rte;
2712 struct rip_packet rip_packet;
paulcc1131a2003-10-15 23:20:17 +00002713 listnode node;
paul718e3742002-12-13 20:15:29 +00002714
2715 memset (&rip_packet, 0, sizeof (rip_packet));
2716
2717 rip_packet.command = RIP_REQUEST;
2718 rip_packet.version = version;
2719 rte = rip_packet.rte;
2720 rte->metric = htonl (RIP_METRIC_INFINITY);
2721
paul931cd542004-01-23 15:31:42 +00002722 if (connected)
2723 {
2724 /*
2725 * connected is only sent for ripv1 case, or when
2726 * interface does not support multicast. Caller loops
2727 * over each connected address for this case.
2728 */
paul11dde9c2004-05-31 14:00:00 +00002729 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002730 to, ifp, connected) != sizeof (rip_packet))
2731 return -1;
2732 else
2733 return sizeof (rip_packet);
2734 }
2735
paulcc1131a2003-10-15 23:20:17 +00002736 /* send request on each connected network */
2737 LIST_LOOP(ifp->connected, connected, node)
2738 {
2739 struct prefix_ipv4 *p;
2740
2741 p = (struct prefix_ipv4 *) connected->address;
2742
2743 if (p->family != AF_INET)
2744 continue;
2745
paul11dde9c2004-05-31 14:00:00 +00002746 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002747 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002748 return -1;
2749 }
2750 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002751}
2752
2753int
2754rip_update_jitter (unsigned long time)
2755{
paul239389b2004-05-05 14:09:37 +00002756#define JITTER_BOUND 4
2757 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2758 Given that, we cannot let time be less than JITTER_BOUND seconds.
2759 The RIPv2 RFC says jitter should be small compared to
2760 update_time. We consider 1/JITTER_BOUND to be small.
2761 */
2762
2763 int jitter_input = time;
2764 int jitter;
2765
2766 if (jitter_input < JITTER_BOUND)
2767 jitter_input = JITTER_BOUND;
2768
2769 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2770
2771 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002772}
2773
2774void
2775rip_event (enum rip_event event, int sock)
2776{
2777 int jitter = 0;
2778
2779 switch (event)
2780 {
2781 case RIP_READ:
2782 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2783 break;
2784 case RIP_UPDATE_EVENT:
2785 if (rip->t_update)
2786 {
2787 thread_cancel (rip->t_update);
2788 rip->t_update = NULL;
2789 }
2790 jitter = rip_update_jitter (rip->update_time);
2791 rip->t_update =
2792 thread_add_timer (master, rip_update, NULL,
2793 sock ? 2 : rip->update_time + jitter);
2794 break;
2795 case RIP_TRIGGERED_UPDATE:
2796 if (rip->t_triggered_interval)
2797 rip->trigger = 1;
2798 else if (! rip->t_triggered_update)
2799 rip->t_triggered_update =
2800 thread_add_event (master, rip_triggered_update, NULL, 0);
2801 break;
2802 default:
2803 break;
2804 }
2805}
2806
2807DEFUN (router_rip,
2808 router_rip_cmd,
2809 "router rip",
2810 "Enable a routing process\n"
2811 "Routing Information Protocol (RIP)\n")
2812{
2813 int ret;
2814
2815 /* If rip is not enabled before. */
2816 if (! rip)
2817 {
2818 ret = rip_create ();
2819 if (ret < 0)
2820 {
2821 zlog_info ("Can't create RIP");
2822 return CMD_WARNING;
2823 }
2824 }
2825 vty->node = RIP_NODE;
2826 vty->index = rip;
2827
2828 return CMD_SUCCESS;
2829}
2830
2831DEFUN (no_router_rip,
2832 no_router_rip_cmd,
2833 "no router rip",
2834 NO_STR
2835 "Enable a routing process\n"
2836 "Routing Information Protocol (RIP)\n")
2837{
2838 if (rip)
2839 rip_clean ();
2840 return CMD_SUCCESS;
2841}
2842
2843DEFUN (rip_version,
2844 rip_version_cmd,
2845 "version <1-2>",
2846 "Set routing protocol version\n"
2847 "version\n")
2848{
2849 int version;
2850
2851 version = atoi (argv[0]);
2852 if (version != RIPv1 && version != RIPv2)
2853 {
2854 vty_out (vty, "invalid rip version %d%s", version,
2855 VTY_NEWLINE);
2856 return CMD_WARNING;
2857 }
paulf38a4712003-06-07 01:10:00 +00002858 rip->version_send = version;
2859 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002860
2861 return CMD_SUCCESS;
2862}
2863
2864DEFUN (no_rip_version,
2865 no_rip_version_cmd,
2866 "no version",
2867 NO_STR
2868 "Set routing protocol version\n")
2869{
2870 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002871 rip->version_send = RI_RIP_VERSION_2;
2872 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002873
2874 return CMD_SUCCESS;
2875}
2876
2877ALIAS (no_rip_version,
2878 no_rip_version_val_cmd,
2879 "no version <1-2>",
2880 NO_STR
2881 "Set routing protocol version\n"
2882 "version\n")
2883
2884DEFUN (rip_route,
2885 rip_route_cmd,
2886 "route A.B.C.D/M",
2887 "RIP static route configuration\n"
2888 "IP prefix <network>/<length>\n")
2889{
2890 int ret;
2891 struct prefix_ipv4 p;
2892 struct route_node *node;
2893
2894 ret = str2prefix_ipv4 (argv[0], &p);
2895 if (ret < 0)
2896 {
2897 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2898 return CMD_WARNING;
2899 }
2900 apply_mask_ipv4 (&p);
2901
2902 /* For router rip configuration. */
2903 node = route_node_get (rip->route, (struct prefix *) &p);
2904
2905 if (node->info)
2906 {
2907 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2908 route_unlock_node (node);
2909 return CMD_WARNING;
2910 }
2911
2912 node->info = "static";
2913
2914 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2915
2916 return CMD_SUCCESS;
2917}
2918
2919DEFUN (no_rip_route,
2920 no_rip_route_cmd,
2921 "no route A.B.C.D/M",
2922 NO_STR
2923 "RIP static route configuration\n"
2924 "IP prefix <network>/<length>\n")
2925{
2926 int ret;
2927 struct prefix_ipv4 p;
2928 struct route_node *node;
2929
2930 ret = str2prefix_ipv4 (argv[0], &p);
2931 if (ret < 0)
2932 {
2933 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2934 return CMD_WARNING;
2935 }
2936 apply_mask_ipv4 (&p);
2937
2938 /* For router rip configuration. */
2939 node = route_node_lookup (rip->route, (struct prefix *) &p);
2940 if (! node)
2941 {
2942 vty_out (vty, "Can't find route %s.%s", argv[0],
2943 VTY_NEWLINE);
2944 return CMD_WARNING;
2945 }
2946
2947 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2948 route_unlock_node (node);
2949
2950 node->info = NULL;
2951 route_unlock_node (node);
2952
2953 return CMD_SUCCESS;
2954}
2955
2956void
2957rip_update_default_metric ()
2958{
2959 struct route_node *np;
2960 struct rip_info *rinfo;
2961
2962 for (np = route_top (rip->table); np; np = route_next (np))
2963 if ((rinfo = np->info) != NULL)
2964 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2965 rinfo->metric = rip->default_metric;
2966}
2967
2968DEFUN (rip_default_metric,
2969 rip_default_metric_cmd,
2970 "default-metric <1-16>",
2971 "Set a metric of redistribute routes\n"
2972 "Default metric\n")
2973{
2974 if (rip)
2975 {
2976 rip->default_metric = atoi (argv[0]);
2977 /* rip_update_default_metric (); */
2978 }
2979 return CMD_SUCCESS;
2980}
2981
2982DEFUN (no_rip_default_metric,
2983 no_rip_default_metric_cmd,
2984 "no default-metric",
2985 NO_STR
2986 "Set a metric of redistribute routes\n"
2987 "Default metric\n")
2988{
2989 if (rip)
2990 {
2991 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2992 /* rip_update_default_metric (); */
2993 }
2994 return CMD_SUCCESS;
2995}
2996
2997ALIAS (no_rip_default_metric,
2998 no_rip_default_metric_val_cmd,
2999 "no default-metric <1-16>",
3000 NO_STR
3001 "Set a metric of redistribute routes\n"
3002 "Default metric\n")
3003
3004DEFUN (rip_timers,
3005 rip_timers_cmd,
3006 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3007 "Adjust routing timers\n"
3008 "Basic routing protocol update timers\n"
3009 "Routing table update timer value in second. Default is 30.\n"
3010 "Routing information timeout timer. Default is 180.\n"
3011 "Garbage collection timer. Default is 120.\n")
3012{
3013 unsigned long update;
3014 unsigned long timeout;
3015 unsigned long garbage;
3016 char *endptr = NULL;
3017 unsigned long RIP_TIMER_MAX = 2147483647;
3018 unsigned long RIP_TIMER_MIN = 5;
3019
3020 update = strtoul (argv[0], &endptr, 10);
3021 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3022 {
3023 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3024 return CMD_WARNING;
3025 }
3026
3027 timeout = strtoul (argv[1], &endptr, 10);
3028 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3029 {
3030 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033
3034 garbage = strtoul (argv[2], &endptr, 10);
3035 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3036 {
3037 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3038 return CMD_WARNING;
3039 }
3040
3041 /* Set each timer value. */
3042 rip->update_time = update;
3043 rip->timeout_time = timeout;
3044 rip->garbage_time = garbage;
3045
3046 /* Reset update timer thread. */
3047 rip_event (RIP_UPDATE_EVENT, 0);
3048
3049 return CMD_SUCCESS;
3050}
3051
3052DEFUN (no_rip_timers,
3053 no_rip_timers_cmd,
3054 "no timers basic",
3055 NO_STR
3056 "Adjust routing timers\n"
3057 "Basic routing protocol update timers\n")
3058{
3059 /* Set each timer value to the default. */
3060 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3061 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3062 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3063
3064 /* Reset update timer thread. */
3065 rip_event (RIP_UPDATE_EVENT, 0);
3066
3067 return CMD_SUCCESS;
3068}
hasso16705132003-05-25 14:49:19 +00003069
3070ALIAS (no_rip_timers,
3071 no_rip_timers_val_cmd,
3072 "no timers basic <0-65535> <0-65535> <0-65535>",
3073 NO_STR
3074 "Adjust routing timers\n"
3075 "Basic routing protocol update timers\n"
3076 "Routing table update timer value in second. Default is 30.\n"
3077 "Routing information timeout timer. Default is 180.\n"
3078 "Garbage collection timer. Default is 120.\n")
3079
paul718e3742002-12-13 20:15:29 +00003080
3081struct route_table *rip_distance_table;
3082
3083struct rip_distance
3084{
3085 /* Distance value for the IP source prefix. */
3086 u_char distance;
3087
3088 /* Name of the access-list to be matched. */
3089 char *access_list;
3090};
3091
3092struct rip_distance *
3093rip_distance_new ()
3094{
3095 struct rip_distance *new;
3096 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3097 memset (new, 0, sizeof (struct rip_distance));
3098 return new;
3099}
3100
3101void
3102rip_distance_free (struct rip_distance *rdistance)
3103{
3104 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3105}
3106
3107int
3108rip_distance_set (struct vty *vty, char *distance_str, char *ip_str,
3109 char *access_list_str)
3110{
3111 int ret;
3112 struct prefix_ipv4 p;
3113 u_char distance;
3114 struct route_node *rn;
3115 struct rip_distance *rdistance;
3116
3117 ret = str2prefix_ipv4 (ip_str, &p);
3118 if (ret == 0)
3119 {
3120 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3121 return CMD_WARNING;
3122 }
3123
3124 distance = atoi (distance_str);
3125
3126 /* Get RIP distance node. */
3127 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3128 if (rn->info)
3129 {
3130 rdistance = rn->info;
3131 route_unlock_node (rn);
3132 }
3133 else
3134 {
3135 rdistance = rip_distance_new ();
3136 rn->info = rdistance;
3137 }
3138
3139 /* Set distance value. */
3140 rdistance->distance = distance;
3141
3142 /* Reset access-list configuration. */
3143 if (rdistance->access_list)
3144 {
3145 free (rdistance->access_list);
3146 rdistance->access_list = NULL;
3147 }
3148 if (access_list_str)
3149 rdistance->access_list = strdup (access_list_str);
3150
3151 return CMD_SUCCESS;
3152}
3153
3154int
3155rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
3156 char *access_list_str)
3157{
3158 int ret;
3159 struct prefix_ipv4 p;
3160 u_char distance;
3161 struct route_node *rn;
3162 struct rip_distance *rdistance;
3163
3164 ret = str2prefix_ipv4 (ip_str, &p);
3165 if (ret == 0)
3166 {
3167 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3168 return CMD_WARNING;
3169 }
3170
3171 distance = atoi (distance_str);
3172
3173 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3174 if (! rn)
3175 {
3176 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3177 return CMD_WARNING;
3178 }
3179
3180 rdistance = rn->info;
3181
3182 if (rdistance->access_list)
3183 free (rdistance->access_list);
3184 rip_distance_free (rdistance);
3185
3186 rn->info = NULL;
3187 route_unlock_node (rn);
3188 route_unlock_node (rn);
3189
3190 return CMD_SUCCESS;
3191}
3192
3193void
3194rip_distance_reset ()
3195{
3196 struct route_node *rn;
3197 struct rip_distance *rdistance;
3198
3199 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3200 if ((rdistance = rn->info) != NULL)
3201 {
3202 if (rdistance->access_list)
3203 free (rdistance->access_list);
3204 rip_distance_free (rdistance);
3205 rn->info = NULL;
3206 route_unlock_node (rn);
3207 }
3208}
3209
3210/* Apply RIP information to distance method. */
3211u_char
3212rip_distance_apply (struct rip_info *rinfo)
3213{
3214 struct route_node *rn;
3215 struct prefix_ipv4 p;
3216 struct rip_distance *rdistance;
3217 struct access_list *alist;
3218
3219 if (! rip)
3220 return 0;
3221
3222 memset (&p, 0, sizeof (struct prefix_ipv4));
3223 p.family = AF_INET;
3224 p.prefix = rinfo->from;
3225 p.prefixlen = IPV4_MAX_BITLEN;
3226
3227 /* Check source address. */
3228 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3229 if (rn)
3230 {
3231 rdistance = rn->info;
3232 route_unlock_node (rn);
3233
3234 if (rdistance->access_list)
3235 {
3236 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3237 if (alist == NULL)
3238 return 0;
3239 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3240 return 0;
3241
3242 return rdistance->distance;
3243 }
3244 else
3245 return rdistance->distance;
3246 }
3247
3248 if (rip->distance)
3249 return rip->distance;
3250
3251 return 0;
3252}
3253
3254void
3255rip_distance_show (struct vty *vty)
3256{
3257 struct route_node *rn;
3258 struct rip_distance *rdistance;
3259 int header = 1;
3260 char buf[BUFSIZ];
3261
3262 vty_out (vty, " Distance: (default is %d)%s",
3263 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3264 VTY_NEWLINE);
3265
3266 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3267 if ((rdistance = rn->info) != NULL)
3268 {
3269 if (header)
3270 {
3271 vty_out (vty, " Address Distance List%s",
3272 VTY_NEWLINE);
3273 header = 0;
3274 }
3275 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3276 vty_out (vty, " %-20s %4d %s%s",
3277 buf, rdistance->distance,
3278 rdistance->access_list ? rdistance->access_list : "",
3279 VTY_NEWLINE);
3280 }
3281}
3282
3283DEFUN (rip_distance,
3284 rip_distance_cmd,
3285 "distance <1-255>",
3286 "Administrative distance\n"
3287 "Distance value\n")
3288{
3289 rip->distance = atoi (argv[0]);
3290 return CMD_SUCCESS;
3291}
3292
3293DEFUN (no_rip_distance,
3294 no_rip_distance_cmd,
3295 "no distance <1-255>",
3296 NO_STR
3297 "Administrative distance\n"
3298 "Distance value\n")
3299{
3300 rip->distance = 0;
3301 return CMD_SUCCESS;
3302}
3303
3304DEFUN (rip_distance_source,
3305 rip_distance_source_cmd,
3306 "distance <1-255> A.B.C.D/M",
3307 "Administrative distance\n"
3308 "Distance value\n"
3309 "IP source prefix\n")
3310{
3311 rip_distance_set (vty, argv[0], argv[1], NULL);
3312 return CMD_SUCCESS;
3313}
3314
3315DEFUN (no_rip_distance_source,
3316 no_rip_distance_source_cmd,
3317 "no distance <1-255> A.B.C.D/M",
3318 NO_STR
3319 "Administrative distance\n"
3320 "Distance value\n"
3321 "IP source prefix\n")
3322{
3323 rip_distance_unset (vty, argv[0], argv[1], NULL);
3324 return CMD_SUCCESS;
3325}
3326
3327DEFUN (rip_distance_source_access_list,
3328 rip_distance_source_access_list_cmd,
3329 "distance <1-255> A.B.C.D/M WORD",
3330 "Administrative distance\n"
3331 "Distance value\n"
3332 "IP source prefix\n"
3333 "Access list name\n")
3334{
3335 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3336 return CMD_SUCCESS;
3337}
3338
3339DEFUN (no_rip_distance_source_access_list,
3340 no_rip_distance_source_access_list_cmd,
3341 "no distance <1-255> A.B.C.D/M WORD",
3342 NO_STR
3343 "Administrative distance\n"
3344 "Distance value\n"
3345 "IP source prefix\n"
3346 "Access list name\n")
3347{
3348 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3349 return CMD_SUCCESS;
3350}
3351
3352/* Print out routes update time. */
3353void
3354rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3355{
3356 struct timeval timer_now;
3357 time_t clock;
3358 struct tm *tm;
3359#define TIME_BUF 25
3360 char timebuf [TIME_BUF];
3361 struct thread *thread;
3362
3363 gettimeofday (&timer_now, NULL);
3364
3365 if ((thread = rinfo->t_timeout) != NULL)
3366 {
3367 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3368 tm = gmtime (&clock);
3369 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3370 vty_out (vty, "%5s", timebuf);
3371 }
3372 else if ((thread = rinfo->t_garbage_collect) != NULL)
3373 {
3374 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3375 tm = gmtime (&clock);
3376 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3377 vty_out (vty, "%5s", timebuf);
3378 }
3379}
3380
3381char *
3382rip_route_type_print (int sub_type)
3383{
3384 switch (sub_type)
3385 {
3386 case RIP_ROUTE_RTE:
3387 return "n";
3388 case RIP_ROUTE_STATIC:
3389 return "s";
3390 case RIP_ROUTE_DEFAULT:
3391 return "d";
3392 case RIP_ROUTE_REDISTRIBUTE:
3393 return "r";
3394 case RIP_ROUTE_INTERFACE:
3395 return "i";
3396 default:
3397 return "?";
3398 }
3399}
3400
3401DEFUN (show_ip_rip,
3402 show_ip_rip_cmd,
3403 "show ip rip",
3404 SHOW_STR
3405 IP_STR
3406 "Show RIP routes\n")
3407{
3408 struct route_node *np;
3409 struct rip_info *rinfo;
3410
3411 if (! rip)
3412 return CMD_SUCCESS;
3413
hasso16705132003-05-25 14:49:19 +00003414 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3415 "Sub-codes:%s"
3416 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003417 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003418 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003419 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003420
3421 for (np = route_top (rip->table); np; np = route_next (np))
3422 if ((rinfo = np->info) != NULL)
3423 {
3424 int len;
3425
3426 len = vty_out (vty, "%s(%s) %s/%d",
3427 /* np->lock, For debugging. */
3428 route_info[rinfo->type].str,
3429 rip_route_type_print (rinfo->sub_type),
3430 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3431
hassoa1455d82004-03-03 19:36:24 +00003432 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003433
3434 if (len > 0)
3435 vty_out (vty, "%*s", len, " ");
3436
3437 if (rinfo->nexthop.s_addr)
3438 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3439 rinfo->metric);
3440 else
3441 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3442
3443 /* Route which exist in kernel routing table. */
3444 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3445 (rinfo->sub_type == RIP_ROUTE_RTE))
3446 {
3447 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003448 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003449 rip_vty_out_uptime (vty, rinfo);
3450 }
3451 else if (rinfo->metric == RIP_METRIC_INFINITY)
3452 {
3453 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003454 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003455 rip_vty_out_uptime (vty, rinfo);
3456 }
3457 else
hasso16705132003-05-25 14:49:19 +00003458 {
3459 vty_out (vty, "self ");
3460 vty_out (vty, "%3d", rinfo->tag);
3461 }
paul718e3742002-12-13 20:15:29 +00003462
3463 vty_out (vty, "%s", VTY_NEWLINE);
3464 }
3465 return CMD_SUCCESS;
3466}
3467
3468/* Return next event time. */
3469int
3470rip_next_thread_timer (struct thread *thread)
3471{
3472 struct timeval timer_now;
3473
3474 gettimeofday (&timer_now, NULL);
3475
3476 return thread->u.sands.tv_sec - timer_now.tv_sec;
3477}
3478
hasso16705132003-05-25 14:49:19 +00003479/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3480DEFUN (show_ip_rip_status,
3481 show_ip_rip_status_cmd,
3482 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003483 SHOW_STR
3484 IP_STR
hasso16705132003-05-25 14:49:19 +00003485 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003486 "IP routing protocol process parameters and statistics\n")
3487{
3488 listnode node;
3489 struct interface *ifp;
3490 struct rip_interface *ri;
3491 extern struct message ri_version_msg[];
3492 char *send_version;
3493 char *receive_version;
3494
3495 if (! rip)
3496 return CMD_SUCCESS;
3497
3498 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3499 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3500 rip->update_time);
3501 vty_out (vty, " next due in %d seconds%s",
3502 rip_next_thread_timer (rip->t_update),
3503 VTY_NEWLINE);
3504 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3505 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3506 VTY_NEWLINE);
3507
3508 /* Filtering status show. */
3509 config_show_distribute (vty);
3510
3511 /* Default metric information. */
3512 vty_out (vty, " Default redistribution metric is %d%s",
3513 rip->default_metric, VTY_NEWLINE);
3514
3515 /* Redistribute information. */
3516 vty_out (vty, " Redistributing:");
3517 config_write_rip_redistribute (vty, 0);
3518 vty_out (vty, "%s", VTY_NEWLINE);
3519
paulf38a4712003-06-07 01:10:00 +00003520 vty_out (vty, " Default version control: send version %s,",
3521 lookup(ri_version_msg,rip->version_send));
3522 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3523 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3524 else
3525 vty_out (vty, " receive version %s %s",
3526 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003527
3528 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3529
3530 for (node = listhead (iflist); node; node = nextnode (node))
3531 {
3532 ifp = getdata (node);
3533 ri = ifp->info;
3534
3535 if (ri->enable_network || ri->enable_interface)
3536 {
3537 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003538 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003539 else
3540 send_version = lookup (ri_version_msg, ri->ri_send);
3541
3542 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003543 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003544 else
3545 receive_version = lookup (ri_version_msg, ri->ri_receive);
3546
3547 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3548 send_version,
3549 receive_version,
3550 ri->key_chain ? ri->key_chain : "",
3551 VTY_NEWLINE);
3552 }
3553 }
3554
3555 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3556 config_write_rip_network (vty, 0);
3557
paul4aaff3f2003-06-07 01:04:45 +00003558 {
3559 int found_passive = 0;
3560 for (node = listhead (iflist); node; node = nextnode (node))
3561 {
3562 ifp = getdata (node);
3563 ri = ifp->info;
3564
3565 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3566 {
3567 if (!found_passive)
3568 {
3569 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3570 found_passive = 1;
3571 }
3572 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3573 }
3574 }
3575 }
3576
paul718e3742002-12-13 20:15:29 +00003577 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3578 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3579 rip_peer_display (vty);
3580
3581 rip_distance_show (vty);
3582
3583 return CMD_SUCCESS;
3584}
3585
3586/* RIP configuration write function. */
3587int
3588config_write_rip (struct vty *vty)
3589{
3590 int write = 0;
3591 struct route_node *rn;
3592 struct rip_distance *rdistance;
3593
3594 if (rip)
3595 {
3596 /* Router RIP statement. */
3597 vty_out (vty, "router rip%s", VTY_NEWLINE);
3598 write++;
3599
3600 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003601 if (rip->version_send != RI_RIP_VERSION_2
3602 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3603 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003604 VTY_NEWLINE);
3605
3606 /* RIP timer configuration. */
3607 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3608 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3609 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3610 vty_out (vty, " timers basic %lu %lu %lu%s",
3611 rip->update_time,
3612 rip->timeout_time,
3613 rip->garbage_time,
3614 VTY_NEWLINE);
3615
3616 /* Default information configuration. */
3617 if (rip->default_information)
3618 {
3619 if (rip->default_information_route_map)
3620 vty_out (vty, " default-information originate route-map %s%s",
3621 rip->default_information_route_map, VTY_NEWLINE);
3622 else
3623 vty_out (vty, " default-information originate%s",
3624 VTY_NEWLINE);
3625 }
3626
3627 /* Redistribute configuration. */
3628 config_write_rip_redistribute (vty, 1);
3629
3630 /* RIP offset-list configuration. */
3631 config_write_rip_offset_list (vty);
3632
3633 /* RIP enabled network and interface configuration. */
3634 config_write_rip_network (vty, 1);
3635
3636 /* RIP default metric configuration */
3637 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3638 vty_out (vty, " default-metric %d%s",
3639 rip->default_metric, VTY_NEWLINE);
3640
3641 /* Distribute configuration. */
3642 write += config_write_distribute (vty);
3643
hasso16705132003-05-25 14:49:19 +00003644 /* Interface routemap configuration */
3645 write += config_write_if_rmap (vty);
3646
paul718e3742002-12-13 20:15:29 +00003647 /* Distance configuration. */
3648 if (rip->distance)
3649 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3650
3651 /* RIP source IP prefix distance configuration. */
3652 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3653 if ((rdistance = rn->info) != NULL)
3654 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3655 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3656 rdistance->access_list ? rdistance->access_list : "",
3657 VTY_NEWLINE);
3658
3659 /* RIP static route configuration. */
3660 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3661 if (rn->info)
3662 vty_out (vty, " route %s/%d%s",
3663 inet_ntoa (rn->p.u.prefix4),
3664 rn->p.prefixlen,
3665 VTY_NEWLINE);
3666
3667 }
3668 return write;
3669}
3670
3671/* RIP node structure. */
3672struct cmd_node rip_node =
3673{
3674 RIP_NODE,
3675 "%s(config-router)# ",
3676 1
3677};
3678
3679/* Distribute-list update functions. */
3680void
3681rip_distribute_update (struct distribute *dist)
3682{
3683 struct interface *ifp;
3684 struct rip_interface *ri;
3685 struct access_list *alist;
3686 struct prefix_list *plist;
3687
3688 if (! dist->ifname)
3689 return;
3690
3691 ifp = if_lookup_by_name (dist->ifname);
3692 if (ifp == NULL)
3693 return;
3694
3695 ri = ifp->info;
3696
3697 if (dist->list[DISTRIBUTE_IN])
3698 {
3699 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3700 if (alist)
3701 ri->list[RIP_FILTER_IN] = alist;
3702 else
3703 ri->list[RIP_FILTER_IN] = NULL;
3704 }
3705 else
3706 ri->list[RIP_FILTER_IN] = NULL;
3707
3708 if (dist->list[DISTRIBUTE_OUT])
3709 {
3710 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3711 if (alist)
3712 ri->list[RIP_FILTER_OUT] = alist;
3713 else
3714 ri->list[RIP_FILTER_OUT] = NULL;
3715 }
3716 else
3717 ri->list[RIP_FILTER_OUT] = NULL;
3718
3719 if (dist->prefix[DISTRIBUTE_IN])
3720 {
3721 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3722 if (plist)
3723 ri->prefix[RIP_FILTER_IN] = plist;
3724 else
3725 ri->prefix[RIP_FILTER_IN] = NULL;
3726 }
3727 else
3728 ri->prefix[RIP_FILTER_IN] = NULL;
3729
3730 if (dist->prefix[DISTRIBUTE_OUT])
3731 {
3732 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3733 if (plist)
3734 ri->prefix[RIP_FILTER_OUT] = plist;
3735 else
3736 ri->prefix[RIP_FILTER_OUT] = NULL;
3737 }
3738 else
3739 ri->prefix[RIP_FILTER_OUT] = NULL;
3740}
3741
3742void
3743rip_distribute_update_interface (struct interface *ifp)
3744{
3745 struct distribute *dist;
3746
3747 dist = distribute_lookup (ifp->name);
3748 if (dist)
3749 rip_distribute_update (dist);
3750}
3751
3752/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003753/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003754void
paul02ff83c2004-06-11 11:27:03 +00003755rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003756{
3757 struct interface *ifp;
3758 listnode node;
3759
3760 for (node = listhead (iflist); node; nextnode (node))
3761 {
3762 ifp = getdata (node);
3763 rip_distribute_update_interface (ifp);
3764 }
3765}
paul11dde9c2004-05-31 14:00:00 +00003766/* ARGSUSED */
3767void
3768rip_distribute_update_all_wrapper(struct access_list *notused)
3769{
paul02ff83c2004-06-11 11:27:03 +00003770 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003771}
paul718e3742002-12-13 20:15:29 +00003772
3773/* Delete all added rip route. */
3774void
3775rip_clean ()
3776{
3777 int i;
3778 struct route_node *rp;
3779 struct rip_info *rinfo;
3780
3781 if (rip)
3782 {
3783 /* Clear RIP routes */
3784 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3785 if ((rinfo = rp->info) != NULL)
3786 {
3787 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3788 rinfo->sub_type == RIP_ROUTE_RTE)
3789 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3790 &rinfo->nexthop, rinfo->metric);
3791
3792 RIP_TIMER_OFF (rinfo->t_timeout);
3793 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3794
3795 rp->info = NULL;
3796 route_unlock_node (rp);
3797
3798 rip_info_free (rinfo);
3799 }
3800
3801 /* Cancel RIP related timers. */
3802 RIP_TIMER_OFF (rip->t_update);
3803 RIP_TIMER_OFF (rip->t_triggered_update);
3804 RIP_TIMER_OFF (rip->t_triggered_interval);
3805
3806 /* Cancel read thread. */
3807 if (rip->t_read)
3808 {
3809 thread_cancel (rip->t_read);
3810 rip->t_read = NULL;
3811 }
3812
3813 /* Close RIP socket. */
3814 if (rip->sock >= 0)
3815 {
3816 close (rip->sock);
3817 rip->sock = -1;
3818 }
3819
3820 /* Static RIP route configuration. */
3821 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3822 if (rp->info)
3823 {
3824 rp->info = NULL;
3825 route_unlock_node (rp);
3826 }
3827
3828 /* RIP neighbor configuration. */
3829 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3830 if (rp->info)
3831 {
3832 rp->info = NULL;
3833 route_unlock_node (rp);
3834 }
3835
3836 /* Redistribute related clear. */
3837 if (rip->default_information_route_map)
3838 free (rip->default_information_route_map);
3839
3840 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3841 if (rip->route_map[i].name)
3842 free (rip->route_map[i].name);
3843
3844 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3845 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3846 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3847
3848 XFREE (MTYPE_RIP, rip);
3849 rip = NULL;
3850 }
3851
3852 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003853 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003854 rip_offset_clean ();
3855 rip_interface_clean ();
3856 rip_distance_reset ();
3857 rip_redistribute_clean ();
3858}
3859
3860/* Reset all values to the default settings. */
3861void
3862rip_reset ()
3863{
3864 /* Reset global counters. */
3865 rip_global_route_changes = 0;
3866 rip_global_queries = 0;
3867
3868 /* Call ripd related reset functions. */
3869 rip_debug_reset ();
3870 rip_route_map_reset ();
3871
3872 /* Call library reset functions. */
3873 vty_reset ();
3874 access_list_reset ();
3875 prefix_list_reset ();
3876
3877 distribute_list_reset ();
3878
3879 rip_interface_reset ();
3880 rip_distance_reset ();
3881
3882 rip_zclient_reset ();
3883}
3884
hasso16705132003-05-25 14:49:19 +00003885void
3886rip_if_rmap_update (struct if_rmap *if_rmap)
3887{
3888 struct interface *ifp;
3889 struct rip_interface *ri;
3890 struct route_map *rmap;
3891
3892 ifp = if_lookup_by_name (if_rmap->ifname);
3893 if (ifp == NULL)
3894 return;
3895
3896 ri = ifp->info;
3897
3898 if (if_rmap->routemap[IF_RMAP_IN])
3899 {
3900 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3901 if (rmap)
3902 ri->routemap[IF_RMAP_IN] = rmap;
3903 else
3904 ri->routemap[IF_RMAP_IN] = NULL;
3905 }
3906 else
3907 ri->routemap[RIP_FILTER_IN] = NULL;
3908
3909 if (if_rmap->routemap[IF_RMAP_OUT])
3910 {
3911 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3912 if (rmap)
3913 ri->routemap[IF_RMAP_OUT] = rmap;
3914 else
3915 ri->routemap[IF_RMAP_OUT] = NULL;
3916 }
3917 else
3918 ri->routemap[RIP_FILTER_OUT] = NULL;
3919}
3920
3921void
3922rip_if_rmap_update_interface (struct interface *ifp)
3923{
3924 struct if_rmap *if_rmap;
3925
3926 if_rmap = if_rmap_lookup (ifp->name);
3927 if (if_rmap)
3928 rip_if_rmap_update (if_rmap);
3929}
3930
3931void
3932rip_routemap_update_redistribute (void)
3933{
3934 int i;
3935
3936 if (rip)
3937 {
3938 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3939 {
3940 if (rip->route_map[i].name)
3941 rip->route_map[i].map =
3942 route_map_lookup_by_name (rip->route_map[i].name);
3943 }
3944 }
3945}
3946
paul11dde9c2004-05-31 14:00:00 +00003947/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003948void
paul11dde9c2004-05-31 14:00:00 +00003949rip_routemap_update (char *notused)
hasso16705132003-05-25 14:49:19 +00003950{
3951 struct interface *ifp;
3952 listnode node;
3953
3954 for (node = listhead (iflist); node; nextnode (node))
3955 {
3956 ifp = getdata (node);
3957 rip_if_rmap_update_interface (ifp);
3958 }
3959
3960 rip_routemap_update_redistribute ();
3961}
3962
paul718e3742002-12-13 20:15:29 +00003963/* Allocate new rip structure and set default value. */
3964void
3965rip_init ()
3966{
3967 /* Randomize for triggered update random(). */
3968 srand (time (NULL));
3969
3970 /* Install top nodes. */
3971 install_node (&rip_node, config_write_rip);
3972
3973 /* Install rip commands. */
3974 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003975 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003976 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003977 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003978 install_element (CONFIG_NODE, &router_rip_cmd);
3979 install_element (CONFIG_NODE, &no_router_rip_cmd);
3980
3981 install_default (RIP_NODE);
3982 install_element (RIP_NODE, &rip_version_cmd);
3983 install_element (RIP_NODE, &no_rip_version_cmd);
3984 install_element (RIP_NODE, &no_rip_version_val_cmd);
3985 install_element (RIP_NODE, &rip_default_metric_cmd);
3986 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3987 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3988 install_element (RIP_NODE, &rip_timers_cmd);
3989 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003990 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003991 install_element (RIP_NODE, &rip_route_cmd);
3992 install_element (RIP_NODE, &no_rip_route_cmd);
3993 install_element (RIP_NODE, &rip_distance_cmd);
3994 install_element (RIP_NODE, &no_rip_distance_cmd);
3995 install_element (RIP_NODE, &rip_distance_source_cmd);
3996 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3997 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3998 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3999
4000 /* Debug related init. */
4001 rip_debug_init ();
4002
paul718e3742002-12-13 20:15:29 +00004003 /* SNMP init. */
4004#ifdef HAVE_SNMP
4005 rip_snmp_init ();
4006#endif /* HAVE_SNMP */
4007
4008 /* Access list install. */
4009 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004010 access_list_add_hook (rip_distribute_update_all_wrapper);
4011 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004012
4013 /* Prefix list initialize.*/
4014 prefix_list_init ();
4015 prefix_list_add_hook (rip_distribute_update_all);
4016 prefix_list_delete_hook (rip_distribute_update_all);
4017
4018 /* Distribute list install. */
4019 distribute_list_init (RIP_NODE);
4020 distribute_list_add_hook (rip_distribute_update);
4021 distribute_list_delete_hook (rip_distribute_update);
4022
hasso16705132003-05-25 14:49:19 +00004023 /* Route-map */
4024 rip_route_map_init ();
4025 rip_offset_init ();
4026
4027 route_map_add_hook (rip_routemap_update);
4028 route_map_delete_hook (rip_routemap_update);
4029
4030 if_rmap_init (RIP_NODE);
4031 if_rmap_hook_add (rip_if_rmap_update);
4032 if_rmap_hook_delete (rip_if_rmap_update);
4033
paul718e3742002-12-13 20:15:29 +00004034 /* Distance control. */
4035 rip_distance_table = route_table_init ();
4036}