blob: 94324f03ab03861859d5e2488850e7f1b99e2c8a [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{
paul718e3742002-12-13 20:15:29 +00002394 struct connected *connected;
hasso52dc7ee2004-09-23 19:18:23 +00002395 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002396 struct sockaddr_in to;
paul931cd542004-01-23 15:31:42 +00002397 struct prefix_ipv4 *saddr = (struct prefix_ipv4 *) sconn->address;
paul718e3742002-12-13 20:15:29 +00002398
2399 /* When RIP version is 2 and multicast enable interface. */
2400 if (version == RIPv2 && if_is_multicast (ifp))
2401 {
2402 if (IS_RIP_DEBUG_EVENT)
2403 zlog_info ("multicast announce on %s ", ifp->name);
2404
hassocaa6f8a2004-03-03 19:48:48 +00002405 rip_output_process (ifp, NULL, NULL, route_type, version,
paul931cd542004-01-23 15:31:42 +00002406 sconn, saddr);
paul718e3742002-12-13 20:15:29 +00002407 return;
2408 }
2409
2410 /* If we can't send multicast packet, send it with unicast. */
2411 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
2412 {
2413 for (node = listhead (ifp->connected); node; nextnode (node))
2414 {
2415 connected = getdata (node);
2416
hasso3fb9cd62004-10-19 19:44:43 +00002417 if (connected->address->family == AF_INET)
paul718e3742002-12-13 20:15:29 +00002418 {
2419 /* Destination address and port setting. */
2420 memset (&to, 0, sizeof (struct sockaddr_in));
hasso3fb9cd62004-10-19 19:44:43 +00002421 if (connected->destination)
2422 /* use specified broadcast or point-to-point destination addr */
2423 to.sin_addr = connected->destination->u.prefix4;
2424 else
2425 /* calculate the appropriate broadcast address */
2426 to.sin_addr.s_addr =
2427 ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
2428 connected->address->prefixlen);
paul718e3742002-12-13 20:15:29 +00002429 to.sin_port = htons (RIP_PORT_DEFAULT);
2430
2431 if (IS_RIP_DEBUG_EVENT)
2432 zlog_info ("%s announce to %s on %s",
2433 if_is_pointopoint (ifp) ? "unicast" : "broadcast",
2434 inet_ntoa (to.sin_addr), ifp->name);
2435
paul727d1042002-12-13 20:50:29 +00002436 rip_output_process (ifp, connected->address, &to, route_type,
hassocaa6f8a2004-03-03 19:48:48 +00002437 version, connected, saddr);
paul718e3742002-12-13 20:15:29 +00002438 }
2439 }
2440 }
2441}
2442
2443/* Update send to all interface and neighbor. */
2444void
2445rip_update_process (int route_type)
2446{
hasso52dc7ee2004-09-23 19:18:23 +00002447 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002448 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002449 struct interface *ifp;
2450 struct rip_interface *ri;
2451 struct route_node *rp;
2452 struct sockaddr_in to;
2453 struct prefix_ipv4 *p;
2454
2455 /* Send RIP update to each interface. */
2456 for (node = listhead (iflist); node; nextnode (node))
2457 {
2458 ifp = getdata (node);
2459
2460 if (if_is_loopback (ifp))
2461 continue;
2462
paul2e3b2e42002-12-13 21:03:13 +00002463 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002464 continue;
2465
2466 /* Fetch RIP interface information. */
2467 ri = ifp->info;
2468
2469 /* When passive interface is specified, suppress announce to the
2470 interface. */
2471 if (ri->passive)
2472 continue;
2473
2474 if (ri->running)
2475 {
2476 if (IS_RIP_DEBUG_EVENT)
2477 {
2478 if (ifp->name)
2479 zlog_info ("SEND UPDATE to %s ifindex %d",
2480 ifp->name, ifp->ifindex);
2481 else
2482 zlog_info ("SEND UPDATE to _unknown_ ifindex %d",
2483 ifp->ifindex);
2484 }
2485
paulcc1131a2003-10-15 23:20:17 +00002486 /* send update on each connected network */
2487
2488 LIST_LOOP(ifp->connected, connected, ifnode)
2489 {
2490 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002491 int done = 0;
2492 /*
2493 * If there is no version configuration in the interface,
2494 * use rip's version setting.
2495 */
paulf38a4712003-06-07 01:10:00 +00002496 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2497 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002498
2499 ifaddr = (struct prefix_ipv4 *) connected->address;
2500
2501 if (ifaddr->family != AF_INET)
2502 continue;
2503
paul931cd542004-01-23 15:31:42 +00002504 if ((vsend & RIPv1) && !done)
2505 rip_update_interface (ifp, RIPv1, route_type, connected);
2506 if ((vsend & RIPv2) && if_is_multicast(ifp))
2507 rip_update_interface (ifp, RIPv2, route_type, connected);
2508 done = 1;
2509 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2510 break;
2511
paulf38a4712003-06-07 01:10:00 +00002512 }
paul718e3742002-12-13 20:15:29 +00002513 }
2514 }
2515
2516 /* RIP send updates to each neighbor. */
2517 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2518 if (rp->info != NULL)
2519 {
2520 p = (struct prefix_ipv4 *) &rp->p;
2521
2522 ifp = if_lookup_address (p->prefix);
2523 if (! ifp)
2524 {
2525 zlog_warn ("Neighbor %s doesn't exist direct connected network",
2526 inet_ntoa (p->prefix));
2527 continue;
2528 }
2529
2530 /* Set destination address and port */
2531 memset (&to, 0, sizeof (struct sockaddr_in));
2532 to.sin_addr = p->prefix;
2533 to.sin_port = htons (RIP_PORT_DEFAULT);
2534
2535 /* RIP version is rip's configuration. */
paul931cd542004-01-23 15:31:42 +00002536 rip_output_process (ifp, NULL, &to, route_type, rip->version_send,
2537 NULL, p);
paul718e3742002-12-13 20:15:29 +00002538 }
2539}
2540
2541/* RIP's periodical timer. */
2542int
2543rip_update (struct thread *t)
2544{
2545 /* Clear timer pointer. */
2546 rip->t_update = NULL;
2547
2548 if (IS_RIP_DEBUG_EVENT)
2549 zlog_info ("update timer fire!");
2550
2551 /* Process update output. */
2552 rip_update_process (rip_all_route);
2553
2554 /* Triggered updates may be suppressed if a regular update is due by
2555 the time the triggered update would be sent. */
2556 if (rip->t_triggered_interval)
2557 {
2558 thread_cancel (rip->t_triggered_interval);
2559 rip->t_triggered_interval = NULL;
2560 }
2561 rip->trigger = 0;
2562
2563 /* Register myself. */
2564 rip_event (RIP_UPDATE_EVENT, 0);
2565
2566 return 0;
2567}
2568
2569/* Walk down the RIP routing table then clear changed flag. */
2570void
2571rip_clear_changed_flag ()
2572{
2573 struct route_node *rp;
2574 struct rip_info *rinfo;
2575
2576 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2577 if ((rinfo = rp->info) != NULL)
2578 if (rinfo->flags & RIP_RTF_CHANGED)
2579 rinfo->flags &= ~RIP_RTF_CHANGED;
2580}
2581
2582/* Triggered update interval timer. */
2583int
2584rip_triggered_interval (struct thread *t)
2585{
2586 int rip_triggered_update (struct thread *);
2587
2588 rip->t_triggered_interval = NULL;
2589
2590 if (rip->trigger)
2591 {
2592 rip->trigger = 0;
2593 rip_triggered_update (t);
2594 }
2595 return 0;
2596}
2597
2598/* Execute triggered update. */
2599int
2600rip_triggered_update (struct thread *t)
2601{
2602 int interval;
2603
2604 /* Clear thred pointer. */
2605 rip->t_triggered_update = NULL;
2606
2607 /* Cancel interval timer. */
2608 if (rip->t_triggered_interval)
2609 {
2610 thread_cancel (rip->t_triggered_interval);
2611 rip->t_triggered_interval = NULL;
2612 }
2613 rip->trigger = 0;
2614
2615 /* Logging triggered update. */
2616 if (IS_RIP_DEBUG_EVENT)
2617 zlog_info ("triggered update!");
2618
2619 /* Split Horizon processing is done when generating triggered
2620 updates as well as normal updates (see section 2.6). */
2621 rip_update_process (rip_changed_route);
2622
2623 /* Once all of the triggered updates have been generated, the route
2624 change flags should be cleared. */
2625 rip_clear_changed_flag ();
2626
2627 /* After a triggered update is sent, a timer should be set for a
2628 random interval between 1 and 5 seconds. If other changes that
2629 would trigger updates occur before the timer expires, a single
2630 update is triggered when the timer expires. */
2631 interval = (random () % 5) + 1;
2632
2633 rip->t_triggered_interval =
2634 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2635
2636 return 0;
2637}
2638
2639/* Withdraw redistributed route. */
2640void
2641rip_redistribute_withdraw (int type)
2642{
2643 struct route_node *rp;
2644 struct rip_info *rinfo;
2645
2646 if (!rip)
2647 return;
2648
2649 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2650 if ((rinfo = rp->info) != NULL)
2651 {
2652 if (rinfo->type == type
2653 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2654 {
2655 /* Perform poisoned reverse. */
2656 rinfo->metric = RIP_METRIC_INFINITY;
2657 RIP_TIMER_ON (rinfo->t_garbage_collect,
2658 rip_garbage_collect, rip->garbage_time);
2659 RIP_TIMER_OFF (rinfo->t_timeout);
2660 rinfo->flags |= RIP_RTF_CHANGED;
2661
hasso16705132003-05-25 14:49:19 +00002662 if (IS_RIP_DEBUG_EVENT) {
2663 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2664
2665 zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2666 inet_ntoa(p->prefix), p->prefixlen,
2667 ifindex2ifname(rinfo->ifindex));
2668 }
2669
paul718e3742002-12-13 20:15:29 +00002670 rip_event (RIP_TRIGGERED_UPDATE, 0);
2671 }
2672 }
2673}
2674
2675/* Create new RIP instance and set it to global variable. */
2676int
2677rip_create ()
2678{
2679 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2680 memset (rip, 0, sizeof (struct rip));
2681
2682 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002683 rip->version_send = RI_RIP_VERSION_2;
2684 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002685 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2686 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2687 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2688 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2689
2690 /* Initialize RIP routig table. */
2691 rip->table = route_table_init ();
2692 rip->route = route_table_init ();
2693 rip->neighbor = route_table_init ();
2694
2695 /* Make output stream. */
2696 rip->obuf = stream_new (1500);
2697
2698 /* Make socket. */
2699 rip->sock = rip_create_socket ();
2700 if (rip->sock < 0)
2701 return rip->sock;
2702
2703 /* Create read and timer thread. */
2704 rip_event (RIP_READ, rip->sock);
2705 rip_event (RIP_UPDATE_EVENT, 1);
2706
2707 return 0;
2708}
2709
2710/* Sned RIP request to the destination. */
2711int
2712rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002713 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002714{
2715 struct rte *rte;
2716 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002717 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002718
2719 memset (&rip_packet, 0, sizeof (rip_packet));
2720
2721 rip_packet.command = RIP_REQUEST;
2722 rip_packet.version = version;
2723 rte = rip_packet.rte;
2724 rte->metric = htonl (RIP_METRIC_INFINITY);
2725
paul931cd542004-01-23 15:31:42 +00002726 if (connected)
2727 {
2728 /*
2729 * connected is only sent for ripv1 case, or when
2730 * interface does not support multicast. Caller loops
2731 * over each connected address for this case.
2732 */
paul11dde9c2004-05-31 14:00:00 +00002733 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002734 to, ifp, connected) != sizeof (rip_packet))
2735 return -1;
2736 else
2737 return sizeof (rip_packet);
2738 }
2739
paulcc1131a2003-10-15 23:20:17 +00002740 /* send request on each connected network */
2741 LIST_LOOP(ifp->connected, connected, node)
2742 {
2743 struct prefix_ipv4 *p;
2744
2745 p = (struct prefix_ipv4 *) connected->address;
2746
2747 if (p->family != AF_INET)
2748 continue;
2749
paul11dde9c2004-05-31 14:00:00 +00002750 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paul931cd542004-01-23 15:31:42 +00002751 to, ifp, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002752 return -1;
2753 }
2754 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002755}
2756
2757int
2758rip_update_jitter (unsigned long time)
2759{
paul239389b2004-05-05 14:09:37 +00002760#define JITTER_BOUND 4
2761 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2762 Given that, we cannot let time be less than JITTER_BOUND seconds.
2763 The RIPv2 RFC says jitter should be small compared to
2764 update_time. We consider 1/JITTER_BOUND to be small.
2765 */
2766
2767 int jitter_input = time;
2768 int jitter;
2769
2770 if (jitter_input < JITTER_BOUND)
2771 jitter_input = JITTER_BOUND;
2772
2773 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2774
2775 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002776}
2777
2778void
2779rip_event (enum rip_event event, int sock)
2780{
2781 int jitter = 0;
2782
2783 switch (event)
2784 {
2785 case RIP_READ:
2786 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2787 break;
2788 case RIP_UPDATE_EVENT:
2789 if (rip->t_update)
2790 {
2791 thread_cancel (rip->t_update);
2792 rip->t_update = NULL;
2793 }
2794 jitter = rip_update_jitter (rip->update_time);
2795 rip->t_update =
2796 thread_add_timer (master, rip_update, NULL,
2797 sock ? 2 : rip->update_time + jitter);
2798 break;
2799 case RIP_TRIGGERED_UPDATE:
2800 if (rip->t_triggered_interval)
2801 rip->trigger = 1;
2802 else if (! rip->t_triggered_update)
2803 rip->t_triggered_update =
2804 thread_add_event (master, rip_triggered_update, NULL, 0);
2805 break;
2806 default:
2807 break;
2808 }
2809}
2810
2811DEFUN (router_rip,
2812 router_rip_cmd,
2813 "router rip",
2814 "Enable a routing process\n"
2815 "Routing Information Protocol (RIP)\n")
2816{
2817 int ret;
2818
2819 /* If rip is not enabled before. */
2820 if (! rip)
2821 {
2822 ret = rip_create ();
2823 if (ret < 0)
2824 {
2825 zlog_info ("Can't create RIP");
2826 return CMD_WARNING;
2827 }
2828 }
2829 vty->node = RIP_NODE;
2830 vty->index = rip;
2831
2832 return CMD_SUCCESS;
2833}
2834
2835DEFUN (no_router_rip,
2836 no_router_rip_cmd,
2837 "no router rip",
2838 NO_STR
2839 "Enable a routing process\n"
2840 "Routing Information Protocol (RIP)\n")
2841{
2842 if (rip)
2843 rip_clean ();
2844 return CMD_SUCCESS;
2845}
2846
2847DEFUN (rip_version,
2848 rip_version_cmd,
2849 "version <1-2>",
2850 "Set routing protocol version\n"
2851 "version\n")
2852{
2853 int version;
2854
2855 version = atoi (argv[0]);
2856 if (version != RIPv1 && version != RIPv2)
2857 {
2858 vty_out (vty, "invalid rip version %d%s", version,
2859 VTY_NEWLINE);
2860 return CMD_WARNING;
2861 }
paulf38a4712003-06-07 01:10:00 +00002862 rip->version_send = version;
2863 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002864
2865 return CMD_SUCCESS;
2866}
2867
2868DEFUN (no_rip_version,
2869 no_rip_version_cmd,
2870 "no version",
2871 NO_STR
2872 "Set routing protocol version\n")
2873{
2874 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002875 rip->version_send = RI_RIP_VERSION_2;
2876 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002877
2878 return CMD_SUCCESS;
2879}
2880
2881ALIAS (no_rip_version,
2882 no_rip_version_val_cmd,
2883 "no version <1-2>",
2884 NO_STR
2885 "Set routing protocol version\n"
2886 "version\n")
2887
2888DEFUN (rip_route,
2889 rip_route_cmd,
2890 "route A.B.C.D/M",
2891 "RIP static route configuration\n"
2892 "IP prefix <network>/<length>\n")
2893{
2894 int ret;
2895 struct prefix_ipv4 p;
2896 struct route_node *node;
2897
2898 ret = str2prefix_ipv4 (argv[0], &p);
2899 if (ret < 0)
2900 {
2901 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2902 return CMD_WARNING;
2903 }
2904 apply_mask_ipv4 (&p);
2905
2906 /* For router rip configuration. */
2907 node = route_node_get (rip->route, (struct prefix *) &p);
2908
2909 if (node->info)
2910 {
2911 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2912 route_unlock_node (node);
2913 return CMD_WARNING;
2914 }
2915
hasso8a676be2004-10-08 06:36:38 +00002916 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002917
2918 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2919
2920 return CMD_SUCCESS;
2921}
2922
2923DEFUN (no_rip_route,
2924 no_rip_route_cmd,
2925 "no route A.B.C.D/M",
2926 NO_STR
2927 "RIP static route configuration\n"
2928 "IP prefix <network>/<length>\n")
2929{
2930 int ret;
2931 struct prefix_ipv4 p;
2932 struct route_node *node;
2933
2934 ret = str2prefix_ipv4 (argv[0], &p);
2935 if (ret < 0)
2936 {
2937 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2938 return CMD_WARNING;
2939 }
2940 apply_mask_ipv4 (&p);
2941
2942 /* For router rip configuration. */
2943 node = route_node_lookup (rip->route, (struct prefix *) &p);
2944 if (! node)
2945 {
2946 vty_out (vty, "Can't find route %s.%s", argv[0],
2947 VTY_NEWLINE);
2948 return CMD_WARNING;
2949 }
2950
2951 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2952 route_unlock_node (node);
2953
2954 node->info = NULL;
2955 route_unlock_node (node);
2956
2957 return CMD_SUCCESS;
2958}
2959
2960void
2961rip_update_default_metric ()
2962{
2963 struct route_node *np;
2964 struct rip_info *rinfo;
2965
2966 for (np = route_top (rip->table); np; np = route_next (np))
2967 if ((rinfo = np->info) != NULL)
2968 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2969 rinfo->metric = rip->default_metric;
2970}
2971
2972DEFUN (rip_default_metric,
2973 rip_default_metric_cmd,
2974 "default-metric <1-16>",
2975 "Set a metric of redistribute routes\n"
2976 "Default metric\n")
2977{
2978 if (rip)
2979 {
2980 rip->default_metric = atoi (argv[0]);
2981 /* rip_update_default_metric (); */
2982 }
2983 return CMD_SUCCESS;
2984}
2985
2986DEFUN (no_rip_default_metric,
2987 no_rip_default_metric_cmd,
2988 "no default-metric",
2989 NO_STR
2990 "Set a metric of redistribute routes\n"
2991 "Default metric\n")
2992{
2993 if (rip)
2994 {
2995 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2996 /* rip_update_default_metric (); */
2997 }
2998 return CMD_SUCCESS;
2999}
3000
3001ALIAS (no_rip_default_metric,
3002 no_rip_default_metric_val_cmd,
3003 "no default-metric <1-16>",
3004 NO_STR
3005 "Set a metric of redistribute routes\n"
3006 "Default metric\n")
3007
3008DEFUN (rip_timers,
3009 rip_timers_cmd,
3010 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3011 "Adjust routing timers\n"
3012 "Basic routing protocol update timers\n"
3013 "Routing table update timer value in second. Default is 30.\n"
3014 "Routing information timeout timer. Default is 180.\n"
3015 "Garbage collection timer. Default is 120.\n")
3016{
3017 unsigned long update;
3018 unsigned long timeout;
3019 unsigned long garbage;
3020 char *endptr = NULL;
3021 unsigned long RIP_TIMER_MAX = 2147483647;
3022 unsigned long RIP_TIMER_MIN = 5;
3023
3024 update = strtoul (argv[0], &endptr, 10);
3025 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3026 {
3027 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3028 return CMD_WARNING;
3029 }
3030
3031 timeout = strtoul (argv[1], &endptr, 10);
3032 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3033 {
3034 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3035 return CMD_WARNING;
3036 }
3037
3038 garbage = strtoul (argv[2], &endptr, 10);
3039 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3040 {
3041 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3042 return CMD_WARNING;
3043 }
3044
3045 /* Set each timer value. */
3046 rip->update_time = update;
3047 rip->timeout_time = timeout;
3048 rip->garbage_time = garbage;
3049
3050 /* Reset update timer thread. */
3051 rip_event (RIP_UPDATE_EVENT, 0);
3052
3053 return CMD_SUCCESS;
3054}
3055
3056DEFUN (no_rip_timers,
3057 no_rip_timers_cmd,
3058 "no timers basic",
3059 NO_STR
3060 "Adjust routing timers\n"
3061 "Basic routing protocol update timers\n")
3062{
3063 /* Set each timer value to the default. */
3064 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3065 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3066 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3067
3068 /* Reset update timer thread. */
3069 rip_event (RIP_UPDATE_EVENT, 0);
3070
3071 return CMD_SUCCESS;
3072}
hasso16705132003-05-25 14:49:19 +00003073
3074ALIAS (no_rip_timers,
3075 no_rip_timers_val_cmd,
3076 "no timers basic <0-65535> <0-65535> <0-65535>",
3077 NO_STR
3078 "Adjust routing timers\n"
3079 "Basic routing protocol update timers\n"
3080 "Routing table update timer value in second. Default is 30.\n"
3081 "Routing information timeout timer. Default is 180.\n"
3082 "Garbage collection timer. Default is 120.\n")
3083
paul718e3742002-12-13 20:15:29 +00003084
3085struct route_table *rip_distance_table;
3086
3087struct rip_distance
3088{
3089 /* Distance value for the IP source prefix. */
3090 u_char distance;
3091
3092 /* Name of the access-list to be matched. */
3093 char *access_list;
3094};
3095
3096struct rip_distance *
3097rip_distance_new ()
3098{
3099 struct rip_distance *new;
3100 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3101 memset (new, 0, sizeof (struct rip_distance));
3102 return new;
3103}
3104
3105void
3106rip_distance_free (struct rip_distance *rdistance)
3107{
3108 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3109}
3110
3111int
hasso98b718a2004-10-11 12:57:57 +00003112rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3113 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003114{
3115 int ret;
3116 struct prefix_ipv4 p;
3117 u_char distance;
3118 struct route_node *rn;
3119 struct rip_distance *rdistance;
3120
3121 ret = str2prefix_ipv4 (ip_str, &p);
3122 if (ret == 0)
3123 {
3124 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3125 return CMD_WARNING;
3126 }
3127
3128 distance = atoi (distance_str);
3129
3130 /* Get RIP distance node. */
3131 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3132 if (rn->info)
3133 {
3134 rdistance = rn->info;
3135 route_unlock_node (rn);
3136 }
3137 else
3138 {
3139 rdistance = rip_distance_new ();
3140 rn->info = rdistance;
3141 }
3142
3143 /* Set distance value. */
3144 rdistance->distance = distance;
3145
3146 /* Reset access-list configuration. */
3147 if (rdistance->access_list)
3148 {
3149 free (rdistance->access_list);
3150 rdistance->access_list = NULL;
3151 }
3152 if (access_list_str)
3153 rdistance->access_list = strdup (access_list_str);
3154
3155 return CMD_SUCCESS;
3156}
3157
3158int
hasso98b718a2004-10-11 12:57:57 +00003159rip_distance_unset (struct vty *vty, const char *distance_str,
3160 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003161{
3162 int ret;
3163 struct prefix_ipv4 p;
3164 u_char distance;
3165 struct route_node *rn;
3166 struct rip_distance *rdistance;
3167
3168 ret = str2prefix_ipv4 (ip_str, &p);
3169 if (ret == 0)
3170 {
3171 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3172 return CMD_WARNING;
3173 }
3174
3175 distance = atoi (distance_str);
3176
3177 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3178 if (! rn)
3179 {
3180 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3181 return CMD_WARNING;
3182 }
3183
3184 rdistance = rn->info;
3185
3186 if (rdistance->access_list)
3187 free (rdistance->access_list);
3188 rip_distance_free (rdistance);
3189
3190 rn->info = NULL;
3191 route_unlock_node (rn);
3192 route_unlock_node (rn);
3193
3194 return CMD_SUCCESS;
3195}
3196
3197void
3198rip_distance_reset ()
3199{
3200 struct route_node *rn;
3201 struct rip_distance *rdistance;
3202
3203 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3204 if ((rdistance = rn->info) != NULL)
3205 {
3206 if (rdistance->access_list)
3207 free (rdistance->access_list);
3208 rip_distance_free (rdistance);
3209 rn->info = NULL;
3210 route_unlock_node (rn);
3211 }
3212}
3213
3214/* Apply RIP information to distance method. */
3215u_char
3216rip_distance_apply (struct rip_info *rinfo)
3217{
3218 struct route_node *rn;
3219 struct prefix_ipv4 p;
3220 struct rip_distance *rdistance;
3221 struct access_list *alist;
3222
3223 if (! rip)
3224 return 0;
3225
3226 memset (&p, 0, sizeof (struct prefix_ipv4));
3227 p.family = AF_INET;
3228 p.prefix = rinfo->from;
3229 p.prefixlen = IPV4_MAX_BITLEN;
3230
3231 /* Check source address. */
3232 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3233 if (rn)
3234 {
3235 rdistance = rn->info;
3236 route_unlock_node (rn);
3237
3238 if (rdistance->access_list)
3239 {
3240 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3241 if (alist == NULL)
3242 return 0;
3243 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3244 return 0;
3245
3246 return rdistance->distance;
3247 }
3248 else
3249 return rdistance->distance;
3250 }
3251
3252 if (rip->distance)
3253 return rip->distance;
3254
3255 return 0;
3256}
3257
3258void
3259rip_distance_show (struct vty *vty)
3260{
3261 struct route_node *rn;
3262 struct rip_distance *rdistance;
3263 int header = 1;
3264 char buf[BUFSIZ];
3265
3266 vty_out (vty, " Distance: (default is %d)%s",
3267 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3268 VTY_NEWLINE);
3269
3270 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3271 if ((rdistance = rn->info) != NULL)
3272 {
3273 if (header)
3274 {
3275 vty_out (vty, " Address Distance List%s",
3276 VTY_NEWLINE);
3277 header = 0;
3278 }
3279 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3280 vty_out (vty, " %-20s %4d %s%s",
3281 buf, rdistance->distance,
3282 rdistance->access_list ? rdistance->access_list : "",
3283 VTY_NEWLINE);
3284 }
3285}
3286
3287DEFUN (rip_distance,
3288 rip_distance_cmd,
3289 "distance <1-255>",
3290 "Administrative distance\n"
3291 "Distance value\n")
3292{
3293 rip->distance = atoi (argv[0]);
3294 return CMD_SUCCESS;
3295}
3296
3297DEFUN (no_rip_distance,
3298 no_rip_distance_cmd,
3299 "no distance <1-255>",
3300 NO_STR
3301 "Administrative distance\n"
3302 "Distance value\n")
3303{
3304 rip->distance = 0;
3305 return CMD_SUCCESS;
3306}
3307
3308DEFUN (rip_distance_source,
3309 rip_distance_source_cmd,
3310 "distance <1-255> A.B.C.D/M",
3311 "Administrative distance\n"
3312 "Distance value\n"
3313 "IP source prefix\n")
3314{
3315 rip_distance_set (vty, argv[0], argv[1], NULL);
3316 return CMD_SUCCESS;
3317}
3318
3319DEFUN (no_rip_distance_source,
3320 no_rip_distance_source_cmd,
3321 "no distance <1-255> A.B.C.D/M",
3322 NO_STR
3323 "Administrative distance\n"
3324 "Distance value\n"
3325 "IP source prefix\n")
3326{
3327 rip_distance_unset (vty, argv[0], argv[1], NULL);
3328 return CMD_SUCCESS;
3329}
3330
3331DEFUN (rip_distance_source_access_list,
3332 rip_distance_source_access_list_cmd,
3333 "distance <1-255> A.B.C.D/M WORD",
3334 "Administrative distance\n"
3335 "Distance value\n"
3336 "IP source prefix\n"
3337 "Access list name\n")
3338{
3339 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3340 return CMD_SUCCESS;
3341}
3342
3343DEFUN (no_rip_distance_source_access_list,
3344 no_rip_distance_source_access_list_cmd,
3345 "no distance <1-255> A.B.C.D/M WORD",
3346 NO_STR
3347 "Administrative distance\n"
3348 "Distance value\n"
3349 "IP source prefix\n"
3350 "Access list name\n")
3351{
3352 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3353 return CMD_SUCCESS;
3354}
3355
3356/* Print out routes update time. */
3357void
3358rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3359{
3360 struct timeval timer_now;
3361 time_t clock;
3362 struct tm *tm;
3363#define TIME_BUF 25
3364 char timebuf [TIME_BUF];
3365 struct thread *thread;
3366
3367 gettimeofday (&timer_now, NULL);
3368
3369 if ((thread = rinfo->t_timeout) != NULL)
3370 {
3371 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3372 tm = gmtime (&clock);
3373 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3374 vty_out (vty, "%5s", timebuf);
3375 }
3376 else if ((thread = rinfo->t_garbage_collect) != NULL)
3377 {
3378 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3379 tm = gmtime (&clock);
3380 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3381 vty_out (vty, "%5s", timebuf);
3382 }
3383}
3384
hasso8a676be2004-10-08 06:36:38 +00003385const char *
paul718e3742002-12-13 20:15:29 +00003386rip_route_type_print (int sub_type)
3387{
3388 switch (sub_type)
3389 {
3390 case RIP_ROUTE_RTE:
3391 return "n";
3392 case RIP_ROUTE_STATIC:
3393 return "s";
3394 case RIP_ROUTE_DEFAULT:
3395 return "d";
3396 case RIP_ROUTE_REDISTRIBUTE:
3397 return "r";
3398 case RIP_ROUTE_INTERFACE:
3399 return "i";
3400 default:
3401 return "?";
3402 }
3403}
3404
3405DEFUN (show_ip_rip,
3406 show_ip_rip_cmd,
3407 "show ip rip",
3408 SHOW_STR
3409 IP_STR
3410 "Show RIP routes\n")
3411{
3412 struct route_node *np;
3413 struct rip_info *rinfo;
3414
3415 if (! rip)
3416 return CMD_SUCCESS;
3417
hasso16705132003-05-25 14:49:19 +00003418 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3419 "Sub-codes:%s"
3420 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003421 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003422 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003423 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003424
3425 for (np = route_top (rip->table); np; np = route_next (np))
3426 if ((rinfo = np->info) != NULL)
3427 {
3428 int len;
3429
3430 len = vty_out (vty, "%s(%s) %s/%d",
3431 /* np->lock, For debugging. */
3432 route_info[rinfo->type].str,
3433 rip_route_type_print (rinfo->sub_type),
3434 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3435
hassoa1455d82004-03-03 19:36:24 +00003436 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003437
3438 if (len > 0)
3439 vty_out (vty, "%*s", len, " ");
3440
3441 if (rinfo->nexthop.s_addr)
3442 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3443 rinfo->metric);
3444 else
3445 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3446
3447 /* Route which exist in kernel routing table. */
3448 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3449 (rinfo->sub_type == RIP_ROUTE_RTE))
3450 {
3451 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003452 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003453 rip_vty_out_uptime (vty, rinfo);
3454 }
3455 else if (rinfo->metric == RIP_METRIC_INFINITY)
3456 {
3457 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003458 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003459 rip_vty_out_uptime (vty, rinfo);
3460 }
3461 else
hasso16705132003-05-25 14:49:19 +00003462 {
3463 vty_out (vty, "self ");
3464 vty_out (vty, "%3d", rinfo->tag);
3465 }
paul718e3742002-12-13 20:15:29 +00003466
3467 vty_out (vty, "%s", VTY_NEWLINE);
3468 }
3469 return CMD_SUCCESS;
3470}
3471
3472/* Return next event time. */
3473int
3474rip_next_thread_timer (struct thread *thread)
3475{
3476 struct timeval timer_now;
3477
3478 gettimeofday (&timer_now, NULL);
3479
3480 return thread->u.sands.tv_sec - timer_now.tv_sec;
3481}
3482
hasso16705132003-05-25 14:49:19 +00003483/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3484DEFUN (show_ip_rip_status,
3485 show_ip_rip_status_cmd,
3486 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003487 SHOW_STR
3488 IP_STR
hasso16705132003-05-25 14:49:19 +00003489 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003490 "IP routing protocol process parameters and statistics\n")
3491{
hasso52dc7ee2004-09-23 19:18:23 +00003492 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003493 struct interface *ifp;
3494 struct rip_interface *ri;
3495 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003496 const char *send_version;
3497 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003498
3499 if (! rip)
3500 return CMD_SUCCESS;
3501
3502 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3503 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3504 rip->update_time);
3505 vty_out (vty, " next due in %d seconds%s",
3506 rip_next_thread_timer (rip->t_update),
3507 VTY_NEWLINE);
3508 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3509 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3510 VTY_NEWLINE);
3511
3512 /* Filtering status show. */
3513 config_show_distribute (vty);
3514
3515 /* Default metric information. */
3516 vty_out (vty, " Default redistribution metric is %d%s",
3517 rip->default_metric, VTY_NEWLINE);
3518
3519 /* Redistribute information. */
3520 vty_out (vty, " Redistributing:");
3521 config_write_rip_redistribute (vty, 0);
3522 vty_out (vty, "%s", VTY_NEWLINE);
3523
paulf38a4712003-06-07 01:10:00 +00003524 vty_out (vty, " Default version control: send version %s,",
3525 lookup(ri_version_msg,rip->version_send));
3526 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3527 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3528 else
3529 vty_out (vty, " receive version %s %s",
3530 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003531
3532 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3533
3534 for (node = listhead (iflist); node; node = nextnode (node))
3535 {
3536 ifp = getdata (node);
3537 ri = ifp->info;
3538
3539 if (ri->enable_network || ri->enable_interface)
3540 {
3541 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003542 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003543 else
3544 send_version = lookup (ri_version_msg, ri->ri_send);
3545
3546 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003547 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003548 else
3549 receive_version = lookup (ri_version_msg, ri->ri_receive);
3550
3551 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3552 send_version,
3553 receive_version,
3554 ri->key_chain ? ri->key_chain : "",
3555 VTY_NEWLINE);
3556 }
3557 }
3558
3559 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3560 config_write_rip_network (vty, 0);
3561
paul4aaff3f2003-06-07 01:04:45 +00003562 {
3563 int found_passive = 0;
3564 for (node = listhead (iflist); node; node = nextnode (node))
3565 {
3566 ifp = getdata (node);
3567 ri = ifp->info;
3568
3569 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3570 {
3571 if (!found_passive)
3572 {
3573 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3574 found_passive = 1;
3575 }
3576 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3577 }
3578 }
3579 }
3580
paul718e3742002-12-13 20:15:29 +00003581 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3582 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3583 rip_peer_display (vty);
3584
3585 rip_distance_show (vty);
3586
3587 return CMD_SUCCESS;
3588}
3589
3590/* RIP configuration write function. */
3591int
3592config_write_rip (struct vty *vty)
3593{
3594 int write = 0;
3595 struct route_node *rn;
3596 struct rip_distance *rdistance;
3597
3598 if (rip)
3599 {
3600 /* Router RIP statement. */
3601 vty_out (vty, "router rip%s", VTY_NEWLINE);
3602 write++;
3603
3604 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003605 if (rip->version_send != RI_RIP_VERSION_2
3606 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3607 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003608 VTY_NEWLINE);
3609
3610 /* RIP timer configuration. */
3611 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3612 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3613 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3614 vty_out (vty, " timers basic %lu %lu %lu%s",
3615 rip->update_time,
3616 rip->timeout_time,
3617 rip->garbage_time,
3618 VTY_NEWLINE);
3619
3620 /* Default information configuration. */
3621 if (rip->default_information)
3622 {
3623 if (rip->default_information_route_map)
3624 vty_out (vty, " default-information originate route-map %s%s",
3625 rip->default_information_route_map, VTY_NEWLINE);
3626 else
3627 vty_out (vty, " default-information originate%s",
3628 VTY_NEWLINE);
3629 }
3630
3631 /* Redistribute configuration. */
3632 config_write_rip_redistribute (vty, 1);
3633
3634 /* RIP offset-list configuration. */
3635 config_write_rip_offset_list (vty);
3636
3637 /* RIP enabled network and interface configuration. */
3638 config_write_rip_network (vty, 1);
3639
3640 /* RIP default metric configuration */
3641 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3642 vty_out (vty, " default-metric %d%s",
3643 rip->default_metric, VTY_NEWLINE);
3644
3645 /* Distribute configuration. */
3646 write += config_write_distribute (vty);
3647
hasso16705132003-05-25 14:49:19 +00003648 /* Interface routemap configuration */
3649 write += config_write_if_rmap (vty);
3650
paul718e3742002-12-13 20:15:29 +00003651 /* Distance configuration. */
3652 if (rip->distance)
3653 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3654
3655 /* RIP source IP prefix distance configuration. */
3656 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3657 if ((rdistance = rn->info) != NULL)
3658 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3659 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3660 rdistance->access_list ? rdistance->access_list : "",
3661 VTY_NEWLINE);
3662
3663 /* RIP static route configuration. */
3664 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3665 if (rn->info)
3666 vty_out (vty, " route %s/%d%s",
3667 inet_ntoa (rn->p.u.prefix4),
3668 rn->p.prefixlen,
3669 VTY_NEWLINE);
3670
3671 }
3672 return write;
3673}
3674
3675/* RIP node structure. */
3676struct cmd_node rip_node =
3677{
3678 RIP_NODE,
3679 "%s(config-router)# ",
3680 1
3681};
3682
3683/* Distribute-list update functions. */
3684void
3685rip_distribute_update (struct distribute *dist)
3686{
3687 struct interface *ifp;
3688 struct rip_interface *ri;
3689 struct access_list *alist;
3690 struct prefix_list *plist;
3691
3692 if (! dist->ifname)
3693 return;
3694
3695 ifp = if_lookup_by_name (dist->ifname);
3696 if (ifp == NULL)
3697 return;
3698
3699 ri = ifp->info;
3700
3701 if (dist->list[DISTRIBUTE_IN])
3702 {
3703 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3704 if (alist)
3705 ri->list[RIP_FILTER_IN] = alist;
3706 else
3707 ri->list[RIP_FILTER_IN] = NULL;
3708 }
3709 else
3710 ri->list[RIP_FILTER_IN] = NULL;
3711
3712 if (dist->list[DISTRIBUTE_OUT])
3713 {
3714 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3715 if (alist)
3716 ri->list[RIP_FILTER_OUT] = alist;
3717 else
3718 ri->list[RIP_FILTER_OUT] = NULL;
3719 }
3720 else
3721 ri->list[RIP_FILTER_OUT] = NULL;
3722
3723 if (dist->prefix[DISTRIBUTE_IN])
3724 {
3725 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3726 if (plist)
3727 ri->prefix[RIP_FILTER_IN] = plist;
3728 else
3729 ri->prefix[RIP_FILTER_IN] = NULL;
3730 }
3731 else
3732 ri->prefix[RIP_FILTER_IN] = NULL;
3733
3734 if (dist->prefix[DISTRIBUTE_OUT])
3735 {
3736 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3737 if (plist)
3738 ri->prefix[RIP_FILTER_OUT] = plist;
3739 else
3740 ri->prefix[RIP_FILTER_OUT] = NULL;
3741 }
3742 else
3743 ri->prefix[RIP_FILTER_OUT] = NULL;
3744}
3745
3746void
3747rip_distribute_update_interface (struct interface *ifp)
3748{
3749 struct distribute *dist;
3750
3751 dist = distribute_lookup (ifp->name);
3752 if (dist)
3753 rip_distribute_update (dist);
3754}
3755
3756/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003757/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003758void
paul02ff83c2004-06-11 11:27:03 +00003759rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003760{
3761 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003762 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003763
3764 for (node = listhead (iflist); node; nextnode (node))
3765 {
3766 ifp = getdata (node);
3767 rip_distribute_update_interface (ifp);
3768 }
3769}
paul11dde9c2004-05-31 14:00:00 +00003770/* ARGSUSED */
3771void
3772rip_distribute_update_all_wrapper(struct access_list *notused)
3773{
paul02ff83c2004-06-11 11:27:03 +00003774 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003775}
paul718e3742002-12-13 20:15:29 +00003776
3777/* Delete all added rip route. */
3778void
3779rip_clean ()
3780{
3781 int i;
3782 struct route_node *rp;
3783 struct rip_info *rinfo;
3784
3785 if (rip)
3786 {
3787 /* Clear RIP routes */
3788 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3789 if ((rinfo = rp->info) != NULL)
3790 {
3791 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3792 rinfo->sub_type == RIP_ROUTE_RTE)
3793 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3794 &rinfo->nexthop, rinfo->metric);
3795
3796 RIP_TIMER_OFF (rinfo->t_timeout);
3797 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3798
3799 rp->info = NULL;
3800 route_unlock_node (rp);
3801
3802 rip_info_free (rinfo);
3803 }
3804
3805 /* Cancel RIP related timers. */
3806 RIP_TIMER_OFF (rip->t_update);
3807 RIP_TIMER_OFF (rip->t_triggered_update);
3808 RIP_TIMER_OFF (rip->t_triggered_interval);
3809
3810 /* Cancel read thread. */
3811 if (rip->t_read)
3812 {
3813 thread_cancel (rip->t_read);
3814 rip->t_read = NULL;
3815 }
3816
3817 /* Close RIP socket. */
3818 if (rip->sock >= 0)
3819 {
3820 close (rip->sock);
3821 rip->sock = -1;
3822 }
3823
3824 /* Static RIP route configuration. */
3825 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3826 if (rp->info)
3827 {
3828 rp->info = NULL;
3829 route_unlock_node (rp);
3830 }
3831
3832 /* RIP neighbor configuration. */
3833 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3834 if (rp->info)
3835 {
3836 rp->info = NULL;
3837 route_unlock_node (rp);
3838 }
3839
3840 /* Redistribute related clear. */
3841 if (rip->default_information_route_map)
3842 free (rip->default_information_route_map);
3843
3844 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3845 if (rip->route_map[i].name)
3846 free (rip->route_map[i].name);
3847
3848 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3849 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3850 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3851
3852 XFREE (MTYPE_RIP, rip);
3853 rip = NULL;
3854 }
3855
3856 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003857 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003858 rip_offset_clean ();
3859 rip_interface_clean ();
3860 rip_distance_reset ();
3861 rip_redistribute_clean ();
3862}
3863
3864/* Reset all values to the default settings. */
3865void
3866rip_reset ()
3867{
3868 /* Reset global counters. */
3869 rip_global_route_changes = 0;
3870 rip_global_queries = 0;
3871
3872 /* Call ripd related reset functions. */
3873 rip_debug_reset ();
3874 rip_route_map_reset ();
3875
3876 /* Call library reset functions. */
3877 vty_reset ();
3878 access_list_reset ();
3879 prefix_list_reset ();
3880
3881 distribute_list_reset ();
3882
3883 rip_interface_reset ();
3884 rip_distance_reset ();
3885
3886 rip_zclient_reset ();
3887}
3888
hasso16705132003-05-25 14:49:19 +00003889void
3890rip_if_rmap_update (struct if_rmap *if_rmap)
3891{
3892 struct interface *ifp;
3893 struct rip_interface *ri;
3894 struct route_map *rmap;
3895
3896 ifp = if_lookup_by_name (if_rmap->ifname);
3897 if (ifp == NULL)
3898 return;
3899
3900 ri = ifp->info;
3901
3902 if (if_rmap->routemap[IF_RMAP_IN])
3903 {
3904 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3905 if (rmap)
3906 ri->routemap[IF_RMAP_IN] = rmap;
3907 else
3908 ri->routemap[IF_RMAP_IN] = NULL;
3909 }
3910 else
3911 ri->routemap[RIP_FILTER_IN] = NULL;
3912
3913 if (if_rmap->routemap[IF_RMAP_OUT])
3914 {
3915 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3916 if (rmap)
3917 ri->routemap[IF_RMAP_OUT] = rmap;
3918 else
3919 ri->routemap[IF_RMAP_OUT] = NULL;
3920 }
3921 else
3922 ri->routemap[RIP_FILTER_OUT] = NULL;
3923}
3924
3925void
3926rip_if_rmap_update_interface (struct interface *ifp)
3927{
3928 struct if_rmap *if_rmap;
3929
3930 if_rmap = if_rmap_lookup (ifp->name);
3931 if (if_rmap)
3932 rip_if_rmap_update (if_rmap);
3933}
3934
3935void
3936rip_routemap_update_redistribute (void)
3937{
3938 int i;
3939
3940 if (rip)
3941 {
3942 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3943 {
3944 if (rip->route_map[i].name)
3945 rip->route_map[i].map =
3946 route_map_lookup_by_name (rip->route_map[i].name);
3947 }
3948 }
3949}
3950
paul11dde9c2004-05-31 14:00:00 +00003951/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003952void
hasso98b718a2004-10-11 12:57:57 +00003953rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003954{
3955 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003956 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003957
3958 for (node = listhead (iflist); node; nextnode (node))
3959 {
3960 ifp = getdata (node);
3961 rip_if_rmap_update_interface (ifp);
3962 }
3963
3964 rip_routemap_update_redistribute ();
3965}
3966
paul718e3742002-12-13 20:15:29 +00003967/* Allocate new rip structure and set default value. */
3968void
3969rip_init ()
3970{
3971 /* Randomize for triggered update random(). */
3972 srand (time (NULL));
3973
3974 /* Install top nodes. */
3975 install_node (&rip_node, config_write_rip);
3976
3977 /* Install rip commands. */
3978 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003979 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003980 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003981 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003982 install_element (CONFIG_NODE, &router_rip_cmd);
3983 install_element (CONFIG_NODE, &no_router_rip_cmd);
3984
3985 install_default (RIP_NODE);
3986 install_element (RIP_NODE, &rip_version_cmd);
3987 install_element (RIP_NODE, &no_rip_version_cmd);
3988 install_element (RIP_NODE, &no_rip_version_val_cmd);
3989 install_element (RIP_NODE, &rip_default_metric_cmd);
3990 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3991 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3992 install_element (RIP_NODE, &rip_timers_cmd);
3993 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003994 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003995 install_element (RIP_NODE, &rip_route_cmd);
3996 install_element (RIP_NODE, &no_rip_route_cmd);
3997 install_element (RIP_NODE, &rip_distance_cmd);
3998 install_element (RIP_NODE, &no_rip_distance_cmd);
3999 install_element (RIP_NODE, &rip_distance_source_cmd);
4000 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4001 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4002 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4003
4004 /* Debug related init. */
4005 rip_debug_init ();
4006
paul718e3742002-12-13 20:15:29 +00004007 /* SNMP init. */
4008#ifdef HAVE_SNMP
4009 rip_snmp_init ();
4010#endif /* HAVE_SNMP */
4011
4012 /* Access list install. */
4013 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004014 access_list_add_hook (rip_distribute_update_all_wrapper);
4015 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004016
4017 /* Prefix list initialize.*/
4018 prefix_list_init ();
4019 prefix_list_add_hook (rip_distribute_update_all);
4020 prefix_list_delete_hook (rip_distribute_update_all);
4021
4022 /* Distribute list install. */
4023 distribute_list_init (RIP_NODE);
4024 distribute_list_add_hook (rip_distribute_update);
4025 distribute_list_delete_hook (rip_distribute_update);
4026
hasso16705132003-05-25 14:49:19 +00004027 /* Route-map */
4028 rip_route_map_init ();
4029 rip_offset_init ();
4030
4031 route_map_add_hook (rip_routemap_update);
4032 route_map_delete_hook (rip_routemap_update);
4033
4034 if_rmap_init (RIP_NODE);
4035 if_rmap_hook_add (rip_if_rmap_update);
4036 if_rmap_hook_delete (rip_if_rmap_update);
4037
paul718e3742002-12-13 20:15:29 +00004038 /* Distance control. */
4039 rip_distance_table = route_table_init ();
4040}