blob: c5baf8a3b5bcd1071d2a24f38f0231140e27dd85 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "if.h"
25#include "command.h"
26#include "prefix.h"
27#include "table.h"
28#include "thread.h"
29#include "memory.h"
30#include "log.h"
31#include "stream.h"
32#include "filter.h"
33#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000034#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000035#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000036#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000037#include "plist.h"
38#include "distribute.h"
39#include "md5-gnu.h"
40#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000041#include "privs.h"
paul718e3742002-12-13 20:15:29 +000042
43#include "ripd/ripd.h"
44#include "ripd/rip_debug.h"
45
paul0b3acf42004-09-17 08:39:08 +000046/* UDP receive buffer size */
47#define RIP_UDP_RCV_BUF 41600
48
49/* privileges global */
pauledd7c242003-06-04 13:59:38 +000050extern struct zebra_privs_t ripd_privs;
51
paul718e3742002-12-13 20:15:29 +000052/* RIP Structure. */
53struct rip *rip = NULL;
54
55/* RIP neighbor address table. */
56struct route_table *rip_neighbor_table;
57
58/* RIP route changes. */
59long rip_global_route_changes = 0;
60
61/* RIP queries. */
62long rip_global_queries = 0;
63
64/* Prototypes. */
65void rip_event (enum rip_event, int);
66
paulc49ad8f2004-10-22 10:27:28 +000067void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
paul718e3742002-12-13 20:15:29 +000068
69/* RIP output routes type. */
70enum
71{
72 rip_all_route,
73 rip_changed_route
74};
75
76/* RIP command strings. */
77struct message rip_msg[] =
78{
79 {RIP_REQUEST, "REQUEST"},
80 {RIP_RESPONSE, "RESPONSE"},
81 {RIP_TRACEON, "TRACEON"},
82 {RIP_TRACEOFF, "TRACEOFF"},
83 {RIP_POLL, "POLL"},
84 {RIP_POLL_ENTRY, "POLL ENTRY"},
85 {0, NULL}
86};
87
88/* Each route type's strings and default preference. */
89struct
90{
91 int key;
hasso8a676be2004-10-08 06:36:38 +000092 const char *str;
93 const char *str_long;
paul718e3742002-12-13 20:15:29 +000094} route_info[] =
95{
96 { ZEBRA_ROUTE_SYSTEM, "X", "system"},
97 { ZEBRA_ROUTE_KERNEL, "K", "kernel"},
98 { ZEBRA_ROUTE_CONNECT, "C", "connected"},
99 { ZEBRA_ROUTE_STATIC, "S", "static"},
100 { ZEBRA_ROUTE_RIP, "R", "rip"},
101 { ZEBRA_ROUTE_RIPNG, "R", "ripng"},
102 { ZEBRA_ROUTE_OSPF, "O", "ospf"},
103 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"},
hasso8a676be2004-10-08 06:36:38 +0000104 { ZEBRA_ROUTE_ISIS, "I", "isis"},
paul718e3742002-12-13 20:15:29 +0000105 { ZEBRA_ROUTE_BGP, "B", "bgp"}
106};
107
108/* Utility function to set boradcast option to the socket. */
109int
110sockopt_broadcast (int sock)
111{
112 int ret;
113 int on = 1;
114
115 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
116 if (ret < 0)
117 {
118 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
119 return -1;
120 }
121 return 0;
122}
123
124int
125rip_route_rte (struct rip_info *rinfo)
126{
127 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
128}
129
130struct rip_info *
131rip_info_new ()
132{
133 struct rip_info *new;
134
135 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
136 memset (new, 0, sizeof (struct rip_info));
137 return new;
138}
139
140void
141rip_info_free (struct rip_info *rinfo)
142{
143 XFREE (MTYPE_RIP_INFO, rinfo);
144}
145
146/* RIP route garbage collect timer. */
147int
148rip_garbage_collect (struct thread *t)
149{
150 struct rip_info *rinfo;
151 struct route_node *rp;
152
153 rinfo = THREAD_ARG (t);
154 rinfo->t_garbage_collect = NULL;
155
156 /* Off timeout timer. */
157 RIP_TIMER_OFF (rinfo->t_timeout);
158
159 /* Get route_node pointer. */
160 rp = rinfo->rp;
161
162 /* Unlock route_node. */
163 rp->info = NULL;
164 route_unlock_node (rp);
165
166 /* Free RIP routing information. */
167 rip_info_free (rinfo);
168
169 return 0;
170}
171
172/* Timeout RIP routes. */
173int
174rip_timeout (struct thread *t)
175{
176 struct rip_info *rinfo;
177 struct route_node *rn;
178
179 rinfo = THREAD_ARG (t);
180 rinfo->t_timeout = NULL;
181
182 rn = rinfo->rp;
183
184 /* - The garbage-collection timer is set for 120 seconds. */
185 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect,
186 rip->garbage_time);
187
188 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,
189 rinfo->metric);
190 /* - The metric for the route is set to 16 (infinity). This causes
191 the route to be removed from service. */
192 rinfo->metric = RIP_METRIC_INFINITY;
193 rinfo->flags &= ~RIP_RTF_FIB;
194
195 /* - The route change flag is to indicate that this entry has been
196 changed. */
197 rinfo->flags |= RIP_RTF_CHANGED;
198
199 /* - The output process is signalled to trigger a response. */
200 rip_event (RIP_TRIGGERED_UPDATE, 0);
201
202 return 0;
203}
204
205void
206rip_timeout_update (struct rip_info *rinfo)
207{
208 if (rinfo->metric != RIP_METRIC_INFINITY)
209 {
210 RIP_TIMER_OFF (rinfo->t_timeout);
211 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
212 }
213}
214
215int
216rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
217{
218 struct distribute *dist;
219 struct access_list *alist;
220 struct prefix_list *plist;
221
222 /* Input distribute-list filtering. */
223 if (ri->list[RIP_FILTER_IN])
224 {
225 if (access_list_apply (ri->list[RIP_FILTER_IN],
226 (struct prefix *) p) == FILTER_DENY)
227 {
228 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000229 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000230 inet_ntoa (p->prefix), p->prefixlen);
231 return -1;
232 }
233 }
234 if (ri->prefix[RIP_FILTER_IN])
235 {
236 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
237 (struct prefix *) p) == PREFIX_DENY)
238 {
239 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000240 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000241 inet_ntoa (p->prefix), p->prefixlen);
242 return -1;
243 }
244 }
245
246 /* All interface filter check. */
247 dist = distribute_lookup (NULL);
248 if (dist)
249 {
250 if (dist->list[DISTRIBUTE_IN])
251 {
252 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
253
254 if (alist)
255 {
256 if (access_list_apply (alist,
257 (struct prefix *) p) == FILTER_DENY)
258 {
259 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000260 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000261 inet_ntoa (p->prefix), p->prefixlen);
262 return -1;
263 }
264 }
265 }
266 if (dist->prefix[DISTRIBUTE_IN])
267 {
268 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
269
270 if (plist)
271 {
272 if (prefix_list_apply (plist,
273 (struct prefix *) p) == PREFIX_DENY)
274 {
275 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000276 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000277 inet_ntoa (p->prefix), p->prefixlen);
278 return -1;
279 }
280 }
281 }
282 }
283 return 0;
284}
285
286int
287rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
288{
289 struct distribute *dist;
290 struct access_list *alist;
291 struct prefix_list *plist;
292
293 if (ri->list[RIP_FILTER_OUT])
294 {
295 if (access_list_apply (ri->list[RIP_FILTER_OUT],
296 (struct prefix *) p) == FILTER_DENY)
297 {
298 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000299 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000300 inet_ntoa (p->prefix), p->prefixlen);
301 return -1;
302 }
303 }
304 if (ri->prefix[RIP_FILTER_OUT])
305 {
306 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
307 (struct prefix *) p) == PREFIX_DENY)
308 {
309 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000310 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000311 inet_ntoa (p->prefix), p->prefixlen);
312 return -1;
313 }
314 }
315
316 /* All interface filter check. */
317 dist = distribute_lookup (NULL);
318 if (dist)
319 {
320 if (dist->list[DISTRIBUTE_OUT])
321 {
322 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
323
324 if (alist)
325 {
326 if (access_list_apply (alist,
327 (struct prefix *) p) == FILTER_DENY)
328 {
329 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000330 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000331 inet_ntoa (p->prefix), p->prefixlen);
332 return -1;
333 }
334 }
335 }
336 if (dist->prefix[DISTRIBUTE_OUT])
337 {
338 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
339
340 if (plist)
341 {
342 if (prefix_list_apply (plist,
343 (struct prefix *) p) == PREFIX_DENY)
344 {
345 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000346 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000347 inet_ntoa (p->prefix), p->prefixlen);
348 return -1;
349 }
350 }
351 }
352 }
353 return 0;
354}
355
356/* Check nexthop address validity. */
357static int
358rip_nexthop_check (struct in_addr *addr)
359{
hasso52dc7ee2004-09-23 19:18:23 +0000360 struct listnode *node;
361 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000362 struct interface *ifp;
363 struct connected *ifc;
364 struct prefix *p;
365
366 /* If nexthop address matches local configured address then it is
367 invalid nexthop. */
368 for (node = listhead (iflist); node; nextnode (node))
369 {
370 ifp = getdata (node);
371
372 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
373 {
374 ifc = getdata (cnode);
375 p = ifc->address;
376
377 if (p->family == AF_INET
378 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
379 return -1;
380 }
381 }
382 return 0;
383}
384
385/* RIP add route to routing table. */
386void
387rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000388 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000389{
390 int ret;
391 struct prefix_ipv4 p;
392 struct route_node *rp;
paulb94f9db2004-05-01 20:45:38 +0000393 struct rip_info *rinfo, rinfotmp;
paul718e3742002-12-13 20:15:29 +0000394 struct rip_interface *ri;
395 struct in_addr *nexthop;
396 u_char oldmetric;
397 int same = 0;
398
399 /* Make prefix structure. */
400 memset (&p, 0, sizeof (struct prefix_ipv4));
401 p.family = AF_INET;
402 p.prefix = rte->prefix;
403 p.prefixlen = ip_masklen (rte->mask);
404
405 /* Make sure mask is applied. */
406 apply_mask_ipv4 (&p);
407
408 /* Apply input filters. */
409 ri = ifp->info;
410
411 ret = rip_incoming_filter (&p, ri);
412 if (ret < 0)
413 return;
414
hasso16705132003-05-25 14:49:19 +0000415 /* Modify entry according to the interface routemap. */
416 if (ri->routemap[RIP_FILTER_IN])
417 {
418 int ret;
419 struct rip_info newinfo;
420
421 memset (&newinfo, 0, sizeof (newinfo));
422 newinfo.type = ZEBRA_ROUTE_RIP;
423 newinfo.sub_type = RIP_ROUTE_RTE;
paula87552c2004-05-03 20:00:17 +0000424 newinfo.nexthop = rte->nexthop;
425 newinfo.from = from->sin_addr;
426 newinfo.ifindex = ifp->ifindex;
hasso16705132003-05-25 14:49:19 +0000427 newinfo.metric = rte->metric;
428 newinfo.metric_out = rte->metric; /* XXX */
paula87552c2004-05-03 20:00:17 +0000429 newinfo.tag = ntohs (rte->tag); /* XXX */
hasso16705132003-05-25 14:49:19 +0000430
431 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000432 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
433 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000434
435 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000436 {
437 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000438 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000439 inet_ntoa (p.prefix), p.prefixlen);
440 return;
441 }
hasso16705132003-05-25 14:49:19 +0000442
443 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000444 rte->nexthop = newinfo.nexthop_out;
445 rte->tag = htons (newinfo.tag_out); /* XXX */
446 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000447 }
448
paul718e3742002-12-13 20:15:29 +0000449 /* Once the entry has been validated, update the metric by
450 adding the cost of the network on wich the message
451 arrived. If the result is greater than infinity, use infinity
452 (RFC2453 Sec. 3.9.2) */
453 /* Zebra ripd can handle offset-list in. */
454 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
455
456 /* If offset-list does not modify the metric use interface's
457 metric. */
paula87552c2004-05-03 20:00:17 +0000458 if (!ret)
paul718e3742002-12-13 20:15:29 +0000459 rte->metric += ifp->metric;
460
461 if (rte->metric > RIP_METRIC_INFINITY)
462 rte->metric = RIP_METRIC_INFINITY;
463
464 /* Set nexthop pointer. */
465 if (rte->nexthop.s_addr == 0)
466 nexthop = &from->sin_addr;
467 else
468 nexthop = &rte->nexthop;
469
hasso16705132003-05-25 14:49:19 +0000470 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000471 if (rip_nexthop_check (nexthop) < 0)
472 {
473 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000474 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000475 return;
476 }
477
478 /* Get index for the prefix. */
479 rp = route_node_get (rip->table, (struct prefix *) &p);
480
481 /* Check to see whether there is already RIP route on the table. */
482 rinfo = rp->info;
483
484 if (rinfo)
485 {
486 /* Redistributed route check. */
487 if (rinfo->type != ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000488 && rinfo->metric != RIP_METRIC_INFINITY)
489 return;
paul718e3742002-12-13 20:15:29 +0000490
491 /* Local static route. */
492 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000493 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
494 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
495 && rinfo->metric != RIP_METRIC_INFINITY)
496 return;
paul718e3742002-12-13 20:15:29 +0000497 }
paula87552c2004-05-03 20:00:17 +0000498
499 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000500 {
501 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000502 for the destination prefix. If there is no such route, add
503 this route to the routing table, unless the metric is
504 infinity (there is no point in adding a route which
505 unusable). */
paul718e3742002-12-13 20:15:29 +0000506 if (rte->metric != RIP_METRIC_INFINITY)
paula87552c2004-05-03 20:00:17 +0000507 {
508 rinfo = rip_info_new ();
paul718e3742002-12-13 20:15:29 +0000509
paula87552c2004-05-03 20:00:17 +0000510 /* - Setting the destination prefix and length to those in
511 the RTE. */
512 rinfo->rp = rp;
paul718e3742002-12-13 20:15:29 +0000513
paula87552c2004-05-03 20:00:17 +0000514 /* - Setting the metric to the newly calculated metric (as
515 described above). */
516 rinfo->metric = rte->metric;
517 rinfo->tag = ntohs (rte->tag);
paul718e3742002-12-13 20:15:29 +0000518
paula87552c2004-05-03 20:00:17 +0000519 /* - Set the next hop address to be the address of the router
520 from which the datagram came or the next hop address
521 specified by a next hop RTE. */
522 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
523 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
524 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000525
paula87552c2004-05-03 20:00:17 +0000526 /* - Initialize the timeout for the route. If the
527 garbage-collection timer is running for this route, stop it
528 (see section 2.3 for a discussion of the timers). */
529 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000530
paula87552c2004-05-03 20:00:17 +0000531 /* - Set the route change flag. */
532 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +0000533
paula87552c2004-05-03 20:00:17 +0000534 /* - Signal the output process to trigger an update (see section
535 2.5). */
536 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000537
paula87552c2004-05-03 20:00:17 +0000538 /* Finally, route goes into the kernel. */
539 rinfo->type = ZEBRA_ROUTE_RIP;
540 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000541
paula87552c2004-05-03 20:00:17 +0000542 /* Set distance value. */
543 rinfo->distance = rip_distance_apply (rinfo);
544
545 rp->info = rinfo;
546 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,
547 rinfo->distance);
548 rinfo->flags |= RIP_RTF_FIB;
549 }
paul718e3742002-12-13 20:15:29 +0000550 }
551 else
552 {
553 /* Route is there but we are not sure the route is RIP or not. */
554 rinfo = rp->info;
paula87552c2004-05-03 20:00:17 +0000555
paul718e3742002-12-13 20:15:29 +0000556 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000557 to the address of the router from which the datagram came.
558 If this datagram is from the same router as the existing
559 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000560 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000561 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000562
563 if (same)
paula87552c2004-05-03 20:00:17 +0000564 rip_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000565
paulb94f9db2004-05-01 20:45:38 +0000566
567 /* Fill in a minimaly temporary rip_info structure, for a future
568 rip_distance_apply() use) */
paula87552c2004-05-03 20:00:17 +0000569 memset (&rinfotmp, 0, sizeof (rinfotmp));
paulb94f9db2004-05-01 20:45:38 +0000570 IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
paula87552c2004-05-03 20:00:17 +0000571 rinfotmp.rp = rinfo->rp;
paulb94f9db2004-05-01 20:45:38 +0000572
573
paul718e3742002-12-13 20:15:29 +0000574 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000575 router as the existing route, and the new metric is different
576 than the old one; or, if the new metric is lower than the old
577 one, or if the tag has been changed; or if there is a route
578 with a lower administrave distance; or an update of the
579 distance on the actual route; do the following actions: */
580 if ((same && rinfo->metric != rte->metric)
581 || (rte->metric < rinfo->metric)
582 || ((same)
583 && (rinfo->metric == rte->metric)
584 && ntohs (rte->tag) != rinfo->tag)
585 || (rinfo->distance > rip_distance_apply (&rinfotmp))
586 || ((rinfo->distance != rip_distance_apply (rinfo)) && same))
587 {
588 /* - Adopt the route from the datagram. That is, put the
589 new metric in, and adjust the next hop address (if
590 necessary). */
591 oldmetric = rinfo->metric;
592 rinfo->metric = rte->metric;
593 rinfo->tag = ntohs (rte->tag);
594 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);
595 rinfo->ifindex = ifp->ifindex;
596 rinfo->distance = rip_distance_apply (rinfo);
paul718e3742002-12-13 20:15:29 +0000597
paula87552c2004-05-03 20:00:17 +0000598 /* Should a new route to this network be established
599 while the garbage-collection timer is running, the
600 new route will replace the one that is about to be
601 deleted. In this case the garbage-collection timer
602 must be cleared. */
paul718e3742002-12-13 20:15:29 +0000603
paula87552c2004-05-03 20:00:17 +0000604 if (oldmetric == RIP_METRIC_INFINITY &&
605 rinfo->metric < RIP_METRIC_INFINITY)
606 {
607 rinfo->type = ZEBRA_ROUTE_RIP;
608 rinfo->sub_type = RIP_ROUTE_RTE;
paul718e3742002-12-13 20:15:29 +0000609
paula87552c2004-05-03 20:00:17 +0000610 RIP_TIMER_OFF (rinfo->t_garbage_collect);
paul718e3742002-12-13 20:15:29 +0000611
paula87552c2004-05-03 20:00:17 +0000612 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
613 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000614
paula87552c2004-05-03 20:00:17 +0000615 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
616 rinfo->distance);
617 rinfo->flags |= RIP_RTF_FIB;
618 }
paul718e3742002-12-13 20:15:29 +0000619
paula87552c2004-05-03 20:00:17 +0000620 /* Update nexthop and/or metric value. */
621 if (oldmetric != RIP_METRIC_INFINITY)
622 {
623 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
624 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,
625 rinfo->distance);
626 rinfo->flags |= RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000627
paula87552c2004-05-03 20:00:17 +0000628 if (!IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
629 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);
630 }
paul718e3742002-12-13 20:15:29 +0000631
paula87552c2004-05-03 20:00:17 +0000632 /* - Set the route change flag and signal the output process
633 to trigger an update. */
634 rinfo->flags |= RIP_RTF_CHANGED;
635 rip_event (RIP_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +0000636
paula87552c2004-05-03 20:00:17 +0000637 /* - If the new metric is infinity, start the deletion
638 process (described above); */
639 if (rinfo->metric == RIP_METRIC_INFINITY)
640 {
641 /* If the new metric is infinity, the deletion process
642 begins for the route, which is no longer used for
643 routing packets. Note that the deletion process is
644 started only when the metric is first set to
645 infinity. If the metric was already infinity, then a
646 new deletion process is not started. */
647 if (oldmetric != RIP_METRIC_INFINITY)
648 {
649 /* - The garbage-collection timer is set for 120 seconds. */
650 RIP_TIMER_ON (rinfo->t_garbage_collect,
651 rip_garbage_collect, rip->garbage_time);
652 RIP_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +0000653
paula87552c2004-05-03 20:00:17 +0000654 /* - The metric for the route is set to 16
655 (infinity). This causes the route to be removed
656 from service. */
657 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);
658 rinfo->flags &= ~RIP_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000659
paula87552c2004-05-03 20:00:17 +0000660 /* - The route change flag is to indicate that this
661 entry has been changed. */
662 /* - The output process is signalled to trigger a
paul718e3742002-12-13 20:15:29 +0000663 response. */
paula87552c2004-05-03 20:00:17 +0000664 ; /* Above processes are already done previously. */
665 }
666 }
667 else
668 {
669 /* otherwise, re-initialize the timeout. */
670 rip_timeout_update (rinfo);
671 }
672 }
paul718e3742002-12-13 20:15:29 +0000673 /* Unlock tempolary lock of the route. */
674 route_unlock_node (rp);
675 }
676}
677
678/* Dump RIP packet */
679void
hasso8a676be2004-10-08 06:36:38 +0000680rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000681{
682 caddr_t lim;
683 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000684 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000685 char pbuf[BUFSIZ], nbuf[BUFSIZ];
686 u_char netmask = 0;
687 u_char *p;
688
689 /* Set command string. */
690 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
691 command_str = lookup (rip_msg, packet->command);
692 else
693 command_str = "unknown";
694
695 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000696 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000697 sndrcv, command_str, packet->version, size);
698
699 /* Dump each routing table entry. */
700 rte = packet->rte;
701
702 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
703 {
704 if (packet->version == RIPv2)
705 {
706 netmask = ip_masklen (rte->mask);
707
paulca5e5162004-06-06 22:06:33 +0000708 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000709 {
paulca5e5162004-06-06 22:06:33 +0000710 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000711 {
712 p = (u_char *)&rte->prefix;
713
ajs5d6c3772004-12-08 19:24:06 +0000714 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000715 ntohs (rte->family), ntohs (rte->tag), p);
716 }
paulca5e5162004-06-06 22:06:33 +0000717 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000718 {
719 struct rip_md5_info *md5;
720
721 md5 = (struct rip_md5_info *) &packet->rte;
722
ajs5d6c3772004-12-08 19:24:06 +0000723 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000724 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000725 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000726 " Auth Data len %d",
727 ntohs (md5->packet_len), md5->keyid,
728 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000729 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000730 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000731 }
paulca5e5162004-06-06 22:06:33 +0000732 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000733 {
734 p = (u_char *)&rte->prefix;
735
ajs5d6c3772004-12-08 19:24:06 +0000736 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000737 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000738 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000739 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000740 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
741 p[7], p[9], p[10], p[11], p[12], p[13],
742 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000743 }
744 else
745 {
ajs5d6c3772004-12-08 19:24:06 +0000746 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000747 ntohs (rte->family), ntohs (rte->tag));
748 }
749 }
750 else
ajs5d6c3772004-12-08 19:24:06 +0000751 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000752 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
753 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
754 BUFSIZ), ntohs (rte->family),
755 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000756 }
757 else
758 {
ajs5d6c3772004-12-08 19:24:06 +0000759 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000760 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
761 ntohs (rte->family), ntohs (rte->tag),
762 (u_long)ntohl (rte->metric));
763 }
764 }
765}
766
767/* Check if the destination address is valid (unicast; not net 0
768 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
769 check net 0 because we accept default route. */
770int
771rip_destination_check (struct in_addr addr)
772{
773 u_int32_t destination;
774
775 /* Convert to host byte order. */
776 destination = ntohl (addr.s_addr);
777
778 if (IPV4_NET127 (destination))
779 return 0;
780
781 /* Net 0 may match to the default route. */
782 if (IPV4_NET0 (destination) && destination != 0)
783 return 0;
784
785 /* Unicast address must belong to class A, B, C. */
786 if (IN_CLASSA (destination))
787 return 1;
788 if (IN_CLASSB (destination))
789 return 1;
790 if (IN_CLASSC (destination))
791 return 1;
792
793 return 0;
794}
795
796/* RIP version 2 authentication. */
797int
798rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
799 struct interface *ifp)
800{
801 struct rip_interface *ri;
802 char *auth_str;
803
804 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000805 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000806 inet_ntoa (from->sin_addr));
807
808 ri = ifp->info;
809
810 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000811 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000812 return 0;
813
814 /* Simple password authentication. */
815 if (ri->auth_str)
816 {
817 auth_str = (char *) &rte->prefix;
818
819 if (strncmp (auth_str, ri->auth_str, 16) == 0)
820 return 1;
821 }
822 if (ri->key_chain)
823 {
824 struct keychain *keychain;
825 struct key *key;
826
827 keychain = keychain_lookup (ri->key_chain);
828 if (keychain == NULL)
829 return 0;
830
831 key = key_match_for_accept (keychain, (char *) &rte->prefix);
832 if (key)
833 return 1;
834 }
835 return 0;
836}
837
838/* RIP version 2 authentication with MD5. */
839int
840rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000841 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000842{
843 struct rip_interface *ri;
844 struct rip_md5_info *md5;
845 struct rip_md5_data *md5data;
846 struct keychain *keychain;
847 struct key *key;
848 struct md5_ctx ctx;
849 u_char pdigest[RIP_AUTH_MD5_SIZE];
850 u_char digest[RIP_AUTH_MD5_SIZE];
851 u_int16_t packet_len;
852 char *auth_str = NULL;
853
854 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000855 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000856 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000857
858 ri = ifp->info;
859 md5 = (struct rip_md5_info *) &packet->rte;
860
861 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000862 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000863 return 0;
864
paulca5e5162004-06-06 22:06:33 +0000865 /* If the authentication length is less than 16, then it must be wrong for
866 * any interpretation of rfc2082. Some implementations also interpret
867 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paulc2bfbcc2004-06-04 01:42:38 +0000868 */
paulca5e5162004-06-06 22:06:33 +0000869 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
870 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000871 {
872 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000873 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000874 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000875 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000876 }
paul718e3742002-12-13 20:15:29 +0000877
paulca5e5162004-06-06 22:06:33 +0000878 /* grab and verify check packet length */
879 packet_len = ntohs (md5->packet_len);
880
881 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
882 {
883 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000884 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000885 "greater than received length %d!",
886 md5->packet_len, length);
887 return 0;
888 }
889
890 /* retrieve authentication data */
891 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
892
paul718e3742002-12-13 20:15:29 +0000893 if (ri->key_chain)
894 {
895 keychain = keychain_lookup (ri->key_chain);
896 if (keychain == NULL)
897 return 0;
898
899 key = key_lookup_for_accept (keychain, md5->keyid);
900 if (key == NULL)
901 return 0;
902
903 auth_str = key->string;
904 }
905
906 if (ri->auth_str)
907 auth_str = ri->auth_str;
908
909 if (! auth_str)
910 return 0;
911
912 /* MD5 digest authentication. */
paul718e3742002-12-13 20:15:29 +0000913
914 /* Save digest to pdigest. */
915 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
916
917 /* Overwrite digest by my secret. */
918 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +0000919 strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000920
921 md5_init_ctx (&ctx);
paulca5e5162004-06-06 22:06:33 +0000922 md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,
paulc2bfbcc2004-06-04 01:42:38 +0000923 &ctx);
paul718e3742002-12-13 20:15:29 +0000924 md5_finish_ctx (&ctx, digest);
925
926 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
927 return packet_len;
928 else
929 return 0;
930}
931
932void
933rip_auth_md5_set (struct stream *s, struct interface *ifp)
934{
935 struct rip_interface *ri;
936 struct keychain *keychain = NULL;
937 struct key *key = NULL;
938 unsigned long len;
939 struct md5_ctx ctx;
940 unsigned char secret[RIP_AUTH_MD5_SIZE];
941 unsigned char digest[RIP_AUTH_MD5_SIZE];
942 char *auth_str = NULL;
943
944 ri = ifp->info;
945
946 /* Make it sure this interface is configured as MD5
947 authentication. */
948 if (ri->auth_type != RIP_AUTH_MD5)
949 return;
950
951 /* Lookup key chain. */
952 if (ri->key_chain)
953 {
954 keychain = keychain_lookup (ri->key_chain);
955 if (keychain == NULL)
956 return;
957
958 /* Lookup key. */
959 key = key_lookup_for_send (keychain);
960 if (key == NULL)
961 return;
962
963 auth_str = key->string;
964 }
965
966 if (ri->auth_str)
967 auth_str = ri->auth_str;
968
969 if (! auth_str)
970 return;
971
972 /* Get packet length. */
973 len = s->putp;
974
975 /* Check packet length. */
976 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
977 {
978 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
979 return;
980 }
981
982 /* Move RTE. */
983 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,
984 s->data + RIP_HEADER_SIZE,
985 len - RIP_HEADER_SIZE);
986
987 /* Set pointer to authentication header. */
988 stream_set_putp (s, RIP_HEADER_SIZE);
989 len += RIP_RTE_SIZE;
990
991 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +0000992 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +0000993 stream_putw (s, RIP_AUTH_MD5);
994
995 /* RIP-2 Packet length. Actual value is filled in
996 rip_auth_md5_set(). */
997 stream_putw (s, len);
998
999 /* Key ID. */
1000 if (key)
1001 stream_putc (s, key->index % 256);
1002 else
1003 stream_putc (s, 1);
1004
paulca5e5162004-06-06 22:06:33 +00001005 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1006 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1007 * to be configurable.
1008 */
1009 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001010
1011 /* Sequence Number (non-decreasing). */
1012 /* RFC2080: The value used in the sequence number is
1013 arbitrary, but two suggestions are the time of the
1014 message's creation or a simple message counter. */
1015 stream_putl (s, time (NULL));
1016
1017 /* Reserved field must be zero. */
1018 stream_putl (s, 0);
1019 stream_putl (s, 0);
1020
1021 /* Set pointer to authentication data. */
1022 stream_set_putp (s, len);
1023
1024 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001025 stream_putw (s, RIP_FAMILY_AUTH);
1026 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001027
1028 /* Generate a digest for the RIP packet. */
1029 memset (secret, 0, RIP_AUTH_MD5_SIZE);
paul11dde9c2004-05-31 14:00:00 +00001030 strncpy ((char *)secret, auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +00001031 md5_init_ctx (&ctx);
1032 md5_process_bytes (s->data, s->endp, &ctx);
1033 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);
1034 md5_finish_ctx (&ctx, digest);
1035
1036 /* Copy the digest to the packet. */
1037 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1038}
1039
1040/* RIP routing information. */
1041void
1042rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001043 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001044{
1045 caddr_t lim;
1046 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001047 struct prefix_ipv4 ifaddr;
1048 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001049 int subnetted;
paul718e3742002-12-13 20:15:29 +00001050
paul727d1042002-12-13 20:50:29 +00001051 /* We don't know yet. */
1052 subnetted = -1;
1053
paul718e3742002-12-13 20:15:29 +00001054 /* The Response must be ignored if it is not from the RIP
1055 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001056 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001057 {
1058 zlog_info ("response doesn't come from RIP port: %d",
1059 from->sin_port);
1060 rip_peer_bad_packet (from);
1061 return;
1062 }
1063
1064 /* The datagram's IPv4 source address should be checked to see
1065 whether the datagram is from a valid neighbor; the source of the
1066 datagram must be on a directly connected network */
paul31a476c2003-09-29 19:54:53 +00001067 if (! if_valid_neighbor (from->sin_addr))
paul718e3742002-12-13 20:15:29 +00001068 {
1069 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1070 inet_ntoa (from->sin_addr));
1071 rip_peer_bad_packet (from);
1072 return;
1073 }
1074
1075 /* It is also worth checking to see whether the response is from one
1076 of the router's own addresses. */
1077
1078 ; /* Alredy done in rip_read () */
1079
1080 /* Update RIP peer. */
1081 rip_peer_update (from, packet->version);
1082
1083 /* Set RTE pointer. */
1084 rte = packet->rte;
1085
1086 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1087 {
1088 /* RIPv2 authentication check. */
1089 /* If the Address Family Identifier of the first (and only the
1090 first) entry in the message is 0xFFFF, then the remainder of
1091 the entry contains the authentication. */
1092 /* If the packet gets here it means authentication enabled */
1093 /* Check is done in rip_read(). So, just skipping it */
1094 if (packet->version == RIPv2 &&
1095 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001096 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001097 continue;
1098
paulca5e5162004-06-06 22:06:33 +00001099 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001100 {
1101 /* Address family check. RIP only supports AF_INET. */
1102 zlog_info ("Unsupported family %d from %s.",
1103 ntohs (rte->family), inet_ntoa (from->sin_addr));
1104 continue;
1105 }
1106
1107 /* - is the destination address valid (e.g., unicast; not net 0
1108 or 127) */
1109 if (! rip_destination_check (rte->prefix))
1110 {
1111 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1112 rip_peer_bad_route (from);
1113 continue;
1114 }
1115
1116 /* Convert metric value to host byte order. */
1117 rte->metric = ntohl (rte->metric);
1118
1119 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1120 if (! (rte->metric >= 1 && rte->metric <= 16))
1121 {
1122 zlog_info ("Route's metric is not in the 1-16 range.");
1123 rip_peer_bad_route (from);
1124 continue;
1125 }
1126
1127 /* RIPv1 does not have nexthop value. */
1128 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1129 {
1130 zlog_info ("RIPv1 packet with nexthop value %s",
1131 inet_ntoa (rte->nexthop));
1132 rip_peer_bad_route (from);
1133 continue;
1134 }
1135
1136 /* That is, if the provided information is ignored, a possibly
1137 sub-optimal, but absolutely valid, route may be taken. If
1138 the received Next Hop is not directly reachable, it should be
1139 treated as 0.0.0.0. */
1140 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1141 {
1142 u_int32_t addrval;
1143
1144 /* Multicast address check. */
1145 addrval = ntohl (rte->nexthop.s_addr);
1146 if (IN_CLASSD (addrval))
1147 {
1148 zlog_info ("Nexthop %s is multicast address, skip this rte",
1149 inet_ntoa (rte->nexthop));
1150 continue;
1151 }
1152
1153 if (! if_lookup_address (rte->nexthop))
1154 {
1155 struct route_node *rn;
1156 struct rip_info *rinfo;
1157
1158 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1159
1160 if (rn)
1161 {
1162 rinfo = rn->info;
1163
1164 if (rinfo->type == ZEBRA_ROUTE_RIP
1165 && rinfo->sub_type == RIP_ROUTE_RTE)
1166 {
1167 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001168 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 +00001169 rte->nexthop = rinfo->from;
1170 }
1171 else
1172 {
1173 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001174 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 +00001175 rte->nexthop.s_addr = 0;
1176 }
1177
1178 route_unlock_node (rn);
1179 }
1180 else
1181 {
1182 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001183 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 +00001184 rte->nexthop.s_addr = 0;
1185 }
1186
1187 }
1188 }
1189
1190 /* For RIPv1, there won't be a valid netmask.
1191
1192 This is a best guess at the masks. If everyone was using old
1193 Ciscos before the 'ip subnet zero' option, it would be almost
1194 right too :-)
1195
1196 Cisco summarize ripv1 advertisments to the classful boundary
1197 (/16 for class B's) except when the RIP packet does to inside
1198 the classful network in question. */
1199
1200 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1201 || (packet->version == RIPv2
1202 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1203 {
1204 u_int32_t destination;
1205
paul727d1042002-12-13 20:50:29 +00001206 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001207 {
1208 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1209 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1210 apply_classful_mask_ipv4 (&ifaddrclass);
1211 subnetted = 0;
1212 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1213 subnetted = 1;
1214 }
paul727d1042002-12-13 20:50:29 +00001215
paul718e3742002-12-13 20:15:29 +00001216 destination = ntohl (rte->prefix.s_addr);
1217
paul727d1042002-12-13 20:50:29 +00001218 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001219 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001220 else if (IN_CLASSB (destination))
1221 masklen2ip (16, &rte->mask);
1222 else if (IN_CLASSC (destination))
1223 masklen2ip (24, &rte->mask);
1224
1225 if (subnetted == 1)
1226 masklen2ip (ifaddrclass.prefixlen,
1227 (struct in_addr *) &destination);
1228 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1229 ifaddrclass.prefix.s_addr))
1230 {
1231 masklen2ip (ifaddr.prefixlen, &rte->mask);
1232 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1233 masklen2ip (32, &rte->mask);
1234 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001235 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001236 }
1237 else
1238 {
1239 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1240 continue;
1241 }
1242
1243 if (IS_RIP_DEBUG_EVENT)
1244 {
ajs5d6c3772004-12-08 19:24:06 +00001245 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1246 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001247 }
1248 }
1249
1250 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1251 ignore the entry. */
1252 if ((packet->version == RIPv2)
1253 && (rte->mask.s_addr != 0)
1254 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1255 {
1256 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1257 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1258 rip_peer_bad_route (from);
1259 continue;
1260 }
1261
1262 /* Default route's netmask is ignored. */
1263 if (packet->version == RIPv2
1264 && (rte->prefix.s_addr == 0)
1265 && (rte->mask.s_addr != 0))
1266 {
1267 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001268 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001269 rte->mask.s_addr = 0;
1270 }
1271
1272 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001273 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001274 }
1275}
1276
paulc49ad8f2004-10-22 10:27:28 +00001277/* RIP packet send to destination address, on interface denoted by
1278 * by connected argument. NULL to argument denotes destination should be
1279 * should be RIP multicast group
1280 */
paul718e3742002-12-13 20:15:29 +00001281int
paulc49ad8f2004-10-22 10:27:28 +00001282rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1283 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001284{
paul931cd542004-01-23 15:31:42 +00001285 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001286 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001287
1288 assert (ifc != NULL);
1289
paul931cd542004-01-23 15:31:42 +00001290 if (IS_RIP_DEBUG_PACKET)
1291 {
1292 char dst[20];
1293 if (to)
1294 {
1295 strcpy(dst, inet_ntoa(to->sin_addr));
1296 }
1297 else
1298 {
1299 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1300 strcpy(dst, inet_ntoa(sin.sin_addr));
1301 }
ajs5d6c3772004-12-08 19:24:06 +00001302 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001303 inet_ntoa(ifc->address->u.prefix4),
1304 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001305 }
paulc49ad8f2004-10-22 10:27:28 +00001306 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001307 {
1308 /*
1309 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1310 * with multiple addresses on the same subnet: the first address
1311 * on the subnet is configured "primary", and all subsequent addresses
1312 * on that subnet are treated as "secondary" addresses.
1313 * In order to avoid routing-table bloat on other rip listeners,
1314 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1315 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1316 * flag is set, we would end up sending a packet for a "secondary"
1317 * source address on non-linux systems.
1318 */
1319 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001320 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001321 return 0;
1322 }
1323
paul718e3742002-12-13 20:15:29 +00001324 /* Make destination address. */
1325 memset (&sin, 0, sizeof (struct sockaddr_in));
1326 sin.sin_family = AF_INET;
1327#ifdef HAVE_SIN_LEN
1328 sin.sin_len = sizeof (struct sockaddr_in);
1329#endif /* HAVE_SIN_LEN */
1330
1331 /* When destination is specified, use it's port and address. */
1332 if (to)
1333 {
paul718e3742002-12-13 20:15:29 +00001334 sin.sin_port = to->sin_port;
1335 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001336 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001337 }
1338 else
1339 {
paul718e3742002-12-13 20:15:29 +00001340
1341 sin.sin_port = htons (RIP_PORT_DEFAULT);
1342 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1343
paul931cd542004-01-23 15:31:42 +00001344 /*
1345 * we have to open a new socket for each packet because this
1346 * is the most portable way to bind to a different source
1347 * ipv4 address for each packet.
1348 */
1349 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
1350 if (send_sock < 0)
1351 {
1352 zlog_warn("rip_send_packet could not create socket %s",
ajs6099b3b2004-11-20 02:06:59 +00001353 safe_strerror(errno));
paul931cd542004-01-23 15:31:42 +00001354 return -1;
1355 }
1356 sockopt_broadcast (send_sock);
1357 sockopt_reuseaddr (send_sock);
1358 sockopt_reuseport (send_sock);
1359#ifdef RIP_RECVMSG
1360 setsockopt_pktinfo (send_sock);
1361#endif /* RIP_RECVMSG */
paulc49ad8f2004-10-22 10:27:28 +00001362 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001363 }
1364
paul931cd542004-01-23 15:31:42 +00001365 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001366 sizeof (struct sockaddr_in));
1367
1368 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001369 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001370 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001371
1372 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001373 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001374
paul931cd542004-01-23 15:31:42 +00001375 if (!to)
1376 close(send_sock);
1377
paul718e3742002-12-13 20:15:29 +00001378 return ret;
1379}
1380
1381/* Add redistributed route to RIP table. */
1382void
1383rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1384 unsigned int ifindex, struct in_addr *nexthop)
1385{
1386 int ret;
1387 struct route_node *rp;
1388 struct rip_info *rinfo;
1389
1390 /* Redistribute route */
1391 ret = rip_destination_check (p->prefix);
1392 if (! ret)
1393 return;
1394
1395 rp = route_node_get (rip->table, (struct prefix *) p);
1396
1397 rinfo = rp->info;
1398
1399 if (rinfo)
1400 {
1401 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1402 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1403 && rinfo->metric != RIP_METRIC_INFINITY)
1404 {
1405 route_unlock_node (rp);
1406 return;
1407 }
1408
1409 /* Manually configured RIP route check. */
1410 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001411 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1412 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001413 {
hasso16705132003-05-25 14:49:19 +00001414 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1415 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001416 {
1417 route_unlock_node (rp);
1418 return;
1419 }
1420 }
1421
1422 RIP_TIMER_OFF (rinfo->t_timeout);
1423 RIP_TIMER_OFF (rinfo->t_garbage_collect);
1424
1425 if (rip_route_rte (rinfo))
1426 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,
1427 rinfo->metric);
1428 rp->info = NULL;
1429 rip_info_free (rinfo);
1430
1431 route_unlock_node (rp);
1432 }
1433
1434 rinfo = rip_info_new ();
1435
1436 rinfo->type = type;
1437 rinfo->sub_type = sub_type;
1438 rinfo->ifindex = ifindex;
1439 rinfo->metric = 1;
1440 rinfo->rp = rp;
1441
1442 if (nexthop)
1443 rinfo->nexthop = *nexthop;
1444
1445 rinfo->flags |= RIP_RTF_FIB;
1446 rp->info = rinfo;
1447
1448 rinfo->flags |= RIP_RTF_CHANGED;
1449
hasso16705132003-05-25 14:49:19 +00001450 if (IS_RIP_DEBUG_EVENT) {
1451 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001452 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001453 inet_ntoa(p->prefix), p->prefixlen,
1454 ifindex2ifname(ifindex));
1455 else
ajs5d6c3772004-12-08 19:24:06 +00001456 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001457 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1458 ifindex2ifname(ifindex));
1459 }
1460
1461
paul718e3742002-12-13 20:15:29 +00001462 rip_event (RIP_TRIGGERED_UPDATE, 0);
1463}
1464
1465/* Delete redistributed route from RIP table. */
1466void
1467rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1468 unsigned int ifindex)
1469{
1470 int ret;
1471 struct route_node *rp;
1472 struct rip_info *rinfo;
1473
1474 ret = rip_destination_check (p->prefix);
1475 if (! ret)
1476 return;
1477
1478 rp = route_node_lookup (rip->table, (struct prefix *) p);
1479 if (rp)
1480 {
1481 rinfo = rp->info;
1482
1483 if (rinfo != NULL
1484 && rinfo->type == type
1485 && rinfo->sub_type == sub_type
1486 && rinfo->ifindex == ifindex)
1487 {
1488 /* Perform poisoned reverse. */
1489 rinfo->metric = RIP_METRIC_INFINITY;
1490 RIP_TIMER_ON (rinfo->t_garbage_collect,
1491 rip_garbage_collect, rip->garbage_time);
1492 RIP_TIMER_OFF (rinfo->t_timeout);
1493 rinfo->flags |= RIP_RTF_CHANGED;
1494
hasso16705132003-05-25 14:49:19 +00001495 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001496 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso16705132003-05-25 14:49:19 +00001497 inet_ntoa(p->prefix), p->prefixlen,
1498 ifindex2ifname(ifindex));
1499
paul718e3742002-12-13 20:15:29 +00001500 rip_event (RIP_TRIGGERED_UPDATE, 0);
1501 }
1502 }
1503}
1504
1505/* Response to request called from rip_read ().*/
1506void
1507rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001508 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001509{
1510 caddr_t lim;
1511 struct rte *rte;
1512 struct prefix_ipv4 p;
1513 struct route_node *rp;
1514 struct rip_info *rinfo;
1515 struct rip_interface *ri;
1516
hasso16705132003-05-25 14:49:19 +00001517 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001518 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001519 return;
1520
hasso429a0f82004-02-22 23:42:22 +00001521 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001522 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001523 if (! ri->running)
1524 return;
paul718e3742002-12-13 20:15:29 +00001525
1526 /* When passive interface is specified, suppress responses */
1527 if (ri->passive)
1528 return;
paulc49ad8f2004-10-22 10:27:28 +00001529
paul718e3742002-12-13 20:15:29 +00001530 /* RIP peer update. */
1531 rip_peer_update (from, packet->version);
1532
1533 lim = ((caddr_t) packet) + size;
1534 rte = packet->rte;
1535
1536 /* The Request is processed entry by entry. If there are no
1537 entries, no response is given. */
1538 if (lim == (caddr_t) rte)
1539 return;
1540
1541 /* There is one special case. If there is exactly one entry in the
1542 request, and it has an address family identifier of zero and a
1543 metric of infinity (i.e., 16), then this is a request to send the
1544 entire routing table. */
1545 if (lim == ((caddr_t) (rte + 1)) &&
1546 ntohs (rte->family) == 0 &&
1547 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1548 {
paulcc1131a2003-10-15 23:20:17 +00001549 struct prefix_ipv4 saddr;
1550
1551 /* saddr will be used for determining which routes to split-horizon.
1552 Since the source address we'll pick will be on the same subnet as the
1553 destination, for the purpose of split-horizoning, we'll
1554 pretend that "from" is our source address. */
1555 saddr.family = AF_INET;
1556 saddr.prefixlen = IPV4_MAX_BITLEN;
1557 saddr.prefix = from->sin_addr;
1558
paul718e3742002-12-13 20:15:29 +00001559 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001560 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001561 }
1562 else
1563 {
1564 /* Examine the list of RTEs in the Request one by one. For each
1565 entry, look up the destination in the router's routing
1566 database and, if there is a route, put that route's metric in
1567 the metric field of the RTE. If there is no explicit route
1568 to the specified destination, put infinity in the metric
1569 field. Once all the entries have been filled in, change the
1570 command from Request to Response and send the datagram back
1571 to the requestor. */
1572 p.family = AF_INET;
1573
1574 for (; ((caddr_t) rte) < lim; rte++)
1575 {
1576 p.prefix = rte->prefix;
1577 p.prefixlen = ip_masklen (rte->mask);
1578 apply_mask_ipv4 (&p);
1579
1580 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1581 if (rp)
1582 {
1583 rinfo = rp->info;
1584 rte->metric = htonl (rinfo->metric);
1585 route_unlock_node (rp);
1586 }
1587 else
1588 rte->metric = htonl (RIP_METRIC_INFINITY);
1589 }
1590 packet->command = RIP_RESPONSE;
1591
paulc49ad8f2004-10-22 10:27:28 +00001592 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001593 }
1594 rip_global_queries++;
1595}
1596
1597#if RIP_RECVMSG
1598/* Set IPv6 packet info to the socket. */
1599static int
1600setsockopt_pktinfo (int sock)
1601{
1602 int ret;
1603 int val = 1;
1604
1605 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1606 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001607 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001608 return ret;
1609}
1610
1611/* Read RIP packet by recvmsg function. */
1612int
1613rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1614 int *ifindex)
1615{
1616 int ret;
1617 struct msghdr msg;
1618 struct iovec iov;
1619 struct cmsghdr *ptr;
1620 char adata[1024];
1621
1622 msg.msg_name = (void *) from;
1623 msg.msg_namelen = sizeof (struct sockaddr_in);
1624 msg.msg_iov = &iov;
1625 msg.msg_iovlen = 1;
1626 msg.msg_control = (void *) adata;
1627 msg.msg_controllen = sizeof adata;
1628 iov.iov_base = buf;
1629 iov.iov_len = size;
1630
1631 ret = recvmsg (sock, &msg, 0);
1632 if (ret < 0)
1633 return ret;
1634
ajsb99760a2005-01-04 16:24:43 +00001635 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001636 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1637 {
1638 struct in_pktinfo *pktinfo;
1639 int i;
1640
1641 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1642 i = pktinfo->ipi_ifindex;
1643 }
1644 return ret;
1645}
1646
1647/* RIP packet read function. */
1648int
1649rip_read_new (struct thread *t)
1650{
1651 int ret;
1652 int sock;
1653 char buf[RIP_PACKET_MAXSIZ];
1654 struct sockaddr_in from;
1655 unsigned int ifindex;
1656
1657 /* Fetch socket then register myself. */
1658 sock = THREAD_FD (t);
1659 rip_event (RIP_READ, sock);
1660
1661 /* Read RIP packet. */
1662 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1663 if (ret < 0)
1664 {
ajs6099b3b2004-11-20 02:06:59 +00001665 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001666 return ret;
1667 }
1668
1669 return ret;
1670}
1671#endif /* RIP_RECVMSG */
1672
1673/* First entry point of RIP packet. */
1674int
1675rip_read (struct thread *t)
1676{
1677 int sock;
1678 int ret;
1679 int rtenum;
1680 union rip_buf rip_buf;
1681 struct rip_packet *packet;
1682 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001683 int len;
1684 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001685 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001686 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001687 struct rip_interface *ri;
1688
1689 /* Fetch socket then register myself. */
1690 sock = THREAD_FD (t);
1691 rip->t_read = NULL;
1692
1693 /* Add myself to tne next event */
1694 rip_event (RIP_READ, sock);
1695
1696 /* RIPd manages only IPv4. */
1697 memset (&from, 0, sizeof (struct sockaddr_in));
1698 fromlen = sizeof (struct sockaddr_in);
1699
1700 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1701 (struct sockaddr *) &from, &fromlen);
1702 if (len < 0)
1703 {
ajs6099b3b2004-11-20 02:06:59 +00001704 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001705 return len;
1706 }
1707
1708 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001709 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001710 {
1711 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001712 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001713 return -1;
1714 }
1715
1716 /* Which interface is this packet comes from. */
1717 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001718
paul718e3742002-12-13 20:15:29 +00001719 /* RIP packet received */
1720 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001721 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001722 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1723 ifp ? ifp->name : "unknown");
1724
1725 /* If this packet come from unknown interface, ignore it. */
1726 if (ifp == NULL)
1727 {
ajs766a0ca2004-12-15 14:55:51 +00001728 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1729 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001730 return -1;
1731 }
1732
1733 ifc = connected_lookup_address (ifp, from.sin_addr);
1734
1735 if (ifc == NULL)
1736 {
ajs766a0ca2004-12-15 14:55:51 +00001737 zlog_info ("rip_read: cannot find connected address for packet from %s "
1738 "port %d on interface %s",
1739 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001740 return -1;
1741 }
1742
1743 /* Packet length check. */
1744 if (len < RIP_PACKET_MINSIZ)
1745 {
1746 zlog_warn ("packet size %d is smaller than minimum size %d",
1747 len, RIP_PACKET_MINSIZ);
1748 rip_peer_bad_packet (&from);
1749 return len;
1750 }
1751 if (len > RIP_PACKET_MAXSIZ)
1752 {
1753 zlog_warn ("packet size %d is larger than max size %d",
1754 len, RIP_PACKET_MAXSIZ);
1755 rip_peer_bad_packet (&from);
1756 return len;
1757 }
1758
1759 /* Packet alignment check. */
1760 if ((len - RIP_PACKET_MINSIZ) % 20)
1761 {
1762 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1763 rip_peer_bad_packet (&from);
1764 return len;
1765 }
1766
1767 /* Set RTE number. */
1768 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1769
1770 /* For easy to handle. */
1771 packet = &rip_buf.rip_packet;
1772
1773 /* RIP version check. */
1774 if (packet->version == 0)
1775 {
1776 zlog_info ("version 0 with command %d received.", packet->command);
1777 rip_peer_bad_packet (&from);
1778 return -1;
1779 }
1780
1781 /* Dump RIP packet. */
1782 if (IS_RIP_DEBUG_RECV)
1783 rip_packet_dump (packet, len, "RECV");
1784
1785 /* RIP version adjust. This code should rethink now. RFC1058 says
1786 that "Version 1 implementations are to ignore this extra data and
1787 process only the fields specified in this document.". So RIPv3
1788 packet should be treated as RIPv1 ignoring must be zero field. */
1789 if (packet->version > RIPv2)
1790 packet->version = RIPv2;
1791
1792 /* Is RIP running or is this RIP neighbor ?*/
1793 ri = ifp->info;
1794 if (! ri->running && ! rip_neighbor_lookup (&from))
1795 {
1796 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001797 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001798 rip_peer_bad_packet (&from);
1799 return -1;
1800 }
1801
1802 /* RIP Version check. */
1803 if (packet->command == RIP_RESPONSE)
1804 {
paulf38a4712003-06-07 01:10:00 +00001805 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1806 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001807 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001808 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001809 {
1810 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001811 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001812 packet->version);
1813 rip_peer_bad_packet (&from);
1814 return -1;
1815 }
1816 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001817 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001818 {
1819 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001820 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001821 packet->version);
1822 rip_peer_bad_packet (&from);
1823 return -1;
1824 }
paul718e3742002-12-13 20:15:29 +00001825 }
1826
1827 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1828 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1829 accepted; authenticated RIP-2 messages shall be discarded. */
1830
1831 if ((ri->auth_type == RIP_NO_AUTH)
1832 && rtenum
paulca5e5162004-06-06 22:06:33 +00001833 && (packet->version == RIPv2)
1834 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001835 {
1836 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001837 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001838 packet->version);
1839 rip_peer_bad_packet (&from);
1840 return -1;
1841 }
1842
1843 /* If the router is configured to authenticate RIP-2 messages, then
1844 RIP-1 messages and RIP-2 messages which pass authentication
1845 testing shall be accepted; unauthenticated and failed
1846 authentication RIP-2 messages shall be discarded. For maximum
1847 security, RIP-1 messages should be ignored when authentication is
1848 in use (see section 4.1); otherwise, the routing information from
1849 authenticated messages will be propagated by RIP-1 routers in an
1850 unauthenticated manner. */
1851
1852 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001853 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001854 {
1855 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001856 if (packet->version == RIPv1
1857 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001858 {
1859 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001860 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001861 ("packet RIPv%d is dropped because authentication enabled",
1862 packet->version);
paul718e3742002-12-13 20:15:29 +00001863 rip_peer_bad_packet (&from);
1864 return -1;
1865 }
1866
1867 /* Check RIPv2 authentication. */
1868 if (packet->version == RIPv2)
1869 {
paulca5e5162004-06-06 22:06:33 +00001870 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001871 {
paulca5e5162004-06-06 22:06:33 +00001872 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001873 {
1874 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1875 if (! ret)
1876 {
1877 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001878 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001879 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001880 rip_peer_bad_packet (&from);
1881 return -1;
1882 }
1883 else
1884 {
1885 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001886 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001887 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001888 }
1889 }
paulca5e5162004-06-06 22:06:33 +00001890 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001891 {
paulca5e5162004-06-06 22:06:33 +00001892 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001893 if (! ret)
1894 {
1895 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001896 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001897 rip_peer_bad_packet (&from);
1898 return -1;
1899 }
1900 else
1901 {
1902 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001903 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001904 }
1905 /* Reset RIP packet length to trim MD5 data. */
1906 len = ret;
1907 }
1908 else
1909 {
1910 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001911 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00001912 ntohs (packet->rte->tag));
1913 rip_peer_bad_packet (&from);
1914 return -1;
1915 }
1916 }
1917 else
1918 {
1919 /* There is no authentication in the packet. */
1920 if (ri->auth_str || ri->key_chain)
1921 {
1922 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001923 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001924 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001925 rip_peer_bad_packet (&from);
1926 return -1;
1927 }
1928 }
1929 }
1930 }
1931
1932 /* Process each command. */
1933 switch (packet->command)
1934 {
1935 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00001936 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001937 break;
1938 case RIP_REQUEST:
1939 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00001940 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001941 break;
1942 case RIP_TRACEON:
1943 case RIP_TRACEOFF:
1944 zlog_info ("Obsolete command %s received, please sent it to routed",
1945 lookup (rip_msg, packet->command));
1946 rip_peer_bad_packet (&from);
1947 break;
1948 case RIP_POLL_ENTRY:
1949 zlog_info ("Obsolete command %s received",
1950 lookup (rip_msg, packet->command));
1951 rip_peer_bad_packet (&from);
1952 break;
1953 default:
1954 zlog_info ("Unknown RIP command %d received", packet->command);
1955 rip_peer_bad_packet (&from);
1956 break;
1957 }
1958
1959 return len;
1960}
1961
1962/* Make socket for RIP protocol. */
1963int
1964rip_create_socket ()
1965{
1966 int ret;
1967 int sock;
1968 struct sockaddr_in addr;
1969 struct servent *sp;
1970
1971 memset (&addr, 0, sizeof (struct sockaddr_in));
1972
1973 /* Set RIP port. */
1974 sp = getservbyname ("router", "udp");
1975 if (sp)
1976 addr.sin_port = sp->s_port;
1977 else
1978 addr.sin_port = htons (RIP_PORT_DEFAULT);
1979
1980 /* Address shoud be any address. */
1981 addr.sin_family = AF_INET;
1982 addr.sin_addr.s_addr = INADDR_ANY;
1983
1984 /* Make datagram socket. */
1985 sock = socket (AF_INET, SOCK_DGRAM, 0);
1986 if (sock < 0)
1987 {
1988 perror ("socket");
1989 exit (1);
1990 }
1991
1992 sockopt_broadcast (sock);
1993 sockopt_reuseaddr (sock);
1994 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00001995 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00001996#ifdef RIP_RECVMSG
1997 setsockopt_pktinfo (sock);
1998#endif /* RIP_RECVMSG */
1999
pauledd7c242003-06-04 13:59:38 +00002000 if (ripd_privs.change (ZPRIVS_RAISE))
2001 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00002002 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
2003 if (ret < 0)
2004 {
2005 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00002006 if (ripd_privs.change (ZPRIVS_LOWER))
2007 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00002008 return ret;
2009 }
pauledd7c242003-06-04 13:59:38 +00002010 if (ripd_privs.change (ZPRIVS_LOWER))
2011 zlog_err ("rip_create_socket: could not lower privs");
2012
paul718e3742002-12-13 20:15:29 +00002013 return sock;
2014}
2015
2016/* Write routing table entry to the stream and return next index of
2017 the routing table entry in the stream. */
2018int
2019rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2020 u_char version, struct rip_info *rinfo, struct interface *ifp)
2021{
2022 struct in_addr mask;
2023 struct rip_interface *ri;
2024
2025 /* RIP packet header. */
2026 if (num == 0)
2027 {
2028 stream_putc (s, RIP_RESPONSE);
2029 stream_putc (s, version);
2030 stream_putw (s, 0);
2031
2032 /* In case of we need RIPv2 authentication. */
2033 if (version == RIPv2 && ifp)
2034 {
2035 ri = ifp->info;
2036
2037 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2038 {
2039 if (ri->auth_str)
2040 {
paulca5e5162004-06-06 22:06:33 +00002041 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002042 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2043
2044 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002045 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002046 stream_set_putp (s, s->putp + 16);
2047
2048 num++;
2049 }
2050 if (ri->key_chain)
2051 {
2052 struct keychain *keychain;
2053 struct key *key;
2054
2055 keychain = keychain_lookup (ri->key_chain);
2056
2057 if (keychain)
2058 {
2059 key = key_lookup_for_send (keychain);
2060
2061 if (key)
2062 {
paulca5e5162004-06-06 22:06:33 +00002063 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002064 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2065
2066 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002067 strncpy ((char *)(s->data + s->putp),
2068 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002069 stream_set_putp (s, s->putp + 16);
2070
2071 num++;
2072 }
2073 }
2074 }
2075 }
2076 }
2077 }
2078
2079 /* Write routing table entry. */
2080 if (version == RIPv1)
2081 {
2082 stream_putw (s, AF_INET);
2083 stream_putw (s, 0);
2084 stream_put_ipv4 (s, p->prefix.s_addr);
2085 stream_put_ipv4 (s, 0);
2086 stream_put_ipv4 (s, 0);
2087 stream_putl (s, rinfo->metric_out);
2088 }
2089 else
2090 {
2091 masklen2ip (p->prefixlen, &mask);
2092
2093 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002094 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002095 stream_put_ipv4 (s, p->prefix.s_addr);
2096 stream_put_ipv4 (s, mask.s_addr);
2097 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2098 stream_putl (s, rinfo->metric_out);
2099 }
2100
2101 return ++num;
2102}
2103
2104/* Send update to the ifp or spcified neighbor. */
2105void
paulc49ad8f2004-10-22 10:27:28 +00002106rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2107 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002108{
2109 int ret;
2110 struct stream *s;
2111 struct route_node *rp;
2112 struct rip_info *rinfo;
2113 struct rip_interface *ri;
2114 struct prefix_ipv4 *p;
2115 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002116 struct prefix_ipv4 ifaddrclass;
paul718e3742002-12-13 20:15:29 +00002117 int num;
2118 int rtemax;
paul01d09082003-06-08 21:22:18 +00002119 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002120
2121 /* Logging output event. */
2122 if (IS_RIP_DEBUG_EVENT)
2123 {
2124 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002125 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002126 else
ajs5d6c3772004-12-08 19:24:06 +00002127 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002128 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002129 }
2130
2131 /* Set output stream. */
2132 s = rip->obuf;
2133
2134 /* Reset stream and RTE counter. */
2135 stream_reset (s);
2136 num = 0;
2137 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2138
2139 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002140 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002141
2142 /* If output interface is in simple password authentication mode, we
2143 need space for authentication data. */
2144 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2145 rtemax -= 1;
2146
2147 /* If output interface is in MD5 authentication mode, we need space
2148 for authentication header and data. */
2149 if (ri->auth_type == RIP_AUTH_MD5)
2150 rtemax -= 2;
2151
2152 /* If output interface is in simple password authentication mode
2153 and string or keychain is specified we need space for auth. data */
2154 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2155 {
2156 if (ri->key_chain)
2157 {
2158 struct keychain *keychain;
2159
2160 keychain = keychain_lookup (ri->key_chain);
2161 if (keychain)
2162 if (key_lookup_for_send (keychain))
2163 rtemax -=1;
2164 }
2165 else
2166 if (ri->auth_str)
2167 rtemax -=1;
2168 }
2169
paul727d1042002-12-13 20:50:29 +00002170 if (version == RIPv1)
2171 {
paulc49ad8f2004-10-22 10:27:28 +00002172 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002173 apply_classful_mask_ipv4 (&ifaddrclass);
2174 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002175 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002176 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002177 }
2178
paul718e3742002-12-13 20:15:29 +00002179 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2180 if ((rinfo = rp->info) != NULL)
2181 {
paul727d1042002-12-13 20:50:29 +00002182 /* For RIPv1, if we are subnetted, output subnets in our network */
2183 /* that have the same mask as the output "interface". For other */
2184 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002185
2186 if (version == RIPv1)
2187 {
paul727d1042002-12-13 20:50:29 +00002188 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002189
2190 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002191 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002192 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002193
paul727d1042002-12-13 20:50:29 +00002194 if (subnetted &&
2195 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2196 {
paulc49ad8f2004-10-22 10:27:28 +00002197 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002198 (rp->p.prefixlen != 32))
2199 continue;
2200 }
2201 else
2202 {
2203 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2204 apply_classful_mask_ipv4(&classfull);
2205 if (rp->p.u.prefix4.s_addr != 0 &&
2206 classfull.prefixlen != rp->p.prefixlen)
2207 continue;
2208 }
paul718e3742002-12-13 20:15:29 +00002209 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002210 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002211 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002212 }
2213 else
2214 p = (struct prefix_ipv4 *) &rp->p;
2215
2216 /* Apply output filters. */
2217 ret = rip_outgoing_filter (p, ri);
2218 if (ret < 0)
2219 continue;
2220
2221 /* Changed route only output. */
2222 if (route_type == rip_changed_route &&
2223 (! (rinfo->flags & RIP_RTF_CHANGED)))
2224 continue;
2225
2226 /* Split horizon. */
2227 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002228 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002229 {
paul42d14d92003-11-17 09:15:18 +00002230 /*
2231 * We perform split horizon for RIP and connected route.
2232 * For rip routes, we want to suppress the route if we would
2233 * end up sending the route back on the interface that we
2234 * learned it from, with a higher metric. For connected routes,
2235 * we suppress the route if the prefix is a subset of the
2236 * source address that we are going to use for the packet
2237 * (in order to handle the case when multiple subnets are
2238 * configured on the same interface).
2239 */
2240 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002241 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002242 continue;
2243 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002244 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002245 continue;
2246 }
2247
2248 /* Preparation for route-map. */
2249 rinfo->metric_set = 0;
2250 rinfo->nexthop_out.s_addr = 0;
2251 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002252 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002253 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002254
hasso16705132003-05-25 14:49:19 +00002255 /* In order to avoid some local loops,
2256 * if the RIP route has a nexthop via this interface, keep the nexthop,
2257 * otherwise set it to 0. The nexthop should not be propagated
2258 * beyond the local broadcast/multicast area in order
2259 * to avoid an IGP multi-level recursive look-up.
2260 * see (4.4)
2261 */
paulc49ad8f2004-10-22 10:27:28 +00002262 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002263 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002264
2265 /* Interface route-map */
2266 if (ri->routemap[RIP_FILTER_OUT])
2267 {
2268 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2269 (struct prefix *) p, RMAP_RIP,
2270 rinfo);
2271
2272 if (ret == RMAP_DENYMATCH)
2273 {
2274 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002275 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002276 inet_ntoa (p->prefix), p->prefixlen);
2277 continue;
2278 }
2279 }
paul718e3742002-12-13 20:15:29 +00002280
hasso16705132003-05-25 14:49:19 +00002281 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002282 if (rip->route_map[rinfo->type].name
2283 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2284 {
2285 ret = route_map_apply (rip->route_map[rinfo->type].map,
2286 (struct prefix *)p, RMAP_RIP, rinfo);
2287
2288 if (ret == RMAP_DENYMATCH)
2289 {
2290 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002291 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002292 inet_ntoa (p->prefix), p->prefixlen);
2293 continue;
2294 }
2295 }
2296
2297 /* When route-map does not set metric. */
2298 if (! rinfo->metric_set)
2299 {
2300 /* If redistribute metric is set. */
2301 if (rip->route_map[rinfo->type].metric_config
2302 && rinfo->metric != RIP_METRIC_INFINITY)
2303 {
2304 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2305 }
2306 else
2307 {
2308 /* If the route is not connected or localy generated
2309 one, use default-metric value*/
2310 if (rinfo->type != ZEBRA_ROUTE_RIP
2311 && rinfo->type != ZEBRA_ROUTE_CONNECT
2312 && rinfo->metric != RIP_METRIC_INFINITY)
2313 rinfo->metric_out = rip->default_metric;
2314 }
2315 }
2316
2317 /* Apply offset-list */
2318 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002319 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002320
2321 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2322 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002323
2324 /* Perform split-horizon with poisoned reverse
2325 * for RIP and connected routes.
2326 **/
2327 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002328 /*
2329 * We perform split horizon for RIP and connected route.
2330 * For rip routes, we want to suppress the route if we would
2331 * end up sending the route back on the interface that we
2332 * learned it from, with a higher metric. For connected routes,
2333 * we suppress the route if the prefix is a subset of the
2334 * source address that we are going to use for the packet
2335 * (in order to handle the case when multiple subnets are
2336 * configured on the same interface).
2337 */
2338 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002339 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002340 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002341 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002342 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002343 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002344 }
2345
paul718e3742002-12-13 20:15:29 +00002346 /* Write RTE to the stream. */
paulc49ad8f2004-10-22 10:27:28 +00002347 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002348 if (num == rtemax)
2349 {
2350 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002351 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002352
2353 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002354 to, ifc);
paul718e3742002-12-13 20:15:29 +00002355
2356 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2357 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2358 stream_get_endp(s), "SEND");
2359 num = 0;
2360 stream_reset (s);
2361 }
2362 }
2363
2364 /* Flush unwritten RTE. */
2365 if (num != 0)
2366 {
2367 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002368 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002369
paulc49ad8f2004-10-22 10:27:28 +00002370 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002371
2372 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2373 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2374 stream_get_endp (s), "SEND");
2375 num = 0;
2376 stream_reset (s);
2377 }
2378
2379 /* Statistics updates. */
2380 ri->sent_updates++;
2381}
2382
2383/* Send RIP packet to the interface. */
2384void
paulc49ad8f2004-10-22 10:27:28 +00002385rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002386{
paul718e3742002-12-13 20:15:29 +00002387 struct sockaddr_in to;
2388
2389 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002390 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002391 {
2392 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002393 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002394
paulc49ad8f2004-10-22 10:27:28 +00002395 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002396 return;
2397 }
paulc49ad8f2004-10-22 10:27:28 +00002398
paul718e3742002-12-13 20:15:29 +00002399 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002400 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002401 {
paulc49ad8f2004-10-22 10:27:28 +00002402 if (ifc->address->family == AF_INET)
2403 {
2404 /* Destination address and port setting. */
2405 memset (&to, 0, sizeof (struct sockaddr_in));
2406 if (ifc->destination)
2407 /* use specified broadcast or point-to-point destination addr */
2408 to.sin_addr = ifc->destination->u.prefix4;
2409 else
2410 /* calculate the appropriate broadcast address */
2411 to.sin_addr.s_addr =
2412 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2413 ifc->address->prefixlen);
2414 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002415
paulc49ad8f2004-10-22 10:27:28 +00002416 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002417 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002418 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2419 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002420
paulc49ad8f2004-10-22 10:27:28 +00002421 rip_output_process (ifc, &to, route_type, version);
2422 }
paul718e3742002-12-13 20:15:29 +00002423 }
2424}
2425
2426/* Update send to all interface and neighbor. */
2427void
2428rip_update_process (int route_type)
2429{
hasso52dc7ee2004-09-23 19:18:23 +00002430 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002431 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002432 struct interface *ifp;
2433 struct rip_interface *ri;
2434 struct route_node *rp;
2435 struct sockaddr_in to;
2436 struct prefix_ipv4 *p;
2437
2438 /* Send RIP update to each interface. */
2439 for (node = listhead (iflist); node; nextnode (node))
2440 {
2441 ifp = getdata (node);
2442
2443 if (if_is_loopback (ifp))
2444 continue;
2445
paul2e3b2e42002-12-13 21:03:13 +00002446 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002447 continue;
2448
2449 /* Fetch RIP interface information. */
2450 ri = ifp->info;
2451
2452 /* When passive interface is specified, suppress announce to the
2453 interface. */
2454 if (ri->passive)
2455 continue;
2456
2457 if (ri->running)
2458 {
2459 if (IS_RIP_DEBUG_EVENT)
2460 {
2461 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002462 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002463 ifp->name, ifp->ifindex);
2464 else
ajs5d6c3772004-12-08 19:24:06 +00002465 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002466 ifp->ifindex);
2467 }
2468
paulcc1131a2003-10-15 23:20:17 +00002469 /* send update on each connected network */
2470
2471 LIST_LOOP(ifp->connected, connected, ifnode)
2472 {
2473 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002474 int done = 0;
2475 /*
2476 * If there is no version configuration in the interface,
2477 * use rip's version setting.
2478 */
paulf38a4712003-06-07 01:10:00 +00002479 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2480 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002481
2482 ifaddr = (struct prefix_ipv4 *) connected->address;
2483
2484 if (ifaddr->family != AF_INET)
2485 continue;
2486
paul931cd542004-01-23 15:31:42 +00002487 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002488 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002489 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002490 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002491 done = 1;
2492 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2493 break;
2494
paulf38a4712003-06-07 01:10:00 +00002495 }
paul718e3742002-12-13 20:15:29 +00002496 }
2497 }
2498
2499 /* RIP send updates to each neighbor. */
2500 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2501 if (rp->info != NULL)
2502 {
2503 p = (struct prefix_ipv4 *) &rp->p;
2504
2505 ifp = if_lookup_address (p->prefix);
2506 if (! ifp)
2507 {
paulc49ad8f2004-10-22 10:27:28 +00002508 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002509 inet_ntoa (p->prefix));
2510 continue;
2511 }
paulc49ad8f2004-10-22 10:27:28 +00002512
2513 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2514 {
2515 zlog_warn ("Neighbor %s doesnt have connected network",
2516 inet_ntoa (p->prefix));
2517 continue;
2518 }
2519
paul718e3742002-12-13 20:15:29 +00002520 /* Set destination address and port */
2521 memset (&to, 0, sizeof (struct sockaddr_in));
2522 to.sin_addr = p->prefix;
2523 to.sin_port = htons (RIP_PORT_DEFAULT);
2524
2525 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002526 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002527 }
2528}
2529
2530/* RIP's periodical timer. */
2531int
2532rip_update (struct thread *t)
2533{
2534 /* Clear timer pointer. */
2535 rip->t_update = NULL;
2536
2537 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002538 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002539
2540 /* Process update output. */
2541 rip_update_process (rip_all_route);
2542
2543 /* Triggered updates may be suppressed if a regular update is due by
2544 the time the triggered update would be sent. */
2545 if (rip->t_triggered_interval)
2546 {
2547 thread_cancel (rip->t_triggered_interval);
2548 rip->t_triggered_interval = NULL;
2549 }
2550 rip->trigger = 0;
2551
2552 /* Register myself. */
2553 rip_event (RIP_UPDATE_EVENT, 0);
2554
2555 return 0;
2556}
2557
2558/* Walk down the RIP routing table then clear changed flag. */
2559void
2560rip_clear_changed_flag ()
2561{
2562 struct route_node *rp;
2563 struct rip_info *rinfo;
2564
2565 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2566 if ((rinfo = rp->info) != NULL)
2567 if (rinfo->flags & RIP_RTF_CHANGED)
2568 rinfo->flags &= ~RIP_RTF_CHANGED;
2569}
2570
2571/* Triggered update interval timer. */
2572int
2573rip_triggered_interval (struct thread *t)
2574{
2575 int rip_triggered_update (struct thread *);
2576
2577 rip->t_triggered_interval = NULL;
2578
2579 if (rip->trigger)
2580 {
2581 rip->trigger = 0;
2582 rip_triggered_update (t);
2583 }
2584 return 0;
2585}
2586
2587/* Execute triggered update. */
2588int
2589rip_triggered_update (struct thread *t)
2590{
2591 int interval;
2592
2593 /* Clear thred pointer. */
2594 rip->t_triggered_update = NULL;
2595
2596 /* Cancel interval timer. */
2597 if (rip->t_triggered_interval)
2598 {
2599 thread_cancel (rip->t_triggered_interval);
2600 rip->t_triggered_interval = NULL;
2601 }
2602 rip->trigger = 0;
2603
2604 /* Logging triggered update. */
2605 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002606 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002607
2608 /* Split Horizon processing is done when generating triggered
2609 updates as well as normal updates (see section 2.6). */
2610 rip_update_process (rip_changed_route);
2611
2612 /* Once all of the triggered updates have been generated, the route
2613 change flags should be cleared. */
2614 rip_clear_changed_flag ();
2615
2616 /* After a triggered update is sent, a timer should be set for a
2617 random interval between 1 and 5 seconds. If other changes that
2618 would trigger updates occur before the timer expires, a single
2619 update is triggered when the timer expires. */
2620 interval = (random () % 5) + 1;
2621
2622 rip->t_triggered_interval =
2623 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2624
2625 return 0;
2626}
2627
2628/* Withdraw redistributed route. */
2629void
2630rip_redistribute_withdraw (int type)
2631{
2632 struct route_node *rp;
2633 struct rip_info *rinfo;
2634
2635 if (!rip)
2636 return;
2637
2638 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2639 if ((rinfo = rp->info) != NULL)
2640 {
2641 if (rinfo->type == type
2642 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2643 {
2644 /* Perform poisoned reverse. */
2645 rinfo->metric = RIP_METRIC_INFINITY;
2646 RIP_TIMER_ON (rinfo->t_garbage_collect,
2647 rip_garbage_collect, rip->garbage_time);
2648 RIP_TIMER_OFF (rinfo->t_timeout);
2649 rinfo->flags |= RIP_RTF_CHANGED;
2650
hasso16705132003-05-25 14:49:19 +00002651 if (IS_RIP_DEBUG_EVENT) {
2652 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2653
ajs5d6c3772004-12-08 19:24:06 +00002654 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002655 inet_ntoa(p->prefix), p->prefixlen,
2656 ifindex2ifname(rinfo->ifindex));
2657 }
2658
paul718e3742002-12-13 20:15:29 +00002659 rip_event (RIP_TRIGGERED_UPDATE, 0);
2660 }
2661 }
2662}
2663
2664/* Create new RIP instance and set it to global variable. */
2665int
2666rip_create ()
2667{
2668 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2669 memset (rip, 0, sizeof (struct rip));
2670
2671 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002672 rip->version_send = RI_RIP_VERSION_2;
2673 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002674 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2675 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2676 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2677 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2678
2679 /* Initialize RIP routig table. */
2680 rip->table = route_table_init ();
2681 rip->route = route_table_init ();
2682 rip->neighbor = route_table_init ();
2683
2684 /* Make output stream. */
2685 rip->obuf = stream_new (1500);
2686
2687 /* Make socket. */
2688 rip->sock = rip_create_socket ();
2689 if (rip->sock < 0)
2690 return rip->sock;
2691
2692 /* Create read and timer thread. */
2693 rip_event (RIP_READ, rip->sock);
2694 rip_event (RIP_UPDATE_EVENT, 1);
2695
2696 return 0;
2697}
2698
2699/* Sned RIP request to the destination. */
2700int
2701rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002702 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002703{
2704 struct rte *rte;
2705 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002706 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002707
2708 memset (&rip_packet, 0, sizeof (rip_packet));
2709
2710 rip_packet.command = RIP_REQUEST;
2711 rip_packet.version = version;
2712 rte = rip_packet.rte;
2713 rte->metric = htonl (RIP_METRIC_INFINITY);
2714
paul931cd542004-01-23 15:31:42 +00002715 if (connected)
2716 {
2717 /*
2718 * connected is only sent for ripv1 case, or when
2719 * interface does not support multicast. Caller loops
2720 * over each connected address for this case.
2721 */
paul11dde9c2004-05-31 14:00:00 +00002722 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002723 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002724 return -1;
2725 else
2726 return sizeof (rip_packet);
2727 }
2728
paulcc1131a2003-10-15 23:20:17 +00002729 /* send request on each connected network */
2730 LIST_LOOP(ifp->connected, connected, node)
2731 {
2732 struct prefix_ipv4 *p;
2733
2734 p = (struct prefix_ipv4 *) connected->address;
2735
2736 if (p->family != AF_INET)
2737 continue;
2738
paul11dde9c2004-05-31 14:00:00 +00002739 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002740 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002741 return -1;
2742 }
2743 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002744}
2745
2746int
2747rip_update_jitter (unsigned long time)
2748{
paul239389b2004-05-05 14:09:37 +00002749#define JITTER_BOUND 4
2750 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2751 Given that, we cannot let time be less than JITTER_BOUND seconds.
2752 The RIPv2 RFC says jitter should be small compared to
2753 update_time. We consider 1/JITTER_BOUND to be small.
2754 */
2755
2756 int jitter_input = time;
2757 int jitter;
2758
2759 if (jitter_input < JITTER_BOUND)
2760 jitter_input = JITTER_BOUND;
2761
2762 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2763
2764 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002765}
2766
2767void
2768rip_event (enum rip_event event, int sock)
2769{
2770 int jitter = 0;
2771
2772 switch (event)
2773 {
2774 case RIP_READ:
2775 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2776 break;
2777 case RIP_UPDATE_EVENT:
2778 if (rip->t_update)
2779 {
2780 thread_cancel (rip->t_update);
2781 rip->t_update = NULL;
2782 }
2783 jitter = rip_update_jitter (rip->update_time);
2784 rip->t_update =
2785 thread_add_timer (master, rip_update, NULL,
2786 sock ? 2 : rip->update_time + jitter);
2787 break;
2788 case RIP_TRIGGERED_UPDATE:
2789 if (rip->t_triggered_interval)
2790 rip->trigger = 1;
2791 else if (! rip->t_triggered_update)
2792 rip->t_triggered_update =
2793 thread_add_event (master, rip_triggered_update, NULL, 0);
2794 break;
2795 default:
2796 break;
2797 }
2798}
2799
2800DEFUN (router_rip,
2801 router_rip_cmd,
2802 "router rip",
2803 "Enable a routing process\n"
2804 "Routing Information Protocol (RIP)\n")
2805{
2806 int ret;
2807
2808 /* If rip is not enabled before. */
2809 if (! rip)
2810 {
2811 ret = rip_create ();
2812 if (ret < 0)
2813 {
2814 zlog_info ("Can't create RIP");
2815 return CMD_WARNING;
2816 }
2817 }
2818 vty->node = RIP_NODE;
2819 vty->index = rip;
2820
2821 return CMD_SUCCESS;
2822}
2823
2824DEFUN (no_router_rip,
2825 no_router_rip_cmd,
2826 "no router rip",
2827 NO_STR
2828 "Enable a routing process\n"
2829 "Routing Information Protocol (RIP)\n")
2830{
2831 if (rip)
2832 rip_clean ();
2833 return CMD_SUCCESS;
2834}
2835
2836DEFUN (rip_version,
2837 rip_version_cmd,
2838 "version <1-2>",
2839 "Set routing protocol version\n"
2840 "version\n")
2841{
2842 int version;
2843
2844 version = atoi (argv[0]);
2845 if (version != RIPv1 && version != RIPv2)
2846 {
2847 vty_out (vty, "invalid rip version %d%s", version,
2848 VTY_NEWLINE);
2849 return CMD_WARNING;
2850 }
paulf38a4712003-06-07 01:10:00 +00002851 rip->version_send = version;
2852 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002853
2854 return CMD_SUCCESS;
2855}
2856
2857DEFUN (no_rip_version,
2858 no_rip_version_cmd,
2859 "no version",
2860 NO_STR
2861 "Set routing protocol version\n")
2862{
2863 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002864 rip->version_send = RI_RIP_VERSION_2;
2865 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002866
2867 return CMD_SUCCESS;
2868}
2869
2870ALIAS (no_rip_version,
2871 no_rip_version_val_cmd,
2872 "no version <1-2>",
2873 NO_STR
2874 "Set routing protocol version\n"
2875 "version\n")
2876
2877DEFUN (rip_route,
2878 rip_route_cmd,
2879 "route A.B.C.D/M",
2880 "RIP static route configuration\n"
2881 "IP prefix <network>/<length>\n")
2882{
2883 int ret;
2884 struct prefix_ipv4 p;
2885 struct route_node *node;
2886
2887 ret = str2prefix_ipv4 (argv[0], &p);
2888 if (ret < 0)
2889 {
2890 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2891 return CMD_WARNING;
2892 }
2893 apply_mask_ipv4 (&p);
2894
2895 /* For router rip configuration. */
2896 node = route_node_get (rip->route, (struct prefix *) &p);
2897
2898 if (node->info)
2899 {
2900 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2901 route_unlock_node (node);
2902 return CMD_WARNING;
2903 }
2904
hasso8a676be2004-10-08 06:36:38 +00002905 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002906
2907 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2908
2909 return CMD_SUCCESS;
2910}
2911
2912DEFUN (no_rip_route,
2913 no_rip_route_cmd,
2914 "no route A.B.C.D/M",
2915 NO_STR
2916 "RIP static route configuration\n"
2917 "IP prefix <network>/<length>\n")
2918{
2919 int ret;
2920 struct prefix_ipv4 p;
2921 struct route_node *node;
2922
2923 ret = str2prefix_ipv4 (argv[0], &p);
2924 if (ret < 0)
2925 {
2926 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2927 return CMD_WARNING;
2928 }
2929 apply_mask_ipv4 (&p);
2930
2931 /* For router rip configuration. */
2932 node = route_node_lookup (rip->route, (struct prefix *) &p);
2933 if (! node)
2934 {
2935 vty_out (vty, "Can't find route %s.%s", argv[0],
2936 VTY_NEWLINE);
2937 return CMD_WARNING;
2938 }
2939
2940 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2941 route_unlock_node (node);
2942
2943 node->info = NULL;
2944 route_unlock_node (node);
2945
2946 return CMD_SUCCESS;
2947}
2948
2949void
2950rip_update_default_metric ()
2951{
2952 struct route_node *np;
2953 struct rip_info *rinfo;
2954
2955 for (np = route_top (rip->table); np; np = route_next (np))
2956 if ((rinfo = np->info) != NULL)
2957 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2958 rinfo->metric = rip->default_metric;
2959}
2960
2961DEFUN (rip_default_metric,
2962 rip_default_metric_cmd,
2963 "default-metric <1-16>",
2964 "Set a metric of redistribute routes\n"
2965 "Default metric\n")
2966{
2967 if (rip)
2968 {
2969 rip->default_metric = atoi (argv[0]);
2970 /* rip_update_default_metric (); */
2971 }
2972 return CMD_SUCCESS;
2973}
2974
2975DEFUN (no_rip_default_metric,
2976 no_rip_default_metric_cmd,
2977 "no default-metric",
2978 NO_STR
2979 "Set a metric of redistribute routes\n"
2980 "Default metric\n")
2981{
2982 if (rip)
2983 {
2984 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2985 /* rip_update_default_metric (); */
2986 }
2987 return CMD_SUCCESS;
2988}
2989
2990ALIAS (no_rip_default_metric,
2991 no_rip_default_metric_val_cmd,
2992 "no default-metric <1-16>",
2993 NO_STR
2994 "Set a metric of redistribute routes\n"
2995 "Default metric\n")
2996
2997DEFUN (rip_timers,
2998 rip_timers_cmd,
2999 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3000 "Adjust routing timers\n"
3001 "Basic routing protocol update timers\n"
3002 "Routing table update timer value in second. Default is 30.\n"
3003 "Routing information timeout timer. Default is 180.\n"
3004 "Garbage collection timer. Default is 120.\n")
3005{
3006 unsigned long update;
3007 unsigned long timeout;
3008 unsigned long garbage;
3009 char *endptr = NULL;
3010 unsigned long RIP_TIMER_MAX = 2147483647;
3011 unsigned long RIP_TIMER_MIN = 5;
3012
3013 update = strtoul (argv[0], &endptr, 10);
3014 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3015 {
3016 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3017 return CMD_WARNING;
3018 }
3019
3020 timeout = strtoul (argv[1], &endptr, 10);
3021 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3022 {
3023 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3024 return CMD_WARNING;
3025 }
3026
3027 garbage = strtoul (argv[2], &endptr, 10);
3028 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3029 {
3030 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033
3034 /* Set each timer value. */
3035 rip->update_time = update;
3036 rip->timeout_time = timeout;
3037 rip->garbage_time = garbage;
3038
3039 /* Reset update timer thread. */
3040 rip_event (RIP_UPDATE_EVENT, 0);
3041
3042 return CMD_SUCCESS;
3043}
3044
3045DEFUN (no_rip_timers,
3046 no_rip_timers_cmd,
3047 "no timers basic",
3048 NO_STR
3049 "Adjust routing timers\n"
3050 "Basic routing protocol update timers\n")
3051{
3052 /* Set each timer value to the default. */
3053 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3054 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3055 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3056
3057 /* Reset update timer thread. */
3058 rip_event (RIP_UPDATE_EVENT, 0);
3059
3060 return CMD_SUCCESS;
3061}
hasso16705132003-05-25 14:49:19 +00003062
3063ALIAS (no_rip_timers,
3064 no_rip_timers_val_cmd,
3065 "no timers basic <0-65535> <0-65535> <0-65535>",
3066 NO_STR
3067 "Adjust routing timers\n"
3068 "Basic routing protocol update timers\n"
3069 "Routing table update timer value in second. Default is 30.\n"
3070 "Routing information timeout timer. Default is 180.\n"
3071 "Garbage collection timer. Default is 120.\n")
3072
paul718e3742002-12-13 20:15:29 +00003073
3074struct route_table *rip_distance_table;
3075
3076struct rip_distance
3077{
3078 /* Distance value for the IP source prefix. */
3079 u_char distance;
3080
3081 /* Name of the access-list to be matched. */
3082 char *access_list;
3083};
3084
3085struct rip_distance *
3086rip_distance_new ()
3087{
3088 struct rip_distance *new;
3089 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3090 memset (new, 0, sizeof (struct rip_distance));
3091 return new;
3092}
3093
3094void
3095rip_distance_free (struct rip_distance *rdistance)
3096{
3097 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3098}
3099
3100int
hasso98b718a2004-10-11 12:57:57 +00003101rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3102 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003103{
3104 int ret;
3105 struct prefix_ipv4 p;
3106 u_char distance;
3107 struct route_node *rn;
3108 struct rip_distance *rdistance;
3109
3110 ret = str2prefix_ipv4 (ip_str, &p);
3111 if (ret == 0)
3112 {
3113 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3114 return CMD_WARNING;
3115 }
3116
3117 distance = atoi (distance_str);
3118
3119 /* Get RIP distance node. */
3120 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3121 if (rn->info)
3122 {
3123 rdistance = rn->info;
3124 route_unlock_node (rn);
3125 }
3126 else
3127 {
3128 rdistance = rip_distance_new ();
3129 rn->info = rdistance;
3130 }
3131
3132 /* Set distance value. */
3133 rdistance->distance = distance;
3134
3135 /* Reset access-list configuration. */
3136 if (rdistance->access_list)
3137 {
3138 free (rdistance->access_list);
3139 rdistance->access_list = NULL;
3140 }
3141 if (access_list_str)
3142 rdistance->access_list = strdup (access_list_str);
3143
3144 return CMD_SUCCESS;
3145}
3146
3147int
hasso98b718a2004-10-11 12:57:57 +00003148rip_distance_unset (struct vty *vty, const char *distance_str,
3149 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003150{
3151 int ret;
3152 struct prefix_ipv4 p;
3153 u_char distance;
3154 struct route_node *rn;
3155 struct rip_distance *rdistance;
3156
3157 ret = str2prefix_ipv4 (ip_str, &p);
3158 if (ret == 0)
3159 {
3160 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3161 return CMD_WARNING;
3162 }
3163
3164 distance = atoi (distance_str);
3165
3166 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3167 if (! rn)
3168 {
3169 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3170 return CMD_WARNING;
3171 }
3172
3173 rdistance = rn->info;
3174
3175 if (rdistance->access_list)
3176 free (rdistance->access_list);
3177 rip_distance_free (rdistance);
3178
3179 rn->info = NULL;
3180 route_unlock_node (rn);
3181 route_unlock_node (rn);
3182
3183 return CMD_SUCCESS;
3184}
3185
3186void
3187rip_distance_reset ()
3188{
3189 struct route_node *rn;
3190 struct rip_distance *rdistance;
3191
3192 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3193 if ((rdistance = rn->info) != NULL)
3194 {
3195 if (rdistance->access_list)
3196 free (rdistance->access_list);
3197 rip_distance_free (rdistance);
3198 rn->info = NULL;
3199 route_unlock_node (rn);
3200 }
3201}
3202
3203/* Apply RIP information to distance method. */
3204u_char
3205rip_distance_apply (struct rip_info *rinfo)
3206{
3207 struct route_node *rn;
3208 struct prefix_ipv4 p;
3209 struct rip_distance *rdistance;
3210 struct access_list *alist;
3211
3212 if (! rip)
3213 return 0;
3214
3215 memset (&p, 0, sizeof (struct prefix_ipv4));
3216 p.family = AF_INET;
3217 p.prefix = rinfo->from;
3218 p.prefixlen = IPV4_MAX_BITLEN;
3219
3220 /* Check source address. */
3221 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3222 if (rn)
3223 {
3224 rdistance = rn->info;
3225 route_unlock_node (rn);
3226
3227 if (rdistance->access_list)
3228 {
3229 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3230 if (alist == NULL)
3231 return 0;
3232 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3233 return 0;
3234
3235 return rdistance->distance;
3236 }
3237 else
3238 return rdistance->distance;
3239 }
3240
3241 if (rip->distance)
3242 return rip->distance;
3243
3244 return 0;
3245}
3246
3247void
3248rip_distance_show (struct vty *vty)
3249{
3250 struct route_node *rn;
3251 struct rip_distance *rdistance;
3252 int header = 1;
3253 char buf[BUFSIZ];
3254
3255 vty_out (vty, " Distance: (default is %d)%s",
3256 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3257 VTY_NEWLINE);
3258
3259 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3260 if ((rdistance = rn->info) != NULL)
3261 {
3262 if (header)
3263 {
3264 vty_out (vty, " Address Distance List%s",
3265 VTY_NEWLINE);
3266 header = 0;
3267 }
3268 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3269 vty_out (vty, " %-20s %4d %s%s",
3270 buf, rdistance->distance,
3271 rdistance->access_list ? rdistance->access_list : "",
3272 VTY_NEWLINE);
3273 }
3274}
3275
3276DEFUN (rip_distance,
3277 rip_distance_cmd,
3278 "distance <1-255>",
3279 "Administrative distance\n"
3280 "Distance value\n")
3281{
3282 rip->distance = atoi (argv[0]);
3283 return CMD_SUCCESS;
3284}
3285
3286DEFUN (no_rip_distance,
3287 no_rip_distance_cmd,
3288 "no distance <1-255>",
3289 NO_STR
3290 "Administrative distance\n"
3291 "Distance value\n")
3292{
3293 rip->distance = 0;
3294 return CMD_SUCCESS;
3295}
3296
3297DEFUN (rip_distance_source,
3298 rip_distance_source_cmd,
3299 "distance <1-255> A.B.C.D/M",
3300 "Administrative distance\n"
3301 "Distance value\n"
3302 "IP source prefix\n")
3303{
3304 rip_distance_set (vty, argv[0], argv[1], NULL);
3305 return CMD_SUCCESS;
3306}
3307
3308DEFUN (no_rip_distance_source,
3309 no_rip_distance_source_cmd,
3310 "no distance <1-255> A.B.C.D/M",
3311 NO_STR
3312 "Administrative distance\n"
3313 "Distance value\n"
3314 "IP source prefix\n")
3315{
3316 rip_distance_unset (vty, argv[0], argv[1], NULL);
3317 return CMD_SUCCESS;
3318}
3319
3320DEFUN (rip_distance_source_access_list,
3321 rip_distance_source_access_list_cmd,
3322 "distance <1-255> A.B.C.D/M WORD",
3323 "Administrative distance\n"
3324 "Distance value\n"
3325 "IP source prefix\n"
3326 "Access list name\n")
3327{
3328 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3329 return CMD_SUCCESS;
3330}
3331
3332DEFUN (no_rip_distance_source_access_list,
3333 no_rip_distance_source_access_list_cmd,
3334 "no distance <1-255> A.B.C.D/M WORD",
3335 NO_STR
3336 "Administrative distance\n"
3337 "Distance value\n"
3338 "IP source prefix\n"
3339 "Access list name\n")
3340{
3341 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3342 return CMD_SUCCESS;
3343}
3344
3345/* Print out routes update time. */
3346void
3347rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3348{
3349 struct timeval timer_now;
3350 time_t clock;
3351 struct tm *tm;
3352#define TIME_BUF 25
3353 char timebuf [TIME_BUF];
3354 struct thread *thread;
3355
3356 gettimeofday (&timer_now, NULL);
3357
3358 if ((thread = rinfo->t_timeout) != NULL)
3359 {
3360 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3361 tm = gmtime (&clock);
3362 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3363 vty_out (vty, "%5s", timebuf);
3364 }
3365 else if ((thread = rinfo->t_garbage_collect) != NULL)
3366 {
3367 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3368 tm = gmtime (&clock);
3369 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3370 vty_out (vty, "%5s", timebuf);
3371 }
3372}
3373
hasso8a676be2004-10-08 06:36:38 +00003374const char *
paul718e3742002-12-13 20:15:29 +00003375rip_route_type_print (int sub_type)
3376{
3377 switch (sub_type)
3378 {
3379 case RIP_ROUTE_RTE:
3380 return "n";
3381 case RIP_ROUTE_STATIC:
3382 return "s";
3383 case RIP_ROUTE_DEFAULT:
3384 return "d";
3385 case RIP_ROUTE_REDISTRIBUTE:
3386 return "r";
3387 case RIP_ROUTE_INTERFACE:
3388 return "i";
3389 default:
3390 return "?";
3391 }
3392}
3393
3394DEFUN (show_ip_rip,
3395 show_ip_rip_cmd,
3396 "show ip rip",
3397 SHOW_STR
3398 IP_STR
3399 "Show RIP routes\n")
3400{
3401 struct route_node *np;
3402 struct rip_info *rinfo;
3403
3404 if (! rip)
3405 return CMD_SUCCESS;
3406
hasso16705132003-05-25 14:49:19 +00003407 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3408 "Sub-codes:%s"
3409 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003410 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003411 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003412 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003413
3414 for (np = route_top (rip->table); np; np = route_next (np))
3415 if ((rinfo = np->info) != NULL)
3416 {
3417 int len;
3418
3419 len = vty_out (vty, "%s(%s) %s/%d",
3420 /* np->lock, For debugging. */
3421 route_info[rinfo->type].str,
3422 rip_route_type_print (rinfo->sub_type),
3423 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3424
hassoa1455d82004-03-03 19:36:24 +00003425 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003426
3427 if (len > 0)
3428 vty_out (vty, "%*s", len, " ");
3429
3430 if (rinfo->nexthop.s_addr)
3431 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3432 rinfo->metric);
3433 else
3434 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3435
3436 /* Route which exist in kernel routing table. */
3437 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3438 (rinfo->sub_type == RIP_ROUTE_RTE))
3439 {
3440 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003441 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003442 rip_vty_out_uptime (vty, rinfo);
3443 }
3444 else if (rinfo->metric == RIP_METRIC_INFINITY)
3445 {
3446 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003447 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003448 rip_vty_out_uptime (vty, rinfo);
3449 }
3450 else
hasso16705132003-05-25 14:49:19 +00003451 {
3452 vty_out (vty, "self ");
3453 vty_out (vty, "%3d", rinfo->tag);
3454 }
paul718e3742002-12-13 20:15:29 +00003455
3456 vty_out (vty, "%s", VTY_NEWLINE);
3457 }
3458 return CMD_SUCCESS;
3459}
3460
3461/* Return next event time. */
3462int
3463rip_next_thread_timer (struct thread *thread)
3464{
3465 struct timeval timer_now;
3466
3467 gettimeofday (&timer_now, NULL);
3468
3469 return thread->u.sands.tv_sec - timer_now.tv_sec;
3470}
3471
hasso16705132003-05-25 14:49:19 +00003472/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3473DEFUN (show_ip_rip_status,
3474 show_ip_rip_status_cmd,
3475 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003476 SHOW_STR
3477 IP_STR
hasso16705132003-05-25 14:49:19 +00003478 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003479 "IP routing protocol process parameters and statistics\n")
3480{
hasso52dc7ee2004-09-23 19:18:23 +00003481 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003482 struct interface *ifp;
3483 struct rip_interface *ri;
3484 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003485 const char *send_version;
3486 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003487
3488 if (! rip)
3489 return CMD_SUCCESS;
3490
3491 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3492 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3493 rip->update_time);
3494 vty_out (vty, " next due in %d seconds%s",
3495 rip_next_thread_timer (rip->t_update),
3496 VTY_NEWLINE);
3497 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3498 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3499 VTY_NEWLINE);
3500
3501 /* Filtering status show. */
3502 config_show_distribute (vty);
3503
3504 /* Default metric information. */
3505 vty_out (vty, " Default redistribution metric is %d%s",
3506 rip->default_metric, VTY_NEWLINE);
3507
3508 /* Redistribute information. */
3509 vty_out (vty, " Redistributing:");
3510 config_write_rip_redistribute (vty, 0);
3511 vty_out (vty, "%s", VTY_NEWLINE);
3512
paulf38a4712003-06-07 01:10:00 +00003513 vty_out (vty, " Default version control: send version %s,",
3514 lookup(ri_version_msg,rip->version_send));
3515 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3516 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3517 else
3518 vty_out (vty, " receive version %s %s",
3519 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003520
3521 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3522
3523 for (node = listhead (iflist); node; node = nextnode (node))
3524 {
3525 ifp = getdata (node);
3526 ri = ifp->info;
3527
3528 if (ri->enable_network || ri->enable_interface)
3529 {
3530 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003531 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003532 else
3533 send_version = lookup (ri_version_msg, ri->ri_send);
3534
3535 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003536 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003537 else
3538 receive_version = lookup (ri_version_msg, ri->ri_receive);
3539
3540 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3541 send_version,
3542 receive_version,
3543 ri->key_chain ? ri->key_chain : "",
3544 VTY_NEWLINE);
3545 }
3546 }
3547
3548 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3549 config_write_rip_network (vty, 0);
3550
paul4aaff3f2003-06-07 01:04:45 +00003551 {
3552 int found_passive = 0;
3553 for (node = listhead (iflist); node; node = nextnode (node))
3554 {
3555 ifp = getdata (node);
3556 ri = ifp->info;
3557
3558 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3559 {
3560 if (!found_passive)
3561 {
3562 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3563 found_passive = 1;
3564 }
3565 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3566 }
3567 }
3568 }
3569
paul718e3742002-12-13 20:15:29 +00003570 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3571 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3572 rip_peer_display (vty);
3573
3574 rip_distance_show (vty);
3575
3576 return CMD_SUCCESS;
3577}
3578
3579/* RIP configuration write function. */
3580int
3581config_write_rip (struct vty *vty)
3582{
3583 int write = 0;
3584 struct route_node *rn;
3585 struct rip_distance *rdistance;
3586
3587 if (rip)
3588 {
3589 /* Router RIP statement. */
3590 vty_out (vty, "router rip%s", VTY_NEWLINE);
3591 write++;
3592
3593 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003594 if (rip->version_send != RI_RIP_VERSION_2
3595 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3596 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003597 VTY_NEWLINE);
3598
3599 /* RIP timer configuration. */
3600 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3601 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3602 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3603 vty_out (vty, " timers basic %lu %lu %lu%s",
3604 rip->update_time,
3605 rip->timeout_time,
3606 rip->garbage_time,
3607 VTY_NEWLINE);
3608
3609 /* Default information configuration. */
3610 if (rip->default_information)
3611 {
3612 if (rip->default_information_route_map)
3613 vty_out (vty, " default-information originate route-map %s%s",
3614 rip->default_information_route_map, VTY_NEWLINE);
3615 else
3616 vty_out (vty, " default-information originate%s",
3617 VTY_NEWLINE);
3618 }
3619
3620 /* Redistribute configuration. */
3621 config_write_rip_redistribute (vty, 1);
3622
3623 /* RIP offset-list configuration. */
3624 config_write_rip_offset_list (vty);
3625
3626 /* RIP enabled network and interface configuration. */
3627 config_write_rip_network (vty, 1);
3628
3629 /* RIP default metric configuration */
3630 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3631 vty_out (vty, " default-metric %d%s",
3632 rip->default_metric, VTY_NEWLINE);
3633
3634 /* Distribute configuration. */
3635 write += config_write_distribute (vty);
3636
hasso16705132003-05-25 14:49:19 +00003637 /* Interface routemap configuration */
3638 write += config_write_if_rmap (vty);
3639
paul718e3742002-12-13 20:15:29 +00003640 /* Distance configuration. */
3641 if (rip->distance)
3642 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3643
3644 /* RIP source IP prefix distance configuration. */
3645 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3646 if ((rdistance = rn->info) != NULL)
3647 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3648 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3649 rdistance->access_list ? rdistance->access_list : "",
3650 VTY_NEWLINE);
3651
3652 /* RIP static route configuration. */
3653 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3654 if (rn->info)
3655 vty_out (vty, " route %s/%d%s",
3656 inet_ntoa (rn->p.u.prefix4),
3657 rn->p.prefixlen,
3658 VTY_NEWLINE);
3659
3660 }
3661 return write;
3662}
3663
3664/* RIP node structure. */
3665struct cmd_node rip_node =
3666{
3667 RIP_NODE,
3668 "%s(config-router)# ",
3669 1
3670};
3671
3672/* Distribute-list update functions. */
3673void
3674rip_distribute_update (struct distribute *dist)
3675{
3676 struct interface *ifp;
3677 struct rip_interface *ri;
3678 struct access_list *alist;
3679 struct prefix_list *plist;
3680
3681 if (! dist->ifname)
3682 return;
3683
3684 ifp = if_lookup_by_name (dist->ifname);
3685 if (ifp == NULL)
3686 return;
3687
3688 ri = ifp->info;
3689
3690 if (dist->list[DISTRIBUTE_IN])
3691 {
3692 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3693 if (alist)
3694 ri->list[RIP_FILTER_IN] = alist;
3695 else
3696 ri->list[RIP_FILTER_IN] = NULL;
3697 }
3698 else
3699 ri->list[RIP_FILTER_IN] = NULL;
3700
3701 if (dist->list[DISTRIBUTE_OUT])
3702 {
3703 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3704 if (alist)
3705 ri->list[RIP_FILTER_OUT] = alist;
3706 else
3707 ri->list[RIP_FILTER_OUT] = NULL;
3708 }
3709 else
3710 ri->list[RIP_FILTER_OUT] = NULL;
3711
3712 if (dist->prefix[DISTRIBUTE_IN])
3713 {
3714 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3715 if (plist)
3716 ri->prefix[RIP_FILTER_IN] = plist;
3717 else
3718 ri->prefix[RIP_FILTER_IN] = NULL;
3719 }
3720 else
3721 ri->prefix[RIP_FILTER_IN] = NULL;
3722
3723 if (dist->prefix[DISTRIBUTE_OUT])
3724 {
3725 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3726 if (plist)
3727 ri->prefix[RIP_FILTER_OUT] = plist;
3728 else
3729 ri->prefix[RIP_FILTER_OUT] = NULL;
3730 }
3731 else
3732 ri->prefix[RIP_FILTER_OUT] = NULL;
3733}
3734
3735void
3736rip_distribute_update_interface (struct interface *ifp)
3737{
3738 struct distribute *dist;
3739
3740 dist = distribute_lookup (ifp->name);
3741 if (dist)
3742 rip_distribute_update (dist);
3743}
3744
3745/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003746/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003747void
paul02ff83c2004-06-11 11:27:03 +00003748rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003749{
3750 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003751 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003752
3753 for (node = listhead (iflist); node; nextnode (node))
3754 {
3755 ifp = getdata (node);
3756 rip_distribute_update_interface (ifp);
3757 }
3758}
paul11dde9c2004-05-31 14:00:00 +00003759/* ARGSUSED */
3760void
3761rip_distribute_update_all_wrapper(struct access_list *notused)
3762{
paul02ff83c2004-06-11 11:27:03 +00003763 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003764}
paul718e3742002-12-13 20:15:29 +00003765
3766/* Delete all added rip route. */
3767void
3768rip_clean ()
3769{
3770 int i;
3771 struct route_node *rp;
3772 struct rip_info *rinfo;
3773
3774 if (rip)
3775 {
3776 /* Clear RIP routes */
3777 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3778 if ((rinfo = rp->info) != NULL)
3779 {
3780 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3781 rinfo->sub_type == RIP_ROUTE_RTE)
3782 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3783 &rinfo->nexthop, rinfo->metric);
3784
3785 RIP_TIMER_OFF (rinfo->t_timeout);
3786 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3787
3788 rp->info = NULL;
3789 route_unlock_node (rp);
3790
3791 rip_info_free (rinfo);
3792 }
3793
3794 /* Cancel RIP related timers. */
3795 RIP_TIMER_OFF (rip->t_update);
3796 RIP_TIMER_OFF (rip->t_triggered_update);
3797 RIP_TIMER_OFF (rip->t_triggered_interval);
3798
3799 /* Cancel read thread. */
3800 if (rip->t_read)
3801 {
3802 thread_cancel (rip->t_read);
3803 rip->t_read = NULL;
3804 }
3805
3806 /* Close RIP socket. */
3807 if (rip->sock >= 0)
3808 {
3809 close (rip->sock);
3810 rip->sock = -1;
3811 }
3812
3813 /* Static RIP route configuration. */
3814 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3815 if (rp->info)
3816 {
3817 rp->info = NULL;
3818 route_unlock_node (rp);
3819 }
3820
3821 /* RIP neighbor configuration. */
3822 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3823 if (rp->info)
3824 {
3825 rp->info = NULL;
3826 route_unlock_node (rp);
3827 }
3828
3829 /* Redistribute related clear. */
3830 if (rip->default_information_route_map)
3831 free (rip->default_information_route_map);
3832
3833 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3834 if (rip->route_map[i].name)
3835 free (rip->route_map[i].name);
3836
3837 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3838 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3839 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3840
3841 XFREE (MTYPE_RIP, rip);
3842 rip = NULL;
3843 }
3844
3845 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003846 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003847 rip_offset_clean ();
3848 rip_interface_clean ();
3849 rip_distance_reset ();
3850 rip_redistribute_clean ();
3851}
3852
3853/* Reset all values to the default settings. */
3854void
3855rip_reset ()
3856{
3857 /* Reset global counters. */
3858 rip_global_route_changes = 0;
3859 rip_global_queries = 0;
3860
3861 /* Call ripd related reset functions. */
3862 rip_debug_reset ();
3863 rip_route_map_reset ();
3864
3865 /* Call library reset functions. */
3866 vty_reset ();
3867 access_list_reset ();
3868 prefix_list_reset ();
3869
3870 distribute_list_reset ();
3871
3872 rip_interface_reset ();
3873 rip_distance_reset ();
3874
3875 rip_zclient_reset ();
3876}
3877
hasso16705132003-05-25 14:49:19 +00003878void
3879rip_if_rmap_update (struct if_rmap *if_rmap)
3880{
3881 struct interface *ifp;
3882 struct rip_interface *ri;
3883 struct route_map *rmap;
3884
3885 ifp = if_lookup_by_name (if_rmap->ifname);
3886 if (ifp == NULL)
3887 return;
3888
3889 ri = ifp->info;
3890
3891 if (if_rmap->routemap[IF_RMAP_IN])
3892 {
3893 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3894 if (rmap)
3895 ri->routemap[IF_RMAP_IN] = rmap;
3896 else
3897 ri->routemap[IF_RMAP_IN] = NULL;
3898 }
3899 else
3900 ri->routemap[RIP_FILTER_IN] = NULL;
3901
3902 if (if_rmap->routemap[IF_RMAP_OUT])
3903 {
3904 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3905 if (rmap)
3906 ri->routemap[IF_RMAP_OUT] = rmap;
3907 else
3908 ri->routemap[IF_RMAP_OUT] = NULL;
3909 }
3910 else
3911 ri->routemap[RIP_FILTER_OUT] = NULL;
3912}
3913
3914void
3915rip_if_rmap_update_interface (struct interface *ifp)
3916{
3917 struct if_rmap *if_rmap;
3918
3919 if_rmap = if_rmap_lookup (ifp->name);
3920 if (if_rmap)
3921 rip_if_rmap_update (if_rmap);
3922}
3923
3924void
3925rip_routemap_update_redistribute (void)
3926{
3927 int i;
3928
3929 if (rip)
3930 {
3931 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3932 {
3933 if (rip->route_map[i].name)
3934 rip->route_map[i].map =
3935 route_map_lookup_by_name (rip->route_map[i].name);
3936 }
3937 }
3938}
3939
paul11dde9c2004-05-31 14:00:00 +00003940/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003941void
hasso98b718a2004-10-11 12:57:57 +00003942rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003943{
3944 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003945 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003946
3947 for (node = listhead (iflist); node; nextnode (node))
3948 {
3949 ifp = getdata (node);
3950 rip_if_rmap_update_interface (ifp);
3951 }
3952
3953 rip_routemap_update_redistribute ();
3954}
3955
paul718e3742002-12-13 20:15:29 +00003956/* Allocate new rip structure and set default value. */
3957void
3958rip_init ()
3959{
3960 /* Randomize for triggered update random(). */
3961 srand (time (NULL));
3962
3963 /* Install top nodes. */
3964 install_node (&rip_node, config_write_rip);
3965
3966 /* Install rip commands. */
3967 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003968 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003969 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003970 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003971 install_element (CONFIG_NODE, &router_rip_cmd);
3972 install_element (CONFIG_NODE, &no_router_rip_cmd);
3973
3974 install_default (RIP_NODE);
3975 install_element (RIP_NODE, &rip_version_cmd);
3976 install_element (RIP_NODE, &no_rip_version_cmd);
3977 install_element (RIP_NODE, &no_rip_version_val_cmd);
3978 install_element (RIP_NODE, &rip_default_metric_cmd);
3979 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3980 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3981 install_element (RIP_NODE, &rip_timers_cmd);
3982 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003983 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003984 install_element (RIP_NODE, &rip_route_cmd);
3985 install_element (RIP_NODE, &no_rip_route_cmd);
3986 install_element (RIP_NODE, &rip_distance_cmd);
3987 install_element (RIP_NODE, &no_rip_distance_cmd);
3988 install_element (RIP_NODE, &rip_distance_source_cmd);
3989 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3990 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3991 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3992
3993 /* Debug related init. */
3994 rip_debug_init ();
3995
paul718e3742002-12-13 20:15:29 +00003996 /* SNMP init. */
3997#ifdef HAVE_SNMP
3998 rip_snmp_init ();
3999#endif /* HAVE_SNMP */
4000
4001 /* Access list install. */
4002 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004003 access_list_add_hook (rip_distribute_update_all_wrapper);
4004 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004005
4006 /* Prefix list initialize.*/
4007 prefix_list_init ();
4008 prefix_list_add_hook (rip_distribute_update_all);
4009 prefix_list_delete_hook (rip_distribute_update_all);
4010
4011 /* Distribute list install. */
4012 distribute_list_init (RIP_NODE);
4013 distribute_list_add_hook (rip_distribute_update);
4014 distribute_list_delete_hook (rip_distribute_update);
4015
hasso16705132003-05-25 14:49:19 +00004016 /* Route-map */
4017 rip_route_map_init ();
4018 rip_offset_init ();
4019
4020 route_map_add_hook (rip_routemap_update);
4021 route_map_delete_hook (rip_routemap_update);
4022
4023 if_rmap_init (RIP_NODE);
4024 if_rmap_hook_add (rip_if_rmap_update);
4025 if_rmap_hook_delete (rip_if_rmap_update);
4026
paul718e3742002-12-13 20:15:29 +00004027 /* Distance control. */
4028 rip_distance_table = route_table_init ();
4029}