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