blob: a7286d3cf26ed803b60adc41d054392c135d64eb [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
vincentfbf5d032005-09-29 11:25:50 +00002 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "command.h"
27#include "prefix.h"
28#include "table.h"
29#include "thread.h"
30#include "memory.h"
31#include "log.h"
32#include "stream.h"
33#include "filter.h"
34#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000035#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000036#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000037#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000038#include "plist.h"
39#include "distribute.h"
vincentc1a03d42005-09-28 15:47:44 +000040#include "md5.h"
paul718e3742002-12-13 20:15:29 +000041#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000042#include "privs.h"
paul718e3742002-12-13 20:15:29 +000043
44#include "ripd/ripd.h"
45#include "ripd/rip_debug.h"
46
paul0b3acf42004-09-17 08:39:08 +000047/* UDP receive buffer size */
48#define RIP_UDP_RCV_BUF 41600
49
50/* privileges global */
pauledd7c242003-06-04 13:59:38 +000051extern struct zebra_privs_t ripd_privs;
52
paul718e3742002-12-13 20:15:29 +000053/* RIP Structure. */
54struct rip *rip = NULL;
55
56/* RIP neighbor address table. */
57struct route_table *rip_neighbor_table;
58
59/* RIP route changes. */
60long rip_global_route_changes = 0;
61
62/* RIP queries. */
63long rip_global_queries = 0;
64
65/* Prototypes. */
pauldc63bfd2005-10-25 23:31:05 +000066static void rip_event (enum rip_event, int);
67static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
68static int rip_triggered_update (struct thread *);
69static int rip_update_jitter (unsigned long);
70
paul718e3742002-12-13 20:15:29 +000071/* 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};
paul718e3742002-12-13 20:15:29 +000089
90/* Utility function to set boradcast option to the socket. */
pauldc63bfd2005-10-25 23:31:05 +000091static int
paul718e3742002-12-13 20:15:29 +000092sockopt_broadcast (int sock)
93{
94 int ret;
95 int on = 1;
96
97 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
98 if (ret < 0)
99 {
100 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
101 return -1;
102 }
103 return 0;
104}
105
pauldc63bfd2005-10-25 23:31:05 +0000106static int
paul718e3742002-12-13 20:15:29 +0000107rip_route_rte (struct rip_info *rinfo)
108{
109 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
110}
111
pauldc63bfd2005-10-25 23:31:05 +0000112static struct rip_info *
paul718e3742002-12-13 20:15:29 +0000113rip_info_new ()
114{
115 struct rip_info *new;
116
117 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
118 memset (new, 0, sizeof (struct rip_info));
119 return new;
120}
121
122void
123rip_info_free (struct rip_info *rinfo)
124{
125 XFREE (MTYPE_RIP_INFO, rinfo);
126}
127
128/* RIP route garbage collect timer. */
pauldc63bfd2005-10-25 23:31:05 +0000129static int
paul718e3742002-12-13 20:15:29 +0000130rip_garbage_collect (struct thread *t)
131{
132 struct rip_info *rinfo;
133 struct route_node *rp;
134
135 rinfo = THREAD_ARG (t);
136 rinfo->t_garbage_collect = NULL;
137
138 /* Off timeout timer. */
139 RIP_TIMER_OFF (rinfo->t_timeout);
140
141 /* Get route_node pointer. */
142 rp = rinfo->rp;
143
144 /* Unlock route_node. */
145 rp->info = NULL;
146 route_unlock_node (rp);
147
148 /* Free RIP routing information. */
149 rip_info_free (rinfo);
150
151 return 0;
152}
153
154/* Timeout RIP routes. */
pauldc63bfd2005-10-25 23:31:05 +0000155static int
paul718e3742002-12-13 20:15:29 +0000156rip_timeout (struct thread *t)
157{
158 struct rip_info *rinfo;
159 struct route_node *rn;
160
161 rinfo = THREAD_ARG (t);
162 rinfo->t_timeout = NULL;
163
164 rn = rinfo->rp;
165
166 /* - The garbage-collection timer is set for 120 seconds. */
167 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
168 rip->garbage_time);
169
170 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
171 rinfo->metric);
172 /* - The metric for the route is set to 16 (infinity). This causes
173 the route to be removed from service. */
174 rinfo->metric = RIP_METRIC_INFINITY;
175 rinfo->flags &= ~RIP_RTF_FIB;
176
177 /* - The route change flag is to indicate that this entry has been
178 changed. */
179 rinfo->flags |= RIP_RTF_CHANGED;
180
181 /* - The output process is signalled to trigger a response. */
182 rip_event (RIP_TRIGGERED_UPDATE, 0);
183
184 return 0;
185}
186
pauldc63bfd2005-10-25 23:31:05 +0000187static void
paul718e3742002-12-13 20:15:29 +0000188rip_timeout_update (struct rip_info *rinfo)
189{
190 if (rinfo->metric != RIP_METRIC_INFINITY)
191 {
192 RIP_TIMER_OFF (rinfo->t_timeout);
193 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
194 }
195}
196
pauldc63bfd2005-10-25 23:31:05 +0000197static int
paul718e3742002-12-13 20:15:29 +0000198rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
199{
200 struct distribute *dist;
201 struct access_list *alist;
202 struct prefix_list *plist;
203
204 /* Input distribute-list filtering. */
205 if (ri->list[RIP_FILTER_IN])
206 {
207 if (access_list_apply (ri->list[RIP_FILTER_IN],
208 (struct prefix *) p) == FILTER_DENY)
209 {
210 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000211 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000212 inet_ntoa (p->prefix), p->prefixlen);
213 return -1;
214 }
215 }
216 if (ri->prefix[RIP_FILTER_IN])
217 {
218 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
219 (struct prefix *) p) == PREFIX_DENY)
220 {
221 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000222 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000223 inet_ntoa (p->prefix), p->prefixlen);
224 return -1;
225 }
226 }
227
228 /* All interface filter check. */
229 dist = distribute_lookup (NULL);
230 if (dist)
231 {
232 if (dist->list[DISTRIBUTE_IN])
233 {
234 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
235
236 if (alist)
237 {
238 if (access_list_apply (alist,
239 (struct prefix *) p) == FILTER_DENY)
240 {
241 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000242 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000243 inet_ntoa (p->prefix), p->prefixlen);
244 return -1;
245 }
246 }
247 }
248 if (dist->prefix[DISTRIBUTE_IN])
249 {
250 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
251
252 if (plist)
253 {
254 if (prefix_list_apply (plist,
255 (struct prefix *) p) == PREFIX_DENY)
256 {
257 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000258 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000259 inet_ntoa (p->prefix), p->prefixlen);
260 return -1;
261 }
262 }
263 }
264 }
265 return 0;
266}
267
pauldc63bfd2005-10-25 23:31:05 +0000268static int
paul718e3742002-12-13 20:15:29 +0000269rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
270{
271 struct distribute *dist;
272 struct access_list *alist;
273 struct prefix_list *plist;
274
275 if (ri->list[RIP_FILTER_OUT])
276 {
277 if (access_list_apply (ri->list[RIP_FILTER_OUT],
278 (struct prefix *) p) == FILTER_DENY)
279 {
280 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000281 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000282 inet_ntoa (p->prefix), p->prefixlen);
283 return -1;
284 }
285 }
286 if (ri->prefix[RIP_FILTER_OUT])
287 {
288 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
289 (struct prefix *) p) == PREFIX_DENY)
290 {
291 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000292 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000293 inet_ntoa (p->prefix), p->prefixlen);
294 return -1;
295 }
296 }
297
298 /* All interface filter check. */
299 dist = distribute_lookup (NULL);
300 if (dist)
301 {
302 if (dist->list[DISTRIBUTE_OUT])
303 {
304 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
305
306 if (alist)
307 {
308 if (access_list_apply (alist,
309 (struct prefix *) p) == FILTER_DENY)
310 {
311 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000312 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000313 inet_ntoa (p->prefix), p->prefixlen);
314 return -1;
315 }
316 }
317 }
318 if (dist->prefix[DISTRIBUTE_OUT])
319 {
320 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
321
322 if (plist)
323 {
324 if (prefix_list_apply (plist,
325 (struct prefix *) p) == PREFIX_DENY)
326 {
327 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000328 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000329 inet_ntoa (p->prefix), p->prefixlen);
330 return -1;
331 }
332 }
333 }
334 }
335 return 0;
336}
337
338/* Check nexthop address validity. */
339static int
340rip_nexthop_check (struct in_addr *addr)
341{
hasso52dc7ee2004-09-23 19:18:23 +0000342 struct listnode *node;
343 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000344 struct interface *ifp;
345 struct connected *ifc;
346 struct prefix *p;
347
348 /* If nexthop address matches local configured address then it is
349 invalid nexthop. */
paul1eb8ef22005-04-07 07:30:20 +0000350 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000351 {
paul1eb8ef22005-04-07 07:30:20 +0000352 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000353 {
paul718e3742002-12-13 20:15:29 +0000354 p = ifc->address;
355
356 if (p->family == AF_INET
357 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
358 return -1;
359 }
360 }
361 return 0;
362}
363
364/* RIP add route to routing table. */
pauldc63bfd2005-10-25 23:31:05 +0000365static void
paul718e3742002-12-13 20:15:29 +0000366rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000367 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000368{
369 int ret;
370 struct prefix_ipv4 p;
371 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000372 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000373 struct rip_interface *ri;
374 struct in_addr *nexthop;
375 u_char oldmetric;
376 int same = 0;
vincentfbf5d032005-09-29 11:25:50 +0000377 int route_reuse = 0;
378 unsigned char old_dist, new_dist;
paul718e3742002-12-13 20:15:29 +0000379
380 /* Make prefix structure. */
381 memset (&p, 0, sizeof (struct prefix_ipv4));
382 p.family = AF_INET;
383 p.prefix = rte->prefix;
384 p.prefixlen = ip_masklen (rte->mask);
385
386 /* Make sure mask is applied. */
387 apply_mask_ipv4 (&p);
388
389 /* Apply input filters. */
390 ri = ifp->info;
391
392 ret = rip_incoming_filter (&p, ri);
393 if (ret < 0)
394 return;
395
hasso16705132003-05-25 14:49:19 +0000396 /* Modify entry according to the interface routemap. */
397 if (ri->routemap[RIP_FILTER_IN])
398 {
399 int ret;
400 struct rip_info newinfo;
401
402 memset (&newinfo, 0, sizeof (newinfo));
403 newinfo.type = ZEBRA_ROUTE_RIP;
404 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000405 newinfo.nexthop = rte->nexthop;
406 newinfo.from = from->sin_addr;
407 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000408 newinfo.metric = rte->metric;
409 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000410 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000411
412 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000413 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
414 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000415
416 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000417 {
418 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000419 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000420 inet_ntoa (p.prefix), p.prefixlen);
421 return;
422 }
hasso16705132003-05-25 14:49:19 +0000423
424 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000425 rte->nexthop = newinfo.nexthop_out;
426 rte->tag = htons (newinfo.tag_out); /* XXX */
427 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000428 }
429
paul718e3742002-12-13 20:15:29 +0000430 /* Once the entry has been validated, update the metric by
431 adding the cost of the network on wich the message
432 arrived. If the result is greater than infinity, use infinity
433 (RFC2453 Sec. 3.9.2) */
434 /* Zebra ripd can handle offset-list in. */
435 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
436
437 /* If offset-list does not modify the metric use interface's
438 metric. */
paula87552c2004-05-03 20:00:17 +0000439 if (!ret)
paul718e3742002-12-13 20:15:29 +0000440 rte->metric += ifp->metric;
441
442 if (rte->metric > RIP_METRIC_INFINITY)
443 rte->metric = RIP_METRIC_INFINITY;
444
445 /* Set nexthop pointer. */
446 if (rte->nexthop.s_addr == 0)
447 nexthop = &from->sin_addr;
448 else
449 nexthop = &rte->nexthop;
450
hasso16705132003-05-25 14:49:19 +0000451 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000452 if (rip_nexthop_check (nexthop) < 0)
453 {
454 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000455 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000456 return;
457 }
458
459 /* Get index for the prefix. */
460 rp = route_node_get (rip->table, (struct prefix *) &p);
461
462 /* Check to see whether there is already RIP route on the table. */
463 rinfo = rp->info;
464
465 if (rinfo)
466 {
paul718e3742002-12-13 20:15:29 +0000467 /* Local static route. */
468 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000469 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
470 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
471 && rinfo->metric != RIP_METRIC_INFINITY)
vincentfbf5d032005-09-29 11:25:50 +0000472 {
473 route_unlock_node (rp);
474 return;
475 }
476
477 /* Redistributed route check. */
478 if (rinfo->type != ZEBRA_ROUTE_RIP
479 && rinfo->metric != RIP_METRIC_INFINITY)
480 {
481 /* Fill in a minimaly temporary rip_info structure, for a future
482 rip_distance_apply() use) */
483 memset (&rinfotmp, 0, sizeof (rinfotmp));
484 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
485 rinfotmp.rp = rinfo->rp;
486 new_dist = rip_distance_apply (&rinfotmp);
487 new_dist = new_dist ? new_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
488 old_dist = rinfo->distance;
489 old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
490 /* If imported route does not have STRICT precedence,
491 mark it as a ghost */
492 if (new_dist > old_dist
493 || rte->metric == RIP_METRIC_INFINITY)
494 {
495 route_unlock_node (rp);
496 return;
497 }
498 else
499 {
500 RIP_TIMER_OFF (rinfo->t_timeout);
501 RIP_TIMER_OFF (rinfo->t_garbage_collect);
502
503 rp->info = NULL;
504 if (rip_route_rte (rinfo))
505 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
506 &rinfo->nexthop, rinfo->metric);
507 rip_info_free (rinfo);
508 rinfo = NULL;
509 route_reuse = 1;
510 }
511 }
paul718e3742002-12-13 20:15:29 +0000512 }
paula87552c2004-05-03 20:00:17 +0000513
514 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000515 {
516 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000517 for the destination prefix. If there is no such route, add
518 this route to the routing table, unless the metric is
519 infinity (there is no point in adding a route which
520 unusable). */
paul718e3742002-12-13 20:15:29 +0000521 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000522 {
523 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000524
paula87552c2004-05-03 20:00:17 +0000525 /* - Setting the destination prefix and length to those in
526 the RTE. */
527 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000528
paula87552c2004-05-03 20:00:17 +0000529 /* - Setting the metric to the newly calculated metric (as
530 described above). */
531 rinfo->metric = rte->metric;
532 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000533
paula87552c2004-05-03 20:00:17 +0000534 /* - Set the next hop address to be the address of the router
535 from which the datagram came or the next hop address
536 specified by a next hop RTE. */
537 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
538 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
539 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000540
paula87552c2004-05-03 20:00:17 +0000541 /* - Initialize the timeout for the route. If the
542 garbage-collection timer is running for this route, stop it
543 (see section 2.3 for a discussion of the timers). */
544 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000545
paula87552c2004-05-03 20:00:17 +0000546 /* - Set the route change flag. */
547 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000548
paula87552c2004-05-03 20:00:17 +0000549 /* - Signal the output process to trigger an update (see section
550 2.5). */
551 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000552
paula87552c2004-05-03 20:00:17 +0000553 /* Finally, route goes into the kernel. */
554 rinfo->type = ZEBRA_ROUTE_RIP;
555 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000556
paula87552c2004-05-03 20:00:17 +0000557 /* Set distance value. */
558 rinfo->distance = rip_distance_apply (rinfo);
559
560 rp->info = rinfo;
561 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
562 rinfo->distance);
563 rinfo->flags |= RIP_RTF_FIB;
564 }
vincentfbf5d032005-09-29 11:25:50 +0000565
566 /* Unlock temporary lock, i.e. same behaviour */
567 if (route_reuse)
568 route_unlock_node (rp);
paul718e3742002-12-13 20:15:29 +0000569 }
570 else
571 {
572 /* Route is there but we are not sure the route is RIP or not. */
573 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000574
paul718e3742002-12-13 20:15:29 +0000575 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000576 to the address of the router from which the datagram came.
577 If this datagram is from the same router as the existing
578 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000579 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000580 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000581
582 if (same)
paula87552c2004-05-03 20:00:17 +0000583 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000584
paulb94f9db2004-05-01 20:45:38 +0000585
586 /* Fill in a minimaly temporary rip_info structure, for a future
587 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000588 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000589 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000590 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000591
592
paul718e3742002-12-13 20:15:29 +0000593 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000594 router as the existing route, and the new metric is different
595 than the old one; or, if the new metric is lower than the old
596 one, or if the tag has been changed; or if there is a route
597 with a lower administrave distance; or an update of the
598 distance on the actual route; do the following actions: */
599 if ((same && rinfo->metric != rte->metric)
600 || (rte->metric < rinfo->metric)
601 || ((same)
602 && (rinfo->metric == rte->metric)
603 && ntohs (rte->tag) != rinfo->tag)
604 || (rinfo->distance > rip_distance_apply (&rinfotmp))
605 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
606 {
607 /* - Adopt the route from the datagram. That is, put the
608 new metric in, and adjust the next hop address (if
609 necessary). */
610 oldmetric = rinfo->metric;
611 rinfo->metric = rte->metric;
612 rinfo->tag = ntohs (rte->tag);
613 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
614 rinfo->ifindex = ifp->ifindex;
615 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000616
paula87552c2004-05-03 20:00:17 +0000617 /* Should a new route to this network be established
618 while the garbage-collection timer is running, the
619 new route will replace the one that is about to be
620 deleted. In this case the garbage-collection timer
621 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000622
paula87552c2004-05-03 20:00:17 +0000623 if (oldmetric == RIP_METRIC_INFINITY &&
624 rinfo->metric < RIP_METRIC_INFINITY)
625 {
626 rinfo->type = ZEBRA_ROUTE_RIP;
627 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000628
paula87552c2004-05-03 20:00:17 +0000629 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000630
paula87552c2004-05-03 20:00:17 +0000631 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
632 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000633
paula87552c2004-05-03 20:00:17 +0000634 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
635 rinfo->distance);
636 rinfo->flags |= RIP_RTF_FIB;
637 }
paul718e3742002-12-13 20:15:29 +0000638
paula87552c2004-05-03 20:00:17 +0000639 /* Update nexthop and/or metric value. */
640 if (oldmetric != RIP_METRIC_INFINITY)
641 {
642 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
643 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
644 rinfo->distance);
645 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000646
paula87552c2004-05-03 20:00:17 +0000647 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
648 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
649 }
paul718e3742002-12-13 20:15:29 +0000650
paula87552c2004-05-03 20:00:17 +0000651 /* - Set the route change flag and signal the output process
652 to trigger an update. */
653 rinfo->flags |= RIP_RTF_CHANGED;
654 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000655
paula87552c2004-05-03 20:00:17 +0000656 /* - If the new metric is infinity, start the deletion
657 process (described above); */
658 if (rinfo->metric == RIP_METRIC_INFINITY)
659 {
660 /* If the new metric is infinity, the deletion process
661 begins for the route, which is no longer used for
662 routing packets. Note that the deletion process is
663 started only when the metric is first set to
664 infinity. If the metric was already infinity, then a
665 new deletion process is not started. */
666 if (oldmetric != RIP_METRIC_INFINITY)
667 {
668 /* - The garbage-collection timer is set for 120 seconds. */
669 RIP_TIMER_ON (rinfo->t_garbage_collect,
670 rip_garbage_collect, rip->garbage_time);
671 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000672
paula87552c2004-05-03 20:00:17 +0000673 /* - The metric for the route is set to 16
674 (infinity). This causes the route to be removed
675 from service. */
676 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
677 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000678
paula87552c2004-05-03 20:00:17 +0000679 /* - The route change flag is to indicate that this
680 entry has been changed. */
681 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000682 response. */
paula87552c2004-05-03 20:00:17 +0000683 ; /* Above processes are already done previously. */
684 }
685 }
686 else
687 {
688 /* otherwise, re-initialize the timeout. */
689 rip_timeout_update (rinfo);
690 }
691 }
paul718e3742002-12-13 20:15:29 +0000692 /* Unlock tempolary lock of the route. */
693 route_unlock_node (rp);
694 }
695}
696
697/* Dump RIP packet */
pauldc63bfd2005-10-25 23:31:05 +0000698static void
hasso8a676be2004-10-08 06:36:38 +0000699rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000700{
701 caddr_t lim;
702 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000703 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000704 char pbuf[BUFSIZ], nbuf[BUFSIZ];
705 u_char netmask = 0;
706 u_char *p;
707
708 /* Set command string. */
709 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
710 command_str = lookup (rip_msg, packet->command);
711 else
712 command_str = "unknown";
713
714 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000715 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000716 sndrcv, command_str, packet->version, size);
717
718 /* Dump each routing table entry. */
719 rte = packet->rte;
720
721 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
722 {
723 if (packet->version == RIPv2)
724 {
725 netmask = ip_masklen (rte->mask);
726
paulca5e5162004-06-06 22:06:33 +0000727 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000728 {
paulca5e5162004-06-06 22:06:33 +0000729 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000730 {
731 p = (u_char *)&rte->prefix;
732
ajs5d6c3772004-12-08 19:24:06 +0000733 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000734 ntohs (rte->family), ntohs (rte->tag), p);
735 }
paulca5e5162004-06-06 22:06:33 +0000736 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000737 {
738 struct rip_md5_info *md5;
739
740 md5 = (struct rip_md5_info *) &packet->rte;
741
ajs5d6c3772004-12-08 19:24:06 +0000742 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000743 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000744 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000745 " Auth Data len %d",
746 ntohs (md5->packet_len), md5->keyid,
747 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000748 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000749 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000750 }
paulca5e5162004-06-06 22:06:33 +0000751 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000752 {
753 p = (u_char *)&rte->prefix;
754
ajs5d6c3772004-12-08 19:24:06 +0000755 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000756 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000757 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000758 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000759 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
760 p[7], p[9], p[10], p[11], p[12], p[13],
761 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000762 }
763 else
764 {
ajs5d6c3772004-12-08 19:24:06 +0000765 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000766 ntohs (rte->family), ntohs (rte->tag));
767 }
768 }
769 else
ajs5d6c3772004-12-08 19:24:06 +0000770 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000771 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
772 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
773 BUFSIZ), ntohs (rte->family),
774 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000775 }
776 else
777 {
ajs5d6c3772004-12-08 19:24:06 +0000778 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000779 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
780 ntohs (rte->family), ntohs (rte->tag),
781 (u_long)ntohl (rte->metric));
782 }
783 }
784}
785
786/* Check if the destination address is valid (unicast; not net 0
787 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
788 check net 0 because we accept default route. */
pauldc63bfd2005-10-25 23:31:05 +0000789static int
paul718e3742002-12-13 20:15:29 +0000790rip_destination_check (struct in_addr addr)
791{
792 u_int32_t destination;
793
794 /* Convert to host byte order. */
795 destination = ntohl (addr.s_addr);
796
797 if (IPV4_NET127 (destination))
798 return 0;
799
800 /* Net 0 may match to the default route. */
801 if (IPV4_NET0 (destination) && destination != 0)
802 return 0;
803
804 /* Unicast address must belong to class A, B, C. */
805 if (IN_CLASSA (destination))
806 return 1;
807 if (IN_CLASSB (destination))
808 return 1;
809 if (IN_CLASSC (destination))
810 return 1;
811
812 return 0;
813}
814
815/* RIP version 2 authentication. */
pauldc63bfd2005-10-25 23:31:05 +0000816static int
paul718e3742002-12-13 20:15:29 +0000817rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
818 struct interface *ifp)
819{
820 struct rip_interface *ri;
821 char *auth_str;
822
823 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000824 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000825 inet_ntoa (from->sin_addr));
826
827 ri = ifp->info;
828
829 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000830 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000831 return 0;
832
833 /* Simple password authentication. */
834 if (ri->auth_str)
835 {
836 auth_str = (char *) &rte->prefix;
837
838 if (strncmp (auth_str, ri->auth_str, 16) == 0)
839 return 1;
840 }
841 if (ri->key_chain)
842 {
843 struct keychain *keychain;
844 struct key *key;
845
846 keychain = keychain_lookup (ri->key_chain);
847 if (keychain == NULL)
848 return 0;
849
850 key = key_match_for_accept (keychain, (char *) &rte->prefix);
851 if (key)
852 return 1;
853 }
854 return 0;
855}
856
857/* RIP version 2 authentication with MD5. */
pauldc63bfd2005-10-25 23:31:05 +0000858static int
paul718e3742002-12-13 20:15:29 +0000859rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000860 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000861{
862 struct rip_interface *ri;
863 struct rip_md5_info *md5;
864 struct rip_md5_data *md5data;
865 struct keychain *keychain;
866 struct key *key;
vincentc1a03d42005-09-28 15:47:44 +0000867 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000868 u_char pdigest[RIP_AUTH_MD5_SIZE];
869 u_char digest[RIP_AUTH_MD5_SIZE];
870 u_int16_t packet_len;
871 char *auth_str = NULL;
872
873 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000874 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000875 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000876
877 ri = ifp->info;
878 md5 = (struct rip_md5_info *) &packet->rte;
879
880 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000881 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000882 return 0;
883
paulca5e5162004-06-06 22:06:33 +0000884 /* If the authentication length is less than 16, then it must be wrong for
885 * any interpretation of rfc2082. Some implementations also interpret
886 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000887 */
paulca5e5162004-06-06 22:06:33 +0000888 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
889 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000890 {
891 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000892 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000893 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000894 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000895 }
paul718e3742002-12-13 20:15:29 +0000896
paulca5e5162004-06-06 22:06:33 +0000897 /* grab and verify check packet length */
898 packet_len = ntohs (md5->packet_len);
899
900 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
901 {
902 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000903 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000904 "greater than received length %d!",
905 md5->packet_len, length);
906 return 0;
907 }
908
909 /* retrieve authentication data */
910 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
911
paul718e3742002-12-13 20:15:29 +0000912 if (ri->key_chain)
913 {
914 keychain = keychain_lookup (ri->key_chain);
915 if (keychain == NULL)
916 return 0;
917
918 key = key_lookup_for_accept (keychain, md5->keyid);
919 if (key == NULL)
920 return 0;
921
922 auth_str = key->string;
923 }
924
925 if (ri->auth_str)
926 auth_str = ri->auth_str;
927
928 if (! auth_str)
929 return 0;
930
931 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000932
933 /* Save digest to pdigest. */
934 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
935
936 /* Overwrite digest by my secret. */
937 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000938 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000939
vincentc1a03d42005-09-28 15:47:44 +0000940 memset (&ctx, 0, sizeof(ctx));
941 MD5Init(&ctx);
942 MD5Update(&ctx, packet, packet_len + md5->auth_len);
943 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000944
945 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
946 return packet_len;
947 else
948 return 0;
949}
950
paulb14ee002005-02-04 23:42:41 +0000951/* Pick correct auth string for sends, prepare auth_str buffer for use.
952 * (left justified and padded).
953 *
954 * presumes one of ri or key is valid, and that the auth strings they point
955 * to are nul terminated. If neither are present, auth_str will be fully
956 * zero padded.
957 *
958 */
959static void
960rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
961 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +0000962{
paulb14ee002005-02-04 23:42:41 +0000963 assert (ri || key);
paul718e3742002-12-13 20:15:29 +0000964
paulb14ee002005-02-04 23:42:41 +0000965 memset (auth_str, 0, len);
966 if (key && key->string)
967 strncpy (auth_str, key->string, len);
968 else if (ri->auth_str)
969 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +0000970
paulb14ee002005-02-04 23:42:41 +0000971 return;
972}
paul718e3742002-12-13 20:15:29 +0000973
paulb14ee002005-02-04 23:42:41 +0000974/* Write RIPv2 simple password authentication information
975 *
976 * auth_str is presumed to be 2 bytes and correctly prepared
977 * (left justified and zero padded).
978 */
979static void
980rip_auth_simple_write (struct stream *s, char *auth_str, int len)
981{
982 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +0000983
paulb14ee002005-02-04 23:42:41 +0000984 stream_putw (s, RIP_FAMILY_AUTH);
985 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
986 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
987
988 return;
989}
990
991/* write RIPv2 MD5 "authentication header"
992 * (uses the auth key data field)
993 *
994 * Digest offset field is set to 0.
995 *
996 * returns: offset of the digest offset field, which must be set when
997 * length to the auth-data MD5 digest is known.
998 */
999static size_t
1000rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
1001 struct key *key)
1002{
1003 size_t len = 0;
1004
1005 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +00001006
1007 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +00001008 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00001009 stream_putw (s, RIP_AUTH_MD5);
1010
paulb14ee002005-02-04 23:42:41 +00001011 /* MD5 AH digest offset field.
1012 *
1013 * Set to placeholder value here, to true value when RIP-2 Packet length
1014 * is known. Actual value is set in .....().
1015 */
paul9985f832005-02-09 15:51:56 +00001016 len = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +00001017 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +00001018
1019 /* Key ID. */
1020 if (key)
1021 stream_putc (s, key->index % 256);
1022 else
1023 stream_putc (s, 1);
1024
paulca5e5162004-06-06 22:06:33 +00001025 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1026 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1027 * to be configurable.
1028 */
1029 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001030
1031 /* Sequence Number (non-decreasing). */
1032 /* RFC2080: The value used in the sequence number is
1033 arbitrary, but two suggestions are the time of the
1034 message's creation or a simple message counter. */
1035 stream_putl (s, time (NULL));
1036
1037 /* Reserved field must be zero. */
1038 stream_putl (s, 0);
1039 stream_putl (s, 0);
1040
paulb14ee002005-02-04 23:42:41 +00001041 return len;
1042}
paul718e3742002-12-13 20:15:29 +00001043
paulb14ee002005-02-04 23:42:41 +00001044/* If authentication is in used, write the appropriate header
1045 * returns stream offset to which length must later be written
1046 * or 0 if this is not required
1047 */
1048static size_t
1049rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1050 struct key *key, char *auth_str, int len)
1051{
1052 assert (ri->auth_type != RIP_NO_AUTH);
1053
1054 switch (ri->auth_type)
1055 {
1056 case RIP_AUTH_SIMPLE_PASSWORD:
1057 rip_auth_prepare_str_send (ri, key, auth_str, len);
1058 rip_auth_simple_write (s, auth_str, len);
1059 return 0;
1060 case RIP_AUTH_MD5:
1061 return rip_auth_md5_ah_write (s, ri, key);
1062 }
1063 assert (1);
1064}
1065
1066/* Write RIPv2 MD5 authentication data trailer */
1067static void
1068rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1069 char *auth_str, int authlen)
1070{
1071 unsigned long len;
vincentc1a03d42005-09-28 15:47:44 +00001072 MD5_CTX ctx;
paulb14ee002005-02-04 23:42:41 +00001073 unsigned char digest[RIP_AUTH_MD5_SIZE];
1074
1075 /* Make it sure this interface is configured as MD5
1076 authentication. */
1077 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1078 assert (doff > 0);
1079
1080 /* Get packet length. */
1081 len = stream_get_endp(s);
1082
1083 /* Check packet length. */
1084 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1085 {
1086 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1087 return;
1088 }
1089
1090 /* Set the digest offset length in the header */
1091 stream_putw_at (s, doff, len);
1092
paul718e3742002-12-13 20:15:29 +00001093 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001094 stream_putw (s, RIP_FAMILY_AUTH);
1095 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001096
1097 /* Generate a digest for the RIP packet. */
vincentc1a03d42005-09-28 15:47:44 +00001098 memset(&ctx, 0, sizeof(ctx));
1099 MD5Init(&ctx);
1100 MD5Update(&ctx, s->data, s->endp);
1101 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1102 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +00001103
1104 /* Copy the digest to the packet. */
1105 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1106}
1107
1108/* RIP routing information. */
pauldc63bfd2005-10-25 23:31:05 +00001109static void
paul718e3742002-12-13 20:15:29 +00001110rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001111 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001112{
1113 caddr_t lim;
1114 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001115 struct prefix_ipv4 ifaddr;
1116 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001117 int subnetted;
paul718e3742002-12-13 20:15:29 +00001118
paul727d1042002-12-13 20:50:29 +00001119 /* We don't know yet. */
1120 subnetted = -1;
1121
paul718e3742002-12-13 20:15:29 +00001122 /* The Response must be ignored if it is not from the RIP
1123 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001124 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001125 {
1126 zlog_info ("response doesn't come from RIP port: %d",
1127 from->sin_port);
1128 rip_peer_bad_packet (from);
1129 return;
1130 }
1131
1132 /* The datagram's IPv4 source address should be checked to see
1133 whether the datagram is from a valid neighbor; the source of the
1134 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001135 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001136 {
1137 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1138 inet_ntoa (from->sin_addr));
1139 rip_peer_bad_packet (from);
1140 return;
1141 }
1142
1143 /* It is also worth checking to see whether the response is from one
1144 of the router's own addresses. */
1145
1146 ; /* Alredy done in rip_read () */
1147
1148 /* Update RIP peer. */
1149 rip_peer_update (from, packet->version);
1150
1151 /* Set RTE pointer. */
1152 rte = packet->rte;
1153
1154 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1155 {
1156 /* RIPv2 authentication check. */
1157 /* If the Address Family Identifier of the first (and only the
1158 first) entry in the message is 0xFFFF, then the remainder of
1159 the entry contains the authentication. */
1160 /* If the packet gets here it means authentication enabled */
1161 /* Check is done in rip_read(). So, just skipping it */
1162 if (packet->version == RIPv2 &&
1163 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001164 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001165 continue;
1166
paulca5e5162004-06-06 22:06:33 +00001167 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001168 {
1169 /* Address family check. RIP only supports AF_INET. */
1170 zlog_info ("Unsupported family %d from %s.",
1171 ntohs (rte->family), inet_ntoa (from->sin_addr));
1172 continue;
1173 }
1174
1175 /* - is the destination address valid (e.g., unicast; not net 0
1176 or 127) */
1177 if (! rip_destination_check (rte->prefix))
1178 {
1179 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1180 rip_peer_bad_route (from);
1181 continue;
1182 }
1183
1184 /* Convert metric value to host byte order. */
1185 rte->metric = ntohl (rte->metric);
1186
1187 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1188 if (! (rte->metric >= 1 && rte->metric <= 16))
1189 {
1190 zlog_info ("Route's metric is not in the 1-16 range.");
1191 rip_peer_bad_route (from);
1192 continue;
1193 }
1194
1195 /* RIPv1 does not have nexthop value. */
1196 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1197 {
1198 zlog_info ("RIPv1 packet with nexthop value %s",
1199 inet_ntoa (rte->nexthop));
1200 rip_peer_bad_route (from);
1201 continue;
1202 }
1203
1204 /* That is, if the provided information is ignored, a possibly
1205 sub-optimal, but absolutely valid, route may be taken. If
1206 the received Next Hop is not directly reachable, it should be
1207 treated as 0.0.0.0. */
1208 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1209 {
1210 u_int32_t addrval;
1211
1212 /* Multicast address check. */
1213 addrval = ntohl (rte->nexthop.s_addr);
1214 if (IN_CLASSD (addrval))
1215 {
1216 zlog_info ("Nexthop %s is multicast address, skip this rte",
1217 inet_ntoa (rte->nexthop));
1218 continue;
1219 }
1220
1221 if (! if_lookup_address (rte->nexthop))
1222 {
1223 struct route_node *rn;
1224 struct rip_info *rinfo;
1225
1226 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1227
1228 if (rn)
1229 {
1230 rinfo = rn->info;
1231
1232 if (rinfo->type == ZEBRA_ROUTE_RIP
1233 && rinfo->sub_type == RIP_ROUTE_RTE)
1234 {
1235 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001236 zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001237 rte->nexthop = rinfo->from;
1238 }
1239 else
1240 {
1241 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001242 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001243 rte->nexthop.s_addr = 0;
1244 }
1245
1246 route_unlock_node (rn);
1247 }
1248 else
1249 {
1250 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001251 zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
paul718e3742002-12-13 20:15:29 +00001252 rte->nexthop.s_addr = 0;
1253 }
1254
1255 }
1256 }
1257
1258 /* For RIPv1, there won't be a valid netmask.
1259
1260 This is a best guess at the masks. If everyone was using old
1261 Ciscos before the 'ip subnet zero' option, it would be almost
1262 right too :-)
1263
1264 Cisco summarize ripv1 advertisments to the classful boundary
1265 (/16 for class B's) except when the RIP packet does to inside
1266 the classful network in question. */
1267
1268 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1269 || (packet->version == RIPv2
1270 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1271 {
1272 u_int32_t destination;
1273
paul727d1042002-12-13 20:50:29 +00001274 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001275 {
1276 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1277 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1278 apply_classful_mask_ipv4 (&ifaddrclass);
1279 subnetted = 0;
1280 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1281 subnetted = 1;
1282 }
paul727d1042002-12-13 20:50:29 +00001283
paul718e3742002-12-13 20:15:29 +00001284 destination = ntohl (rte->prefix.s_addr);
1285
paul727d1042002-12-13 20:50:29 +00001286 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001287 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001288 else if (IN_CLASSB (destination))
1289 masklen2ip (16, &rte->mask);
1290 else if (IN_CLASSC (destination))
1291 masklen2ip (24, &rte->mask);
1292
1293 if (subnetted == 1)
1294 masklen2ip (ifaddrclass.prefixlen,
1295 (struct in_addr *) &destination);
1296 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1297 ifaddrclass.prefix.s_addr))
1298 {
1299 masklen2ip (ifaddr.prefixlen, &rte->mask);
1300 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1301 masklen2ip (32, &rte->mask);
1302 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001303 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001304 }
1305 else
1306 {
1307 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1308 continue;
1309 }
1310
1311 if (IS_RIP_DEBUG_EVENT)
1312 {
ajs5d6c3772004-12-08 19:24:06 +00001313 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1314 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001315 }
1316 }
1317
1318 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1319 ignore the entry. */
1320 if ((packet->version == RIPv2)
1321 && (rte->mask.s_addr != 0)
1322 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1323 {
1324 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1325 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1326 rip_peer_bad_route (from);
1327 continue;
1328 }
1329
1330 /* Default route's netmask is ignored. */
1331 if (packet->version == RIPv2
1332 && (rte->prefix.s_addr == 0)
1333 && (rte->mask.s_addr != 0))
1334 {
1335 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001336 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001337 rte->mask.s_addr = 0;
1338 }
1339
1340 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001341 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001342 }
1343}
1344
paula4e987e2005-06-03 17:46:49 +00001345/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001346static int
paul2c61ae32005-08-16 15:22:14 +00001347rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001348{
1349 int ret;
1350 int sock;
1351 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001352
paul2c61ae32005-08-16 15:22:14 +00001353 memset (&addr, 0, sizeof (struct sockaddr_in));
1354
1355 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001356 {
paulf69bd9d2005-06-03 18:01:50 +00001357 addr.sin_family = AF_INET;
1358 addr.sin_addr.s_addr = INADDR_ANY;
paul2c61ae32005-08-16 15:22:14 +00001359#ifdef HAVE_SINLEN
1360 addr.sin_len = sizeof (struct sockaddr_in);
1361#endif /* HAVE_SINLEN */
jardin38d3c162005-10-19 19:29:59 +00001362 } else {
1363 memcpy(&addr, from, sizeof(addr));
paulf69bd9d2005-06-03 18:01:50 +00001364 }
1365
paul2c61ae32005-08-16 15:22:14 +00001366 /* sending port must always be the RIP port */
1367 addr.sin_port = htons (RIP_PORT_DEFAULT);
1368
paula4e987e2005-06-03 17:46:49 +00001369 /* Make datagram socket. */
1370 sock = socket (AF_INET, SOCK_DGRAM, 0);
1371 if (sock < 0)
1372 {
1373 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1374 exit (1);
1375 }
1376
1377 sockopt_broadcast (sock);
1378 sockopt_reuseaddr (sock);
1379 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001380#ifdef RIP_RECVMSG
1381 setsockopt_pktinfo (sock);
1382#endif /* RIP_RECVMSG */
1383
1384 if (ripd_privs.change (ZPRIVS_RAISE))
1385 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001386 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1387 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1388
paula4e987e2005-06-03 17:46:49 +00001389 {
1390 int save_errno = errno;
1391 if (ripd_privs.change (ZPRIVS_LOWER))
1392 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001393
1394 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1395 sock, inet_ntoa(addr.sin_addr),
1396 (int) ntohs(addr.sin_port),
1397 safe_strerror(save_errno));
1398
paulf69bd9d2005-06-03 18:01:50 +00001399 close (sock);
paula4e987e2005-06-03 17:46:49 +00001400 return ret;
1401 }
paulf69bd9d2005-06-03 18:01:50 +00001402
paula4e987e2005-06-03 17:46:49 +00001403 if (ripd_privs.change (ZPRIVS_LOWER))
1404 zlog_err ("rip_create_socket: could not lower privs");
1405
1406 return sock;
1407}
1408
paulc49ad8f2004-10-22 10:27:28 +00001409/* RIP packet send to destination address, on interface denoted by
1410 * by connected argument. NULL to argument denotes destination should be
1411 * should be RIP multicast group
1412 */
pauldc63bfd2005-10-25 23:31:05 +00001413static int
paulc49ad8f2004-10-22 10:27:28 +00001414rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1415 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001416{
paul931cd542004-01-23 15:31:42 +00001417 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001418 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001419
1420 assert (ifc != NULL);
1421
paul931cd542004-01-23 15:31:42 +00001422 if (IS_RIP_DEBUG_PACKET)
1423 {
paulf69bd9d2005-06-03 18:01:50 +00001424#define ADDRESS_SIZE 20
1425 char dst[ADDRESS_SIZE];
1426 dst[ADDRESS_SIZE - 1] = '\0';
1427
paul931cd542004-01-23 15:31:42 +00001428 if (to)
1429 {
paulf69bd9d2005-06-03 18:01:50 +00001430 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001431 }
1432 else
1433 {
1434 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001435 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001436 }
paulf69bd9d2005-06-03 18:01:50 +00001437#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001438 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001439 inet_ntoa(ifc->address->u.prefix4),
1440 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001441 }
paulf69bd9d2005-06-03 18:01:50 +00001442
paulc49ad8f2004-10-22 10:27:28 +00001443 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001444 {
1445 /*
1446 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1447 * with multiple addresses on the same subnet: the first address
1448 * on the subnet is configured "primary", and all subsequent addresses
1449 * on that subnet are treated as "secondary" addresses.
1450 * In order to avoid routing-table bloat on other rip listeners,
1451 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1452 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1453 * flag is set, we would end up sending a packet for a "secondary"
1454 * source address on non-linux systems.
1455 */
1456 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001457 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001458 return 0;
1459 }
1460
paul718e3742002-12-13 20:15:29 +00001461 /* Make destination address. */
1462 memset (&sin, 0, sizeof (struct sockaddr_in));
1463 sin.sin_family = AF_INET;
1464#ifdef HAVE_SIN_LEN
1465 sin.sin_len = sizeof (struct sockaddr_in);
1466#endif /* HAVE_SIN_LEN */
1467
1468 /* When destination is specified, use it's port and address. */
1469 if (to)
1470 {
paul718e3742002-12-13 20:15:29 +00001471 sin.sin_port = to->sin_port;
1472 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001473 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001474 }
1475 else
1476 {
paul2c61ae32005-08-16 15:22:14 +00001477 struct sockaddr_in from;
1478
paul718e3742002-12-13 20:15:29 +00001479 sin.sin_port = htons (RIP_PORT_DEFAULT);
1480 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001481
1482 /* multicast send should bind to local interface address */
1483 from.sin_family = AF_INET;
1484 from.sin_port = htons (RIP_PORT_DEFAULT);
1485 from.sin_addr = ifc->address->u.prefix4;
1486#ifdef HAVE_SIN_LEN
1487 from.sin_len = sizeof (struct sockaddr_in);
1488#endif /* HAVE_SIN_LEN */
1489
paul931cd542004-01-23 15:31:42 +00001490 /*
1491 * we have to open a new socket for each packet because this
1492 * is the most portable way to bind to a different source
1493 * ipv4 address for each packet.
1494 */
paul2c61ae32005-08-16 15:22:14 +00001495 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001496 {
paulf69bd9d2005-06-03 18:01:50 +00001497 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001498 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001499 }
paulc49ad8f2004-10-22 10:27:28 +00001500 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001501 }
1502
paul931cd542004-01-23 15:31:42 +00001503 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001504 sizeof (struct sockaddr_in));
1505
1506 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001507 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001508 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001509
1510 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001511 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001512
paul931cd542004-01-23 15:31:42 +00001513 if (!to)
1514 close(send_sock);
1515
paul718e3742002-12-13 20:15:29 +00001516 return ret;
1517}
1518
1519/* Add redistributed route to RIP table. */
1520void
1521rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
vincentfbf5d032005-09-29 11:25:50 +00001522 unsigned int ifindex, struct in_addr *nexthop,
1523 unsigned int metric, unsigned char distance)
paul718e3742002-12-13 20:15:29 +00001524{
1525 int ret;
1526 struct route_node *rp;
1527 struct rip_info *rinfo;
1528
1529 /* Redistribute route */
1530 ret = rip_destination_check (p->prefix);
1531 if (! ret)
1532 return;
1533
1534 rp = route_node_get (rip->table, (struct prefix *) p);
1535
1536 rinfo = rp->info;
1537
1538 if (rinfo)
1539 {
1540 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1541 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1542 && rinfo->metric != RIP_METRIC_INFINITY)
1543 {
1544 route_unlock_node (rp);
1545 return;
1546 }
1547
1548 /* Manually configured RIP route check. */
1549 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001550 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1551 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001552 {
hasso16705132003-05-25 14:49:19 +00001553 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1554 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001555 {
1556 route_unlock_node (rp);
1557 return;
1558 }
1559 }
1560
1561 RIP_TIMER_OFF (rinfo->t_timeout);
1562 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1563
1564 if (rip_route_rte (rinfo))
1565 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1566 rinfo->metric);
1567 rp->info = NULL;
1568 rip_info_free (rinfo);
1569
1570 route_unlock_node (rp);
1571 }
1572
1573 rinfo = rip_info_new ();
1574
1575 rinfo->type = type;
1576 rinfo->sub_type = sub_type;
1577 rinfo->ifindex = ifindex;
1578 rinfo->metric = 1;
vincentfbf5d032005-09-29 11:25:50 +00001579 rinfo->external_metric = metric;
1580 rinfo->distance = distance;
paul718e3742002-12-13 20:15:29 +00001581 rinfo->rp = rp;
1582
1583 if (nexthop)
1584 rinfo->nexthop = *nexthop;
1585
1586 rinfo->flags |= RIP_RTF_FIB;
1587 rp->info = rinfo;
1588
1589 rinfo->flags |= RIP_RTF_CHANGED;
1590
hasso16705132003-05-25 14:49:19 +00001591 if (IS_RIP_DEBUG_EVENT) {
1592 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001593 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001594 inet_ntoa(p->prefix), p->prefixlen,
1595 ifindex2ifname(ifindex));
1596 else
ajs5d6c3772004-12-08 19:24:06 +00001597 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001598 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1599 ifindex2ifname(ifindex));
1600 }
1601
1602
paul718e3742002-12-13 20:15:29 +00001603 rip_event (RIP_TRIGGERED_UPDATE, 0);
1604}
1605
1606/* Delete redistributed route from RIP table. */
1607void
1608rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1609 unsigned int ifindex)
1610{
1611 int ret;
1612 struct route_node *rp;
1613 struct rip_info *rinfo;
1614
1615 ret = rip_destination_check (p->prefix);
1616 if (! ret)
1617 return;
1618
1619 rp = route_node_lookup (rip->table, (struct prefix *) p);
1620 if (rp)
1621 {
1622 rinfo = rp->info;
1623
1624 if (rinfo != NULL
1625 && rinfo->type == type
1626 && rinfo->sub_type == sub_type
1627 && rinfo->ifindex == ifindex)
1628 {
1629 /* Perform poisoned reverse. */
1630 rinfo->metric = RIP_METRIC_INFINITY;
1631 RIP_TIMER_ON (rinfo->t_garbage_collect,
1632 rip_garbage_collect, rip->garbage_time);
1633 RIP_TIMER_OFF (rinfo->t_timeout);
1634 rinfo->flags |= RIP_RTF_CHANGED;
1635
hasso16705132003-05-25 14:49:19 +00001636 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001637 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001638 inet_ntoa(p->prefix), p->prefixlen,
1639 ifindex2ifname(ifindex));
1640
paul718e3742002-12-13 20:15:29 +00001641 rip_event (RIP_TRIGGERED_UPDATE, 0);
1642 }
1643 }
1644}
1645
1646/* Response to request called from rip_read ().*/
pauldc63bfd2005-10-25 23:31:05 +00001647static void
paul718e3742002-12-13 20:15:29 +00001648rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001649 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001650{
1651 caddr_t lim;
1652 struct rte *rte;
1653 struct prefix_ipv4 p;
1654 struct route_node *rp;
1655 struct rip_info *rinfo;
1656 struct rip_interface *ri;
1657
hasso16705132003-05-25 14:49:19 +00001658 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001659 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001660 return;
1661
hasso429a0f82004-02-22 23:42:22 +00001662 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001663 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001664 if (! ri->running)
1665 return;
paul718e3742002-12-13 20:15:29 +00001666
1667 /* When passive interface is specified, suppress responses */
1668 if (ri->passive)
1669 return;
paulc49ad8f2004-10-22 10:27:28 +00001670
paul718e3742002-12-13 20:15:29 +00001671 /* RIP peer update. */
1672 rip_peer_update (from, packet->version);
1673
1674 lim = ((caddr_t) packet) + size;
1675 rte = packet->rte;
1676
1677 /* The Request is processed entry by entry. If there are no
1678 entries, no response is given. */
1679 if (lim == (caddr_t) rte)
1680 return;
1681
1682 /* There is one special case. If there is exactly one entry in the
1683 request, and it has an address family identifier of zero and a
1684 metric of infinity (i.e., 16), then this is a request to send the
1685 entire routing table. */
1686 if (lim == ((caddr_t) (rte + 1)) &&
1687 ntohs (rte->family) == 0 &&
1688 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1689 {
paulcc1131a2003-10-15 23:20:17 +00001690 struct prefix_ipv4 saddr;
1691
1692 /* saddr will be used for determining which routes to split-horizon.
1693 Since the source address we'll pick will be on the same subnet as the
1694 destination, for the purpose of split-horizoning, we'll
1695 pretend that "from" is our source address. */
1696 saddr.family = AF_INET;
1697 saddr.prefixlen = IPV4_MAX_BITLEN;
1698 saddr.prefix = from->sin_addr;
1699
paul718e3742002-12-13 20:15:29 +00001700 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001701 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001702 }
1703 else
1704 {
1705 /* Examine the list of RTEs in the Request one by one. For each
1706 entry, look up the destination in the router's routing
1707 database and, if there is a route, put that route's metric in
1708 the metric field of the RTE. If there is no explicit route
1709 to the specified destination, put infinity in the metric
1710 field. Once all the entries have been filled in, change the
1711 command from Request to Response and send the datagram back
1712 to the requestor. */
1713 p.family = AF_INET;
1714
1715 for (; ((caddr_t) rte) < lim; rte++)
1716 {
1717 p.prefix = rte->prefix;
1718 p.prefixlen = ip_masklen (rte->mask);
1719 apply_mask_ipv4 (&p);
1720
1721 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1722 if (rp)
1723 {
1724 rinfo = rp->info;
1725 rte->metric = htonl (rinfo->metric);
1726 route_unlock_node (rp);
1727 }
1728 else
1729 rte->metric = htonl (RIP_METRIC_INFINITY);
1730 }
1731 packet->command = RIP_RESPONSE;
1732
paulc49ad8f2004-10-22 10:27:28 +00001733 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001734 }
1735 rip_global_queries++;
1736}
1737
1738#if RIP_RECVMSG
1739/* Set IPv6 packet info to the socket. */
1740static int
1741setsockopt_pktinfo (int sock)
1742{
1743 int ret;
1744 int val = 1;
1745
1746 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1747 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001748 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001749 return ret;
1750}
1751
1752/* Read RIP packet by recvmsg function. */
1753int
1754rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1755 int *ifindex)
1756{
1757 int ret;
1758 struct msghdr msg;
1759 struct iovec iov;
1760 struct cmsghdr *ptr;
1761 char adata[1024];
1762
1763 msg.msg_name = (void *) from;
1764 msg.msg_namelen = sizeof (struct sockaddr_in);
1765 msg.msg_iov = &iov;
1766 msg.msg_iovlen = 1;
1767 msg.msg_control = (void *) adata;
1768 msg.msg_controllen = sizeof adata;
1769 iov.iov_base = buf;
1770 iov.iov_len = size;
1771
1772 ret = recvmsg (sock, &msg, 0);
1773 if (ret < 0)
1774 return ret;
1775
ajsb99760a2005-01-04 16:24:43 +00001776 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001777 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1778 {
1779 struct in_pktinfo *pktinfo;
1780 int i;
1781
1782 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1783 i = pktinfo->ipi_ifindex;
1784 }
1785 return ret;
1786}
1787
1788/* RIP packet read function. */
1789int
1790rip_read_new (struct thread *t)
1791{
1792 int ret;
1793 int sock;
1794 char buf[RIP_PACKET_MAXSIZ];
1795 struct sockaddr_in from;
1796 unsigned int ifindex;
1797
1798 /* Fetch socket then register myself. */
1799 sock = THREAD_FD (t);
1800 rip_event (RIP_READ, sock);
1801
1802 /* Read RIP packet. */
1803 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1804 if (ret < 0)
1805 {
ajs6099b3b2004-11-20 02:06:59 +00001806 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001807 return ret;
1808 }
1809
1810 return ret;
1811}
1812#endif /* RIP_RECVMSG */
1813
1814/* First entry point of RIP packet. */
pauldc63bfd2005-10-25 23:31:05 +00001815static int
paul718e3742002-12-13 20:15:29 +00001816rip_read (struct thread *t)
1817{
1818 int sock;
1819 int ret;
1820 int rtenum;
1821 union rip_buf rip_buf;
1822 struct rip_packet *packet;
1823 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001824 int len;
1825 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001826 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001827 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001828 struct rip_interface *ri;
1829
1830 /* Fetch socket then register myself. */
1831 sock = THREAD_FD (t);
1832 rip->t_read = NULL;
1833
1834 /* Add myself to tne next event */
1835 rip_event (RIP_READ, sock);
1836
1837 /* RIPd manages only IPv4. */
1838 memset (&from, 0, sizeof (struct sockaddr_in));
1839 fromlen = sizeof (struct sockaddr_in);
1840
1841 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1842 (struct sockaddr *) &from, &fromlen);
1843 if (len < 0)
1844 {
ajs6099b3b2004-11-20 02:06:59 +00001845 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001846 return len;
1847 }
1848
1849 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001850 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001851 {
1852 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001853 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001854 return -1;
1855 }
1856
1857 /* Which interface is this packet comes from. */
1858 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001859
paul718e3742002-12-13 20:15:29 +00001860 /* RIP packet received */
1861 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001862 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001863 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1864 ifp ? ifp->name : "unknown");
1865
1866 /* If this packet come from unknown interface, ignore it. */
1867 if (ifp == NULL)
1868 {
ajs766a0ca2004-12-15 14:55:51 +00001869 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1870 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001871 return -1;
1872 }
1873
1874 ifc = connected_lookup_address (ifp, from.sin_addr);
1875
1876 if (ifc == NULL)
1877 {
ajs766a0ca2004-12-15 14:55:51 +00001878 zlog_info ("rip_read: cannot find connected address for packet from %s "
1879 "port %d on interface %s",
1880 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001881 return -1;
1882 }
1883
1884 /* Packet length check. */
1885 if (len < RIP_PACKET_MINSIZ)
1886 {
1887 zlog_warn ("packet size %d is smaller than minimum size %d",
1888 len, RIP_PACKET_MINSIZ);
1889 rip_peer_bad_packet (&from);
1890 return len;
1891 }
1892 if (len > RIP_PACKET_MAXSIZ)
1893 {
1894 zlog_warn ("packet size %d is larger than max size %d",
1895 len, RIP_PACKET_MAXSIZ);
1896 rip_peer_bad_packet (&from);
1897 return len;
1898 }
1899
1900 /* Packet alignment check. */
1901 if ((len - RIP_PACKET_MINSIZ) % 20)
1902 {
1903 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1904 rip_peer_bad_packet (&from);
1905 return len;
1906 }
1907
1908 /* Set RTE number. */
1909 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1910
1911 /* For easy to handle. */
1912 packet = &rip_buf.rip_packet;
1913
1914 /* RIP version check. */
1915 if (packet->version == 0)
1916 {
1917 zlog_info ("version 0 with command %d received.", packet->command);
1918 rip_peer_bad_packet (&from);
1919 return -1;
1920 }
1921
1922 /* Dump RIP packet. */
1923 if (IS_RIP_DEBUG_RECV)
1924 rip_packet_dump (packet, len, "RECV");
1925
1926 /* RIP version adjust. This code should rethink now. RFC1058 says
1927 that "Version 1 implementations are to ignore this extra data and
1928 process only the fields specified in this document.". So RIPv3
1929 packet should be treated as RIPv1 ignoring must be zero field. */
1930 if (packet->version > RIPv2)
1931 packet->version = RIPv2;
1932
1933 /* Is RIP running or is this RIP neighbor ?*/
1934 ri = ifp->info;
1935 if (! ri->running && ! rip_neighbor_lookup (&from))
1936 {
1937 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001938 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001939 rip_peer_bad_packet (&from);
1940 return -1;
1941 }
1942
1943 /* RIP Version check. */
1944 if (packet->command == RIP_RESPONSE)
1945 {
paulf38a4712003-06-07 01:10:00 +00001946 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1947 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001948 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001949 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001950 {
1951 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001952 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001953 packet->version);
1954 rip_peer_bad_packet (&from);
1955 return -1;
1956 }
1957 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001958 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001959 {
1960 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001961 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001962 packet->version);
1963 rip_peer_bad_packet (&from);
1964 return -1;
1965 }
paul718e3742002-12-13 20:15:29 +00001966 }
1967
1968 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1969 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1970 accepted; authenticated RIP-2 messages shall be discarded. */
1971
1972 if ((ri->auth_type == RIP_NO_AUTH)
1973 && rtenum
paulca5e5162004-06-06 22:06:33 +00001974 && (packet->version == RIPv2)
1975 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001976 {
1977 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001978 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001979 packet->version);
1980 rip_peer_bad_packet (&from);
1981 return -1;
1982 }
1983
1984 /* If the router is configured to authenticate RIP-2 messages, then
1985 RIP-1 messages and RIP-2 messages which pass authentication
1986 testing shall be accepted; unauthenticated and failed
1987 authentication RIP-2 messages shall be discarded. For maximum
1988 security, RIP-1 messages should be ignored when authentication is
1989 in use (see section 4.1); otherwise, the routing information from
1990 authenticated messages will be propagated by RIP-1 routers in an
1991 unauthenticated manner. */
1992
1993 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001994 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001995 {
1996 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001997 if (packet->version == RIPv1
1998 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001999 {
2000 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002001 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002002 ("packet RIPv%d is dropped because authentication enabled",
2003 packet->version);
paul718e3742002-12-13 20:15:29 +00002004 rip_peer_bad_packet (&from);
2005 return -1;
2006 }
2007
2008 /* Check RIPv2 authentication. */
2009 if (packet->version == RIPv2)
2010 {
paulca5e5162004-06-06 22:06:33 +00002011 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00002012 {
paulca5e5162004-06-06 22:06:33 +00002013 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00002014 {
2015 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2016 if (! ret)
2017 {
2018 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002019 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002020 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00002021 rip_peer_bad_packet (&from);
2022 return -1;
2023 }
2024 else
2025 {
2026 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002027 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002028 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00002029 }
2030 }
paulca5e5162004-06-06 22:06:33 +00002031 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00002032 {
paulca5e5162004-06-06 22:06:33 +00002033 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00002034 if (! ret)
2035 {
2036 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002037 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00002038 rip_peer_bad_packet (&from);
2039 return -1;
2040 }
2041 else
2042 {
2043 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002044 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00002045 }
2046 /* Reset RIP packet length to trim MD5 data. */
2047 len = ret;
2048 }
2049 else
2050 {
2051 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002052 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00002053 ntohs (packet->rte->tag));
2054 rip_peer_bad_packet (&from);
2055 return -1;
2056 }
2057 }
2058 else
2059 {
2060 /* There is no authentication in the packet. */
2061 if (ri->auth_str || ri->key_chain)
2062 {
2063 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002064 zlog_debug
paulca5e5162004-06-06 22:06:33 +00002065 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00002066 rip_peer_bad_packet (&from);
2067 return -1;
2068 }
2069 }
2070 }
2071 }
2072
2073 /* Process each command. */
2074 switch (packet->command)
2075 {
2076 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002077 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002078 break;
2079 case RIP_REQUEST:
2080 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002081 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002082 break;
2083 case RIP_TRACEON:
2084 case RIP_TRACEOFF:
2085 zlog_info ("Obsolete command %s received, please sent it to routed",
2086 lookup (rip_msg, packet->command));
2087 rip_peer_bad_packet (&from);
2088 break;
2089 case RIP_POLL_ENTRY:
2090 zlog_info ("Obsolete command %s received",
2091 lookup (rip_msg, packet->command));
2092 rip_peer_bad_packet (&from);
2093 break;
2094 default:
2095 zlog_info ("Unknown RIP command %d received", packet->command);
2096 rip_peer_bad_packet (&from);
2097 break;
2098 }
2099
2100 return len;
2101}
2102
paul718e3742002-12-13 20:15:29 +00002103/* Write routing table entry to the stream and return next index of
2104 the routing table entry in the stream. */
pauldc63bfd2005-10-25 23:31:05 +00002105static int
paul718e3742002-12-13 20:15:29 +00002106rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002107 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002108{
2109 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002110
2111 /* Write routing table entry. */
2112 if (version == RIPv1)
2113 {
2114 stream_putw (s, AF_INET);
2115 stream_putw (s, 0);
2116 stream_put_ipv4 (s, p->prefix.s_addr);
2117 stream_put_ipv4 (s, 0);
2118 stream_put_ipv4 (s, 0);
2119 stream_putl (s, rinfo->metric_out);
2120 }
2121 else
2122 {
2123 masklen2ip (p->prefixlen, &mask);
2124
2125 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002126 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002127 stream_put_ipv4 (s, p->prefix.s_addr);
2128 stream_put_ipv4 (s, mask.s_addr);
2129 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2130 stream_putl (s, rinfo->metric_out);
2131 }
2132
2133 return ++num;
2134}
2135
2136/* Send update to the ifp or spcified neighbor. */
2137void
paulc49ad8f2004-10-22 10:27:28 +00002138rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2139 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002140{
2141 int ret;
2142 struct stream *s;
2143 struct route_node *rp;
2144 struct rip_info *rinfo;
2145 struct rip_interface *ri;
2146 struct prefix_ipv4 *p;
2147 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002148 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002149 struct key *key = NULL;
2150 /* this might need to made dynamic if RIP ever supported auth methods
2151 with larger key string sizes */
2152 char auth_str[RIP_AUTH_SIMPLE_SIZE];
pauldc63bfd2005-10-25 23:31:05 +00002153 size_t doff = 0; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002154 int num = 0;
paul718e3742002-12-13 20:15:29 +00002155 int rtemax;
paul01d09082003-06-08 21:22:18 +00002156 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002157
2158 /* Logging output event. */
2159 if (IS_RIP_DEBUG_EVENT)
2160 {
2161 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002162 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002163 else
ajs5d6c3772004-12-08 19:24:06 +00002164 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002165 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002166 }
2167
2168 /* Set output stream. */
2169 s = rip->obuf;
2170
2171 /* Reset stream and RTE counter. */
2172 stream_reset (s);
paul718e3742002-12-13 20:15:29 +00002173 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2174
2175 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002176 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002177
2178 /* If output interface is in simple password authentication mode, we
2179 need space for authentication data. */
2180 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2181 rtemax -= 1;
2182
2183 /* If output interface is in MD5 authentication mode, we need space
2184 for authentication header and data. */
2185 if (ri->auth_type == RIP_AUTH_MD5)
2186 rtemax -= 2;
2187
2188 /* If output interface is in simple password authentication mode
2189 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002190 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002191 {
2192 if (ri->key_chain)
2193 {
2194 struct keychain *keychain;
2195
2196 keychain = keychain_lookup (ri->key_chain);
2197 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002198 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002199 }
paulb14ee002005-02-04 23:42:41 +00002200 /* to be passed to auth functions later */
2201 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002202 }
2203
paul727d1042002-12-13 20:50:29 +00002204 if (version == RIPv1)
2205 {
paulc49ad8f2004-10-22 10:27:28 +00002206 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002207 apply_classful_mask_ipv4 (&ifaddrclass);
2208 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002209 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002210 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002211 }
2212
paul718e3742002-12-13 20:15:29 +00002213 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2214 if ((rinfo = rp->info) != NULL)
2215 {
paul727d1042002-12-13 20:50:29 +00002216 /* For RIPv1, if we are subnetted, output subnets in our network */
2217 /* that have the same mask as the output "interface". For other */
2218 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002219
2220 if (version == RIPv1)
2221 {
paul727d1042002-12-13 20:50:29 +00002222 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002223
2224 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002225 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002226 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002227
paul727d1042002-12-13 20:50:29 +00002228 if (subnetted &&
2229 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2230 {
paulc49ad8f2004-10-22 10:27:28 +00002231 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002232 (rp->p.prefixlen != 32))
2233 continue;
2234 }
2235 else
2236 {
2237 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2238 apply_classful_mask_ipv4(&classfull);
2239 if (rp->p.u.prefix4.s_addr != 0 &&
2240 classfull.prefixlen != rp->p.prefixlen)
2241 continue;
2242 }
paul718e3742002-12-13 20:15:29 +00002243 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002244 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002245 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002246 }
2247 else
2248 p = (struct prefix_ipv4 *) &rp->p;
2249
2250 /* Apply output filters. */
2251 ret = rip_outgoing_filter (p, ri);
2252 if (ret < 0)
2253 continue;
2254
2255 /* Changed route only output. */
2256 if (route_type == rip_changed_route &&
2257 (! (rinfo->flags & RIP_RTF_CHANGED)))
2258 continue;
2259
2260 /* Split horizon. */
2261 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002262 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002263 {
paul42d14d92003-11-17 09:15:18 +00002264 /*
2265 * We perform split horizon for RIP and connected route.
2266 * For rip routes, we want to suppress the route if we would
2267 * end up sending the route back on the interface that we
2268 * learned it from, with a higher metric. For connected routes,
2269 * we suppress the route if the prefix is a subset of the
2270 * source address that we are going to use for the packet
2271 * (in order to handle the case when multiple subnets are
2272 * configured on the same interface).
2273 */
2274 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002275 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002276 continue;
2277 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002278 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002279 continue;
2280 }
2281
2282 /* Preparation for route-map. */
2283 rinfo->metric_set = 0;
2284 rinfo->nexthop_out.s_addr = 0;
2285 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002286 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002287 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002288
hasso16705132003-05-25 14:49:19 +00002289 /* In order to avoid some local loops,
2290 * if the RIP route has a nexthop via this interface, keep the nexthop,
2291 * otherwise set it to 0. The nexthop should not be propagated
2292 * beyond the local broadcast/multicast area in order
2293 * to avoid an IGP multi-level recursive look-up.
2294 * see (4.4)
2295 */
paulc49ad8f2004-10-22 10:27:28 +00002296 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002297 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002298
2299 /* Interface route-map */
2300 if (ri->routemap[RIP_FILTER_OUT])
2301 {
2302 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2303 (struct prefix *) p, RMAP_RIP,
2304 rinfo);
2305
2306 if (ret == RMAP_DENYMATCH)
2307 {
2308 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002309 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002310 inet_ntoa (p->prefix), p->prefixlen);
2311 continue;
2312 }
2313 }
paul718e3742002-12-13 20:15:29 +00002314
hasso16705132003-05-25 14:49:19 +00002315 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002316 if (rip->route_map[rinfo->type].name
2317 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2318 {
2319 ret = route_map_apply (rip->route_map[rinfo->type].map,
2320 (struct prefix *)p, RMAP_RIP, rinfo);
2321
2322 if (ret == RMAP_DENYMATCH)
2323 {
2324 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002325 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002326 inet_ntoa (p->prefix), p->prefixlen);
2327 continue;
2328 }
2329 }
2330
2331 /* When route-map does not set metric. */
2332 if (! rinfo->metric_set)
2333 {
2334 /* If redistribute metric is set. */
2335 if (rip->route_map[rinfo->type].metric_config
2336 && rinfo->metric != RIP_METRIC_INFINITY)
2337 {
2338 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2339 }
2340 else
2341 {
2342 /* If the route is not connected or localy generated
2343 one, use default-metric value*/
2344 if (rinfo->type != ZEBRA_ROUTE_RIP
2345 && rinfo->type != ZEBRA_ROUTE_CONNECT
2346 && rinfo->metric != RIP_METRIC_INFINITY)
2347 rinfo->metric_out = rip->default_metric;
2348 }
2349 }
2350
2351 /* Apply offset-list */
2352 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002353 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002354
2355 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2356 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002357
2358 /* Perform split-horizon with poisoned reverse
2359 * for RIP and connected routes.
2360 **/
2361 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002362 /*
2363 * We perform split horizon for RIP and connected route.
2364 * For rip routes, we want to suppress the route if we would
2365 * end up sending the route back on the interface that we
2366 * learned it from, with a higher metric. For connected routes,
2367 * we suppress the route if the prefix is a subset of the
2368 * source address that we are going to use for the packet
2369 * (in order to handle the case when multiple subnets are
2370 * configured on the same interface).
2371 */
2372 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002373 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002374 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002375 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002376 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002377 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002378 }
paulb14ee002005-02-04 23:42:41 +00002379
2380 /* Prepare preamble, auth headers, if needs be */
2381 if (num == 0)
2382 {
2383 stream_putc (s, RIP_RESPONSE);
2384 stream_putc (s, version);
2385 stream_putw (s, 0);
2386
paul0cb8a012005-05-29 11:27:24 +00002387 /* auth header for !v1 && !no_auth */
2388 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002389 doff = rip_auth_header_write (s, ri, key, auth_str,
2390 RIP_AUTH_SIMPLE_SIZE);
2391 }
2392
paul718e3742002-12-13 20:15:29 +00002393 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002394 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002395 if (num == rtemax)
2396 {
2397 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002398 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002399
2400 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002401 to, ifc);
paul718e3742002-12-13 20:15:29 +00002402
2403 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2404 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2405 stream_get_endp(s), "SEND");
2406 num = 0;
2407 stream_reset (s);
2408 }
2409 }
2410
2411 /* Flush unwritten RTE. */
2412 if (num != 0)
2413 {
2414 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002415 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002416
paulc49ad8f2004-10-22 10:27:28 +00002417 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002418
2419 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2420 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2421 stream_get_endp (s), "SEND");
2422 num = 0;
2423 stream_reset (s);
2424 }
2425
2426 /* Statistics updates. */
2427 ri->sent_updates++;
2428}
2429
2430/* Send RIP packet to the interface. */
pauldc63bfd2005-10-25 23:31:05 +00002431static void
paulc49ad8f2004-10-22 10:27:28 +00002432rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002433{
paul718e3742002-12-13 20:15:29 +00002434 struct sockaddr_in to;
2435
2436 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002437 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002438 {
2439 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002440 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002441
paulc49ad8f2004-10-22 10:27:28 +00002442 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002443 return;
2444 }
paulc49ad8f2004-10-22 10:27:28 +00002445
paul718e3742002-12-13 20:15:29 +00002446 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002447 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002448 {
paulc49ad8f2004-10-22 10:27:28 +00002449 if (ifc->address->family == AF_INET)
2450 {
2451 /* Destination address and port setting. */
2452 memset (&to, 0, sizeof (struct sockaddr_in));
2453 if (ifc->destination)
2454 /* use specified broadcast or point-to-point destination addr */
2455 to.sin_addr = ifc->destination->u.prefix4;
2456 else
2457 /* calculate the appropriate broadcast address */
2458 to.sin_addr.s_addr =
2459 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2460 ifc->address->prefixlen);
2461 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002462
paulc49ad8f2004-10-22 10:27:28 +00002463 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002464 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002465 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2466 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002467
paulc49ad8f2004-10-22 10:27:28 +00002468 rip_output_process (ifc, &to, route_type, version);
2469 }
paul718e3742002-12-13 20:15:29 +00002470 }
2471}
2472
2473/* Update send to all interface and neighbor. */
pauldc63bfd2005-10-25 23:31:05 +00002474static void
paul718e3742002-12-13 20:15:29 +00002475rip_update_process (int route_type)
2476{
paul1eb8ef22005-04-07 07:30:20 +00002477 struct listnode *node;
2478 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002479 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002480 struct interface *ifp;
2481 struct rip_interface *ri;
2482 struct route_node *rp;
2483 struct sockaddr_in to;
2484 struct prefix_ipv4 *p;
2485
2486 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002487 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002488 {
paul718e3742002-12-13 20:15:29 +00002489 if (if_is_loopback (ifp))
2490 continue;
2491
paul2e3b2e42002-12-13 21:03:13 +00002492 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002493 continue;
2494
2495 /* Fetch RIP interface information. */
2496 ri = ifp->info;
2497
2498 /* When passive interface is specified, suppress announce to the
2499 interface. */
2500 if (ri->passive)
2501 continue;
2502
2503 if (ri->running)
2504 {
2505 if (IS_RIP_DEBUG_EVENT)
2506 {
2507 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002508 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002509 ifp->name, ifp->ifindex);
2510 else
ajs5d6c3772004-12-08 19:24:06 +00002511 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002512 ifp->ifindex);
2513 }
2514
paulcc1131a2003-10-15 23:20:17 +00002515 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002516 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002517 {
2518 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002519 int done = 0;
2520 /*
2521 * If there is no version configuration in the interface,
2522 * use rip's version setting.
2523 */
paulf38a4712003-06-07 01:10:00 +00002524 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2525 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002526
2527 ifaddr = (struct prefix_ipv4 *) connected->address;
2528
2529 if (ifaddr->family != AF_INET)
2530 continue;
2531
paul931cd542004-01-23 15:31:42 +00002532 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002533 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002534 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002535 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002536 done = 1;
2537 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2538 break;
2539
paulf38a4712003-06-07 01:10:00 +00002540 }
paul718e3742002-12-13 20:15:29 +00002541 }
2542 }
2543
2544 /* RIP send updates to each neighbor. */
2545 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2546 if (rp->info != NULL)
2547 {
2548 p = (struct prefix_ipv4 *) &rp->p;
2549
2550 ifp = if_lookup_address (p->prefix);
2551 if (! ifp)
2552 {
paulc49ad8f2004-10-22 10:27:28 +00002553 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002554 inet_ntoa (p->prefix));
2555 continue;
2556 }
paulc49ad8f2004-10-22 10:27:28 +00002557
2558 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2559 {
2560 zlog_warn ("Neighbor %s doesnt have connected network",
2561 inet_ntoa (p->prefix));
2562 continue;
2563 }
2564
paul718e3742002-12-13 20:15:29 +00002565 /* Set destination address and port */
2566 memset (&to, 0, sizeof (struct sockaddr_in));
2567 to.sin_addr = p->prefix;
2568 to.sin_port = htons (RIP_PORT_DEFAULT);
2569
2570 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002571 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002572 }
2573}
2574
2575/* RIP's periodical timer. */
pauldc63bfd2005-10-25 23:31:05 +00002576static int
paul718e3742002-12-13 20:15:29 +00002577rip_update (struct thread *t)
2578{
2579 /* Clear timer pointer. */
2580 rip->t_update = NULL;
2581
2582 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002583 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002584
2585 /* Process update output. */
2586 rip_update_process (rip_all_route);
2587
2588 /* Triggered updates may be suppressed if a regular update is due by
2589 the time the triggered update would be sent. */
2590 if (rip->t_triggered_interval)
2591 {
2592 thread_cancel (rip->t_triggered_interval);
2593 rip->t_triggered_interval = NULL;
2594 }
2595 rip->trigger = 0;
2596
2597 /* Register myself. */
2598 rip_event (RIP_UPDATE_EVENT, 0);
2599
2600 return 0;
2601}
2602
2603/* Walk down the RIP routing table then clear changed flag. */
pauldc63bfd2005-10-25 23:31:05 +00002604static void
paul718e3742002-12-13 20:15:29 +00002605rip_clear_changed_flag ()
2606{
2607 struct route_node *rp;
2608 struct rip_info *rinfo;
2609
2610 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2611 if ((rinfo = rp->info) != NULL)
2612 if (rinfo->flags & RIP_RTF_CHANGED)
2613 rinfo->flags &= ~RIP_RTF_CHANGED;
2614}
2615
2616/* Triggered update interval timer. */
pauldc63bfd2005-10-25 23:31:05 +00002617static int
paul718e3742002-12-13 20:15:29 +00002618rip_triggered_interval (struct thread *t)
2619{
2620 int rip_triggered_update (struct thread *);
2621
2622 rip->t_triggered_interval = NULL;
2623
2624 if (rip->trigger)
2625 {
2626 rip->trigger = 0;
2627 rip_triggered_update (t);
2628 }
2629 return 0;
2630}
2631
2632/* Execute triggered update. */
pauldc63bfd2005-10-25 23:31:05 +00002633static int
paul718e3742002-12-13 20:15:29 +00002634rip_triggered_update (struct thread *t)
2635{
2636 int interval;
2637
2638 /* Clear thred pointer. */
2639 rip->t_triggered_update = NULL;
2640
2641 /* Cancel interval timer. */
2642 if (rip->t_triggered_interval)
2643 {
2644 thread_cancel (rip->t_triggered_interval);
2645 rip->t_triggered_interval = NULL;
2646 }
2647 rip->trigger = 0;
2648
2649 /* Logging triggered update. */
2650 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002651 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002652
2653 /* Split Horizon processing is done when generating triggered
2654 updates as well as normal updates (see section 2.6). */
2655 rip_update_process (rip_changed_route);
2656
2657 /* Once all of the triggered updates have been generated, the route
2658 change flags should be cleared. */
2659 rip_clear_changed_flag ();
2660
2661 /* After a triggered update is sent, a timer should be set for a
2662 random interval between 1 and 5 seconds. If other changes that
2663 would trigger updates occur before the timer expires, a single
2664 update is triggered when the timer expires. */
2665 interval = (random () % 5) + 1;
2666
2667 rip->t_triggered_interval =
2668 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2669
2670 return 0;
2671}
2672
2673/* Withdraw redistributed route. */
2674void
2675rip_redistribute_withdraw (int type)
2676{
2677 struct route_node *rp;
2678 struct rip_info *rinfo;
2679
2680 if (!rip)
2681 return;
2682
2683 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2684 if ((rinfo = rp->info) != NULL)
2685 {
2686 if (rinfo->type == type
2687 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2688 {
2689 /* Perform poisoned reverse. */
2690 rinfo->metric = RIP_METRIC_INFINITY;
2691 RIP_TIMER_ON (rinfo->t_garbage_collect,
2692 rip_garbage_collect, rip->garbage_time);
2693 RIP_TIMER_OFF (rinfo->t_timeout);
2694 rinfo->flags |= RIP_RTF_CHANGED;
2695
hasso16705132003-05-25 14:49:19 +00002696 if (IS_RIP_DEBUG_EVENT) {
2697 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2698
ajs5d6c3772004-12-08 19:24:06 +00002699 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002700 inet_ntoa(p->prefix), p->prefixlen,
2701 ifindex2ifname(rinfo->ifindex));
2702 }
2703
paul718e3742002-12-13 20:15:29 +00002704 rip_event (RIP_TRIGGERED_UPDATE, 0);
2705 }
2706 }
2707}
2708
2709/* Create new RIP instance and set it to global variable. */
pauldc63bfd2005-10-25 23:31:05 +00002710static int
2711rip_create (void)
paul718e3742002-12-13 20:15:29 +00002712{
2713 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2714 memset (rip, 0, sizeof (struct rip));
2715
2716 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002717 rip->version_send = RI_RIP_VERSION_2;
2718 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002719 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2720 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2721 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2722 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2723
2724 /* Initialize RIP routig table. */
2725 rip->table = route_table_init ();
2726 rip->route = route_table_init ();
2727 rip->neighbor = route_table_init ();
2728
2729 /* Make output stream. */
2730 rip->obuf = stream_new (1500);
2731
2732 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002733 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002734 if (rip->sock < 0)
2735 return rip->sock;
2736
2737 /* Create read and timer thread. */
2738 rip_event (RIP_READ, rip->sock);
2739 rip_event (RIP_UPDATE_EVENT, 1);
2740
2741 return 0;
2742}
2743
2744/* Sned RIP request to the destination. */
2745int
2746rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002747 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002748{
2749 struct rte *rte;
2750 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002751 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002752
2753 memset (&rip_packet, 0, sizeof (rip_packet));
2754
2755 rip_packet.command = RIP_REQUEST;
2756 rip_packet.version = version;
2757 rte = rip_packet.rte;
2758 rte->metric = htonl (RIP_METRIC_INFINITY);
2759
paul931cd542004-01-23 15:31:42 +00002760 if (connected)
2761 {
2762 /*
2763 * connected is only sent for ripv1 case, or when
2764 * interface does not support multicast. Caller loops
2765 * over each connected address for this case.
2766 */
paul11dde9c2004-05-31 14:00:00 +00002767 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002768 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002769 return -1;
2770 else
2771 return sizeof (rip_packet);
2772 }
2773
paulcc1131a2003-10-15 23:20:17 +00002774 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002775 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002776 {
2777 struct prefix_ipv4 *p;
2778
2779 p = (struct prefix_ipv4 *) connected->address;
2780
2781 if (p->family != AF_INET)
2782 continue;
2783
paul11dde9c2004-05-31 14:00:00 +00002784 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002785 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002786 return -1;
2787 }
2788 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002789}
2790
pauldc63bfd2005-10-25 23:31:05 +00002791static int
paul718e3742002-12-13 20:15:29 +00002792rip_update_jitter (unsigned long time)
2793{
paul239389b2004-05-05 14:09:37 +00002794#define JITTER_BOUND 4
2795 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2796 Given that, we cannot let time be less than JITTER_BOUND seconds.
2797 The RIPv2 RFC says jitter should be small compared to
2798 update_time. We consider 1/JITTER_BOUND to be small.
2799 */
2800
2801 int jitter_input = time;
2802 int jitter;
2803
2804 if (jitter_input < JITTER_BOUND)
2805 jitter_input = JITTER_BOUND;
2806
2807 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2808
2809 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002810}
2811
2812void
2813rip_event (enum rip_event event, int sock)
2814{
2815 int jitter = 0;
2816
2817 switch (event)
2818 {
2819 case RIP_READ:
2820 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2821 break;
2822 case RIP_UPDATE_EVENT:
2823 if (rip->t_update)
2824 {
2825 thread_cancel (rip->t_update);
2826 rip->t_update = NULL;
2827 }
2828 jitter = rip_update_jitter (rip->update_time);
2829 rip->t_update =
2830 thread_add_timer (master, rip_update, NULL,
2831 sock ? 2 : rip->update_time + jitter);
2832 break;
2833 case RIP_TRIGGERED_UPDATE:
2834 if (rip->t_triggered_interval)
2835 rip->trigger = 1;
2836 else if (! rip->t_triggered_update)
2837 rip->t_triggered_update =
2838 thread_add_event (master, rip_triggered_update, NULL, 0);
2839 break;
2840 default:
2841 break;
2842 }
2843}
2844
2845DEFUN (router_rip,
2846 router_rip_cmd,
2847 "router rip",
2848 "Enable a routing process\n"
2849 "Routing Information Protocol (RIP)\n")
2850{
2851 int ret;
2852
2853 /* If rip is not enabled before. */
2854 if (! rip)
2855 {
2856 ret = rip_create ();
2857 if (ret < 0)
2858 {
2859 zlog_info ("Can't create RIP");
2860 return CMD_WARNING;
2861 }
2862 }
2863 vty->node = RIP_NODE;
2864 vty->index = rip;
2865
2866 return CMD_SUCCESS;
2867}
2868
2869DEFUN (no_router_rip,
2870 no_router_rip_cmd,
2871 "no router rip",
2872 NO_STR
2873 "Enable a routing process\n"
2874 "Routing Information Protocol (RIP)\n")
2875{
2876 if (rip)
2877 rip_clean ();
2878 return CMD_SUCCESS;
2879}
2880
2881DEFUN (rip_version,
2882 rip_version_cmd,
2883 "version <1-2>",
2884 "Set routing protocol version\n"
2885 "version\n")
2886{
2887 int version;
2888
2889 version = atoi (argv[0]);
2890 if (version != RIPv1 && version != RIPv2)
2891 {
2892 vty_out (vty, "invalid rip version %d%s", version,
2893 VTY_NEWLINE);
2894 return CMD_WARNING;
2895 }
paulf38a4712003-06-07 01:10:00 +00002896 rip->version_send = version;
2897 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002898
2899 return CMD_SUCCESS;
2900}
2901
2902DEFUN (no_rip_version,
2903 no_rip_version_cmd,
2904 "no version",
2905 NO_STR
2906 "Set routing protocol version\n")
2907{
2908 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002909 rip->version_send = RI_RIP_VERSION_2;
2910 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002911
2912 return CMD_SUCCESS;
2913}
2914
2915ALIAS (no_rip_version,
2916 no_rip_version_val_cmd,
2917 "no version <1-2>",
2918 NO_STR
2919 "Set routing protocol version\n"
2920 "version\n")
2921
2922DEFUN (rip_route,
2923 rip_route_cmd,
2924 "route A.B.C.D/M",
2925 "RIP static route configuration\n"
2926 "IP prefix <network>/<length>\n")
2927{
2928 int ret;
2929 struct prefix_ipv4 p;
2930 struct route_node *node;
2931
2932 ret = str2prefix_ipv4 (argv[0], &p);
2933 if (ret < 0)
2934 {
2935 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2936 return CMD_WARNING;
2937 }
2938 apply_mask_ipv4 (&p);
2939
2940 /* For router rip configuration. */
2941 node = route_node_get (rip->route, (struct prefix *) &p);
2942
2943 if (node->info)
2944 {
2945 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2946 route_unlock_node (node);
2947 return CMD_WARNING;
2948 }
2949
hasso8a676be2004-10-08 06:36:38 +00002950 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002951
vincentfbf5d032005-09-29 11:25:50 +00002952 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
paul718e3742002-12-13 20:15:29 +00002953
2954 return CMD_SUCCESS;
2955}
2956
2957DEFUN (no_rip_route,
2958 no_rip_route_cmd,
2959 "no route A.B.C.D/M",
2960 NO_STR
2961 "RIP static route configuration\n"
2962 "IP prefix <network>/<length>\n")
2963{
2964 int ret;
2965 struct prefix_ipv4 p;
2966 struct route_node *node;
2967
2968 ret = str2prefix_ipv4 (argv[0], &p);
2969 if (ret < 0)
2970 {
2971 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2972 return CMD_WARNING;
2973 }
2974 apply_mask_ipv4 (&p);
2975
2976 /* For router rip configuration. */
2977 node = route_node_lookup (rip->route, (struct prefix *) &p);
2978 if (! node)
2979 {
2980 vty_out (vty, "Can't find route %s.%s", argv[0],
2981 VTY_NEWLINE);
2982 return CMD_WARNING;
2983 }
2984
2985 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2986 route_unlock_node (node);
2987
2988 node->info = NULL;
2989 route_unlock_node (node);
2990
2991 return CMD_SUCCESS;
2992}
2993
pauldc63bfd2005-10-25 23:31:05 +00002994static void
paul718e3742002-12-13 20:15:29 +00002995rip_update_default_metric ()
2996{
2997 struct route_node *np;
2998 struct rip_info *rinfo;
2999
3000 for (np = route_top (rip->table); np; np = route_next (np))
3001 if ((rinfo = np->info) != NULL)
3002 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3003 rinfo->metric = rip->default_metric;
3004}
3005
3006DEFUN (rip_default_metric,
3007 rip_default_metric_cmd,
3008 "default-metric <1-16>",
3009 "Set a metric of redistribute routes\n"
3010 "Default metric\n")
3011{
3012 if (rip)
3013 {
3014 rip->default_metric = atoi (argv[0]);
3015 /* rip_update_default_metric (); */
3016 }
3017 return CMD_SUCCESS;
3018}
3019
3020DEFUN (no_rip_default_metric,
3021 no_rip_default_metric_cmd,
3022 "no default-metric",
3023 NO_STR
3024 "Set a metric of redistribute routes\n"
3025 "Default metric\n")
3026{
3027 if (rip)
3028 {
3029 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3030 /* rip_update_default_metric (); */
3031 }
3032 return CMD_SUCCESS;
3033}
3034
3035ALIAS (no_rip_default_metric,
3036 no_rip_default_metric_val_cmd,
3037 "no default-metric <1-16>",
3038 NO_STR
3039 "Set a metric of redistribute routes\n"
3040 "Default metric\n")
3041
3042DEFUN (rip_timers,
3043 rip_timers_cmd,
3044 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3045 "Adjust routing timers\n"
3046 "Basic routing protocol update timers\n"
3047 "Routing table update timer value in second. Default is 30.\n"
3048 "Routing information timeout timer. Default is 180.\n"
3049 "Garbage collection timer. Default is 120.\n")
3050{
3051 unsigned long update;
3052 unsigned long timeout;
3053 unsigned long garbage;
3054 char *endptr = NULL;
3055 unsigned long RIP_TIMER_MAX = 2147483647;
3056 unsigned long RIP_TIMER_MIN = 5;
3057
3058 update = strtoul (argv[0], &endptr, 10);
3059 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3060 {
3061 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3062 return CMD_WARNING;
3063 }
3064
3065 timeout = strtoul (argv[1], &endptr, 10);
3066 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3067 {
3068 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3069 return CMD_WARNING;
3070 }
3071
3072 garbage = strtoul (argv[2], &endptr, 10);
3073 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3074 {
3075 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3076 return CMD_WARNING;
3077 }
3078
3079 /* Set each timer value. */
3080 rip->update_time = update;
3081 rip->timeout_time = timeout;
3082 rip->garbage_time = garbage;
3083
3084 /* Reset update timer thread. */
3085 rip_event (RIP_UPDATE_EVENT, 0);
3086
3087 return CMD_SUCCESS;
3088}
3089
3090DEFUN (no_rip_timers,
3091 no_rip_timers_cmd,
3092 "no timers basic",
3093 NO_STR
3094 "Adjust routing timers\n"
3095 "Basic routing protocol update timers\n")
3096{
3097 /* Set each timer value to the default. */
3098 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3099 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3100 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3101
3102 /* Reset update timer thread. */
3103 rip_event (RIP_UPDATE_EVENT, 0);
3104
3105 return CMD_SUCCESS;
3106}
hasso16705132003-05-25 14:49:19 +00003107
3108ALIAS (no_rip_timers,
3109 no_rip_timers_val_cmd,
3110 "no timers basic <0-65535> <0-65535> <0-65535>",
3111 NO_STR
3112 "Adjust routing timers\n"
3113 "Basic routing protocol update timers\n"
3114 "Routing table update timer value in second. Default is 30.\n"
3115 "Routing information timeout timer. Default is 180.\n"
3116 "Garbage collection timer. Default is 120.\n")
3117
paul718e3742002-12-13 20:15:29 +00003118
3119struct route_table *rip_distance_table;
3120
3121struct rip_distance
3122{
3123 /* Distance value for the IP source prefix. */
3124 u_char distance;
3125
3126 /* Name of the access-list to be matched. */
3127 char *access_list;
3128};
3129
pauldc63bfd2005-10-25 23:31:05 +00003130static struct rip_distance *
paul718e3742002-12-13 20:15:29 +00003131rip_distance_new ()
3132{
3133 struct rip_distance *new;
3134 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3135 memset (new, 0, sizeof (struct rip_distance));
3136 return new;
3137}
3138
pauldc63bfd2005-10-25 23:31:05 +00003139static void
paul718e3742002-12-13 20:15:29 +00003140rip_distance_free (struct rip_distance *rdistance)
3141{
3142 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3143}
3144
pauldc63bfd2005-10-25 23:31:05 +00003145static int
hasso98b718a2004-10-11 12:57:57 +00003146rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3147 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003148{
3149 int ret;
3150 struct prefix_ipv4 p;
3151 u_char distance;
3152 struct route_node *rn;
3153 struct rip_distance *rdistance;
3154
3155 ret = str2prefix_ipv4 (ip_str, &p);
3156 if (ret == 0)
3157 {
3158 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3159 return CMD_WARNING;
3160 }
3161
3162 distance = atoi (distance_str);
3163
3164 /* Get RIP distance node. */
3165 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3166 if (rn->info)
3167 {
3168 rdistance = rn->info;
3169 route_unlock_node (rn);
3170 }
3171 else
3172 {
3173 rdistance = rip_distance_new ();
3174 rn->info = rdistance;
3175 }
3176
3177 /* Set distance value. */
3178 rdistance->distance = distance;
3179
3180 /* Reset access-list configuration. */
3181 if (rdistance->access_list)
3182 {
3183 free (rdistance->access_list);
3184 rdistance->access_list = NULL;
3185 }
3186 if (access_list_str)
3187 rdistance->access_list = strdup (access_list_str);
3188
3189 return CMD_SUCCESS;
3190}
3191
pauldc63bfd2005-10-25 23:31:05 +00003192static int
hasso98b718a2004-10-11 12:57:57 +00003193rip_distance_unset (struct vty *vty, const char *distance_str,
3194 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003195{
3196 int ret;
3197 struct prefix_ipv4 p;
3198 u_char distance;
3199 struct route_node *rn;
3200 struct rip_distance *rdistance;
3201
3202 ret = str2prefix_ipv4 (ip_str, &p);
3203 if (ret == 0)
3204 {
3205 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3206 return CMD_WARNING;
3207 }
3208
3209 distance = atoi (distance_str);
3210
3211 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3212 if (! rn)
3213 {
3214 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3215 return CMD_WARNING;
3216 }
3217
3218 rdistance = rn->info;
3219
3220 if (rdistance->access_list)
3221 free (rdistance->access_list);
3222 rip_distance_free (rdistance);
3223
3224 rn->info = NULL;
3225 route_unlock_node (rn);
3226 route_unlock_node (rn);
3227
3228 return CMD_SUCCESS;
3229}
3230
pauldc63bfd2005-10-25 23:31:05 +00003231static void
paul718e3742002-12-13 20:15:29 +00003232rip_distance_reset ()
3233{
3234 struct route_node *rn;
3235 struct rip_distance *rdistance;
3236
3237 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3238 if ((rdistance = rn->info) != NULL)
3239 {
3240 if (rdistance->access_list)
3241 free (rdistance->access_list);
3242 rip_distance_free (rdistance);
3243 rn->info = NULL;
3244 route_unlock_node (rn);
3245 }
3246}
3247
3248/* Apply RIP information to distance method. */
3249u_char
3250rip_distance_apply (struct rip_info *rinfo)
3251{
3252 struct route_node *rn;
3253 struct prefix_ipv4 p;
3254 struct rip_distance *rdistance;
3255 struct access_list *alist;
3256
3257 if (! rip)
3258 return 0;
3259
3260 memset (&p, 0, sizeof (struct prefix_ipv4));
3261 p.family = AF_INET;
3262 p.prefix = rinfo->from;
3263 p.prefixlen = IPV4_MAX_BITLEN;
3264
3265 /* Check source address. */
3266 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3267 if (rn)
3268 {
3269 rdistance = rn->info;
3270 route_unlock_node (rn);
3271
3272 if (rdistance->access_list)
3273 {
3274 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3275 if (alist == NULL)
3276 return 0;
3277 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3278 return 0;
3279
3280 return rdistance->distance;
3281 }
3282 else
3283 return rdistance->distance;
3284 }
3285
3286 if (rip->distance)
3287 return rip->distance;
3288
3289 return 0;
3290}
3291
pauldc63bfd2005-10-25 23:31:05 +00003292static void
paul718e3742002-12-13 20:15:29 +00003293rip_distance_show (struct vty *vty)
3294{
3295 struct route_node *rn;
3296 struct rip_distance *rdistance;
3297 int header = 1;
3298 char buf[BUFSIZ];
3299
3300 vty_out (vty, " Distance: (default is %d)%s",
3301 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3302 VTY_NEWLINE);
3303
3304 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3305 if ((rdistance = rn->info) != NULL)
3306 {
3307 if (header)
3308 {
3309 vty_out (vty, " Address Distance List%s",
3310 VTY_NEWLINE);
3311 header = 0;
3312 }
3313 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3314 vty_out (vty, " %-20s %4d %s%s",
3315 buf, rdistance->distance,
3316 rdistance->access_list ? rdistance->access_list : "",
3317 VTY_NEWLINE);
3318 }
3319}
3320
3321DEFUN (rip_distance,
3322 rip_distance_cmd,
3323 "distance <1-255>",
3324 "Administrative distance\n"
3325 "Distance value\n")
3326{
3327 rip->distance = atoi (argv[0]);
3328 return CMD_SUCCESS;
3329}
3330
3331DEFUN (no_rip_distance,
3332 no_rip_distance_cmd,
3333 "no distance <1-255>",
3334 NO_STR
3335 "Administrative distance\n"
3336 "Distance value\n")
3337{
3338 rip->distance = 0;
3339 return CMD_SUCCESS;
3340}
3341
3342DEFUN (rip_distance_source,
3343 rip_distance_source_cmd,
3344 "distance <1-255> A.B.C.D/M",
3345 "Administrative distance\n"
3346 "Distance value\n"
3347 "IP source prefix\n")
3348{
3349 rip_distance_set (vty, argv[0], argv[1], NULL);
3350 return CMD_SUCCESS;
3351}
3352
3353DEFUN (no_rip_distance_source,
3354 no_rip_distance_source_cmd,
3355 "no distance <1-255> A.B.C.D/M",
3356 NO_STR
3357 "Administrative distance\n"
3358 "Distance value\n"
3359 "IP source prefix\n")
3360{
3361 rip_distance_unset (vty, argv[0], argv[1], NULL);
3362 return CMD_SUCCESS;
3363}
3364
3365DEFUN (rip_distance_source_access_list,
3366 rip_distance_source_access_list_cmd,
3367 "distance <1-255> A.B.C.D/M WORD",
3368 "Administrative distance\n"
3369 "Distance value\n"
3370 "IP source prefix\n"
3371 "Access list name\n")
3372{
3373 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3374 return CMD_SUCCESS;
3375}
3376
3377DEFUN (no_rip_distance_source_access_list,
3378 no_rip_distance_source_access_list_cmd,
3379 "no distance <1-255> A.B.C.D/M WORD",
3380 NO_STR
3381 "Administrative distance\n"
3382 "Distance value\n"
3383 "IP source prefix\n"
3384 "Access list name\n")
3385{
3386 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3387 return CMD_SUCCESS;
3388}
3389
3390/* Print out routes update time. */
pauldc63bfd2005-10-25 23:31:05 +00003391static void
paul718e3742002-12-13 20:15:29 +00003392rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3393{
3394 struct timeval timer_now;
3395 time_t clock;
3396 struct tm *tm;
3397#define TIME_BUF 25
3398 char timebuf [TIME_BUF];
3399 struct thread *thread;
3400
3401 gettimeofday (&timer_now, NULL);
3402
3403 if ((thread = rinfo->t_timeout) != NULL)
3404 {
3405 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3406 tm = gmtime (&clock);
3407 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3408 vty_out (vty, "%5s", timebuf);
3409 }
3410 else if ((thread = rinfo->t_garbage_collect) != NULL)
3411 {
3412 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3413 tm = gmtime (&clock);
3414 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3415 vty_out (vty, "%5s", timebuf);
3416 }
3417}
3418
pauldc63bfd2005-10-25 23:31:05 +00003419static const char *
paul718e3742002-12-13 20:15:29 +00003420rip_route_type_print (int sub_type)
3421{
3422 switch (sub_type)
3423 {
3424 case RIP_ROUTE_RTE:
3425 return "n";
3426 case RIP_ROUTE_STATIC:
3427 return "s";
3428 case RIP_ROUTE_DEFAULT:
3429 return "d";
3430 case RIP_ROUTE_REDISTRIBUTE:
3431 return "r";
3432 case RIP_ROUTE_INTERFACE:
3433 return "i";
3434 default:
3435 return "?";
3436 }
3437}
3438
3439DEFUN (show_ip_rip,
3440 show_ip_rip_cmd,
3441 "show ip rip",
3442 SHOW_STR
3443 IP_STR
3444 "Show RIP routes\n")
3445{
3446 struct route_node *np;
3447 struct rip_info *rinfo;
3448
3449 if (! rip)
3450 return CMD_SUCCESS;
3451
hasso16705132003-05-25 14:49:19 +00003452 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3453 "Sub-codes:%s"
3454 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003455 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003456 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003457 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003458
3459 for (np = route_top (rip->table); np; np = route_next (np))
3460 if ((rinfo = np->info) != NULL)
3461 {
3462 int len;
3463
ajsf52d13c2005-10-01 17:38:06 +00003464 len = vty_out (vty, "%c(%s) %s/%d",
paul718e3742002-12-13 20:15:29 +00003465 /* np->lock, For debugging. */
ajsf52d13c2005-10-01 17:38:06 +00003466 zebra_route_char(rinfo->type),
paul718e3742002-12-13 20:15:29 +00003467 rip_route_type_print (rinfo->sub_type),
3468 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3469
hassoa1455d82004-03-03 19:36:24 +00003470 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003471
3472 if (len > 0)
3473 vty_out (vty, "%*s", len, " ");
3474
3475 if (rinfo->nexthop.s_addr)
3476 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3477 rinfo->metric);
3478 else
3479 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3480
3481 /* Route which exist in kernel routing table. */
3482 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3483 (rinfo->sub_type == RIP_ROUTE_RTE))
3484 {
3485 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003486 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003487 rip_vty_out_uptime (vty, rinfo);
3488 }
3489 else if (rinfo->metric == RIP_METRIC_INFINITY)
3490 {
3491 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003492 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003493 rip_vty_out_uptime (vty, rinfo);
3494 }
3495 else
hasso16705132003-05-25 14:49:19 +00003496 {
vincentfbf5d032005-09-29 11:25:50 +00003497 if (rinfo->external_metric)
3498 {
3499 len = vty_out (vty, "self (%s:%d)",
ajsf52d13c2005-10-01 17:38:06 +00003500 zebra_route_string(rinfo->type),
vincentfbf5d032005-09-29 11:25:50 +00003501 rinfo->external_metric);
3502 len = 16 - len;
3503 if (len > 0)
3504 vty_out (vty, "%*s", len, " ");
3505 }
3506 else
3507 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003508 vty_out (vty, "%3d", rinfo->tag);
3509 }
paul718e3742002-12-13 20:15:29 +00003510
3511 vty_out (vty, "%s", VTY_NEWLINE);
3512 }
3513 return CMD_SUCCESS;
3514}
3515
3516/* Return next event time. */
pauldc63bfd2005-10-25 23:31:05 +00003517static int
paul718e3742002-12-13 20:15:29 +00003518rip_next_thread_timer (struct thread *thread)
3519{
3520 struct timeval timer_now;
3521
3522 gettimeofday (&timer_now, NULL);
3523
3524 return thread->u.sands.tv_sec - timer_now.tv_sec;
3525}
3526
hasso16705132003-05-25 14:49:19 +00003527/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3528DEFUN (show_ip_rip_status,
3529 show_ip_rip_status_cmd,
3530 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003531 SHOW_STR
3532 IP_STR
hasso16705132003-05-25 14:49:19 +00003533 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003534 "IP routing protocol process parameters and statistics\n")
3535{
hasso52dc7ee2004-09-23 19:18:23 +00003536 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003537 struct interface *ifp;
3538 struct rip_interface *ri;
3539 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003540 const char *send_version;
3541 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003542
3543 if (! rip)
3544 return CMD_SUCCESS;
3545
3546 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3547 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3548 rip->update_time);
3549 vty_out (vty, " next due in %d seconds%s",
3550 rip_next_thread_timer (rip->t_update),
3551 VTY_NEWLINE);
3552 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3553 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3554 VTY_NEWLINE);
3555
3556 /* Filtering status show. */
3557 config_show_distribute (vty);
3558
3559 /* Default metric information. */
3560 vty_out (vty, " Default redistribution metric is %d%s",
3561 rip->default_metric, VTY_NEWLINE);
3562
3563 /* Redistribute information. */
3564 vty_out (vty, " Redistributing:");
3565 config_write_rip_redistribute (vty, 0);
3566 vty_out (vty, "%s", VTY_NEWLINE);
3567
paulf38a4712003-06-07 01:10:00 +00003568 vty_out (vty, " Default version control: send version %s,",
3569 lookup(ri_version_msg,rip->version_send));
3570 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3571 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3572 else
3573 vty_out (vty, " receive version %s %s",
3574 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003575
3576 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3577
paul1eb8ef22005-04-07 07:30:20 +00003578 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003579 {
paul718e3742002-12-13 20:15:29 +00003580 ri = ifp->info;
3581
3582 if (ri->enable_network || ri->enable_interface)
3583 {
3584 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003585 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003586 else
3587 send_version = lookup (ri_version_msg, ri->ri_send);
3588
3589 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003590 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003591 else
3592 receive_version = lookup (ri_version_msg, ri->ri_receive);
3593
3594 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3595 send_version,
3596 receive_version,
3597 ri->key_chain ? ri->key_chain : "",
3598 VTY_NEWLINE);
3599 }
3600 }
3601
3602 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3603 config_write_rip_network (vty, 0);
3604
paul4aaff3f2003-06-07 01:04:45 +00003605 {
3606 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003607 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003608 {
paul4aaff3f2003-06-07 01:04:45 +00003609 ri = ifp->info;
3610
3611 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3612 {
3613 if (!found_passive)
3614 {
3615 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3616 found_passive = 1;
3617 }
3618 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3619 }
3620 }
3621 }
3622
paul718e3742002-12-13 20:15:29 +00003623 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3624 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3625 rip_peer_display (vty);
3626
3627 rip_distance_show (vty);
3628
3629 return CMD_SUCCESS;
3630}
3631
3632/* RIP configuration write function. */
pauldc63bfd2005-10-25 23:31:05 +00003633static int
paul718e3742002-12-13 20:15:29 +00003634config_write_rip (struct vty *vty)
3635{
3636 int write = 0;
3637 struct route_node *rn;
3638 struct rip_distance *rdistance;
3639
3640 if (rip)
3641 {
3642 /* Router RIP statement. */
3643 vty_out (vty, "router rip%s", VTY_NEWLINE);
3644 write++;
3645
3646 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003647 if (rip->version_send != RI_RIP_VERSION_2
3648 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3649 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003650 VTY_NEWLINE);
3651
3652 /* RIP timer configuration. */
3653 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3654 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3655 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3656 vty_out (vty, " timers basic %lu %lu %lu%s",
3657 rip->update_time,
3658 rip->timeout_time,
3659 rip->garbage_time,
3660 VTY_NEWLINE);
3661
3662 /* Default information configuration. */
3663 if (rip->default_information)
3664 {
3665 if (rip->default_information_route_map)
3666 vty_out (vty, " default-information originate route-map %s%s",
3667 rip->default_information_route_map, VTY_NEWLINE);
3668 else
3669 vty_out (vty, " default-information originate%s",
3670 VTY_NEWLINE);
3671 }
3672
3673 /* Redistribute configuration. */
3674 config_write_rip_redistribute (vty, 1);
3675
3676 /* RIP offset-list configuration. */
3677 config_write_rip_offset_list (vty);
3678
3679 /* RIP enabled network and interface configuration. */
3680 config_write_rip_network (vty, 1);
3681
3682 /* RIP default metric configuration */
3683 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3684 vty_out (vty, " default-metric %d%s",
3685 rip->default_metric, VTY_NEWLINE);
3686
3687 /* Distribute configuration. */
3688 write += config_write_distribute (vty);
3689
hasso16705132003-05-25 14:49:19 +00003690 /* Interface routemap configuration */
3691 write += config_write_if_rmap (vty);
3692
paul718e3742002-12-13 20:15:29 +00003693 /* Distance configuration. */
3694 if (rip->distance)
3695 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3696
3697 /* RIP source IP prefix distance configuration. */
3698 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3699 if ((rdistance = rn->info) != NULL)
3700 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3701 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3702 rdistance->access_list ? rdistance->access_list : "",
3703 VTY_NEWLINE);
3704
3705 /* RIP static route configuration. */
3706 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3707 if (rn->info)
3708 vty_out (vty, " route %s/%d%s",
3709 inet_ntoa (rn->p.u.prefix4),
3710 rn->p.prefixlen,
3711 VTY_NEWLINE);
3712
3713 }
3714 return write;
3715}
3716
3717/* RIP node structure. */
3718struct cmd_node rip_node =
3719{
3720 RIP_NODE,
3721 "%s(config-router)# ",
3722 1
3723};
3724
3725/* Distribute-list update functions. */
pauldc63bfd2005-10-25 23:31:05 +00003726static void
paul718e3742002-12-13 20:15:29 +00003727rip_distribute_update (struct distribute *dist)
3728{
3729 struct interface *ifp;
3730 struct rip_interface *ri;
3731 struct access_list *alist;
3732 struct prefix_list *plist;
3733
3734 if (! dist->ifname)
3735 return;
3736
3737 ifp = if_lookup_by_name (dist->ifname);
3738 if (ifp == NULL)
3739 return;
3740
3741 ri = ifp->info;
3742
3743 if (dist->list[DISTRIBUTE_IN])
3744 {
3745 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3746 if (alist)
3747 ri->list[RIP_FILTER_IN] = alist;
3748 else
3749 ri->list[RIP_FILTER_IN] = NULL;
3750 }
3751 else
3752 ri->list[RIP_FILTER_IN] = NULL;
3753
3754 if (dist->list[DISTRIBUTE_OUT])
3755 {
3756 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3757 if (alist)
3758 ri->list[RIP_FILTER_OUT] = alist;
3759 else
3760 ri->list[RIP_FILTER_OUT] = NULL;
3761 }
3762 else
3763 ri->list[RIP_FILTER_OUT] = NULL;
3764
3765 if (dist->prefix[DISTRIBUTE_IN])
3766 {
3767 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3768 if (plist)
3769 ri->prefix[RIP_FILTER_IN] = plist;
3770 else
3771 ri->prefix[RIP_FILTER_IN] = NULL;
3772 }
3773 else
3774 ri->prefix[RIP_FILTER_IN] = NULL;
3775
3776 if (dist->prefix[DISTRIBUTE_OUT])
3777 {
3778 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3779 if (plist)
3780 ri->prefix[RIP_FILTER_OUT] = plist;
3781 else
3782 ri->prefix[RIP_FILTER_OUT] = NULL;
3783 }
3784 else
3785 ri->prefix[RIP_FILTER_OUT] = NULL;
3786}
3787
3788void
3789rip_distribute_update_interface (struct interface *ifp)
3790{
3791 struct distribute *dist;
3792
3793 dist = distribute_lookup (ifp->name);
3794 if (dist)
3795 rip_distribute_update (dist);
3796}
3797
3798/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003799/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00003800static void
paul02ff83c2004-06-11 11:27:03 +00003801rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003802{
3803 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003804 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003805
paul1eb8ef22005-04-07 07:30:20 +00003806 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3807 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003808}
paul11dde9c2004-05-31 14:00:00 +00003809/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00003810static void
paul11dde9c2004-05-31 14:00:00 +00003811rip_distribute_update_all_wrapper(struct access_list *notused)
3812{
paul02ff83c2004-06-11 11:27:03 +00003813 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003814}
paul718e3742002-12-13 20:15:29 +00003815
3816/* Delete all added rip route. */
3817void
3818rip_clean ()
3819{
3820 int i;
3821 struct route_node *rp;
3822 struct rip_info *rinfo;
3823
3824 if (rip)
3825 {
3826 /* Clear RIP routes */
3827 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3828 if ((rinfo = rp->info) != NULL)
3829 {
3830 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3831 rinfo->sub_type == RIP_ROUTE_RTE)
3832 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3833 &rinfo->nexthop, rinfo->metric);
3834
3835 RIP_TIMER_OFF (rinfo->t_timeout);
3836 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3837
3838 rp->info = NULL;
3839 route_unlock_node (rp);
3840
3841 rip_info_free (rinfo);
3842 }
3843
3844 /* Cancel RIP related timers. */
3845 RIP_TIMER_OFF (rip->t_update);
3846 RIP_TIMER_OFF (rip->t_triggered_update);
3847 RIP_TIMER_OFF (rip->t_triggered_interval);
3848
3849 /* Cancel read thread. */
3850 if (rip->t_read)
3851 {
3852 thread_cancel (rip->t_read);
3853 rip->t_read = NULL;
3854 }
3855
3856 /* Close RIP socket. */
3857 if (rip->sock >= 0)
3858 {
3859 close (rip->sock);
3860 rip->sock = -1;
3861 }
3862
3863 /* Static RIP route configuration. */
3864 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3865 if (rp->info)
3866 {
3867 rp->info = NULL;
3868 route_unlock_node (rp);
3869 }
3870
3871 /* RIP neighbor configuration. */
3872 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3873 if (rp->info)
3874 {
3875 rp->info = NULL;
3876 route_unlock_node (rp);
3877 }
3878
3879 /* Redistribute related clear. */
3880 if (rip->default_information_route_map)
3881 free (rip->default_information_route_map);
3882
3883 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3884 if (rip->route_map[i].name)
3885 free (rip->route_map[i].name);
3886
3887 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3888 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3889 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3890
3891 XFREE (MTYPE_RIP, rip);
3892 rip = NULL;
3893 }
3894
3895 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003896 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003897 rip_offset_clean ();
3898 rip_interface_clean ();
3899 rip_distance_reset ();
3900 rip_redistribute_clean ();
3901}
3902
3903/* Reset all values to the default settings. */
3904void
3905rip_reset ()
3906{
3907 /* Reset global counters. */
3908 rip_global_route_changes = 0;
3909 rip_global_queries = 0;
3910
3911 /* Call ripd related reset functions. */
3912 rip_debug_reset ();
3913 rip_route_map_reset ();
3914
3915 /* Call library reset functions. */
3916 vty_reset ();
3917 access_list_reset ();
3918 prefix_list_reset ();
3919
3920 distribute_list_reset ();
3921
3922 rip_interface_reset ();
3923 rip_distance_reset ();
3924
3925 rip_zclient_reset ();
3926}
3927
pauldc63bfd2005-10-25 23:31:05 +00003928static void
hasso16705132003-05-25 14:49:19 +00003929rip_if_rmap_update (struct if_rmap *if_rmap)
3930{
3931 struct interface *ifp;
3932 struct rip_interface *ri;
3933 struct route_map *rmap;
3934
3935 ifp = if_lookup_by_name (if_rmap->ifname);
3936 if (ifp == NULL)
3937 return;
3938
3939 ri = ifp->info;
3940
3941 if (if_rmap->routemap[IF_RMAP_IN])
3942 {
3943 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3944 if (rmap)
3945 ri->routemap[IF_RMAP_IN] = rmap;
3946 else
3947 ri->routemap[IF_RMAP_IN] = NULL;
3948 }
3949 else
3950 ri->routemap[RIP_FILTER_IN] = NULL;
3951
3952 if (if_rmap->routemap[IF_RMAP_OUT])
3953 {
3954 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3955 if (rmap)
3956 ri->routemap[IF_RMAP_OUT] = rmap;
3957 else
3958 ri->routemap[IF_RMAP_OUT] = NULL;
3959 }
3960 else
3961 ri->routemap[RIP_FILTER_OUT] = NULL;
3962}
3963
3964void
3965rip_if_rmap_update_interface (struct interface *ifp)
3966{
3967 struct if_rmap *if_rmap;
3968
3969 if_rmap = if_rmap_lookup (ifp->name);
3970 if (if_rmap)
3971 rip_if_rmap_update (if_rmap);
3972}
3973
pauldc63bfd2005-10-25 23:31:05 +00003974static void
hasso16705132003-05-25 14:49:19 +00003975rip_routemap_update_redistribute (void)
3976{
3977 int i;
3978
3979 if (rip)
3980 {
3981 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3982 {
3983 if (rip->route_map[i].name)
3984 rip->route_map[i].map =
3985 route_map_lookup_by_name (rip->route_map[i].name);
3986 }
3987 }
3988}
3989
paul11dde9c2004-05-31 14:00:00 +00003990/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00003991static void
hasso98b718a2004-10-11 12:57:57 +00003992rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003993{
3994 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003995 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00003996
paul1eb8ef22005-04-07 07:30:20 +00003997 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3998 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00003999
4000 rip_routemap_update_redistribute ();
4001}
4002
paul718e3742002-12-13 20:15:29 +00004003/* Allocate new rip structure and set default value. */
4004void
pauldc63bfd2005-10-25 23:31:05 +00004005rip_init (void)
paul718e3742002-12-13 20:15:29 +00004006{
4007 /* Randomize for triggered update random(). */
4008 srand (time (NULL));
4009
4010 /* Install top nodes. */
4011 install_node (&rip_node, config_write_rip);
4012
4013 /* Install rip commands. */
4014 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004015 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004016 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004017 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004018 install_element (CONFIG_NODE, &router_rip_cmd);
4019 install_element (CONFIG_NODE, &no_router_rip_cmd);
4020
4021 install_default (RIP_NODE);
4022 install_element (RIP_NODE, &rip_version_cmd);
4023 install_element (RIP_NODE, &no_rip_version_cmd);
4024 install_element (RIP_NODE, &no_rip_version_val_cmd);
4025 install_element (RIP_NODE, &rip_default_metric_cmd);
4026 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4027 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4028 install_element (RIP_NODE, &rip_timers_cmd);
4029 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00004030 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00004031 install_element (RIP_NODE, &rip_route_cmd);
4032 install_element (RIP_NODE, &no_rip_route_cmd);
4033 install_element (RIP_NODE, &rip_distance_cmd);
4034 install_element (RIP_NODE, &no_rip_distance_cmd);
4035 install_element (RIP_NODE, &rip_distance_source_cmd);
4036 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4037 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4038 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4039
4040 /* Debug related init. */
4041 rip_debug_init ();
4042
paul718e3742002-12-13 20:15:29 +00004043 /* SNMP init. */
4044#ifdef HAVE_SNMP
4045 rip_snmp_init ();
4046#endif /* HAVE_SNMP */
4047
4048 /* Access list install. */
4049 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004050 access_list_add_hook (rip_distribute_update_all_wrapper);
4051 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004052
4053 /* Prefix list initialize.*/
4054 prefix_list_init ();
4055 prefix_list_add_hook (rip_distribute_update_all);
4056 prefix_list_delete_hook (rip_distribute_update_all);
4057
4058 /* Distribute list install. */
4059 distribute_list_init (RIP_NODE);
4060 distribute_list_add_hook (rip_distribute_update);
4061 distribute_list_delete_hook (rip_distribute_update);
4062
hasso16705132003-05-25 14:49:19 +00004063 /* Route-map */
4064 rip_route_map_init ();
4065 rip_offset_init ();
4066
4067 route_map_add_hook (rip_routemap_update);
4068 route_map_delete_hook (rip_routemap_update);
4069
4070 if_rmap_init (RIP_NODE);
4071 if_rmap_hook_add (rip_if_rmap_update);
4072 if_rmap_hook_delete (rip_if_rmap_update);
4073
paul718e3742002-12-13 20:15:29 +00004074 /* Distance control. */
4075 rip_distance_table = route_table_init ();
4076}