blob: 2b4e1b2f79e15ba1efa3da43f72b2616b3e9329d [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "if.h"
25#include "command.h"
26#include "prefix.h"
27#include "table.h"
28#include "thread.h"
29#include "memory.h"
30#include "log.h"
31#include "stream.h"
32#include "filter.h"
33#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000034#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000035#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000036#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000037#include "plist.h"
38#include "distribute.h"
39#include "md5-gnu.h"
40#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000041#include "privs.h"
paul718e3742002-12-13 20:15:29 +000042
43#include "ripd/ripd.h"
44#include "ripd/rip_debug.h"
45
paul0b3acf42004-09-17 08:39:08 +000046/* UDP receive buffer size */
47#define RIP_UDP_RCV_BUF 41600
48
49/* privileges global */
pauledd7c242003-06-04 13:59:38 +000050extern struct zebra_privs_t ripd_privs;
51
paul718e3742002-12-13 20:15:29 +000052/* RIP Structure. */
53struct rip *rip = NULL;
54
55/* RIP neighbor address table. */
56struct route_table *rip_neighbor_table;
57
58/* RIP route changes. */
59long rip_global_route_changes = 0;
60
61/* RIP queries. */
62long rip_global_queries = 0;
63
64/* Prototypes. */
65void rip_event (enum rip_event, int);
66
paul727d1042002-12-13 20:50:29 +000067void rip_output_process (struct interface *, struct prefix *,
paulcc1131a2003-10-15 23:20:17 +000068 struct sockaddr_in *, int, u_char,
paul931cd542004-01-23 15:31:42 +000069 struct connected *, struct prefix_ipv4 *);
paul718e3742002-12-13 20:15:29 +000070
71/* RIP output routes type. */
72enum
73{
74 rip_all_route,
75 rip_changed_route
76};
77
78/* RIP command strings. */
79struct message rip_msg[] =
80{
81 {RIP_REQUEST, "REQUEST"},
82 {RIP_RESPONSE, "RESPONSE"},
83 {RIP_TRACEON, "TRACEON"},
84 {RIP_TRACEOFF, "TRACEOFF"},
85 {RIP_POLL, "POLL"},
86 {RIP_POLL_ENTRY, "POLL ENTRY"},
87 {0, NULL}
88};
89
90/* Each route type's strings and default preference. */
91struct
92{
93 int key;
hasso8a676be2004-10-08 06:36:38 +000094 const char *str;
95 const char *str_long;
paul718e3742002-12-13 20:15:29 +000096} route_info[] =
97{
98 { ZEBRA_ROUTE_SYSTEM, "X", "system"},
99 { ZEBRA_ROUTE_KERNEL, "K", "kernel"},
100 { ZEBRA_ROUTE_CONNECT, "C", "connected"},
101 { ZEBRA_ROUTE_STATIC, "S", "static"},
102 { ZEBRA_ROUTE_RIP, "R", "rip"},
103 { ZEBRA_ROUTE_RIPNG, "R", "ripng"},
104 { ZEBRA_ROUTE_OSPF, "O", "ospf"},
105 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"},
hasso8a676be2004-10-08 06:36:38 +0000106 { ZEBRA_ROUTE_ISIS, "I", "isis"},
paul718e3742002-12-13 20:15:29 +0000107 { ZEBRA_ROUTE_BGP, "B", "bgp"}
108};
109
110/* Utility function to set boradcast option to the socket. */
111int
112sockopt_broadcast (int sock)
113{
114 int ret;
115 int on = 1;
116
117 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
118 if (ret < 0)
119 {
120 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
121 return -1;
122 }
123 return 0;
124}
125
126int
127rip_route_rte (struct rip_info *rinfo)
128{
129 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
130}
131
132struct rip_info *
133rip_info_new ()
134{
135 struct rip_info *new;
136
137 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
138 memset (new, 0, sizeof (struct rip_info));
139 return new;
140}
141
142void
143rip_info_free (struct rip_info *rinfo)
144{
145 XFREE (MTYPE_RIP_INFO, rinfo);
146}
147
148/* RIP route garbage collect timer. */
149int
150rip_garbage_collect (struct thread *t)
151{
152 struct rip_info *rinfo;
153 struct route_node *rp;
154
155 rinfo = THREAD_ARG (t);
156 rinfo->t_garbage_collect = NULL;
157
158 /* Off timeout timer. */
159 RIP_TIMER_OFF (rinfo->t_timeout);
160
161 /* Get route_node pointer. */
162 rp = rinfo->rp;
163
164 /* Unlock route_node. */
165 rp->info = NULL;
166 route_unlock_node (rp);
167
168 /* Free RIP routing information. */
169 rip_info_free (rinfo);
170
171 return 0;
172}
173
174/* Timeout RIP routes. */
175int
176rip_timeout (struct thread *t)
177{
178 struct rip_info *rinfo;
179 struct route_node *rn;
180
181 rinfo = THREAD_ARG (t);
182 rinfo->t_timeout = NULL;
183
184 rn = rinfo->rp;
185
186 /* - The garbage-collection timer is set for 120 seconds. */
187 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
188 rip->garbage_time);
189
190 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
191 rinfo->metric);
192 /* - The metric for the route is set to 16 (infinity). This causes
193 the route to be removed from service. */
194 rinfo->metric = RIP_METRIC_INFINITY;
195 rinfo->flags &= ~RIP_RTF_FIB;
196
197 /* - The route change flag is to indicate that this entry has been
198 changed. */
199 rinfo->flags |= RIP_RTF_CHANGED;
200
201 /* - The output process is signalled to trigger a response. */
202 rip_event (RIP_TRIGGERED_UPDATE, 0);
203
204 return 0;
205}
206
207void
208rip_timeout_update (struct rip_info *rinfo)
209{
210 if (rinfo->metric != RIP_METRIC_INFINITY)
211 {
212 RIP_TIMER_OFF (rinfo->t_timeout);
213 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
214 }
215}
216
217int
218rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
219{
220 struct distribute *dist;
221 struct access_list *alist;
222 struct prefix_list *plist;
223
224 /* Input distribute-list filtering. */
225 if (ri->list[RIP_FILTER_IN])
226 {
227 if (access_list_apply (ri->list[RIP_FILTER_IN],
228 (struct prefix *) p) == FILTER_DENY)
229 {
230 if (IS_RIP_DEBUG_PACKET)
231 zlog_info ("%s/%d filtered by distribute in",
232 inet_ntoa (p->prefix), p->prefixlen);
233 return -1;
234 }
235 }
236 if (ri->prefix[RIP_FILTER_IN])
237 {
238 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
239 (struct prefix *) p) == PREFIX_DENY)
240 {
241 if (IS_RIP_DEBUG_PACKET)
242 zlog_info ("%s/%d filtered by prefix-list in",
243 inet_ntoa (p->prefix), p->prefixlen);
244 return -1;
245 }
246 }
247
248 /* All interface filter check. */
249 dist = distribute_lookup (NULL);
250 if (dist)
251 {
252 if (dist->list[DISTRIBUTE_IN])
253 {
254 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
255
256 if (alist)
257 {
258 if (access_list_apply (alist,
259 (struct prefix *) p) == FILTER_DENY)
260 {
261 if (IS_RIP_DEBUG_PACKET)
262 zlog_info ("%s/%d filtered by distribute in",
263 inet_ntoa (p->prefix), p->prefixlen);
264 return -1;
265 }
266 }
267 }
268 if (dist->prefix[DISTRIBUTE_IN])
269 {
270 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
271
272 if (plist)
273 {
274 if (prefix_list_apply (plist,
275 (struct prefix *) p) == PREFIX_DENY)
276 {
277 if (IS_RIP_DEBUG_PACKET)
278 zlog_info ("%s/%d filtered by prefix-list in",
279 inet_ntoa (p->prefix), p->prefixlen);
280 return -1;
281 }
282 }
283 }
284 }
285 return 0;
286}
287
288int
289rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
290{
291 struct distribute *dist;
292 struct access_list *alist;
293 struct prefix_list *plist;
294
295 if (ri->list[RIP_FILTER_OUT])
296 {
297 if (access_list_apply (ri->list[RIP_FILTER_OUT],
298 (struct prefix *) p) == FILTER_DENY)
299 {
300 if (IS_RIP_DEBUG_PACKET)
301 zlog_info ("%s/%d is filtered by distribute out",
302 inet_ntoa (p->prefix), p->prefixlen);
303 return -1;
304 }
305 }
306 if (ri->prefix[RIP_FILTER_OUT])
307 {
308 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
309 (struct prefix *) p) == PREFIX_DENY)
310 {
311 if (IS_RIP_DEBUG_PACKET)
312 zlog_info ("%s/%d is filtered by prefix-list out",
313 inet_ntoa (p->prefix), p->prefixlen);
314 return -1;
315 }
316 }
317
318 /* All interface filter check. */
319 dist = distribute_lookup (NULL);
320 if (dist)
321 {
322 if (dist->list[DISTRIBUTE_OUT])
323 {
324 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
325
326 if (alist)
327 {
328 if (access_list_apply (alist,
329 (struct prefix *) p) == FILTER_DENY)
330 {
331 if (IS_RIP_DEBUG_PACKET)
332 zlog_info ("%s/%d filtered by distribute out",
333 inet_ntoa (p->prefix), p->prefixlen);
334 return -1;
335 }
336 }
337 }
338 if (dist->prefix[DISTRIBUTE_OUT])
339 {
340 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
341
342 if (plist)
343 {
344 if (prefix_list_apply (plist,
345 (struct prefix *) p) == PREFIX_DENY)
346 {
347 if (IS_RIP_DEBUG_PACKET)
348 zlog_info ("%s/%d filtered by prefix-list out",
349 inet_ntoa (p->prefix), p->prefixlen);
350 return -1;
351 }
352 }
353 }
354 }
355 return 0;
356}
357
358/* Check nexthop address validity. */
359static int
360rip_nexthop_check (struct in_addr *addr)
361{
hasso52dc7ee2004-09-23 19:18:23 +0000362 struct listnode *node;
363 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000364 struct interface *ifp;
365 struct connected *ifc;
366 struct prefix *p;
367
368 /* If nexthop address matches local configured address then it is
369 invalid nexthop. */
370 for (node = listhead (iflist); node; nextnode (node))
371 {
372 ifp = getdata (node);
373
374 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
375 {
376 ifc = getdata (cnode);
377 p = ifc->address;
378
379 if (p->family == AF_INET
380 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
381 return -1;
382 }
383 }
384 return 0;
385}
386
387/* RIP add route to routing table. */
388void
389rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000390 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000391{
392 int ret;
393 struct prefix_ipv4 p;
394 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000395 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000396 struct rip_interface *ri;
397 struct in_addr *nexthop;
398 u_char oldmetric;
399 int same = 0;
400
401 /* Make prefix structure. */
402 memset (&p, 0, sizeof (struct prefix_ipv4));
403 p.family = AF_INET;
404 p.prefix = rte->prefix;
405 p.prefixlen = ip_masklen (rte->mask);
406
407 /* Make sure mask is applied. */
408 apply_mask_ipv4 (&p);
409
410 /* Apply input filters. */
411 ri = ifp->info;
412
413 ret = rip_incoming_filter (&p, ri);
414 if (ret < 0)
415 return;
416
hasso16705132003-05-25 14:49:19 +0000417 /* Modify entry according to the interface routemap. */
418 if (ri->routemap[RIP_FILTER_IN])
419 {
420 int ret;
421 struct rip_info newinfo;
422
423 memset (&newinfo, 0, sizeof (newinfo));
424 newinfo.type = ZEBRA_ROUTE_RIP;
425 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000426 newinfo.nexthop = rte->nexthop;
427 newinfo.from = from->sin_addr;
428 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000429 newinfo.metric = rte->metric;
430 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000431 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000432
433 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000434 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
435 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000436
437 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000438 {
439 if (IS_RIP_DEBUG_PACKET)
440 zlog_info ("RIP %s/%d is filtered by route-map in",
441 inet_ntoa (p.prefix), p.prefixlen);
442 return;
443 }
hasso16705132003-05-25 14:49:19 +0000444
445 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000446 rte->nexthop = newinfo.nexthop_out;
447 rte->tag = htons (newinfo.tag_out); /* XXX */
448 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000449 }
450
paul718e3742002-12-13 20:15:29 +0000451 /* Once the entry has been validated, update the metric by
452 adding the cost of the network on wich the message
453 arrived. If the result is greater than infinity, use infinity
454 (RFC2453 Sec. 3.9.2) */
455 /* Zebra ripd can handle offset-list in. */
456 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
457
458 /* If offset-list does not modify the metric use interface's
459 metric. */
paula87552c2004-05-03 20:00:17 +0000460 if (!ret)
paul718e3742002-12-13 20:15:29 +0000461 rte->metric += ifp->metric;
462
463 if (rte->metric > RIP_METRIC_INFINITY)
464 rte->metric = RIP_METRIC_INFINITY;
465
466 /* Set nexthop pointer. */
467 if (rte->nexthop.s_addr == 0)
468 nexthop = &from->sin_addr;
469 else
470 nexthop = &rte->nexthop;
471
hasso16705132003-05-25 14:49:19 +0000472 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000473 if (rip_nexthop_check (nexthop) < 0)
474 {
475 if (IS_RIP_DEBUG_PACKET)
paula87552c2004-05-03 20:00:17 +0000476 zlog_info ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000477 return;
478 }
479
480 /* Get index for the prefix. */
481 rp = route_node_get (rip->table, (struct prefix *) &p);
482
483 /* Check to see whether there is already RIP route on the table. */
484 rinfo = rp->info;
485
486 if (rinfo)
487 {
488 /* Redistributed route check. */
489 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000490 && rinfo->metric != RIP_METRIC_INFINITY)
491 return;
paul718e3742002-12-13 20:15:29 +0000492
493 /* Local static route. */
494 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000495 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
496 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
497 && rinfo->metric != RIP_METRIC_INFINITY)
498 return;
paul718e3742002-12-13 20:15:29 +0000499 }
paula87552c2004-05-03 20:00:17 +0000500
501 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000502 {
503 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000504 for the destination prefix. If there is no such route, add
505 this route to the routing table, unless the metric is
506 infinity (there is no point in adding a route which
507 unusable). */
paul718e3742002-12-13 20:15:29 +0000508 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000509 {
510 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000511
paula87552c2004-05-03 20:00:17 +0000512 /* - Setting the destination prefix and length to those in
513 the RTE. */
514 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000515
paula87552c2004-05-03 20:00:17 +0000516 /* - Setting the metric to the newly calculated metric (as
517 described above). */
518 rinfo->metric = rte->metric;
519 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000520
paula87552c2004-05-03 20:00:17 +0000521 /* - Set the next hop address to be the address of the router
522 from which the datagram came or the next hop address
523 specified by a next hop RTE. */
524 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
525 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
526 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000527
paula87552c2004-05-03 20:00:17 +0000528 /* - Initialize the timeout for the route. If the
529 garbage-collection timer is running for this route, stop it
530 (see section 2.3 for a discussion of the timers). */
531 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000532
paula87552c2004-05-03 20:00:17 +0000533 /* - Set the route change flag. */
534 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000535
paula87552c2004-05-03 20:00:17 +0000536 /* - Signal the output process to trigger an update (see section
537 2.5). */
538 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000539
paula87552c2004-05-03 20:00:17 +0000540 /* Finally, route goes into the kernel. */
541 rinfo->type = ZEBRA_ROUTE_RIP;
542 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000543
paula87552c2004-05-03 20:00:17 +0000544 /* Set distance value. */
545 rinfo->distance = rip_distance_apply (rinfo);
546
547 rp->info = rinfo;
548 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
549 rinfo->distance);
550 rinfo->flags |= RIP_RTF_FIB;
551 }
paul718e3742002-12-13 20:15:29 +0000552 }
553 else
554 {
555 /* Route is there but we are not sure the route is RIP or not. */
556 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000557
paul718e3742002-12-13 20:15:29 +0000558 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000559 to the address of the router from which the datagram came.
560 If this datagram is from the same router as the existing
561 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000562 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000563 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000564
565 if (same)
paula87552c2004-05-03 20:00:17 +0000566 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000567
paulb94f9db2004-05-01 20:45:38 +0000568
569 /* Fill in a minimaly temporary rip_info structure, for a future
570 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000571 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000572 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000573 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000574
575
paul718e3742002-12-13 20:15:29 +0000576 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000577 router as the existing route, and the new metric is different
578 than the old one; or, if the new metric is lower than the old
579 one, or if the tag has been changed; or if there is a route
580 with a lower administrave distance; or an update of the
581 distance on the actual route; do the following actions: */
582 if ((same && rinfo->metric != rte->metric)
583 || (rte->metric < rinfo->metric)
584 || ((same)
585 && (rinfo->metric == rte->metric)
586 && ntohs (rte->tag) != rinfo->tag)
587 || (rinfo->distance > rip_distance_apply (&rinfotmp))
588 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
589 {
590 /* - Adopt the route from the datagram. That is, put the
591 new metric in, and adjust the next hop address (if
592 necessary). */
593 oldmetric = rinfo->metric;
594 rinfo->metric = rte->metric;
595 rinfo->tag = ntohs (rte->tag);
596 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
597 rinfo->ifindex = ifp->ifindex;
598 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000599
paula87552c2004-05-03 20:00:17 +0000600 /* Should a new route to this network be established
601 while the garbage-collection timer is running, the
602 new route will replace the one that is about to be
603 deleted. In this case the garbage-collection timer
604 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000605
paula87552c2004-05-03 20:00:17 +0000606 if (oldmetric == RIP_METRIC_INFINITY &&
607 rinfo->metric < RIP_METRIC_INFINITY)
608 {
609 rinfo->type = ZEBRA_ROUTE_RIP;
610 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000613
paula87552c2004-05-03 20:00:17 +0000614 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
615 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000616
paula87552c2004-05-03 20:00:17 +0000617 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
618 rinfo->distance);
619 rinfo->flags |= RIP_RTF_FIB;
620 }
paul718e3742002-12-13 20:15:29 +0000621
paula87552c2004-05-03 20:00:17 +0000622 /* Update nexthop and/or metric value. */
623 if (oldmetric != RIP_METRIC_INFINITY)
624 {
625 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
626 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
627 rinfo->distance);
628 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000629
paula87552c2004-05-03 20:00:17 +0000630 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
631 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
632 }
paul718e3742002-12-13 20:15:29 +0000633
paula87552c2004-05-03 20:00:17 +0000634 /* - Set the route change flag and signal the output process
635 to trigger an update. */
636 rinfo->flags |= RIP_RTF_CHANGED;
637 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000638
paula87552c2004-05-03 20:00:17 +0000639 /* - If the new metric is infinity, start the deletion
640 process (described above); */
641 if (rinfo->metric == RIP_METRIC_INFINITY)
642 {
643 /* If the new metric is infinity, the deletion process
644 begins for the route, which is no longer used for
645 routing packets. Note that the deletion process is
646 started only when the metric is first set to
647 infinity. If the metric was already infinity, then a
648 new deletion process is not started. */
649 if (oldmetric != RIP_METRIC_INFINITY)
650 {
651 /* - The garbage-collection timer is set for 120 seconds. */
652 RIP_TIMER_ON (rinfo->t_garbage_collect,
653 rip_garbage_collect, rip->garbage_time);
654 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000655
paula87552c2004-05-03 20:00:17 +0000656 /* - The metric for the route is set to 16
657 (infinity). This causes the route to be removed
658 from service. */
659 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
660 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000661
paula87552c2004-05-03 20:00:17 +0000662 /* - The route change flag is to indicate that this
663 entry has been changed. */
664 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000665 response. */
paula87552c2004-05-03 20:00:17 +0000666 ; /* Above processes are already done previously. */
667 }
668 }
669 else
670 {
671 /* otherwise, re-initialize the timeout. */
672 rip_timeout_update (rinfo);
673 }
674 }
paul718e3742002-12-13 20:15:29 +0000675 /* Unlock tempolary lock of the route. */
676 route_unlock_node (rp);
677 }
678}
679
680/* Dump RIP packet */
681void
hasso8a676be2004-10-08 06:36:38 +0000682rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000683{
684 caddr_t lim;
685 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000686 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000687 char pbuf[BUFSIZ], nbuf[BUFSIZ];
688 u_char netmask = 0;
689 u_char *p;
690
691 /* Set command string. */
692 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
693 command_str = lookup (rip_msg, packet->command);
694 else
695 command_str = "unknown";
696
697 /* Dump packet header. */
698 zlog_info ("%s %s version %d packet size %d",
699 sndrcv, command_str, packet->version, size);
700
701 /* Dump each routing table entry. */
702 rte = packet->rte;
703
704 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
705 {
706 if (packet->version == RIPv2)
707 {
708 netmask = ip_masklen (rte->mask);
709
paulca5e5162004-06-06 22:06:33 +0000710 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000711 {
paulca5e5162004-06-06 22:06:33 +0000712 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000713 {
714 p = (u_char *)&rte->prefix;
715
716 zlog_info (" family 0x%X type %d auth string: %s",
717 ntohs (rte->family), ntohs (rte->tag), p);
718 }
paulca5e5162004-06-06 22:06:33 +0000719 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000720 {
721 struct rip_md5_info *md5;
722
723 md5 = (struct rip_md5_info *) &packet->rte;
724
725 zlog_info (" family 0x%X type %d (MD5 authentication)",
726 ntohs (md5->family), ntohs (md5->type));
727 zlog_info (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000728 " Auth Data len %d",
729 ntohs (md5->packet_len), md5->keyid,
730 md5->auth_len);
731 zlog_info (" Sequence Number %ld",
732 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000733 }
paulca5e5162004-06-06 22:06:33 +0000734 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000735 {
736 p = (u_char *)&rte->prefix;
737
738 zlog_info (" family 0x%X type %d (MD5 data)",
739 ntohs (rte->family), ntohs (rte->tag));
740 zlog_info (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
741 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000742 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
743 p[7], p[9], p[10], p[11], p[12], p[13],
744 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000745 }
746 else
747 {
748 zlog_info (" family 0x%X type %d (Unknown auth type)",
749 ntohs (rte->family), ntohs (rte->tag));
750 }
751 }
752 else
753 zlog_info (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000754 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
755 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
756 BUFSIZ), ntohs (rte->family),
757 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000758 }
759 else
760 {
761 zlog_info (" %s family %d tag %d metric %ld",
762 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
763 ntohs (rte->family), ntohs (rte->tag),
764 (u_long)ntohl (rte->metric));
765 }
766 }
767}
768
769/* Check if the destination address is valid (unicast; not net 0
770 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
771 check net 0 because we accept default route. */
772int
773rip_destination_check (struct in_addr addr)
774{
775 u_int32_t destination;
776
777 /* Convert to host byte order. */
778 destination = ntohl (addr.s_addr);
779
780 if (IPV4_NET127 (destination))
781 return 0;
782
783 /* Net 0 may match to the default route. */
784 if (IPV4_NET0 (destination) && destination != 0)
785 return 0;
786
787 /* Unicast address must belong to class A, B, C. */
788 if (IN_CLASSA (destination))
789 return 1;
790 if (IN_CLASSB (destination))
791 return 1;
792 if (IN_CLASSC (destination))
793 return 1;
794
795 return 0;
796}
797
798/* RIP version 2 authentication. */
799int
800rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
801 struct interface *ifp)
802{
803 struct rip_interface *ri;
804 char *auth_str;
805
806 if (IS_RIP_DEBUG_EVENT)
807 zlog_info ("RIPv2 simple password authentication from %s",
808 inet_ntoa (from->sin_addr));
809
810 ri = ifp->info;
811
812 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000813 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000814 return 0;
815
816 /* Simple password authentication. */
817 if (ri->auth_str)
818 {
819 auth_str = (char *) &rte->prefix;
820
821 if (strncmp (auth_str, ri->auth_str, 16) == 0)
822 return 1;
823 }
824 if (ri->key_chain)
825 {
826 struct keychain *keychain;
827 struct key *key;
828
829 keychain = keychain_lookup (ri->key_chain);
830 if (keychain == NULL)
831 return 0;
832
833 key = key_match_for_accept (keychain, (char *) &rte->prefix);
834 if (key)
835 return 1;
836 }
837 return 0;
838}
839
840/* RIP version 2 authentication with MD5. */
841int
842rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000843 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000844{
845 struct rip_interface *ri;
846 struct rip_md5_info *md5;
847 struct rip_md5_data *md5data;
848 struct keychain *keychain;
849 struct key *key;
850 struct md5_ctx ctx;
851 u_char pdigest[RIP_AUTH_MD5_SIZE];
852 u_char digest[RIP_AUTH_MD5_SIZE];
853 u_int16_t packet_len;
854 char *auth_str = NULL;
855
856 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000857 zlog_info ("RIPv2 MD5 authentication from %s",
858 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000859
860 ri = ifp->info;
861 md5 = (struct rip_md5_info *) &packet->rte;
862
863 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000864 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000865 return 0;
866
paulca5e5162004-06-06 22:06:33 +0000867 /* If the authentication length is less than 16, then it must be wrong for
868 * any interpretation of rfc2082. Some implementations also interpret
869 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000870 */
paulca5e5162004-06-06 22:06:33 +0000871 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
872 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000873 {
874 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +0000875 zlog_warn ("RIPv2 MD5 authentication, strange authentication "
876 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000877 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000878 }
paul718e3742002-12-13 20:15:29 +0000879
paulca5e5162004-06-06 22:06:33 +0000880 /* grab and verify check packet length */
881 packet_len = ntohs (md5->packet_len);
882
883 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
884 {
885 if (IS_RIP_DEBUG_EVENT)
886 zlog_warn ("RIPv2 MD5 authentication, packet length field %d "
887 "greater than received length %d!",
888 md5->packet_len, length);
889 return 0;
890 }
891
892 /* retrieve authentication data */
893 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
894
paul718e3742002-12-13 20:15:29 +0000895 if (ri->key_chain)
896 {
897 keychain = keychain_lookup (ri->key_chain);
898 if (keychain == NULL)
899 return 0;
900
901 key = key_lookup_for_accept (keychain, md5->keyid);
902 if (key == NULL)
903 return 0;
904
905 auth_str = key->string;
906 }
907
908 if (ri->auth_str)
909 auth_str = ri->auth_str;
910
911 if (! auth_str)
912 return 0;
913
914 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000915
916 /* Save digest to pdigest. */
917 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
918
919 /* Overwrite digest by my secret. */
920 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000921 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000922
923 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000924 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000925 &ctx);
paul718e3742002-12-13 20:15:29 +0000926 md5_finish_ctx (&ctx, digest);
927
928 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
929 return packet_len;
930 else
931 return 0;
932}
933
934void
935rip_auth_md5_set (struct stream *s, struct interface *ifp)
936{
937 struct rip_interface *ri;
938 struct keychain *keychain = NULL;
939 struct key *key = NULL;
940 unsigned long len;
941 struct md5_ctx ctx;
942 unsigned char secret[RIP_AUTH_MD5_SIZE];
943 unsigned char digest[RIP_AUTH_MD5_SIZE];
944 char *auth_str = NULL;
945
946 ri = ifp->info;
947
948 /* Make it sure this interface is configured as MD5
949 authentication. */
950 if (ri->auth_type != RIP_AUTH_MD5)
951 return;
952
953 /* Lookup key chain. */
954 if (ri->key_chain)
955 {
956 keychain = keychain_lookup (ri->key_chain);
957 if (keychain == NULL)
958 return;
959
960 /* Lookup key. */
961 key = key_lookup_for_send (keychain);
962 if (key == NULL)
963 return;
964
965 auth_str = key->string;
966 }
967
968 if (ri->auth_str)
969 auth_str = ri->auth_str;
970
971 if (! auth_str)
972 return;
973
974 /* Get packet length. */
975 len = s->putp;
976
977 /* Check packet length. */
978 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
979 {
980 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
981 return;
982 }
983
984 /* Move RTE. */
985 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
986 s->data + RIP_HEADER_SIZE,
987 len - RIP_HEADER_SIZE);
988
989 /* Set pointer to authentication header. */
990 stream_set_putp (s, RIP_HEADER_SIZE);
991 len += RIP_RTE_SIZE;
992
993 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000994 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000995 stream_putw (s, RIP_AUTH_MD5);
996
997 /* RIP-2 Packet length. Actual value is filled in
998 rip_auth_md5_set(). */
999 stream_putw (s, len);
1000
1001 /* Key ID. */
1002 if (key)
1003 stream_putc (s, key->index % 256);
1004 else
1005 stream_putc (s, 1);
1006
paulca5e5162004-06-06 22:06:33 +00001007 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1008 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1009 * to be configurable.
1010 */
1011 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001012
1013 /* Sequence Number (non-decreasing). */
1014 /* RFC2080: The value used in the sequence number is
1015 arbitrary, but two suggestions are the time of the
1016 message's creation or a simple message counter. */
1017 stream_putl (s, time (NULL));
1018
1019 /* Reserved field must be zero. */
1020 stream_putl (s, 0);
1021 stream_putl (s, 0);
1022
1023 /* Set pointer to authentication data. */
1024 stream_set_putp (s, len);
1025
1026 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001027 stream_putw (s, RIP_FAMILY_AUTH);
1028 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001029
1030 /* Generate a digest for the RIP packet. */
1031 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001032 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001033 md5_init_ctx (&ctx);
1034 md5_process_bytes (s->data, s->endp, &ctx);
1035 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1036 md5_finish_ctx (&ctx, digest);
1037
1038 /* Copy the digest to the packet. */
1039 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1040}
1041
1042/* RIP routing information. */
1043void
1044rip_response_process (struct rip_packet *packet, int size,
1045 struct sockaddr_in *from, struct interface *ifp)
1046{
1047 caddr_t lim;
1048 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001049 struct prefix_ipv4 ifaddr;
1050 struct prefix_ipv4 ifaddrclass;
1051 struct connected *c;
1052 int subnetted;
paul718e3742002-12-13 20:15:29 +00001053
paul727d1042002-12-13 20:50:29 +00001054 /* We don't know yet. */
1055 subnetted = -1;
1056
paul718e3742002-12-13 20:15:29 +00001057 /* The Response must be ignored if it is not from the RIP
1058 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001059 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001060 {
1061 zlog_info ("response doesn't come from RIP port: %d",
1062 from->sin_port);
1063 rip_peer_bad_packet (from);
1064 return;
1065 }
1066
1067 /* The datagram's IPv4 source address should be checked to see
1068 whether the datagram is from a valid neighbor; the source of the
1069 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001070 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001071 {
1072 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1073 inet_ntoa (from->sin_addr));
1074 rip_peer_bad_packet (from);
1075 return;
1076 }
1077
1078 /* It is also worth checking to see whether the response is from one
1079 of the router's own addresses. */
1080
1081 ; /* Alredy done in rip_read () */
1082
1083 /* Update RIP peer. */
1084 rip_peer_update (from, packet->version);
1085
1086 /* Set RTE pointer. */
1087 rte = packet->rte;
1088
1089 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1090 {
1091 /* RIPv2 authentication check. */
1092 /* If the Address Family Identifier of the first (and only the
1093 first) entry in the message is 0xFFFF, then the remainder of
1094 the entry contains the authentication. */
1095 /* If the packet gets here it means authentication enabled */
1096 /* Check is done in rip_read(). So, just skipping it */
1097 if (packet->version == RIPv2 &&
1098 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001099 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001100 continue;
1101
paulca5e5162004-06-06 22:06:33 +00001102 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001103 {
1104 /* Address family check. RIP only supports AF_INET. */
1105 zlog_info ("Unsupported family %d from %s.",
1106 ntohs (rte->family), inet_ntoa (from->sin_addr));
1107 continue;
1108 }
1109
1110 /* - is the destination address valid (e.g., unicast; not net 0
1111 or 127) */
1112 if (! rip_destination_check (rte->prefix))
1113 {
1114 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1115 rip_peer_bad_route (from);
1116 continue;
1117 }
1118
1119 /* Convert metric value to host byte order. */
1120 rte->metric = ntohl (rte->metric);
1121
1122 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1123 if (! (rte->metric >= 1 && rte->metric <= 16))
1124 {
1125 zlog_info ("Route's metric is not in the 1-16 range.");
1126 rip_peer_bad_route (from);
1127 continue;
1128 }
1129
1130 /* RIPv1 does not have nexthop value. */
1131 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1132 {
1133 zlog_info ("RIPv1 packet with nexthop value %s",
1134 inet_ntoa (rte->nexthop));
1135 rip_peer_bad_route (from);
1136 continue;
1137 }
1138
1139 /* That is, if the provided information is ignored, a possibly
1140 sub-optimal, but absolutely valid, route may be taken. If
1141 the received Next Hop is not directly reachable, it should be
1142 treated as 0.0.0.0. */
1143 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1144 {
1145 u_int32_t addrval;
1146
1147 /* Multicast address check. */
1148 addrval = ntohl (rte->nexthop.s_addr);
1149 if (IN_CLASSD (addrval))
1150 {
1151 zlog_info ("Nexthop %s is multicast address, skip this rte",
1152 inet_ntoa (rte->nexthop));
1153 continue;
1154 }
1155
1156 if (! if_lookup_address (rte->nexthop))
1157 {
1158 struct route_node *rn;
1159 struct rip_info *rinfo;
1160
1161 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1162
1163 if (rn)
1164 {
1165 rinfo = rn->info;
1166
1167 if (rinfo->type == ZEBRA_ROUTE_RIP
1168 && rinfo->sub_type == RIP_ROUTE_RTE)
1169 {
1170 if (IS_RIP_DEBUG_EVENT)
1171 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1172 rte->nexthop = rinfo->from;
1173 }
1174 else
1175 {
1176 if (IS_RIP_DEBUG_EVENT)
1177 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1178 rte->nexthop.s_addr = 0;
1179 }
1180
1181 route_unlock_node (rn);
1182 }
1183 else
1184 {
1185 if (IS_RIP_DEBUG_EVENT)
1186 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1187 rte->nexthop.s_addr = 0;
1188 }
1189
1190 }
1191 }
1192
1193 /* For RIPv1, there won't be a valid netmask.
1194
1195 This is a best guess at the masks. If everyone was using old
1196 Ciscos before the 'ip subnet zero' option, it would be almost
1197 right too :-)
1198
1199 Cisco summarize ripv1 advertisments to the classful boundary
1200 (/16 for class B's) except when the RIP packet does to inside
1201 the classful network in question. */
1202
1203 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1204 || (packet->version == RIPv2
1205 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1206 {
1207 u_int32_t destination;
1208
paul727d1042002-12-13 20:50:29 +00001209 if (subnetted == -1)
1210 {
1211 c = connected_lookup_address (ifp, from->sin_addr);
1212 if (c != NULL)
1213 {
1214 memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
1215 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1216 apply_classful_mask_ipv4 (&ifaddrclass);
1217 subnetted = 0;
1218 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1219 subnetted = 1;
1220 }
1221 }
1222
paul718e3742002-12-13 20:15:29 +00001223 destination = ntohl (rte->prefix.s_addr);
1224
paul727d1042002-12-13 20:50:29 +00001225 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001226 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001227 else if (IN_CLASSB (destination))
1228 masklen2ip (16, &rte->mask);
1229 else if (IN_CLASSC (destination))
1230 masklen2ip (24, &rte->mask);
1231
1232 if (subnetted == 1)
1233 masklen2ip (ifaddrclass.prefixlen,
1234 (struct in_addr *) &destination);
1235 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1236 ifaddrclass.prefix.s_addr))
1237 {
1238 masklen2ip (ifaddr.prefixlen, &rte->mask);
1239 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1240 masklen2ip (32, &rte->mask);
1241 if (IS_RIP_DEBUG_EVENT)
1242 zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
1243 }
1244 else
1245 {
1246 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1247 continue;
1248 }
1249
1250 if (IS_RIP_DEBUG_EVENT)
1251 {
1252 zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
1253 zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001254 }
1255 }
1256
1257 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1258 ignore the entry. */
1259 if ((packet->version == RIPv2)
1260 && (rte->mask.s_addr != 0)
1261 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1262 {
1263 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1264 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1265 rip_peer_bad_route (from);
1266 continue;
1267 }
1268
1269 /* Default route's netmask is ignored. */
1270 if (packet->version == RIPv2
1271 && (rte->prefix.s_addr == 0)
1272 && (rte->mask.s_addr != 0))
1273 {
1274 if (IS_RIP_DEBUG_EVENT)
1275 zlog_info ("Default route with non-zero netmask. Set zero to netmask");
1276 rte->mask.s_addr = 0;
1277 }
1278
1279 /* Routing table updates. */
1280 rip_rte_process (rte, from, ifp);
1281 }
1282}
1283
1284/* RIP packet send to destination address. */
1285int
paul11dde9c2004-05-31 14:00:00 +00001286rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
paul931cd542004-01-23 15:31:42 +00001287 struct interface *ifp, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00001288{
paul931cd542004-01-23 15:31:42 +00001289 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001290 struct sockaddr_in sin;
paul718e3742002-12-13 20:15:29 +00001291
paul931cd542004-01-23 15:31:42 +00001292 if (IS_RIP_DEBUG_PACKET)
1293 {
1294 char dst[20];
1295 if (to)
1296 {
1297 strcpy(dst, inet_ntoa(to->sin_addr));
1298 }
1299 else
1300 {
1301 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1302 strcpy(dst, inet_ntoa(sin.sin_addr));
1303 }
1304 zlog_info("rip_send_packet %s > %s (%s)",
hassoda9c9a22004-03-18 02:40:55 +00001305 (connected ? inet_ntoa(connected->address->u.prefix4) : ""),
1306 dst, ifp->name);
paul931cd542004-01-23 15:31:42 +00001307 }
hassoda9c9a22004-03-18 02:40:55 +00001308 if (connected && connected->flags & ZEBRA_IFA_SECONDARY)
paul931cd542004-01-23 15:31:42 +00001309 {
1310 /*
1311 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1312 * with multiple addresses on the same subnet: the first address
1313 * on the subnet is configured "primary", and all subsequent addresses
1314 * on that subnet are treated as "secondary" addresses.
1315 * In order to avoid routing-table bloat on other rip listeners,
1316 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1317 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1318 * flag is set, we would end up sending a packet for a "secondary"
1319 * source address on non-linux systems.
1320 */
1321 if (IS_RIP_DEBUG_PACKET)
1322 zlog_info("duplicate dropped");
1323 return 0;
1324 }
1325
paul718e3742002-12-13 20:15:29 +00001326 /* Make destination address. */
1327 memset (&sin, 0, sizeof (struct sockaddr_in));
1328 sin.sin_family = AF_INET;
1329#ifdef HAVE_SIN_LEN
1330 sin.sin_len = sizeof (struct sockaddr_in);
1331#endif /* HAVE_SIN_LEN */
1332
1333 /* When destination is specified, use it's port and address. */
1334 if (to)
1335 {
paul718e3742002-12-13 20:15:29 +00001336 sin.sin_port = to->sin_port;
1337 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001338 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001339 }
1340 else
1341 {
paul718e3742002-12-13 20:15:29 +00001342
1343 sin.sin_port = htons (RIP_PORT_DEFAULT);
1344 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1345
paul931cd542004-01-23 15:31:42 +00001346 /*
1347 * we have to open a new socket for each packet because this
1348 * is the most portable way to bind to a different source
1349 * ipv4 address for each packet.
1350 */
1351 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1352 if (send_sock < 0)
1353 {
1354 zlog_warn("rip_send_packet could not create socket %s",
1355 strerror(errno));
1356 return -1;
1357 }
1358 sockopt_broadcast (send_sock);
1359 sockopt_reuseaddr (send_sock);
1360 sockopt_reuseport (send_sock);
1361#ifdef RIP_RECVMSG
1362 setsockopt_pktinfo (send_sock);
1363#endif /* RIP_RECVMSG */
paul1a517862004-08-19 04:03:08 +00001364 rip_interface_multicast_set (send_sock, connected);
paul718e3742002-12-13 20:15:29 +00001365 }
1366
paul931cd542004-01-23 15:31:42 +00001367 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001368 sizeof (struct sockaddr_in));
1369
1370 if (IS_RIP_DEBUG_EVENT)
paulcc1131a2003-10-15 23:20:17 +00001371 zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1372 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001373
1374 if (ret < 0)
1375 zlog_warn ("can't send packet : %s", strerror (errno));
1376
paul931cd542004-01-23 15:31:42 +00001377 if (!to)
1378 close(send_sock);
1379
paul718e3742002-12-13 20:15:29 +00001380 return ret;
1381}
1382
1383/* Add redistributed route to RIP table. */
1384void
1385rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1386 unsigned int ifindex, struct in_addr *nexthop)
1387{
1388 int ret;
1389 struct route_node *rp;
1390 struct rip_info *rinfo;
1391
1392 /* Redistribute route */
1393 ret = rip_destination_check (p->prefix);
1394 if (! ret)
1395 return;
1396
1397 rp = route_node_get (rip->table, (struct prefix *) p);
1398
1399 rinfo = rp->info;
1400
1401 if (rinfo)
1402 {
1403 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1404 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1405 && rinfo->metric != RIP_METRIC_INFINITY)
1406 {
1407 route_unlock_node (rp);
1408 return;
1409 }
1410
1411 /* Manually configured RIP route check. */
1412 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001413 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1414 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001415 {
hasso16705132003-05-25 14:49:19 +00001416 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1417 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001418 {
1419 route_unlock_node (rp);
1420 return;
1421 }
1422 }
1423
1424 RIP_TIMER_OFF (rinfo->t_timeout);
1425 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1426
1427 if (rip_route_rte (rinfo))
1428 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1429 rinfo->metric);
1430 rp->info = NULL;
1431 rip_info_free (rinfo);
1432
1433 route_unlock_node (rp);
1434 }
1435
1436 rinfo = rip_info_new ();
1437
1438 rinfo->type = type;
1439 rinfo->sub_type = sub_type;
1440 rinfo->ifindex = ifindex;
1441 rinfo->metric = 1;
1442 rinfo->rp = rp;
1443
1444 if (nexthop)
1445 rinfo->nexthop = *nexthop;
1446
1447 rinfo->flags |= RIP_RTF_FIB;
1448 rp->info = rinfo;
1449
1450 rinfo->flags |= RIP_RTF_CHANGED;
1451
hasso16705132003-05-25 14:49:19 +00001452 if (IS_RIP_DEBUG_EVENT) {
1453 if (!nexthop)
1454 zlog_info ("Redistribute new prefix %s/%d on the interface %s",
1455 inet_ntoa(p->prefix), p->prefixlen,
1456 ifindex2ifname(ifindex));
1457 else
1458 zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1459 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1460 ifindex2ifname(ifindex));
1461 }
1462
1463
paul718e3742002-12-13 20:15:29 +00001464 rip_event (RIP_TRIGGERED_UPDATE, 0);
1465}
1466
1467/* Delete redistributed route from RIP table. */
1468void
1469rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1470 unsigned int ifindex)
1471{
1472 int ret;
1473 struct route_node *rp;
1474 struct rip_info *rinfo;
1475
1476 ret = rip_destination_check (p->prefix);
1477 if (! ret)
1478 return;
1479
1480 rp = route_node_lookup (rip->table, (struct prefix *) p);
1481 if (rp)
1482 {
1483 rinfo = rp->info;
1484
1485 if (rinfo != NULL
1486 && rinfo->type == type
1487 && rinfo->sub_type == sub_type
1488 && rinfo->ifindex == ifindex)
1489 {
1490 /* Perform poisoned reverse. */
1491 rinfo->metric = RIP_METRIC_INFINITY;
1492 RIP_TIMER_ON (rinfo->t_garbage_collect,
1493 rip_garbage_collect, rip->garbage_time);
1494 RIP_TIMER_OFF (rinfo->t_timeout);
1495 rinfo->flags |= RIP_RTF_CHANGED;
1496
hasso16705132003-05-25 14:49:19 +00001497 if (IS_RIP_DEBUG_EVENT)
1498 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1499 inet_ntoa(p->prefix), p->prefixlen,
1500 ifindex2ifname(ifindex));
1501
paul718e3742002-12-13 20:15:29 +00001502 rip_event (RIP_TRIGGERED_UPDATE, 0);
1503 }
1504 }
1505}
1506
1507/* Response to request called from rip_read ().*/
1508void
1509rip_request_process (struct rip_packet *packet, int size,
1510 struct sockaddr_in *from, struct interface *ifp)
1511{
1512 caddr_t lim;
1513 struct rte *rte;
1514 struct prefix_ipv4 p;
1515 struct route_node *rp;
1516 struct rip_info *rinfo;
1517 struct rip_interface *ri;
1518
hasso16705132003-05-25 14:49:19 +00001519 /* Does not reponse to the requests on the loopback interfaces */
1520 if (if_is_loopback (ifp))
1521 return;
1522
hasso429a0f82004-02-22 23:42:22 +00001523 /* Check RIP process is enabled on this interface. */
paul718e3742002-12-13 20:15:29 +00001524 ri = ifp->info;
hasso16705132003-05-25 14:49:19 +00001525 if (! ri->running)
1526 return;
paul718e3742002-12-13 20:15:29 +00001527
1528 /* When passive interface is specified, suppress responses */
1529 if (ri->passive)
1530 return;
1531
1532 /* RIP peer update. */
1533 rip_peer_update (from, packet->version);
1534
1535 lim = ((caddr_t) packet) + size;
1536 rte = packet->rte;
1537
1538 /* The Request is processed entry by entry. If there are no
1539 entries, no response is given. */
1540 if (lim == (caddr_t) rte)
1541 return;
1542
1543 /* There is one special case. If there is exactly one entry in the
1544 request, and it has an address family identifier of zero and a
1545 metric of infinity (i.e., 16), then this is a request to send the
1546 entire routing table. */
1547 if (lim == ((caddr_t) (rte + 1)) &&
1548 ntohs (rte->family) == 0 &&
1549 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1550 {
paulcc1131a2003-10-15 23:20:17 +00001551 struct prefix_ipv4 saddr;
1552
1553 /* saddr will be used for determining which routes to split-horizon.
1554 Since the source address we'll pick will be on the same subnet as the
1555 destination, for the purpose of split-horizoning, we'll
1556 pretend that "from" is our source address. */
1557 saddr.family = AF_INET;
1558 saddr.prefixlen = IPV4_MAX_BITLEN;
1559 saddr.prefix = from->sin_addr;
1560
paul718e3742002-12-13 20:15:29 +00001561 /* All route with split horizon */
paulcc1131a2003-10-15 23:20:17 +00001562 rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
paul931cd542004-01-23 15:31:42 +00001563 NULL, &saddr);
paul718e3742002-12-13 20:15:29 +00001564 }
1565 else
1566 {
1567 /* Examine the list of RTEs in the Request one by one. For each
1568 entry, look up the destination in the router's routing
1569 database and, if there is a route, put that route's metric in
1570 the metric field of the RTE. If there is no explicit route
1571 to the specified destination, put infinity in the metric
1572 field. Once all the entries have been filled in, change the
1573 command from Request to Response and send the datagram back
1574 to the requestor. */
1575 p.family = AF_INET;
1576
1577 for (; ((caddr_t) rte) < lim; rte++)
1578 {
1579 p.prefix = rte->prefix;
1580 p.prefixlen = ip_masklen (rte->mask);
1581 apply_mask_ipv4 (&p);
1582
1583 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1584 if (rp)
1585 {
1586 rinfo = rp->info;
1587 rte->metric = htonl (rinfo->metric);
1588 route_unlock_node (rp);
1589 }
1590 else
1591 rte->metric = htonl (RIP_METRIC_INFINITY);
1592 }
1593 packet->command = RIP_RESPONSE;
1594
paul11dde9c2004-05-31 14:00:00 +00001595 rip_send_packet ((u_char *)packet, size, from, ifp, NULL);
paul718e3742002-12-13 20:15:29 +00001596 }
1597 rip_global_queries++;
1598}
1599
1600#if RIP_RECVMSG
1601/* Set IPv6 packet info to the socket. */
1602static int
1603setsockopt_pktinfo (int sock)
1604{
1605 int ret;
1606 int val = 1;
1607
1608 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1609 if (ret < 0)
1610 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));
1611 return ret;
1612}
1613
1614/* Read RIP packet by recvmsg function. */
1615int
1616rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1617 int *ifindex)
1618{
1619 int ret;
1620 struct msghdr msg;
1621 struct iovec iov;
1622 struct cmsghdr *ptr;
1623 char adata[1024];
1624
1625 msg.msg_name = (void *) from;
1626 msg.msg_namelen = sizeof (struct sockaddr_in);
1627 msg.msg_iov = &iov;
1628 msg.msg_iovlen = 1;
1629 msg.msg_control = (void *) adata;
1630 msg.msg_controllen = sizeof adata;
1631 iov.iov_base = buf;
1632 iov.iov_len = size;
1633
1634 ret = recvmsg (sock, &msg, 0);
1635 if (ret < 0)
1636 return ret;
1637
1638 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1639 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1640 {
1641 struct in_pktinfo *pktinfo;
1642 int i;
1643
1644 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1645 i = pktinfo->ipi_ifindex;
1646 }
1647 return ret;
1648}
1649
1650/* RIP packet read function. */
1651int
1652rip_read_new (struct thread *t)
1653{
1654 int ret;
1655 int sock;
1656 char buf[RIP_PACKET_MAXSIZ];
1657 struct sockaddr_in from;
1658 unsigned int ifindex;
1659
1660 /* Fetch socket then register myself. */
1661 sock = THREAD_FD (t);
1662 rip_event (RIP_READ, sock);
1663
1664 /* Read RIP packet. */
1665 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1666 if (ret < 0)
1667 {
1668 zlog_warn ("Can't read RIP packet: %s", strerror (errno));
1669 return ret;
1670 }
1671
1672 return ret;
1673}
1674#endif /* RIP_RECVMSG */
1675
1676/* First entry point of RIP packet. */
1677int
1678rip_read (struct thread *t)
1679{
1680 int sock;
1681 int ret;
1682 int rtenum;
1683 union rip_buf rip_buf;
1684 struct rip_packet *packet;
1685 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001686 int len;
1687 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001688 struct interface *ifp;
1689 struct rip_interface *ri;
1690
1691 /* Fetch socket then register myself. */
1692 sock = THREAD_FD (t);
1693 rip->t_read = NULL;
1694
1695 /* Add myself to tne next event */
1696 rip_event (RIP_READ, sock);
1697
1698 /* RIPd manages only IPv4. */
1699 memset (&from, 0, sizeof (struct sockaddr_in));
1700 fromlen = sizeof (struct sockaddr_in);
1701
1702 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1703 (struct sockaddr *) &from, &fromlen);
1704 if (len < 0)
1705 {
1706 zlog_info ("recvfrom failed: %s", strerror (errno));
1707 return len;
1708 }
1709
1710 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001711 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001712 {
1713 if (IS_RIP_DEBUG_PACKET)
1714 zlog_warn ("ignore packet comes from myself");
1715 return -1;
1716 }
1717
1718 /* Which interface is this packet comes from. */
1719 ifp = if_lookup_address (from.sin_addr);
1720
1721 /* RIP packet received */
1722 if (IS_RIP_DEBUG_EVENT)
1723 zlog_info ("RECV packet from %s port %d on %s",
1724 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1725 ifp ? ifp->name : "unknown");
1726
1727 /* If this packet come from unknown interface, ignore it. */
1728 if (ifp == NULL)
1729 {
1730 zlog_info ("packet comes from unknown interface");
1731 return -1;
1732 }
1733
1734 /* Packet length check. */
1735 if (len < RIP_PACKET_MINSIZ)
1736 {
1737 zlog_warn ("packet size %d is smaller than minimum size %d",
1738 len, RIP_PACKET_MINSIZ);
1739 rip_peer_bad_packet (&from);
1740 return len;
1741 }
1742 if (len > RIP_PACKET_MAXSIZ)
1743 {
1744 zlog_warn ("packet size %d is larger than max size %d",
1745 len, RIP_PACKET_MAXSIZ);
1746 rip_peer_bad_packet (&from);
1747 return len;
1748 }
1749
1750 /* Packet alignment check. */
1751 if ((len - RIP_PACKET_MINSIZ) % 20)
1752 {
1753 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1754 rip_peer_bad_packet (&from);
1755 return len;
1756 }
1757
1758 /* Set RTE number. */
1759 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1760
1761 /* For easy to handle. */
1762 packet = &rip_buf.rip_packet;
1763
1764 /* RIP version check. */
1765 if (packet->version == 0)
1766 {
1767 zlog_info ("version 0 with command %d received.", packet->command);
1768 rip_peer_bad_packet (&from);
1769 return -1;
1770 }
1771
1772 /* Dump RIP packet. */
1773 if (IS_RIP_DEBUG_RECV)
1774 rip_packet_dump (packet, len, "RECV");
1775
1776 /* RIP version adjust. This code should rethink now. RFC1058 says
1777 that "Version 1 implementations are to ignore this extra data and
1778 process only the fields specified in this document.". So RIPv3
1779 packet should be treated as RIPv1 ignoring must be zero field. */
1780 if (packet->version > RIPv2)
1781 packet->version = RIPv2;
1782
1783 /* Is RIP running or is this RIP neighbor ?*/
1784 ri = ifp->info;
1785 if (! ri->running && ! rip_neighbor_lookup (&from))
1786 {
1787 if (IS_RIP_DEBUG_EVENT)
1788 zlog_info ("RIP is not enabled on interface %s.", ifp->name);
1789 rip_peer_bad_packet (&from);
1790 return -1;
1791 }
1792
1793 /* RIP Version check. */
1794 if (packet->command == RIP_RESPONSE)
1795 {
paulf38a4712003-06-07 01:10:00 +00001796 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1797 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001798 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001799 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001800 {
1801 if (IS_RIP_DEBUG_PACKET)
1802 zlog_warn (" packet's v%d doesn't fit to if version spec",
1803 packet->version);
1804 rip_peer_bad_packet (&from);
1805 return -1;
1806 }
1807 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001808 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001809 {
1810 if (IS_RIP_DEBUG_PACKET)
1811 zlog_warn (" packet's v%d doesn't fit to if version spec",
1812 packet->version);
1813 rip_peer_bad_packet (&from);
1814 return -1;
1815 }
paul718e3742002-12-13 20:15:29 +00001816 }
1817
1818 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1819 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1820 accepted; authenticated RIP-2 messages shall be discarded. */
1821
1822 if ((ri->auth_type == RIP_NO_AUTH)
1823 && rtenum
paulca5e5162004-06-06 22:06:33 +00001824 && (packet->version == RIPv2)
1825 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001826 {
1827 if (IS_RIP_DEBUG_EVENT)
1828 zlog_warn ("packet RIPv%d is dropped because authentication disabled",
1829 packet->version);
1830 rip_peer_bad_packet (&from);
1831 return -1;
1832 }
1833
1834 /* If the router is configured to authenticate RIP-2 messages, then
1835 RIP-1 messages and RIP-2 messages which pass authentication
1836 testing shall be accepted; unauthenticated and failed
1837 authentication RIP-2 messages shall be discarded. For maximum
1838 security, RIP-1 messages should be ignored when authentication is
1839 in use (see section 4.1); otherwise, the routing information from
1840 authenticated messages will be propagated by RIP-1 routers in an
1841 unauthenticated manner. */
1842
1843 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001844 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001845 {
1846 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001847 if (packet->version == RIPv1
1848 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001849 {
1850 if (IS_RIP_DEBUG_PACKET)
paulca5e5162004-06-06 22:06:33 +00001851 zlog_warn
1852 ("packet RIPv%d is dropped because authentication enabled",
1853 packet->version);
paul718e3742002-12-13 20:15:29 +00001854 rip_peer_bad_packet (&from);
1855 return -1;
1856 }
1857
1858 /* Check RIPv2 authentication. */
1859 if (packet->version == RIPv2)
1860 {
paulca5e5162004-06-06 22:06:33 +00001861 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001862 {
paulca5e5162004-06-06 22:06:33 +00001863 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001864 {
1865 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1866 if (! ret)
1867 {
1868 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001869 zlog_warn
1870 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001871 rip_peer_bad_packet (&from);
1872 return -1;
1873 }
1874 else
1875 {
1876 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001877 zlog_info
1878 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001879 }
1880 }
paulca5e5162004-06-06 22:06:33 +00001881 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001882 {
paulca5e5162004-06-06 22:06:33 +00001883 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001884 if (! ret)
1885 {
1886 if (IS_RIP_DEBUG_EVENT)
1887 zlog_warn ("RIPv2 MD5 authentication failed");
1888 rip_peer_bad_packet (&from);
1889 return -1;
1890 }
1891 else
1892 {
1893 if (IS_RIP_DEBUG_EVENT)
1894 zlog_info ("RIPv2 MD5 authentication success");
1895 }
1896 /* Reset RIP packet length to trim MD5 data. */
1897 len = ret;
1898 }
1899 else
1900 {
1901 if (IS_RIP_DEBUG_EVENT)
1902 zlog_warn ("Unknown authentication type %d",
1903 ntohs (packet->rte->tag));
1904 rip_peer_bad_packet (&from);
1905 return -1;
1906 }
1907 }
1908 else
1909 {
1910 /* There is no authentication in the packet. */
1911 if (ri->auth_str || ri->key_chain)
1912 {
1913 if (IS_RIP_DEBUG_EVENT)
paulca5e5162004-06-06 22:06:33 +00001914 zlog_warn
1915 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001916 rip_peer_bad_packet (&from);
1917 return -1;
1918 }
1919 }
1920 }
1921 }
1922
1923 /* Process each command. */
1924 switch (packet->command)
1925 {
1926 case RIP_RESPONSE:
1927 rip_response_process (packet, len, &from, ifp);
1928 break;
1929 case RIP_REQUEST:
1930 case RIP_POLL:
1931 rip_request_process (packet, len, &from, ifp);
1932 break;
1933 case RIP_TRACEON:
1934 case RIP_TRACEOFF:
1935 zlog_info ("Obsolete command %s received, please sent it to routed",
1936 lookup (rip_msg, packet->command));
1937 rip_peer_bad_packet (&from);
1938 break;
1939 case RIP_POLL_ENTRY:
1940 zlog_info ("Obsolete command %s received",
1941 lookup (rip_msg, packet->command));
1942 rip_peer_bad_packet (&from);
1943 break;
1944 default:
1945 zlog_info ("Unknown RIP command %d received", packet->command);
1946 rip_peer_bad_packet (&from);
1947 break;
1948 }
1949
1950 return len;
1951}
1952
1953/* Make socket for RIP protocol. */
1954int
1955rip_create_socket ()
1956{
1957 int ret;
1958 int sock;
1959 struct sockaddr_in addr;
1960 struct servent *sp;
1961
1962 memset (&addr, 0, sizeof (struct sockaddr_in));
1963
1964 /* Set RIP port. */
1965 sp = getservbyname ("router", "udp");
1966 if (sp)
1967 addr.sin_port = sp->s_port;
1968 else
1969 addr.sin_port = htons (RIP_PORT_DEFAULT);
1970
1971 /* Address shoud be any address. */
1972 addr.sin_family = AF_INET;
1973 addr.sin_addr.s_addr = INADDR_ANY;
1974
1975 /* Make datagram socket. */
1976 sock = socket (AF_INET, SOCK_DGRAM, 0);
1977 if (sock < 0)
1978 {
1979 perror ("socket");
1980 exit (1);
1981 }
1982
1983 sockopt_broadcast (sock);
1984 sockopt_reuseaddr (sock);
1985 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00001986 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00001987#ifdef RIP_RECVMSG
1988 setsockopt_pktinfo (sock);
1989#endif /* RIP_RECVMSG */
1990
pauledd7c242003-06-04 13:59:38 +00001991 if (ripd_privs.change (ZPRIVS_RAISE))
1992 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001993 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
1994 if (ret < 0)
1995 {
1996 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00001997 if (ripd_privs.change (ZPRIVS_LOWER))
1998 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00001999 return ret;
2000 }
pauledd7c242003-06-04 13:59:38 +00002001 if (ripd_privs.change (ZPRIVS_LOWER))
2002 zlog_err ("rip_create_socket: could not lower privs");
2003
paul718e3742002-12-13 20:15:29 +00002004 return sock;
2005}
2006
2007/* Write routing table entry to the stream and return next index of
2008 the routing table entry in the stream. */
2009int
2010rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2011 u_char version, struct rip_info *rinfo, struct interface *ifp)
2012{
2013 struct in_addr mask;
2014 struct rip_interface *ri;
2015
2016 /* RIP packet header. */
2017 if (num == 0)
2018 {
2019 stream_putc (s, RIP_RESPONSE);
2020 stream_putc (s, version);
2021 stream_putw (s, 0);
2022
2023 /* In case of we need RIPv2 authentication. */
2024 if (version == RIPv2 && ifp)
2025 {
2026 ri = ifp->info;
2027
2028 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2029 {
2030 if (ri->auth_str)
2031 {
paulca5e5162004-06-06 22:06:33 +00002032 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002033 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2034
2035 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002036 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002037 stream_set_putp (s, s->putp + 16);
2038
2039 num++;
2040 }
2041 if (ri->key_chain)
2042 {
2043 struct keychain *keychain;
2044 struct key *key;
2045
2046 keychain = keychain_lookup (ri->key_chain);
2047
2048 if (keychain)
2049 {
2050 key = key_lookup_for_send (keychain);
2051
2052 if (key)
2053 {
paulca5e5162004-06-06 22:06:33 +00002054 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002055 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2056
2057 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002058 strncpy ((char *)(s->data + s->putp),
2059 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002060 stream_set_putp (s, s->putp + 16);
2061
2062 num++;
2063 }
2064 }
2065 }
2066 }
2067 }
2068 }
2069
2070 /* Write routing table entry. */
2071 if (version == RIPv1)
2072 {
2073 stream_putw (s, AF_INET);
2074 stream_putw (s, 0);
2075 stream_put_ipv4 (s, p->prefix.s_addr);
2076 stream_put_ipv4 (s, 0);
2077 stream_put_ipv4 (s, 0);
2078 stream_putl (s, rinfo->metric_out);
2079 }
2080 else
2081 {
2082 masklen2ip (p->prefixlen, &mask);
2083
2084 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002085 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002086 stream_put_ipv4 (s, p->prefix.s_addr);
2087 stream_put_ipv4 (s, mask.s_addr);
2088 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2089 stream_putl (s, rinfo->metric_out);
2090 }
2091
2092 return ++num;
2093}
2094
2095/* Send update to the ifp or spcified neighbor. */
2096void
paul727d1042002-12-13 20:50:29 +00002097rip_output_process (struct interface *ifp, struct prefix *ifaddr,
paulcc1131a2003-10-15 23:20:17 +00002098 struct sockaddr_in *to, int route_type, u_char version,
paul931cd542004-01-23 15:31:42 +00002099 struct connected *connected, struct prefix_ipv4 *saddr)
paul718e3742002-12-13 20:15:29 +00002100{
2101 int ret;
2102 struct stream *s;
2103 struct route_node *rp;
2104 struct rip_info *rinfo;
2105 struct rip_interface *ri;
2106 struct prefix_ipv4 *p;
2107 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002108 struct prefix_ipv4 ifaddrclass;
2109 struct connected *c;
paul718e3742002-12-13 20:15:29 +00002110 int num;
2111 int rtemax;
paul01d09082003-06-08 21:22:18 +00002112 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002113
2114 /* Logging output event. */
2115 if (IS_RIP_DEBUG_EVENT)
2116 {
2117 if (to)
2118 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2119 else
2120 zlog_info ("update routes on interface %s ifindex %d",
2121 ifp->name, ifp->ifindex);
2122 }
2123
2124 /* Set output stream. */
2125 s = rip->obuf;
2126
2127 /* Reset stream and RTE counter. */
2128 stream_reset (s);
2129 num = 0;
2130 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2131
2132 /* Get RIP interface. */
2133 ri = ifp->info;
2134
2135 /* If output interface is in simple password authentication mode, we
2136 need space for authentication data. */
2137 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2138 rtemax -= 1;
2139
2140 /* If output interface is in MD5 authentication mode, we need space
2141 for authentication header and data. */
2142 if (ri->auth_type == RIP_AUTH_MD5)
2143 rtemax -= 2;
2144
2145 /* If output interface is in simple password authentication mode
2146 and string or keychain is specified we need space for auth. data */
2147 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2148 {
2149 if (ri->key_chain)
2150 {
2151 struct keychain *keychain;
2152
2153 keychain = keychain_lookup (ri->key_chain);
2154 if (keychain)
2155 if (key_lookup_for_send (keychain))
2156 rtemax -=1;
2157 }
2158 else
2159 if (ri->auth_str)
2160 rtemax -=1;
2161 }
2162
paul727d1042002-12-13 20:50:29 +00002163 if (version == RIPv1)
2164 {
2165 if (ifaddr == NULL)
2166 {
2167 c = connected_lookup_address (ifp, to->sin_addr);
2168 if (c != NULL)
2169 ifaddr = c->address;
2170 }
2171 if (ifaddr == NULL)
2172 {
2173 zlog_warn ("cannot find source address for packets to neighbor %s",
2174 inet_ntoa (to->sin_addr));
2175 return;
2176 }
2177 memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
2178 apply_classful_mask_ipv4 (&ifaddrclass);
2179 subnetted = 0;
2180 if (ifaddr->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002181 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002182 }
2183
paul718e3742002-12-13 20:15:29 +00002184 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2185 if ((rinfo = rp->info) != NULL)
2186 {
paul727d1042002-12-13 20:50:29 +00002187 /* For RIPv1, if we are subnetted, output subnets in our network */
2188 /* that have the same mask as the output "interface". For other */
2189 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002190
2191 if (version == RIPv1)
2192 {
paul727d1042002-12-13 20:50:29 +00002193 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002194
2195 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002196 zlog_info("RIPv1 mask check, %s/%d considered for output",
2197 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002198
paul727d1042002-12-13 20:50:29 +00002199 if (subnetted &&
2200 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2201 {
2202 if ((ifaddr->prefixlen != rp->p.prefixlen) &&
2203 (rp->p.prefixlen != 32))
2204 continue;
2205 }
2206 else
2207 {
2208 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2209 apply_classful_mask_ipv4(&classfull);
2210 if (rp->p.u.prefix4.s_addr != 0 &&
2211 classfull.prefixlen != rp->p.prefixlen)
2212 continue;
2213 }
paul718e3742002-12-13 20:15:29 +00002214 if (IS_RIP_DEBUG_PACKET)
paul727d1042002-12-13 20:50:29 +00002215 zlog_info("RIPv1 mask check, %s/%d made it through",
2216 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002217 }
2218 else
2219 p = (struct prefix_ipv4 *) &rp->p;
2220
2221 /* Apply output filters. */
2222 ret = rip_outgoing_filter (p, ri);
2223 if (ret < 0)
2224 continue;
2225
2226 /* Changed route only output. */
2227 if (route_type == rip_changed_route &&
2228 (! (rinfo->flags & RIP_RTF_CHANGED)))
2229 continue;
2230
2231 /* Split horizon. */
2232 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002233 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002234 {
paul42d14d92003-11-17 09:15:18 +00002235 /*
2236 * We perform split horizon for RIP and connected route.
2237 * For rip routes, we want to suppress the route if we would
2238 * end up sending the route back on the interface that we
2239 * learned it from, with a higher metric. For connected routes,
2240 * we suppress the route if the prefix is a subset of the
2241 * source address that we are going to use for the packet
2242 * (in order to handle the case when multiple subnets are
2243 * configured on the same interface).
2244 */
2245 if (rinfo->type == ZEBRA_ROUTE_RIP &&
2246 rinfo->ifindex == ifp->ifindex)
2247 continue;
2248 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulcc1131a2003-10-15 23:20:17 +00002249 prefix_match((struct prefix *)p, (struct prefix *)saddr))
paul718e3742002-12-13 20:15:29 +00002250 continue;
2251 }
2252
2253 /* Preparation for route-map. */
2254 rinfo->metric_set = 0;
2255 rinfo->nexthop_out.s_addr = 0;
2256 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002257 rinfo->tag_out = rinfo->tag;
paul718e3742002-12-13 20:15:29 +00002258 rinfo->ifindex_out = ifp->ifindex;
2259
hasso16705132003-05-25 14:49:19 +00002260 /* In order to avoid some local loops,
2261 * if the RIP route has a nexthop via this interface, keep the nexthop,
2262 * otherwise set it to 0. The nexthop should not be propagated
2263 * beyond the local broadcast/multicast area in order
2264 * to avoid an IGP multi-level recursive look-up.
2265 * see (4.4)
2266 */
2267 if (rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002268 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002269
2270 /* Interface route-map */
2271 if (ri->routemap[RIP_FILTER_OUT])
2272 {
2273 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2274 (struct prefix *) p, RMAP_RIP,
2275 rinfo);
2276
2277 if (ret == RMAP_DENYMATCH)
2278 {
2279 if (IS_RIP_DEBUG_PACKET)
2280 zlog_info ("RIP %s/%d is filtered by route-map out",
2281 inet_ntoa (p->prefix), p->prefixlen);
2282 continue;
2283 }
2284 }
paul718e3742002-12-13 20:15:29 +00002285
hasso16705132003-05-25 14:49:19 +00002286 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002287 if (rip->route_map[rinfo->type].name
2288 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2289 {
2290 ret = route_map_apply (rip->route_map[rinfo->type].map,
2291 (struct prefix *)p, RMAP_RIP, rinfo);
2292
2293 if (ret == RMAP_DENYMATCH)
2294 {
2295 if (IS_RIP_DEBUG_PACKET)
2296 zlog_info ("%s/%d is filtered by route-map",
2297 inet_ntoa (p->prefix), p->prefixlen);
2298 continue;
2299 }
2300 }
2301
2302 /* When route-map does not set metric. */
2303 if (! rinfo->metric_set)
2304 {
2305 /* If redistribute metric is set. */
2306 if (rip->route_map[rinfo->type].metric_config
2307 && rinfo->metric != RIP_METRIC_INFINITY)
2308 {
2309 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2310 }
2311 else
2312 {
2313 /* If the route is not connected or localy generated
2314 one, use default-metric value*/
2315 if (rinfo->type != ZEBRA_ROUTE_RIP
2316 && rinfo->type != ZEBRA_ROUTE_CONNECT
2317 && rinfo->metric != RIP_METRIC_INFINITY)
2318 rinfo->metric_out = rip->default_metric;
2319 }
2320 }
2321
2322 /* Apply offset-list */
2323 if (rinfo->metric != RIP_METRIC_INFINITY)
2324 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);
2325
2326 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2327 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002328
2329 /* Perform split-horizon with poisoned reverse
2330 * for RIP and connected routes.
2331 **/
2332 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002333 /*
2334 * We perform split horizon for RIP and connected route.
2335 * For rip routes, we want to suppress the route if we would
2336 * end up sending the route back on the interface that we
2337 * learned it from, with a higher metric. For connected routes,
2338 * we suppress the route if the prefix is a subset of the
2339 * source address that we are going to use for the packet
2340 * (in order to handle the case when multiple subnets are
2341 * configured on the same interface).
2342 */
2343 if (rinfo->type == ZEBRA_ROUTE_RIP &&
hasso16705132003-05-25 14:49:19 +00002344 rinfo->ifindex == ifp->ifindex)
2345 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002346 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
2347 prefix_match((struct prefix *)p, (struct prefix *)saddr))
2348 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002349 }
2350
paul718e3742002-12-13 20:15:29 +00002351 /* Write RTE to the stream. */
2352 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
2353 if (num == rtemax)
2354 {
2355 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2356 rip_auth_md5_set (s, ifp);
2357
2358 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paul931cd542004-01-23 15:31:42 +00002359 to, ifp, connected);
paul718e3742002-12-13 20:15:29 +00002360
2361 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2362 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2363 stream_get_endp(s), "SEND");
2364 num = 0;
2365 stream_reset (s);
2366 }
2367 }
2368
2369 /* Flush unwritten RTE. */
2370 if (num != 0)
2371 {
2372 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2373 rip_auth_md5_set (s, ifp);
2374
paul931cd542004-01-23 15:31:42 +00002375 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp,
2376 connected);
paul718e3742002-12-13 20:15:29 +00002377
2378 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2379 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2380 stream_get_endp (s), "SEND");
2381 num = 0;
2382 stream_reset (s);
2383 }
2384
2385 /* Statistics updates. */
2386 ri->sent_updates++;
2387}
2388
2389/* Send RIP packet to the interface. */
2390void
paulcc1131a2003-10-15 23:20:17 +00002391rip_update_interface (struct interface *ifp, u_char version, int route_type,
paul931cd542004-01-23 15:31:42 +00002392 struct connected *sconn)
paul718e3742002-12-13 20:15:29 +00002393{
2394 struct prefix_ipv4 *p;
2395 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +00002396 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002397 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002398 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002399
2400 /* When RIP version is 2 and multicast enable interface. */
2401 if (version == RIPv2 && if_is_multicast (ifp))
2402 {
2403 if (IS_RIP_DEBUG_EVENT)
2404 zlog_info ("multicast announce on %s ", ifp->name);
2405
hassocaa6f8a2004-03-03 19:48:48 +00002406 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002407 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002408 return;
2409 }
2410
2411 /* If we can't send multicast packet, send it with unicast. */
2412 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2413 {
2414 for (node = listhead (ifp->connected); node; nextnode (node))
2415 {
2416 connected = getdata (node);
2417
2418 /* Fetch broadcast address or poin-to-point destination
2419 address . */
2420 p = (struct prefix_ipv4 *) connected->destination;
2421
2422 if (p->family == AF_INET)
2423 {
2424 /* Destination address and port setting. */
2425 memset (&to, 0, sizeof (struct sockaddr_in));
2426 to.sin_addr = p->prefix;
2427 to.sin_port = htons (RIP_PORT_DEFAULT);
2428
2429 if (IS_RIP_DEBUG_EVENT)
2430 zlog_info ("%s announce to %s on %s",
2431 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2432 inet_ntoa (to.sin_addr), ifp->name);
2433
paul727d1042002-12-13 20:50:29 +00002434 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002435 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002436 }
2437 }
2438 }
2439}
2440
2441/* Update send to all interface and neighbor. */
2442void
2443rip_update_process (int route_type)
2444{
hasso52dc7ee2004-09-23 19:18:23 +00002445 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002446 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002447 struct interface *ifp;
2448 struct rip_interface *ri;
2449 struct route_node *rp;
2450 struct sockaddr_in to;
2451 struct prefix_ipv4 *p;
2452
2453 /* Send RIP update to each interface. */
2454 for (node = listhead (iflist); node; nextnode (node))
2455 {
2456 ifp = getdata (node);
2457
2458 if (if_is_loopback (ifp))
2459 continue;
2460
paul2e3b2e42002-12-13 21:03:13 +00002461 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002462 continue;
2463
2464 /* Fetch RIP interface information. */
2465 ri = ifp->info;
2466
2467 /* When passive interface is specified, suppress announce to the
2468 interface. */
2469 if (ri->passive)
2470 continue;
2471
2472 if (ri->running)
2473 {
2474 if (IS_RIP_DEBUG_EVENT)
2475 {
2476 if (ifp->name)
2477 zlog_info ("SEND UPDATE to %s ifindex %d",
2478 ifp->name, ifp->ifindex);
2479 else
2480 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2481 ifp->ifindex);
2482 }
2483
paulcc1131a2003-10-15 23:20:17 +00002484 /* send update on each connected network */
2485
2486 LIST_LOOP(ifp->connected, connected, ifnode)
2487 {
2488 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002489 int done = 0;
2490 /*
2491 * If there is no version configuration in the interface,
2492 * use rip's version setting.
2493 */
paulf38a4712003-06-07 01:10:00 +00002494 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2495 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002496
2497 ifaddr = (struct prefix_ipv4 *) connected->address;
2498
2499 if (ifaddr->family != AF_INET)
2500 continue;
2501
paul931cd542004-01-23 15:31:42 +00002502 if ((vsend & RIPv1) && !done)
2503 rip_update_interface (ifp, RIPv1, route_type, connected);
2504 if ((vsend & RIPv2) && if_is_multicast(ifp))
2505 rip_update_interface (ifp, RIPv2, route_type, connected);
2506 done = 1;
2507 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2508 break;
2509
paulf38a4712003-06-07 01:10:00 +00002510 }
paul718e3742002-12-13 20:15:29 +00002511 }
2512 }
2513
2514 /* RIP send updates to each neighbor. */
2515 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2516 if (rp->info != NULL)
2517 {
2518 p = (struct prefix_ipv4 *) &rp->p;
2519
2520 ifp = if_lookup_address (p->prefix);
2521 if (! ifp)
2522 {
2523 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2524 inet_ntoa (p->prefix));
2525 continue;
2526 }
2527
2528 /* Set destination address and port */
2529 memset (&to, 0, sizeof (struct sockaddr_in));
2530 to.sin_addr = p->prefix;
2531 to.sin_port = htons (RIP_PORT_DEFAULT);
2532
2533 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002534 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2535 NULL, p);
paul718e3742002-12-13 20:15:29 +00002536 }
2537}
2538
2539/* RIP's periodical timer. */
2540int
2541rip_update (struct thread *t)
2542{
2543 /* Clear timer pointer. */
2544 rip->t_update = NULL;
2545
2546 if (IS_RIP_DEBUG_EVENT)
2547 zlog_info ("update timer fire!");
2548
2549 /* Process update output. */
2550 rip_update_process (rip_all_route);
2551
2552 /* Triggered updates may be suppressed if a regular update is due by
2553 the time the triggered update would be sent. */
2554 if (rip->t_triggered_interval)
2555 {
2556 thread_cancel (rip->t_triggered_interval);
2557 rip->t_triggered_interval = NULL;
2558 }
2559 rip->trigger = 0;
2560
2561 /* Register myself. */
2562 rip_event (RIP_UPDATE_EVENT, 0);
2563
2564 return 0;
2565}
2566
2567/* Walk down the RIP routing table then clear changed flag. */
2568void
2569rip_clear_changed_flag ()
2570{
2571 struct route_node *rp;
2572 struct rip_info *rinfo;
2573
2574 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2575 if ((rinfo = rp->info) != NULL)
2576 if (rinfo->flags & RIP_RTF_CHANGED)
2577 rinfo->flags &= ~RIP_RTF_CHANGED;
2578}
2579
2580/* Triggered update interval timer. */
2581int
2582rip_triggered_interval (struct thread *t)
2583{
2584 int rip_triggered_update (struct thread *);
2585
2586 rip->t_triggered_interval = NULL;
2587
2588 if (rip->trigger)
2589 {
2590 rip->trigger = 0;
2591 rip_triggered_update (t);
2592 }
2593 return 0;
2594}
2595
2596/* Execute triggered update. */
2597int
2598rip_triggered_update (struct thread *t)
2599{
2600 int interval;
2601
2602 /* Clear thred pointer. */
2603 rip->t_triggered_update = NULL;
2604
2605 /* Cancel interval timer. */
2606 if (rip->t_triggered_interval)
2607 {
2608 thread_cancel (rip->t_triggered_interval);
2609 rip->t_triggered_interval = NULL;
2610 }
2611 rip->trigger = 0;
2612
2613 /* Logging triggered update. */
2614 if (IS_RIP_DEBUG_EVENT)
2615 zlog_info ("triggered update!");
2616
2617 /* Split Horizon processing is done when generating triggered
2618 updates as well as normal updates (see section 2.6). */
2619 rip_update_process (rip_changed_route);
2620
2621 /* Once all of the triggered updates have been generated, the route
2622 change flags should be cleared. */
2623 rip_clear_changed_flag ();
2624
2625 /* After a triggered update is sent, a timer should be set for a
2626 random interval between 1 and 5 seconds. If other changes that
2627 would trigger updates occur before the timer expires, a single
2628 update is triggered when the timer expires. */
2629 interval = (random () % 5) + 1;
2630
2631 rip->t_triggered_interval =
2632 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2633
2634 return 0;
2635}
2636
2637/* Withdraw redistributed route. */
2638void
2639rip_redistribute_withdraw (int type)
2640{
2641 struct route_node *rp;
2642 struct rip_info *rinfo;
2643
2644 if (!rip)
2645 return;
2646
2647 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2648 if ((rinfo = rp->info) != NULL)
2649 {
2650 if (rinfo->type == type
2651 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2652 {
2653 /* Perform poisoned reverse. */
2654 rinfo->metric = RIP_METRIC_INFINITY;
2655 RIP_TIMER_ON (rinfo->t_garbage_collect,
2656 rip_garbage_collect, rip->garbage_time);
2657 RIP_TIMER_OFF (rinfo->t_timeout);
2658 rinfo->flags |= RIP_RTF_CHANGED;
2659
hasso16705132003-05-25 14:49:19 +00002660 if (IS_RIP_DEBUG_EVENT) {
2661 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2662
2663 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2664 inet_ntoa(p->prefix), p->prefixlen,
2665 ifindex2ifname(rinfo->ifindex));
2666 }
2667
paul718e3742002-12-13 20:15:29 +00002668 rip_event (RIP_TRIGGERED_UPDATE, 0);
2669 }
2670 }
2671}
2672
2673/* Create new RIP instance and set it to global variable. */
2674int
2675rip_create ()
2676{
2677 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2678 memset (rip, 0, sizeof (struct rip));
2679
2680 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002681 rip->version_send = RI_RIP_VERSION_2;
2682 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002683 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2684 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2685 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2686 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2687
2688 /* Initialize RIP routig table. */
2689 rip->table = route_table_init ();
2690 rip->route = route_table_init ();
2691 rip->neighbor = route_table_init ();
2692
2693 /* Make output stream. */
2694 rip->obuf = stream_new (1500);
2695
2696 /* Make socket. */
2697 rip->sock = rip_create_socket ();
2698 if (rip->sock < 0)
2699 return rip->sock;
2700
2701 /* Create read and timer thread. */
2702 rip_event (RIP_READ, rip->sock);
2703 rip_event (RIP_UPDATE_EVENT, 1);
2704
2705 return 0;
2706}
2707
2708/* Sned RIP request to the destination. */
2709int
2710rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002711 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002712{
2713 struct rte *rte;
2714 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002715 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002716
2717 memset (&rip_packet, 0, sizeof (rip_packet));
2718
2719 rip_packet.command = RIP_REQUEST;
2720 rip_packet.version = version;
2721 rte = rip_packet.rte;
2722 rte->metric = htonl (RIP_METRIC_INFINITY);
2723
paul931cd542004-01-23 15:31:42 +00002724 if (connected)
2725 {
2726 /*
2727 * connected is only sent for ripv1 case, or when
2728 * interface does not support multicast. Caller loops
2729 * over each connected address for this case.
2730 */
paul11dde9c2004-05-31 14:00:00 +00002731 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002732 to, ifp, connected) != sizeof (rip_packet))
2733 return -1;
2734 else
2735 return sizeof (rip_packet);
2736 }
2737
paulcc1131a2003-10-15 23:20:17 +00002738 /* send request on each connected network */
2739 LIST_LOOP(ifp->connected, connected, node)
2740 {
2741 struct prefix_ipv4 *p;
2742
2743 p = (struct prefix_ipv4 *) connected->address;
2744
2745 if (p->family != AF_INET)
2746 continue;
2747
paul11dde9c2004-05-31 14:00:00 +00002748 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002749 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002750 return -1;
2751 }
2752 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002753}
2754
2755int
2756rip_update_jitter (unsigned long time)
2757{
paul239389b2004-05-05 14:09:37 +00002758#define JITTER_BOUND 4
2759 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2760 Given that, we cannot let time be less than JITTER_BOUND seconds.
2761 The RIPv2 RFC says jitter should be small compared to
2762 update_time. We consider 1/JITTER_BOUND to be small.
2763 */
2764
2765 int jitter_input = time;
2766 int jitter;
2767
2768 if (jitter_input < JITTER_BOUND)
2769 jitter_input = JITTER_BOUND;
2770
2771 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2772
2773 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002774}
2775
2776void
2777rip_event (enum rip_event event, int sock)
2778{
2779 int jitter = 0;
2780
2781 switch (event)
2782 {
2783 case RIP_READ:
2784 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2785 break;
2786 case RIP_UPDATE_EVENT:
2787 if (rip->t_update)
2788 {
2789 thread_cancel (rip->t_update);
2790 rip->t_update = NULL;
2791 }
2792 jitter = rip_update_jitter (rip->update_time);
2793 rip->t_update =
2794 thread_add_timer (master, rip_update, NULL,
2795 sock ? 2 : rip->update_time + jitter);
2796 break;
2797 case RIP_TRIGGERED_UPDATE:
2798 if (rip->t_triggered_interval)
2799 rip->trigger = 1;
2800 else if (! rip->t_triggered_update)
2801 rip->t_triggered_update =
2802 thread_add_event (master, rip_triggered_update, NULL, 0);
2803 break;
2804 default:
2805 break;
2806 }
2807}
2808
2809DEFUN (router_rip,
2810 router_rip_cmd,
2811 "router rip",
2812 "Enable a routing process\n"
2813 "Routing Information Protocol (RIP)\n")
2814{
2815 int ret;
2816
2817 /* If rip is not enabled before. */
2818 if (! rip)
2819 {
2820 ret = rip_create ();
2821 if (ret < 0)
2822 {
2823 zlog_info ("Can't create RIP");
2824 return CMD_WARNING;
2825 }
2826 }
2827 vty->node = RIP_NODE;
2828 vty->index = rip;
2829
2830 return CMD_SUCCESS;
2831}
2832
2833DEFUN (no_router_rip,
2834 no_router_rip_cmd,
2835 "no router rip",
2836 NO_STR
2837 "Enable a routing process\n"
2838 "Routing Information Protocol (RIP)\n")
2839{
2840 if (rip)
2841 rip_clean ();
2842 return CMD_SUCCESS;
2843}
2844
2845DEFUN (rip_version,
2846 rip_version_cmd,
2847 "version <1-2>",
2848 "Set routing protocol version\n"
2849 "version\n")
2850{
2851 int version;
2852
2853 version = atoi (argv[0]);
2854 if (version != RIPv1 && version != RIPv2)
2855 {
2856 vty_out (vty, "invalid rip version %d%s", version,
2857 VTY_NEWLINE);
2858 return CMD_WARNING;
2859 }
paulf38a4712003-06-07 01:10:00 +00002860 rip->version_send = version;
2861 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002862
2863 return CMD_SUCCESS;
2864}
2865
2866DEFUN (no_rip_version,
2867 no_rip_version_cmd,
2868 "no version",
2869 NO_STR
2870 "Set routing protocol version\n")
2871{
2872 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002873 rip->version_send = RI_RIP_VERSION_2;
2874 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002875
2876 return CMD_SUCCESS;
2877}
2878
2879ALIAS (no_rip_version,
2880 no_rip_version_val_cmd,
2881 "no version <1-2>",
2882 NO_STR
2883 "Set routing protocol version\n"
2884 "version\n")
2885
2886DEFUN (rip_route,
2887 rip_route_cmd,
2888 "route A.B.C.D/M",
2889 "RIP static route configuration\n"
2890 "IP prefix <network>/<length>\n")
2891{
2892 int ret;
2893 struct prefix_ipv4 p;
2894 struct route_node *node;
2895
2896 ret = str2prefix_ipv4 (argv[0], &p);
2897 if (ret < 0)
2898 {
2899 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2900 return CMD_WARNING;
2901 }
2902 apply_mask_ipv4 (&p);
2903
2904 /* For router rip configuration. */
2905 node = route_node_get (rip->route, (struct prefix *) &p);
2906
2907 if (node->info)
2908 {
2909 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2910 route_unlock_node (node);
2911 return CMD_WARNING;
2912 }
2913
hasso8a676be2004-10-08 06:36:38 +00002914 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002915
2916 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2917
2918 return CMD_SUCCESS;
2919}
2920
2921DEFUN (no_rip_route,
2922 no_rip_route_cmd,
2923 "no route A.B.C.D/M",
2924 NO_STR
2925 "RIP static route configuration\n"
2926 "IP prefix <network>/<length>\n")
2927{
2928 int ret;
2929 struct prefix_ipv4 p;
2930 struct route_node *node;
2931
2932 ret = str2prefix_ipv4 (argv[0], &p);
2933 if (ret < 0)
2934 {
2935 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2936 return CMD_WARNING;
2937 }
2938 apply_mask_ipv4 (&p);
2939
2940 /* For router rip configuration. */
2941 node = route_node_lookup (rip->route, (struct prefix *) &p);
2942 if (! node)
2943 {
2944 vty_out (vty, "Can't find route %s.%s", argv[0],
2945 VTY_NEWLINE);
2946 return CMD_WARNING;
2947 }
2948
2949 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2950 route_unlock_node (node);
2951
2952 node->info = NULL;
2953 route_unlock_node (node);
2954
2955 return CMD_SUCCESS;
2956}
2957
2958void
2959rip_update_default_metric ()
2960{
2961 struct route_node *np;
2962 struct rip_info *rinfo;
2963
2964 for (np = route_top (rip->table); np; np = route_next (np))
2965 if ((rinfo = np->info) != NULL)
2966 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2967 rinfo->metric = rip->default_metric;
2968}
2969
2970DEFUN (rip_default_metric,
2971 rip_default_metric_cmd,
2972 "default-metric <1-16>",
2973 "Set a metric of redistribute routes\n"
2974 "Default metric\n")
2975{
2976 if (rip)
2977 {
2978 rip->default_metric = atoi (argv[0]);
2979 /* rip_update_default_metric (); */
2980 }
2981 return CMD_SUCCESS;
2982}
2983
2984DEFUN (no_rip_default_metric,
2985 no_rip_default_metric_cmd,
2986 "no default-metric",
2987 NO_STR
2988 "Set a metric of redistribute routes\n"
2989 "Default metric\n")
2990{
2991 if (rip)
2992 {
2993 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2994 /* rip_update_default_metric (); */
2995 }
2996 return CMD_SUCCESS;
2997}
2998
2999ALIAS (no_rip_default_metric,
3000 no_rip_default_metric_val_cmd,
3001 "no default-metric <1-16>",
3002 NO_STR
3003 "Set a metric of redistribute routes\n"
3004 "Default metric\n")
3005
3006DEFUN (rip_timers,
3007 rip_timers_cmd,
3008 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3009 "Adjust routing timers\n"
3010 "Basic routing protocol update timers\n"
3011 "Routing table update timer value in second. Default is 30.\n"
3012 "Routing information timeout timer. Default is 180.\n"
3013 "Garbage collection timer. Default is 120.\n")
3014{
3015 unsigned long update;
3016 unsigned long timeout;
3017 unsigned long garbage;
3018 char *endptr = NULL;
3019 unsigned long RIP_TIMER_MAX = 2147483647;
3020 unsigned long RIP_TIMER_MIN = 5;
3021
3022 update = strtoul (argv[0], &endptr, 10);
3023 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3024 {
3025 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3026 return CMD_WARNING;
3027 }
3028
3029 timeout = strtoul (argv[1], &endptr, 10);
3030 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3031 {
3032 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3033 return CMD_WARNING;
3034 }
3035
3036 garbage = strtoul (argv[2], &endptr, 10);
3037 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3038 {
3039 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3040 return CMD_WARNING;
3041 }
3042
3043 /* Set each timer value. */
3044 rip->update_time = update;
3045 rip->timeout_time = timeout;
3046 rip->garbage_time = garbage;
3047
3048 /* Reset update timer thread. */
3049 rip_event (RIP_UPDATE_EVENT, 0);
3050
3051 return CMD_SUCCESS;
3052}
3053
3054DEFUN (no_rip_timers,
3055 no_rip_timers_cmd,
3056 "no timers basic",
3057 NO_STR
3058 "Adjust routing timers\n"
3059 "Basic routing protocol update timers\n")
3060{
3061 /* Set each timer value to the default. */
3062 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3063 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3064 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3065
3066 /* Reset update timer thread. */
3067 rip_event (RIP_UPDATE_EVENT, 0);
3068
3069 return CMD_SUCCESS;
3070}
hasso16705132003-05-25 14:49:19 +00003071
3072ALIAS (no_rip_timers,
3073 no_rip_timers_val_cmd,
3074 "no timers basic <0-65535> <0-65535> <0-65535>",
3075 NO_STR
3076 "Adjust routing timers\n"
3077 "Basic routing protocol update timers\n"
3078 "Routing table update timer value in second. Default is 30.\n"
3079 "Routing information timeout timer. Default is 180.\n"
3080 "Garbage collection timer. Default is 120.\n")
3081
paul718e3742002-12-13 20:15:29 +00003082
3083struct route_table *rip_distance_table;
3084
3085struct rip_distance
3086{
3087 /* Distance value for the IP source prefix. */
3088 u_char distance;
3089
3090 /* Name of the access-list to be matched. */
3091 char *access_list;
3092};
3093
3094struct rip_distance *
3095rip_distance_new ()
3096{
3097 struct rip_distance *new;
3098 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3099 memset (new, 0, sizeof (struct rip_distance));
3100 return new;
3101}
3102
3103void
3104rip_distance_free (struct rip_distance *rdistance)
3105{
3106 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3107}
3108
3109int
hasso98b718a2004-10-11 12:57:57 +00003110rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3111 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003112{
3113 int ret;
3114 struct prefix_ipv4 p;
3115 u_char distance;
3116 struct route_node *rn;
3117 struct rip_distance *rdistance;
3118
3119 ret = str2prefix_ipv4 (ip_str, &p);
3120 if (ret == 0)
3121 {
3122 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3123 return CMD_WARNING;
3124 }
3125
3126 distance = atoi (distance_str);
3127
3128 /* Get RIP distance node. */
3129 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3130 if (rn->info)
3131 {
3132 rdistance = rn->info;
3133 route_unlock_node (rn);
3134 }
3135 else
3136 {
3137 rdistance = rip_distance_new ();
3138 rn->info = rdistance;
3139 }
3140
3141 /* Set distance value. */
3142 rdistance->distance = distance;
3143
3144 /* Reset access-list configuration. */
3145 if (rdistance->access_list)
3146 {
3147 free (rdistance->access_list);
3148 rdistance->access_list = NULL;
3149 }
3150 if (access_list_str)
3151 rdistance->access_list = strdup (access_list_str);
3152
3153 return CMD_SUCCESS;
3154}
3155
3156int
hasso98b718a2004-10-11 12:57:57 +00003157rip_distance_unset (struct vty *vty, const char *distance_str,
3158 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003159{
3160 int ret;
3161 struct prefix_ipv4 p;
3162 u_char distance;
3163 struct route_node *rn;
3164 struct rip_distance *rdistance;
3165
3166 ret = str2prefix_ipv4 (ip_str, &p);
3167 if (ret == 0)
3168 {
3169 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3170 return CMD_WARNING;
3171 }
3172
3173 distance = atoi (distance_str);
3174
3175 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3176 if (! rn)
3177 {
3178 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3179 return CMD_WARNING;
3180 }
3181
3182 rdistance = rn->info;
3183
3184 if (rdistance->access_list)
3185 free (rdistance->access_list);
3186 rip_distance_free (rdistance);
3187
3188 rn->info = NULL;
3189 route_unlock_node (rn);
3190 route_unlock_node (rn);
3191
3192 return CMD_SUCCESS;
3193}
3194
3195void
3196rip_distance_reset ()
3197{
3198 struct route_node *rn;
3199 struct rip_distance *rdistance;
3200
3201 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3202 if ((rdistance = rn->info) != NULL)
3203 {
3204 if (rdistance->access_list)
3205 free (rdistance->access_list);
3206 rip_distance_free (rdistance);
3207 rn->info = NULL;
3208 route_unlock_node (rn);
3209 }
3210}
3211
3212/* Apply RIP information to distance method. */
3213u_char
3214rip_distance_apply (struct rip_info *rinfo)
3215{
3216 struct route_node *rn;
3217 struct prefix_ipv4 p;
3218 struct rip_distance *rdistance;
3219 struct access_list *alist;
3220
3221 if (! rip)
3222 return 0;
3223
3224 memset (&p, 0, sizeof (struct prefix_ipv4));
3225 p.family = AF_INET;
3226 p.prefix = rinfo->from;
3227 p.prefixlen = IPV4_MAX_BITLEN;
3228
3229 /* Check source address. */
3230 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3231 if (rn)
3232 {
3233 rdistance = rn->info;
3234 route_unlock_node (rn);
3235
3236 if (rdistance->access_list)
3237 {
3238 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3239 if (alist == NULL)
3240 return 0;
3241 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3242 return 0;
3243
3244 return rdistance->distance;
3245 }
3246 else
3247 return rdistance->distance;
3248 }
3249
3250 if (rip->distance)
3251 return rip->distance;
3252
3253 return 0;
3254}
3255
3256void
3257rip_distance_show (struct vty *vty)
3258{
3259 struct route_node *rn;
3260 struct rip_distance *rdistance;
3261 int header = 1;
3262 char buf[BUFSIZ];
3263
3264 vty_out (vty, " Distance: (default is %d)%s",
3265 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3266 VTY_NEWLINE);
3267
3268 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3269 if ((rdistance = rn->info) != NULL)
3270 {
3271 if (header)
3272 {
3273 vty_out (vty, " Address Distance List%s",
3274 VTY_NEWLINE);
3275 header = 0;
3276 }
3277 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3278 vty_out (vty, " %-20s %4d %s%s",
3279 buf, rdistance->distance,
3280 rdistance->access_list ? rdistance->access_list : "",
3281 VTY_NEWLINE);
3282 }
3283}
3284
3285DEFUN (rip_distance,
3286 rip_distance_cmd,
3287 "distance <1-255>",
3288 "Administrative distance\n"
3289 "Distance value\n")
3290{
3291 rip->distance = atoi (argv[0]);
3292 return CMD_SUCCESS;
3293}
3294
3295DEFUN (no_rip_distance,
3296 no_rip_distance_cmd,
3297 "no distance <1-255>",
3298 NO_STR
3299 "Administrative distance\n"
3300 "Distance value\n")
3301{
3302 rip->distance = 0;
3303 return CMD_SUCCESS;
3304}
3305
3306DEFUN (rip_distance_source,
3307 rip_distance_source_cmd,
3308 "distance <1-255> A.B.C.D/M",
3309 "Administrative distance\n"
3310 "Distance value\n"
3311 "IP source prefix\n")
3312{
3313 rip_distance_set (vty, argv[0], argv[1], NULL);
3314 return CMD_SUCCESS;
3315}
3316
3317DEFUN (no_rip_distance_source,
3318 no_rip_distance_source_cmd,
3319 "no distance <1-255> A.B.C.D/M",
3320 NO_STR
3321 "Administrative distance\n"
3322 "Distance value\n"
3323 "IP source prefix\n")
3324{
3325 rip_distance_unset (vty, argv[0], argv[1], NULL);
3326 return CMD_SUCCESS;
3327}
3328
3329DEFUN (rip_distance_source_access_list,
3330 rip_distance_source_access_list_cmd,
3331 "distance <1-255> A.B.C.D/M WORD",
3332 "Administrative distance\n"
3333 "Distance value\n"
3334 "IP source prefix\n"
3335 "Access list name\n")
3336{
3337 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3338 return CMD_SUCCESS;
3339}
3340
3341DEFUN (no_rip_distance_source_access_list,
3342 no_rip_distance_source_access_list_cmd,
3343 "no distance <1-255> A.B.C.D/M WORD",
3344 NO_STR
3345 "Administrative distance\n"
3346 "Distance value\n"
3347 "IP source prefix\n"
3348 "Access list name\n")
3349{
3350 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3351 return CMD_SUCCESS;
3352}
3353
3354/* Print out routes update time. */
3355void
3356rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3357{
3358 struct timeval timer_now;
3359 time_t clock;
3360 struct tm *tm;
3361#define TIME_BUF 25
3362 char timebuf [TIME_BUF];
3363 struct thread *thread;
3364
3365 gettimeofday (&timer_now, NULL);
3366
3367 if ((thread = rinfo->t_timeout) != NULL)
3368 {
3369 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3370 tm = gmtime (&clock);
3371 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3372 vty_out (vty, "%5s", timebuf);
3373 }
3374 else if ((thread = rinfo->t_garbage_collect) != NULL)
3375 {
3376 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3377 tm = gmtime (&clock);
3378 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3379 vty_out (vty, "%5s", timebuf);
3380 }
3381}
3382
hasso8a676be2004-10-08 06:36:38 +00003383const char *
paul718e3742002-12-13 20:15:29 +00003384rip_route_type_print (int sub_type)
3385{
3386 switch (sub_type)
3387 {
3388 case RIP_ROUTE_RTE:
3389 return "n";
3390 case RIP_ROUTE_STATIC:
3391 return "s";
3392 case RIP_ROUTE_DEFAULT:
3393 return "d";
3394 case RIP_ROUTE_REDISTRIBUTE:
3395 return "r";
3396 case RIP_ROUTE_INTERFACE:
3397 return "i";
3398 default:
3399 return "?";
3400 }
3401}
3402
3403DEFUN (show_ip_rip,
3404 show_ip_rip_cmd,
3405 "show ip rip",
3406 SHOW_STR
3407 IP_STR
3408 "Show RIP routes\n")
3409{
3410 struct route_node *np;
3411 struct rip_info *rinfo;
3412
3413 if (! rip)
3414 return CMD_SUCCESS;
3415
hasso16705132003-05-25 14:49:19 +00003416 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3417 "Sub-codes:%s"
3418 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003419 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003420 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003421 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003422
3423 for (np = route_top (rip->table); np; np = route_next (np))
3424 if ((rinfo = np->info) != NULL)
3425 {
3426 int len;
3427
3428 len = vty_out (vty, "%s(%s) %s/%d",
3429 /* np->lock, For debugging. */
3430 route_info[rinfo->type].str,
3431 rip_route_type_print (rinfo->sub_type),
3432 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3433
hassoa1455d82004-03-03 19:36:24 +00003434 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003435
3436 if (len > 0)
3437 vty_out (vty, "%*s", len, " ");
3438
3439 if (rinfo->nexthop.s_addr)
3440 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3441 rinfo->metric);
3442 else
3443 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3444
3445 /* Route which exist in kernel routing table. */
3446 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3447 (rinfo->sub_type == RIP_ROUTE_RTE))
3448 {
3449 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003450 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003451 rip_vty_out_uptime (vty, rinfo);
3452 }
3453 else if (rinfo->metric == RIP_METRIC_INFINITY)
3454 {
3455 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003456 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003457 rip_vty_out_uptime (vty, rinfo);
3458 }
3459 else
hasso16705132003-05-25 14:49:19 +00003460 {
3461 vty_out (vty, "self ");
3462 vty_out (vty, "%3d", rinfo->tag);
3463 }
paul718e3742002-12-13 20:15:29 +00003464
3465 vty_out (vty, "%s", VTY_NEWLINE);
3466 }
3467 return CMD_SUCCESS;
3468}
3469
3470/* Return next event time. */
3471int
3472rip_next_thread_timer (struct thread *thread)
3473{
3474 struct timeval timer_now;
3475
3476 gettimeofday (&timer_now, NULL);
3477
3478 return thread->u.sands.tv_sec - timer_now.tv_sec;
3479}
3480
hasso16705132003-05-25 14:49:19 +00003481/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3482DEFUN (show_ip_rip_status,
3483 show_ip_rip_status_cmd,
3484 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003485 SHOW_STR
3486 IP_STR
hasso16705132003-05-25 14:49:19 +00003487 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003488 "IP routing protocol process parameters and statistics\n")
3489{
hasso52dc7ee2004-09-23 19:18:23 +00003490 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003491 struct interface *ifp;
3492 struct rip_interface *ri;
3493 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003494 const char *send_version;
3495 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003496
3497 if (! rip)
3498 return CMD_SUCCESS;
3499
3500 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3501 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3502 rip->update_time);
3503 vty_out (vty, " next due in %d seconds%s",
3504 rip_next_thread_timer (rip->t_update),
3505 VTY_NEWLINE);
3506 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3507 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3508 VTY_NEWLINE);
3509
3510 /* Filtering status show. */
3511 config_show_distribute (vty);
3512
3513 /* Default metric information. */
3514 vty_out (vty, " Default redistribution metric is %d%s",
3515 rip->default_metric, VTY_NEWLINE);
3516
3517 /* Redistribute information. */
3518 vty_out (vty, " Redistributing:");
3519 config_write_rip_redistribute (vty, 0);
3520 vty_out (vty, "%s", VTY_NEWLINE);
3521
paulf38a4712003-06-07 01:10:00 +00003522 vty_out (vty, " Default version control: send version %s,",
3523 lookup(ri_version_msg,rip->version_send));
3524 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3525 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3526 else
3527 vty_out (vty, " receive version %s %s",
3528 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003529
3530 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3531
3532 for (node = listhead (iflist); node; node = nextnode (node))
3533 {
3534 ifp = getdata (node);
3535 ri = ifp->info;
3536
3537 if (ri->enable_network || ri->enable_interface)
3538 {
3539 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003540 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003541 else
3542 send_version = lookup (ri_version_msg, ri->ri_send);
3543
3544 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003545 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003546 else
3547 receive_version = lookup (ri_version_msg, ri->ri_receive);
3548
3549 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3550 send_version,
3551 receive_version,
3552 ri->key_chain ? ri->key_chain : "",
3553 VTY_NEWLINE);
3554 }
3555 }
3556
3557 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3558 config_write_rip_network (vty, 0);
3559
paul4aaff3f2003-06-07 01:04:45 +00003560 {
3561 int found_passive = 0;
3562 for (node = listhead (iflist); node; node = nextnode (node))
3563 {
3564 ifp = getdata (node);
3565 ri = ifp->info;
3566
3567 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3568 {
3569 if (!found_passive)
3570 {
3571 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3572 found_passive = 1;
3573 }
3574 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3575 }
3576 }
3577 }
3578
paul718e3742002-12-13 20:15:29 +00003579 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3580 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3581 rip_peer_display (vty);
3582
3583 rip_distance_show (vty);
3584
3585 return CMD_SUCCESS;
3586}
3587
3588/* RIP configuration write function. */
3589int
3590config_write_rip (struct vty *vty)
3591{
3592 int write = 0;
3593 struct route_node *rn;
3594 struct rip_distance *rdistance;
3595
3596 if (rip)
3597 {
3598 /* Router RIP statement. */
3599 vty_out (vty, "router rip%s", VTY_NEWLINE);
3600 write++;
3601
3602 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003603 if (rip->version_send != RI_RIP_VERSION_2
3604 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3605 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003606 VTY_NEWLINE);
3607
3608 /* RIP timer configuration. */
3609 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3610 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3611 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3612 vty_out (vty, " timers basic %lu %lu %lu%s",
3613 rip->update_time,
3614 rip->timeout_time,
3615 rip->garbage_time,
3616 VTY_NEWLINE);
3617
3618 /* Default information configuration. */
3619 if (rip->default_information)
3620 {
3621 if (rip->default_information_route_map)
3622 vty_out (vty, " default-information originate route-map %s%s",
3623 rip->default_information_route_map, VTY_NEWLINE);
3624 else
3625 vty_out (vty, " default-information originate%s",
3626 VTY_NEWLINE);
3627 }
3628
3629 /* Redistribute configuration. */
3630 config_write_rip_redistribute (vty, 1);
3631
3632 /* RIP offset-list configuration. */
3633 config_write_rip_offset_list (vty);
3634
3635 /* RIP enabled network and interface configuration. */
3636 config_write_rip_network (vty, 1);
3637
3638 /* RIP default metric configuration */
3639 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3640 vty_out (vty, " default-metric %d%s",
3641 rip->default_metric, VTY_NEWLINE);
3642
3643 /* Distribute configuration. */
3644 write += config_write_distribute (vty);
3645
hasso16705132003-05-25 14:49:19 +00003646 /* Interface routemap configuration */
3647 write += config_write_if_rmap (vty);
3648
paul718e3742002-12-13 20:15:29 +00003649 /* Distance configuration. */
3650 if (rip->distance)
3651 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3652
3653 /* RIP source IP prefix distance configuration. */
3654 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3655 if ((rdistance = rn->info) != NULL)
3656 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3657 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3658 rdistance->access_list ? rdistance->access_list : "",
3659 VTY_NEWLINE);
3660
3661 /* RIP static route configuration. */
3662 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3663 if (rn->info)
3664 vty_out (vty, " route %s/%d%s",
3665 inet_ntoa (rn->p.u.prefix4),
3666 rn->p.prefixlen,
3667 VTY_NEWLINE);
3668
3669 }
3670 return write;
3671}
3672
3673/* RIP node structure. */
3674struct cmd_node rip_node =
3675{
3676 RIP_NODE,
3677 "%s(config-router)# ",
3678 1
3679};
3680
3681/* Distribute-list update functions. */
3682void
3683rip_distribute_update (struct distribute *dist)
3684{
3685 struct interface *ifp;
3686 struct rip_interface *ri;
3687 struct access_list *alist;
3688 struct prefix_list *plist;
3689
3690 if (! dist->ifname)
3691 return;
3692
3693 ifp = if_lookup_by_name (dist->ifname);
3694 if (ifp == NULL)
3695 return;
3696
3697 ri = ifp->info;
3698
3699 if (dist->list[DISTRIBUTE_IN])
3700 {
3701 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3702 if (alist)
3703 ri->list[RIP_FILTER_IN] = alist;
3704 else
3705 ri->list[RIP_FILTER_IN] = NULL;
3706 }
3707 else
3708 ri->list[RIP_FILTER_IN] = NULL;
3709
3710 if (dist->list[DISTRIBUTE_OUT])
3711 {
3712 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3713 if (alist)
3714 ri->list[RIP_FILTER_OUT] = alist;
3715 else
3716 ri->list[RIP_FILTER_OUT] = NULL;
3717 }
3718 else
3719 ri->list[RIP_FILTER_OUT] = NULL;
3720
3721 if (dist->prefix[DISTRIBUTE_IN])
3722 {
3723 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3724 if (plist)
3725 ri->prefix[RIP_FILTER_IN] = plist;
3726 else
3727 ri->prefix[RIP_FILTER_IN] = NULL;
3728 }
3729 else
3730 ri->prefix[RIP_FILTER_IN] = NULL;
3731
3732 if (dist->prefix[DISTRIBUTE_OUT])
3733 {
3734 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3735 if (plist)
3736 ri->prefix[RIP_FILTER_OUT] = plist;
3737 else
3738 ri->prefix[RIP_FILTER_OUT] = NULL;
3739 }
3740 else
3741 ri->prefix[RIP_FILTER_OUT] = NULL;
3742}
3743
3744void
3745rip_distribute_update_interface (struct interface *ifp)
3746{
3747 struct distribute *dist;
3748
3749 dist = distribute_lookup (ifp->name);
3750 if (dist)
3751 rip_distribute_update (dist);
3752}
3753
3754/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003755/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003756void
paul02ff83c2004-06-11 11:27:03 +00003757rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003758{
3759 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003760 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003761
3762 for (node = listhead (iflist); node; nextnode (node))
3763 {
3764 ifp = getdata (node);
3765 rip_distribute_update_interface (ifp);
3766 }
3767}
paul11dde9c2004-05-31 14:00:00 +00003768/* ARGSUSED */
3769void
3770rip_distribute_update_all_wrapper(struct access_list *notused)
3771{
paul02ff83c2004-06-11 11:27:03 +00003772 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003773}
paul718e3742002-12-13 20:15:29 +00003774
3775/* Delete all added rip route. */
3776void
3777rip_clean ()
3778{
3779 int i;
3780 struct route_node *rp;
3781 struct rip_info *rinfo;
3782
3783 if (rip)
3784 {
3785 /* Clear RIP routes */
3786 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3787 if ((rinfo = rp->info) != NULL)
3788 {
3789 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3790 rinfo->sub_type == RIP_ROUTE_RTE)
3791 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3792 &rinfo->nexthop, rinfo->metric);
3793
3794 RIP_TIMER_OFF (rinfo->t_timeout);
3795 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3796
3797 rp->info = NULL;
3798 route_unlock_node (rp);
3799
3800 rip_info_free (rinfo);
3801 }
3802
3803 /* Cancel RIP related timers. */
3804 RIP_TIMER_OFF (rip->t_update);
3805 RIP_TIMER_OFF (rip->t_triggered_update);
3806 RIP_TIMER_OFF (rip->t_triggered_interval);
3807
3808 /* Cancel read thread. */
3809 if (rip->t_read)
3810 {
3811 thread_cancel (rip->t_read);
3812 rip->t_read = NULL;
3813 }
3814
3815 /* Close RIP socket. */
3816 if (rip->sock >= 0)
3817 {
3818 close (rip->sock);
3819 rip->sock = -1;
3820 }
3821
3822 /* Static RIP route configuration. */
3823 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3824 if (rp->info)
3825 {
3826 rp->info = NULL;
3827 route_unlock_node (rp);
3828 }
3829
3830 /* RIP neighbor configuration. */
3831 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3832 if (rp->info)
3833 {
3834 rp->info = NULL;
3835 route_unlock_node (rp);
3836 }
3837
3838 /* Redistribute related clear. */
3839 if (rip->default_information_route_map)
3840 free (rip->default_information_route_map);
3841
3842 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3843 if (rip->route_map[i].name)
3844 free (rip->route_map[i].name);
3845
3846 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3847 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3848 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3849
3850 XFREE (MTYPE_RIP, rip);
3851 rip = NULL;
3852 }
3853
3854 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003855 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003856 rip_offset_clean ();
3857 rip_interface_clean ();
3858 rip_distance_reset ();
3859 rip_redistribute_clean ();
3860}
3861
3862/* Reset all values to the default settings. */
3863void
3864rip_reset ()
3865{
3866 /* Reset global counters. */
3867 rip_global_route_changes = 0;
3868 rip_global_queries = 0;
3869
3870 /* Call ripd related reset functions. */
3871 rip_debug_reset ();
3872 rip_route_map_reset ();
3873
3874 /* Call library reset functions. */
3875 vty_reset ();
3876 access_list_reset ();
3877 prefix_list_reset ();
3878
3879 distribute_list_reset ();
3880
3881 rip_interface_reset ();
3882 rip_distance_reset ();
3883
3884 rip_zclient_reset ();
3885}
3886
hasso16705132003-05-25 14:49:19 +00003887void
3888rip_if_rmap_update (struct if_rmap *if_rmap)
3889{
3890 struct interface *ifp;
3891 struct rip_interface *ri;
3892 struct route_map *rmap;
3893
3894 ifp = if_lookup_by_name (if_rmap->ifname);
3895 if (ifp == NULL)
3896 return;
3897
3898 ri = ifp->info;
3899
3900 if (if_rmap->routemap[IF_RMAP_IN])
3901 {
3902 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3903 if (rmap)
3904 ri->routemap[IF_RMAP_IN] = rmap;
3905 else
3906 ri->routemap[IF_RMAP_IN] = NULL;
3907 }
3908 else
3909 ri->routemap[RIP_FILTER_IN] = NULL;
3910
3911 if (if_rmap->routemap[IF_RMAP_OUT])
3912 {
3913 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3914 if (rmap)
3915 ri->routemap[IF_RMAP_OUT] = rmap;
3916 else
3917 ri->routemap[IF_RMAP_OUT] = NULL;
3918 }
3919 else
3920 ri->routemap[RIP_FILTER_OUT] = NULL;
3921}
3922
3923void
3924rip_if_rmap_update_interface (struct interface *ifp)
3925{
3926 struct if_rmap *if_rmap;
3927
3928 if_rmap = if_rmap_lookup (ifp->name);
3929 if (if_rmap)
3930 rip_if_rmap_update (if_rmap);
3931}
3932
3933void
3934rip_routemap_update_redistribute (void)
3935{
3936 int i;
3937
3938 if (rip)
3939 {
3940 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3941 {
3942 if (rip->route_map[i].name)
3943 rip->route_map[i].map =
3944 route_map_lookup_by_name (rip->route_map[i].name);
3945 }
3946 }
3947}
3948
paul11dde9c2004-05-31 14:00:00 +00003949/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003950void
hasso98b718a2004-10-11 12:57:57 +00003951rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003952{
3953 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003954 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003955
3956 for (node = listhead (iflist); node; nextnode (node))
3957 {
3958 ifp = getdata (node);
3959 rip_if_rmap_update_interface (ifp);
3960 }
3961
3962 rip_routemap_update_redistribute ();
3963}
3964
paul718e3742002-12-13 20:15:29 +00003965/* Allocate new rip structure and set default value. */
3966void
3967rip_init ()
3968{
3969 /* Randomize for triggered update random(). */
3970 srand (time (NULL));
3971
3972 /* Install top nodes. */
3973 install_node (&rip_node, config_write_rip);
3974
3975 /* Install rip commands. */
3976 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003977 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003978 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003979 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003980 install_element (CONFIG_NODE, &router_rip_cmd);
3981 install_element (CONFIG_NODE, &no_router_rip_cmd);
3982
3983 install_default (RIP_NODE);
3984 install_element (RIP_NODE, &rip_version_cmd);
3985 install_element (RIP_NODE, &no_rip_version_cmd);
3986 install_element (RIP_NODE, &no_rip_version_val_cmd);
3987 install_element (RIP_NODE, &rip_default_metric_cmd);
3988 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3989 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3990 install_element (RIP_NODE, &rip_timers_cmd);
3991 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003992 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003993 install_element (RIP_NODE, &rip_route_cmd);
3994 install_element (RIP_NODE, &no_rip_route_cmd);
3995 install_element (RIP_NODE, &rip_distance_cmd);
3996 install_element (RIP_NODE, &no_rip_distance_cmd);
3997 install_element (RIP_NODE, &rip_distance_source_cmd);
3998 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3999 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4000 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4001
4002 /* Debug related init. */
4003 rip_debug_init ();
4004
paul718e3742002-12-13 20:15:29 +00004005 /* SNMP init. */
4006#ifdef HAVE_SNMP
4007 rip_snmp_init ();
4008#endif /* HAVE_SNMP */
4009
4010 /* Access list install. */
4011 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004012 access_list_add_hook (rip_distribute_update_all_wrapper);
4013 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004014
4015 /* Prefix list initialize.*/
4016 prefix_list_init ();
4017 prefix_list_add_hook (rip_distribute_update_all);
4018 prefix_list_delete_hook (rip_distribute_update_all);
4019
4020 /* Distribute list install. */
4021 distribute_list_init (RIP_NODE);
4022 distribute_list_add_hook (rip_distribute_update);
4023 distribute_list_delete_hook (rip_distribute_update);
4024
hasso16705132003-05-25 14:49:19 +00004025 /* Route-map */
4026 rip_route_map_init ();
4027 rip_offset_init ();
4028
4029 route_map_add_hook (rip_routemap_update);
4030 route_map_delete_hook (rip_routemap_update);
4031
4032 if_rmap_init (RIP_NODE);
4033 if_rmap_hook_add (rip_if_rmap_update);
4034 if_rmap_hook_delete (rip_if_rmap_update);
4035
paul718e3742002-12-13 20:15:29 +00004036 /* Distance control. */
4037 rip_distance_table = route_table_init ();
4038}