blob: 01e669f45fb742c45e791852ac768d1af82cfa98 [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
1635 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1636 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 {
paulc49ad8f2004-10-22 10:27:28 +00001728 zlog_info ("rip_read: packet comes from unknown interface");
1729 return -1;
1730 }
1731
1732 ifc = connected_lookup_address (ifp, from.sin_addr);
1733
1734 if (ifc == NULL)
1735 {
1736 zlog_info ("rip_read: packet comes from unknown network");
paul718e3742002-12-13 20:15:29 +00001737 return -1;
1738 }
1739
1740 /* Packet length check. */
1741 if (len < RIP_PACKET_MINSIZ)
1742 {
1743 zlog_warn ("packet size %d is smaller than minimum size %d",
1744 len, RIP_PACKET_MINSIZ);
1745 rip_peer_bad_packet (&from);
1746 return len;
1747 }
1748 if (len > RIP_PACKET_MAXSIZ)
1749 {
1750 zlog_warn ("packet size %d is larger than max size %d",
1751 len, RIP_PACKET_MAXSIZ);
1752 rip_peer_bad_packet (&from);
1753 return len;
1754 }
1755
1756 /* Packet alignment check. */
1757 if ((len - RIP_PACKET_MINSIZ) % 20)
1758 {
1759 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1760 rip_peer_bad_packet (&from);
1761 return len;
1762 }
1763
1764 /* Set RTE number. */
1765 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1766
1767 /* For easy to handle. */
1768 packet = &rip_buf.rip_packet;
1769
1770 /* RIP version check. */
1771 if (packet->version == 0)
1772 {
1773 zlog_info ("version 0 with command %d received.", packet->command);
1774 rip_peer_bad_packet (&from);
1775 return -1;
1776 }
1777
1778 /* Dump RIP packet. */
1779 if (IS_RIP_DEBUG_RECV)
1780 rip_packet_dump (packet, len, "RECV");
1781
1782 /* RIP version adjust. This code should rethink now. RFC1058 says
1783 that "Version 1 implementations are to ignore this extra data and
1784 process only the fields specified in this document.". So RIPv3
1785 packet should be treated as RIPv1 ignoring must be zero field. */
1786 if (packet->version > RIPv2)
1787 packet->version = RIPv2;
1788
1789 /* Is RIP running or is this RIP neighbor ?*/
1790 ri = ifp->info;
1791 if (! ri->running && ! rip_neighbor_lookup (&from))
1792 {
1793 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001794 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001795 rip_peer_bad_packet (&from);
1796 return -1;
1797 }
1798
1799 /* RIP Version check. */
1800 if (packet->command == RIP_RESPONSE)
1801 {
paulf38a4712003-06-07 01:10:00 +00001802 int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1803 rip->version_recv : ri->ri_receive);
paul718e3742002-12-13 20:15:29 +00001804 if (packet->version == RIPv1)
paulf38a4712003-06-07 01:10:00 +00001805 if (! (vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001806 {
1807 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001808 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001809 packet->version);
1810 rip_peer_bad_packet (&from);
1811 return -1;
1812 }
1813 if (packet->version == RIPv2)
paulf38a4712003-06-07 01:10:00 +00001814 if (! (vrecv & RIPv2))
paul718e3742002-12-13 20:15:29 +00001815 {
1816 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001817 zlog_debug (" packet's v%d doesn't fit to if version spec",
paul718e3742002-12-13 20:15:29 +00001818 packet->version);
1819 rip_peer_bad_packet (&from);
1820 return -1;
1821 }
paul718e3742002-12-13 20:15:29 +00001822 }
1823
1824 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
1825 messages, then RIP-1 and unauthenticated RIP-2 messages will be
1826 accepted; authenticated RIP-2 messages shall be discarded. */
1827
1828 if ((ri->auth_type == RIP_NO_AUTH)
1829 && rtenum
paulca5e5162004-06-06 22:06:33 +00001830 && (packet->version == RIPv2)
1831 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00001832 {
1833 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001834 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00001835 packet->version);
1836 rip_peer_bad_packet (&from);
1837 return -1;
1838 }
1839
1840 /* If the router is configured to authenticate RIP-2 messages, then
1841 RIP-1 messages and RIP-2 messages which pass authentication
1842 testing shall be accepted; unauthenticated and failed
1843 authentication RIP-2 messages shall be discarded. For maximum
1844 security, RIP-1 messages should be ignored when authentication is
1845 in use (see section 4.1); otherwise, the routing information from
1846 authenticated messages will be propagated by RIP-1 routers in an
1847 unauthenticated manner. */
1848
1849 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +00001850 || ri->auth_type == RIP_AUTH_MD5) && rtenum)
paul718e3742002-12-13 20:15:29 +00001851 {
1852 /* We follow maximum security. */
paulca5e5162004-06-06 22:06:33 +00001853 if (packet->version == RIPv1
1854 && packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001855 {
1856 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001857 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001858 ("packet RIPv%d is dropped because authentication enabled",
1859 packet->version);
paul718e3742002-12-13 20:15:29 +00001860 rip_peer_bad_packet (&from);
1861 return -1;
1862 }
1863
1864 /* Check RIPv2 authentication. */
1865 if (packet->version == RIPv2)
1866 {
paulca5e5162004-06-06 22:06:33 +00001867 if (packet->rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001868 {
paulca5e5162004-06-06 22:06:33 +00001869 if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +00001870 {
1871 ret = rip_auth_simple_password (packet->rte, &from, ifp);
1872 if (! ret)
1873 {
1874 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001875 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001876 ("RIPv2 simple password authentication failed");
paul718e3742002-12-13 20:15:29 +00001877 rip_peer_bad_packet (&from);
1878 return -1;
1879 }
1880 else
1881 {
1882 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001883 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001884 ("RIPv2 simple password authentication success");
paul718e3742002-12-13 20:15:29 +00001885 }
1886 }
paulca5e5162004-06-06 22:06:33 +00001887 else if (packet->rte->tag == htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +00001888 {
paulca5e5162004-06-06 22:06:33 +00001889 ret = rip_auth_md5 (packet, &from, len, ifp);
paul718e3742002-12-13 20:15:29 +00001890 if (! ret)
1891 {
1892 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001893 zlog_debug ("RIPv2 MD5 authentication failed");
paul718e3742002-12-13 20:15:29 +00001894 rip_peer_bad_packet (&from);
1895 return -1;
1896 }
1897 else
1898 {
1899 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001900 zlog_debug ("RIPv2 MD5 authentication success");
paul718e3742002-12-13 20:15:29 +00001901 }
1902 /* Reset RIP packet length to trim MD5 data. */
1903 len = ret;
1904 }
1905 else
1906 {
1907 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001908 zlog_debug ("Unknown authentication type %d",
paul718e3742002-12-13 20:15:29 +00001909 ntohs (packet->rte->tag));
1910 rip_peer_bad_packet (&from);
1911 return -1;
1912 }
1913 }
1914 else
1915 {
1916 /* There is no authentication in the packet. */
1917 if (ri->auth_str || ri->key_chain)
1918 {
1919 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001920 zlog_debug
paulca5e5162004-06-06 22:06:33 +00001921 ("RIPv2 authentication failed: no authentication in packet");
paul718e3742002-12-13 20:15:29 +00001922 rip_peer_bad_packet (&from);
1923 return -1;
1924 }
1925 }
1926 }
1927 }
1928
1929 /* Process each command. */
1930 switch (packet->command)
1931 {
1932 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00001933 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001934 break;
1935 case RIP_REQUEST:
1936 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00001937 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00001938 break;
1939 case RIP_TRACEON:
1940 case RIP_TRACEOFF:
1941 zlog_info ("Obsolete command %s received, please sent it to routed",
1942 lookup (rip_msg, packet->command));
1943 rip_peer_bad_packet (&from);
1944 break;
1945 case RIP_POLL_ENTRY:
1946 zlog_info ("Obsolete command %s received",
1947 lookup (rip_msg, packet->command));
1948 rip_peer_bad_packet (&from);
1949 break;
1950 default:
1951 zlog_info ("Unknown RIP command %d received", packet->command);
1952 rip_peer_bad_packet (&from);
1953 break;
1954 }
1955
1956 return len;
1957}
1958
1959/* Make socket for RIP protocol. */
1960int
1961rip_create_socket ()
1962{
1963 int ret;
1964 int sock;
1965 struct sockaddr_in addr;
1966 struct servent *sp;
1967
1968 memset (&addr, 0, sizeof (struct sockaddr_in));
1969
1970 /* Set RIP port. */
1971 sp = getservbyname ("router", "udp");
1972 if (sp)
1973 addr.sin_port = sp->s_port;
1974 else
1975 addr.sin_port = htons (RIP_PORT_DEFAULT);
1976
1977 /* Address shoud be any address. */
1978 addr.sin_family = AF_INET;
1979 addr.sin_addr.s_addr = INADDR_ANY;
1980
1981 /* Make datagram socket. */
1982 sock = socket (AF_INET, SOCK_DGRAM, 0);
1983 if (sock < 0)
1984 {
1985 perror ("socket");
1986 exit (1);
1987 }
1988
1989 sockopt_broadcast (sock);
1990 sockopt_reuseaddr (sock);
1991 sockopt_reuseport (sock);
paul0b3acf42004-09-17 08:39:08 +00001992 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
paul718e3742002-12-13 20:15:29 +00001993#ifdef RIP_RECVMSG
1994 setsockopt_pktinfo (sock);
1995#endif /* RIP_RECVMSG */
1996
pauledd7c242003-06-04 13:59:38 +00001997 if (ripd_privs.change (ZPRIVS_RAISE))
1998 zlog_err ("rip_create_socket: could not raise privs");
paul718e3742002-12-13 20:15:29 +00001999 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));
2000 if (ret < 0)
2001 {
2002 perror ("bind");
pauld62262a2003-11-17 09:08:45 +00002003 if (ripd_privs.change (ZPRIVS_LOWER))
2004 zlog_err ("rip_create_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +00002005 return ret;
2006 }
pauledd7c242003-06-04 13:59:38 +00002007 if (ripd_privs.change (ZPRIVS_LOWER))
2008 zlog_err ("rip_create_socket: could not lower privs");
2009
paul718e3742002-12-13 20:15:29 +00002010 return sock;
2011}
2012
2013/* Write routing table entry to the stream and return next index of
2014 the routing table entry in the stream. */
2015int
2016rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2017 u_char version, struct rip_info *rinfo, struct interface *ifp)
2018{
2019 struct in_addr mask;
2020 struct rip_interface *ri;
2021
2022 /* RIP packet header. */
2023 if (num == 0)
2024 {
2025 stream_putc (s, RIP_RESPONSE);
2026 stream_putc (s, version);
2027 stream_putw (s, 0);
2028
2029 /* In case of we need RIPv2 authentication. */
2030 if (version == RIPv2 && ifp)
2031 {
2032 ri = ifp->info;
2033
2034 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2035 {
2036 if (ri->auth_str)
2037 {
paulca5e5162004-06-06 22:06:33 +00002038 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002039 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2040
2041 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002042 strncpy ((char *)(s->data + s->putp), ri->auth_str, 16);
paul718e3742002-12-13 20:15:29 +00002043 stream_set_putp (s, s->putp + 16);
2044
2045 num++;
2046 }
2047 if (ri->key_chain)
2048 {
2049 struct keychain *keychain;
2050 struct key *key;
2051
2052 keychain = keychain_lookup (ri->key_chain);
2053
2054 if (keychain)
2055 {
2056 key = key_lookup_for_send (keychain);
2057
2058 if (key)
2059 {
paulca5e5162004-06-06 22:06:33 +00002060 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00002061 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
2062
2063 memset ((s->data + s->putp), 0, 16);
paul11dde9c2004-05-31 14:00:00 +00002064 strncpy ((char *)(s->data + s->putp),
2065 key->string, 16);
paul718e3742002-12-13 20:15:29 +00002066 stream_set_putp (s, s->putp + 16);
2067
2068 num++;
2069 }
2070 }
2071 }
2072 }
2073 }
2074 }
2075
2076 /* Write routing table entry. */
2077 if (version == RIPv1)
2078 {
2079 stream_putw (s, AF_INET);
2080 stream_putw (s, 0);
2081 stream_put_ipv4 (s, p->prefix.s_addr);
2082 stream_put_ipv4 (s, 0);
2083 stream_put_ipv4 (s, 0);
2084 stream_putl (s, rinfo->metric_out);
2085 }
2086 else
2087 {
2088 masklen2ip (p->prefixlen, &mask);
2089
2090 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002091 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002092 stream_put_ipv4 (s, p->prefix.s_addr);
2093 stream_put_ipv4 (s, mask.s_addr);
2094 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2095 stream_putl (s, rinfo->metric_out);
2096 }
2097
2098 return ++num;
2099}
2100
2101/* Send update to the ifp or spcified neighbor. */
2102void
paulc49ad8f2004-10-22 10:27:28 +00002103rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2104 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002105{
2106 int ret;
2107 struct stream *s;
2108 struct route_node *rp;
2109 struct rip_info *rinfo;
2110 struct rip_interface *ri;
2111 struct prefix_ipv4 *p;
2112 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002113 struct prefix_ipv4 ifaddrclass;
paul718e3742002-12-13 20:15:29 +00002114 int num;
2115 int rtemax;
paul01d09082003-06-08 21:22:18 +00002116 int subnetted = 0;
paul718e3742002-12-13 20:15:29 +00002117
2118 /* Logging output event. */
2119 if (IS_RIP_DEBUG_EVENT)
2120 {
2121 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002122 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002123 else
ajs5d6c3772004-12-08 19:24:06 +00002124 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002125 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002126 }
2127
2128 /* Set output stream. */
2129 s = rip->obuf;
2130
2131 /* Reset stream and RTE counter. */
2132 stream_reset (s);
2133 num = 0;
2134 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;
2135
2136 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002137 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002138
2139 /* If output interface is in simple password authentication mode, we
2140 need space for authentication data. */
2141 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2142 rtemax -= 1;
2143
2144 /* If output interface is in MD5 authentication mode, we need space
2145 for authentication header and data. */
2146 if (ri->auth_type == RIP_AUTH_MD5)
2147 rtemax -= 2;
2148
2149 /* If output interface is in simple password authentication mode
2150 and string or keychain is specified we need space for auth. data */
2151 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2152 {
2153 if (ri->key_chain)
2154 {
2155 struct keychain *keychain;
2156
2157 keychain = keychain_lookup (ri->key_chain);
2158 if (keychain)
2159 if (key_lookup_for_send (keychain))
2160 rtemax -=1;
2161 }
2162 else
2163 if (ri->auth_str)
2164 rtemax -=1;
2165 }
2166
paul727d1042002-12-13 20:50:29 +00002167 if (version == RIPv1)
2168 {
paulc49ad8f2004-10-22 10:27:28 +00002169 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002170 apply_classful_mask_ipv4 (&ifaddrclass);
2171 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002172 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002173 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002174 }
2175
paul718e3742002-12-13 20:15:29 +00002176 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2177 if ((rinfo = rp->info) != NULL)
2178 {
paul727d1042002-12-13 20:50:29 +00002179 /* For RIPv1, if we are subnetted, output subnets in our network */
2180 /* that have the same mask as the output "interface". For other */
2181 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002182
2183 if (version == RIPv1)
2184 {
paul727d1042002-12-13 20:50:29 +00002185 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002186
2187 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002188 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002189 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002190
paul727d1042002-12-13 20:50:29 +00002191 if (subnetted &&
2192 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2193 {
paulc49ad8f2004-10-22 10:27:28 +00002194 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002195 (rp->p.prefixlen != 32))
2196 continue;
2197 }
2198 else
2199 {
2200 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2201 apply_classful_mask_ipv4(&classfull);
2202 if (rp->p.u.prefix4.s_addr != 0 &&
2203 classfull.prefixlen != rp->p.prefixlen)
2204 continue;
2205 }
paul718e3742002-12-13 20:15:29 +00002206 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002207 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002208 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002209 }
2210 else
2211 p = (struct prefix_ipv4 *) &rp->p;
2212
2213 /* Apply output filters. */
2214 ret = rip_outgoing_filter (p, ri);
2215 if (ret < 0)
2216 continue;
2217
2218 /* Changed route only output. */
2219 if (route_type == rip_changed_route &&
2220 (! (rinfo->flags & RIP_RTF_CHANGED)))
2221 continue;
2222
2223 /* Split horizon. */
2224 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002225 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002226 {
paul42d14d92003-11-17 09:15:18 +00002227 /*
2228 * We perform split horizon for RIP and connected route.
2229 * For rip routes, we want to suppress the route if we would
2230 * end up sending the route back on the interface that we
2231 * learned it from, with a higher metric. For connected routes,
2232 * we suppress the route if the prefix is a subset of the
2233 * source address that we are going to use for the packet
2234 * (in order to handle the case when multiple subnets are
2235 * configured on the same interface).
2236 */
2237 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002238 rinfo->ifindex == ifc->ifp->ifindex)
paul42d14d92003-11-17 09:15:18 +00002239 continue;
2240 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002241 prefix_match((struct prefix *)p, ifc->address))
paul718e3742002-12-13 20:15:29 +00002242 continue;
2243 }
2244
2245 /* Preparation for route-map. */
2246 rinfo->metric_set = 0;
2247 rinfo->nexthop_out.s_addr = 0;
2248 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002249 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002250 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002251
hasso16705132003-05-25 14:49:19 +00002252 /* In order to avoid some local loops,
2253 * if the RIP route has a nexthop via this interface, keep the nexthop,
2254 * otherwise set it to 0. The nexthop should not be propagated
2255 * beyond the local broadcast/multicast area in order
2256 * to avoid an IGP multi-level recursive look-up.
2257 * see (4.4)
2258 */
paulc49ad8f2004-10-22 10:27:28 +00002259 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002260 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002261
2262 /* Interface route-map */
2263 if (ri->routemap[RIP_FILTER_OUT])
2264 {
2265 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2266 (struct prefix *) p, RMAP_RIP,
2267 rinfo);
2268
2269 if (ret == RMAP_DENYMATCH)
2270 {
2271 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002272 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002273 inet_ntoa (p->prefix), p->prefixlen);
2274 continue;
2275 }
2276 }
paul718e3742002-12-13 20:15:29 +00002277
hasso16705132003-05-25 14:49:19 +00002278 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002279 if (rip->route_map[rinfo->type].name
2280 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2281 {
2282 ret = route_map_apply (rip->route_map[rinfo->type].map,
2283 (struct prefix *)p, RMAP_RIP, rinfo);
2284
2285 if (ret == RMAP_DENYMATCH)
2286 {
2287 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002288 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002289 inet_ntoa (p->prefix), p->prefixlen);
2290 continue;
2291 }
2292 }
2293
2294 /* When route-map does not set metric. */
2295 if (! rinfo->metric_set)
2296 {
2297 /* If redistribute metric is set. */
2298 if (rip->route_map[rinfo->type].metric_config
2299 && rinfo->metric != RIP_METRIC_INFINITY)
2300 {
2301 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2302 }
2303 else
2304 {
2305 /* If the route is not connected or localy generated
2306 one, use default-metric value*/
2307 if (rinfo->type != ZEBRA_ROUTE_RIP
2308 && rinfo->type != ZEBRA_ROUTE_CONNECT
2309 && rinfo->metric != RIP_METRIC_INFINITY)
2310 rinfo->metric_out = rip->default_metric;
2311 }
2312 }
2313
2314 /* Apply offset-list */
2315 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002316 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002317
2318 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2319 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002320
2321 /* Perform split-horizon with poisoned reverse
2322 * for RIP and connected routes.
2323 **/
2324 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002325 /*
2326 * We perform split horizon for RIP and connected route.
2327 * For rip routes, we want to suppress the route if we would
2328 * end up sending the route back on the interface that we
2329 * learned it from, with a higher metric. For connected routes,
2330 * we suppress the route if the prefix is a subset of the
2331 * source address that we are going to use for the packet
2332 * (in order to handle the case when multiple subnets are
2333 * configured on the same interface).
2334 */
2335 if (rinfo->type == ZEBRA_ROUTE_RIP &&
paulc49ad8f2004-10-22 10:27:28 +00002336 rinfo->ifindex == ifc->ifp->ifindex)
hasso16705132003-05-25 14:49:19 +00002337 rinfo->metric_out = RIP_METRIC_INFINITY;
paul42d14d92003-11-17 09:15:18 +00002338 if (rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002339 prefix_match((struct prefix *)p, ifc->address))
paul42d14d92003-11-17 09:15:18 +00002340 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002341 }
2342
paul718e3742002-12-13 20:15:29 +00002343 /* Write RTE to the stream. */
paulc49ad8f2004-10-22 10:27:28 +00002344 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002345 if (num == rtemax)
2346 {
2347 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002348 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002349
2350 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002351 to, ifc);
paul718e3742002-12-13 20:15:29 +00002352
2353 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2354 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2355 stream_get_endp(s), "SEND");
2356 num = 0;
2357 stream_reset (s);
2358 }
2359 }
2360
2361 /* Flush unwritten RTE. */
2362 if (num != 0)
2363 {
2364 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulc49ad8f2004-10-22 10:27:28 +00002365 rip_auth_md5_set (s, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00002366
paulc49ad8f2004-10-22 10:27:28 +00002367 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002368
2369 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2370 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2371 stream_get_endp (s), "SEND");
2372 num = 0;
2373 stream_reset (s);
2374 }
2375
2376 /* Statistics updates. */
2377 ri->sent_updates++;
2378}
2379
2380/* Send RIP packet to the interface. */
2381void
paulc49ad8f2004-10-22 10:27:28 +00002382rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002383{
paul718e3742002-12-13 20:15:29 +00002384 struct sockaddr_in to;
2385
2386 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002387 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002388 {
2389 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002390 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002391
paulc49ad8f2004-10-22 10:27:28 +00002392 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002393 return;
2394 }
paulc49ad8f2004-10-22 10:27:28 +00002395
paul718e3742002-12-13 20:15:29 +00002396 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002397 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002398 {
paulc49ad8f2004-10-22 10:27:28 +00002399 if (ifc->address->family == AF_INET)
2400 {
2401 /* Destination address and port setting. */
2402 memset (&to, 0, sizeof (struct sockaddr_in));
2403 if (ifc->destination)
2404 /* use specified broadcast or point-to-point destination addr */
2405 to.sin_addr = ifc->destination->u.prefix4;
2406 else
2407 /* calculate the appropriate broadcast address */
2408 to.sin_addr.s_addr =
2409 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2410 ifc->address->prefixlen);
2411 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002412
paulc49ad8f2004-10-22 10:27:28 +00002413 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002414 zlog_debug ("%s announce to %s on %s",
paulc49ad8f2004-10-22 10:27:28 +00002415 if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
2416 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002417
paulc49ad8f2004-10-22 10:27:28 +00002418 rip_output_process (ifc, &to, route_type, version);
2419 }
paul718e3742002-12-13 20:15:29 +00002420 }
2421}
2422
2423/* Update send to all interface and neighbor. */
2424void
2425rip_update_process (int route_type)
2426{
hasso52dc7ee2004-09-23 19:18:23 +00002427 struct listnode *node, *ifnode;
paulcc1131a2003-10-15 23:20:17 +00002428 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002429 struct interface *ifp;
2430 struct rip_interface *ri;
2431 struct route_node *rp;
2432 struct sockaddr_in to;
2433 struct prefix_ipv4 *p;
2434
2435 /* Send RIP update to each interface. */
2436 for (node = listhead (iflist); node; nextnode (node))
2437 {
2438 ifp = getdata (node);
2439
2440 if (if_is_loopback (ifp))
2441 continue;
2442
paul2e3b2e42002-12-13 21:03:13 +00002443 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002444 continue;
2445
2446 /* Fetch RIP interface information. */
2447 ri = ifp->info;
2448
2449 /* When passive interface is specified, suppress announce to the
2450 interface. */
2451 if (ri->passive)
2452 continue;
2453
2454 if (ri->running)
2455 {
2456 if (IS_RIP_DEBUG_EVENT)
2457 {
2458 if (ifp->name)
ajs5d6c3772004-12-08 19:24:06 +00002459 zlog_debug ("SEND UPDATE to %s ifindex %d",
paul718e3742002-12-13 20:15:29 +00002460 ifp->name, ifp->ifindex);
2461 else
ajs5d6c3772004-12-08 19:24:06 +00002462 zlog_debug ("SEND UPDATE to _unknown_ ifindex %d",
paul718e3742002-12-13 20:15:29 +00002463 ifp->ifindex);
2464 }
2465
paulcc1131a2003-10-15 23:20:17 +00002466 /* send update on each connected network */
2467
2468 LIST_LOOP(ifp->connected, connected, ifnode)
2469 {
2470 struct prefix_ipv4 *ifaddr;
paul931cd542004-01-23 15:31:42 +00002471 int done = 0;
2472 /*
2473 * If there is no version configuration in the interface,
2474 * use rip's version setting.
2475 */
paulf38a4712003-06-07 01:10:00 +00002476 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2477 rip->version_send : ri->ri_send);
paulcc1131a2003-10-15 23:20:17 +00002478
2479 ifaddr = (struct prefix_ipv4 *) connected->address;
2480
2481 if (ifaddr->family != AF_INET)
2482 continue;
2483
paul931cd542004-01-23 15:31:42 +00002484 if ((vsend & RIPv1) && !done)
paulc49ad8f2004-10-22 10:27:28 +00002485 rip_update_interface (connected, RIPv1, route_type);
paul931cd542004-01-23 15:31:42 +00002486 if ((vsend & RIPv2) && if_is_multicast(ifp))
paulc49ad8f2004-10-22 10:27:28 +00002487 rip_update_interface (connected, RIPv2, route_type);
paul931cd542004-01-23 15:31:42 +00002488 done = 1;
2489 if (!(vsend & RIPv2) || !if_is_multicast(ifp))
2490 break;
2491
paulf38a4712003-06-07 01:10:00 +00002492 }
paul718e3742002-12-13 20:15:29 +00002493 }
2494 }
2495
2496 /* RIP send updates to each neighbor. */
2497 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2498 if (rp->info != NULL)
2499 {
2500 p = (struct prefix_ipv4 *) &rp->p;
2501
2502 ifp = if_lookup_address (p->prefix);
2503 if (! ifp)
2504 {
paulc49ad8f2004-10-22 10:27:28 +00002505 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002506 inet_ntoa (p->prefix));
2507 continue;
2508 }
paulc49ad8f2004-10-22 10:27:28 +00002509
2510 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2511 {
2512 zlog_warn ("Neighbor %s doesnt have connected network",
2513 inet_ntoa (p->prefix));
2514 continue;
2515 }
2516
paul718e3742002-12-13 20:15:29 +00002517 /* Set destination address and port */
2518 memset (&to, 0, sizeof (struct sockaddr_in));
2519 to.sin_addr = p->prefix;
2520 to.sin_port = htons (RIP_PORT_DEFAULT);
2521
2522 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002523 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002524 }
2525}
2526
2527/* RIP's periodical timer. */
2528int
2529rip_update (struct thread *t)
2530{
2531 /* Clear timer pointer. */
2532 rip->t_update = NULL;
2533
2534 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002535 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002536
2537 /* Process update output. */
2538 rip_update_process (rip_all_route);
2539
2540 /* Triggered updates may be suppressed if a regular update is due by
2541 the time the triggered update would be sent. */
2542 if (rip->t_triggered_interval)
2543 {
2544 thread_cancel (rip->t_triggered_interval);
2545 rip->t_triggered_interval = NULL;
2546 }
2547 rip->trigger = 0;
2548
2549 /* Register myself. */
2550 rip_event (RIP_UPDATE_EVENT, 0);
2551
2552 return 0;
2553}
2554
2555/* Walk down the RIP routing table then clear changed flag. */
2556void
2557rip_clear_changed_flag ()
2558{
2559 struct route_node *rp;
2560 struct rip_info *rinfo;
2561
2562 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2563 if ((rinfo = rp->info) != NULL)
2564 if (rinfo->flags & RIP_RTF_CHANGED)
2565 rinfo->flags &= ~RIP_RTF_CHANGED;
2566}
2567
2568/* Triggered update interval timer. */
2569int
2570rip_triggered_interval (struct thread *t)
2571{
2572 int rip_triggered_update (struct thread *);
2573
2574 rip->t_triggered_interval = NULL;
2575
2576 if (rip->trigger)
2577 {
2578 rip->trigger = 0;
2579 rip_triggered_update (t);
2580 }
2581 return 0;
2582}
2583
2584/* Execute triggered update. */
2585int
2586rip_triggered_update (struct thread *t)
2587{
2588 int interval;
2589
2590 /* Clear thred pointer. */
2591 rip->t_triggered_update = NULL;
2592
2593 /* Cancel interval timer. */
2594 if (rip->t_triggered_interval)
2595 {
2596 thread_cancel (rip->t_triggered_interval);
2597 rip->t_triggered_interval = NULL;
2598 }
2599 rip->trigger = 0;
2600
2601 /* Logging triggered update. */
2602 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002603 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002604
2605 /* Split Horizon processing is done when generating triggered
2606 updates as well as normal updates (see section 2.6). */
2607 rip_update_process (rip_changed_route);
2608
2609 /* Once all of the triggered updates have been generated, the route
2610 change flags should be cleared. */
2611 rip_clear_changed_flag ();
2612
2613 /* After a triggered update is sent, a timer should be set for a
2614 random interval between 1 and 5 seconds. If other changes that
2615 would trigger updates occur before the timer expires, a single
2616 update is triggered when the timer expires. */
2617 interval = (random () % 5) + 1;
2618
2619 rip->t_triggered_interval =
2620 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2621
2622 return 0;
2623}
2624
2625/* Withdraw redistributed route. */
2626void
2627rip_redistribute_withdraw (int type)
2628{
2629 struct route_node *rp;
2630 struct rip_info *rinfo;
2631
2632 if (!rip)
2633 return;
2634
2635 for (rp = route_top (rip->table); rp; rp = route_next (rp))
2636 if ((rinfo = rp->info) != NULL)
2637 {
2638 if (rinfo->type == type
2639 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2640 {
2641 /* Perform poisoned reverse. */
2642 rinfo->metric = RIP_METRIC_INFINITY;
2643 RIP_TIMER_ON (rinfo->t_garbage_collect,
2644 rip_garbage_collect, rip->garbage_time);
2645 RIP_TIMER_OFF (rinfo->t_timeout);
2646 rinfo->flags |= RIP_RTF_CHANGED;
2647
hasso16705132003-05-25 14:49:19 +00002648 if (IS_RIP_DEBUG_EVENT) {
2649 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2650
ajs5d6c3772004-12-08 19:24:06 +00002651 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002652 inet_ntoa(p->prefix), p->prefixlen,
2653 ifindex2ifname(rinfo->ifindex));
2654 }
2655
paul718e3742002-12-13 20:15:29 +00002656 rip_event (RIP_TRIGGERED_UPDATE, 0);
2657 }
2658 }
2659}
2660
2661/* Create new RIP instance and set it to global variable. */
2662int
2663rip_create ()
2664{
2665 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));
2666 memset (rip, 0, sizeof (struct rip));
2667
2668 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002669 rip->version_send = RI_RIP_VERSION_2;
2670 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002671 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2672 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2673 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2674 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2675
2676 /* Initialize RIP routig table. */
2677 rip->table = route_table_init ();
2678 rip->route = route_table_init ();
2679 rip->neighbor = route_table_init ();
2680
2681 /* Make output stream. */
2682 rip->obuf = stream_new (1500);
2683
2684 /* Make socket. */
2685 rip->sock = rip_create_socket ();
2686 if (rip->sock < 0)
2687 return rip->sock;
2688
2689 /* Create read and timer thread. */
2690 rip_event (RIP_READ, rip->sock);
2691 rip_event (RIP_UPDATE_EVENT, 1);
2692
2693 return 0;
2694}
2695
2696/* Sned RIP request to the destination. */
2697int
2698rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002699 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002700{
2701 struct rte *rte;
2702 struct rip_packet rip_packet;
hasso52dc7ee2004-09-23 19:18:23 +00002703 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002704
2705 memset (&rip_packet, 0, sizeof (rip_packet));
2706
2707 rip_packet.command = RIP_REQUEST;
2708 rip_packet.version = version;
2709 rte = rip_packet.rte;
2710 rte->metric = htonl (RIP_METRIC_INFINITY);
2711
paul931cd542004-01-23 15:31:42 +00002712 if (connected)
2713 {
2714 /*
2715 * connected is only sent for ripv1 case, or when
2716 * interface does not support multicast. Caller loops
2717 * over each connected address for this case.
2718 */
paul11dde9c2004-05-31 14:00:00 +00002719 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002720 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002721 return -1;
2722 else
2723 return sizeof (rip_packet);
2724 }
2725
paulcc1131a2003-10-15 23:20:17 +00002726 /* send request on each connected network */
2727 LIST_LOOP(ifp->connected, connected, node)
2728 {
2729 struct prefix_ipv4 *p;
2730
2731 p = (struct prefix_ipv4 *) connected->address;
2732
2733 if (p->family != AF_INET)
2734 continue;
2735
paul11dde9c2004-05-31 14:00:00 +00002736 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002737 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002738 return -1;
2739 }
2740 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002741}
2742
2743int
2744rip_update_jitter (unsigned long time)
2745{
paul239389b2004-05-05 14:09:37 +00002746#define JITTER_BOUND 4
2747 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2748 Given that, we cannot let time be less than JITTER_BOUND seconds.
2749 The RIPv2 RFC says jitter should be small compared to
2750 update_time. We consider 1/JITTER_BOUND to be small.
2751 */
2752
2753 int jitter_input = time;
2754 int jitter;
2755
2756 if (jitter_input < JITTER_BOUND)
2757 jitter_input = JITTER_BOUND;
2758
2759 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2760
2761 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002762}
2763
2764void
2765rip_event (enum rip_event event, int sock)
2766{
2767 int jitter = 0;
2768
2769 switch (event)
2770 {
2771 case RIP_READ:
2772 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2773 break;
2774 case RIP_UPDATE_EVENT:
2775 if (rip->t_update)
2776 {
2777 thread_cancel (rip->t_update);
2778 rip->t_update = NULL;
2779 }
2780 jitter = rip_update_jitter (rip->update_time);
2781 rip->t_update =
2782 thread_add_timer (master, rip_update, NULL,
2783 sock ? 2 : rip->update_time + jitter);
2784 break;
2785 case RIP_TRIGGERED_UPDATE:
2786 if (rip->t_triggered_interval)
2787 rip->trigger = 1;
2788 else if (! rip->t_triggered_update)
2789 rip->t_triggered_update =
2790 thread_add_event (master, rip_triggered_update, NULL, 0);
2791 break;
2792 default:
2793 break;
2794 }
2795}
2796
2797DEFUN (router_rip,
2798 router_rip_cmd,
2799 "router rip",
2800 "Enable a routing process\n"
2801 "Routing Information Protocol (RIP)\n")
2802{
2803 int ret;
2804
2805 /* If rip is not enabled before. */
2806 if (! rip)
2807 {
2808 ret = rip_create ();
2809 if (ret < 0)
2810 {
2811 zlog_info ("Can't create RIP");
2812 return CMD_WARNING;
2813 }
2814 }
2815 vty->node = RIP_NODE;
2816 vty->index = rip;
2817
2818 return CMD_SUCCESS;
2819}
2820
2821DEFUN (no_router_rip,
2822 no_router_rip_cmd,
2823 "no router rip",
2824 NO_STR
2825 "Enable a routing process\n"
2826 "Routing Information Protocol (RIP)\n")
2827{
2828 if (rip)
2829 rip_clean ();
2830 return CMD_SUCCESS;
2831}
2832
2833DEFUN (rip_version,
2834 rip_version_cmd,
2835 "version <1-2>",
2836 "Set routing protocol version\n"
2837 "version\n")
2838{
2839 int version;
2840
2841 version = atoi (argv[0]);
2842 if (version != RIPv1 && version != RIPv2)
2843 {
2844 vty_out (vty, "invalid rip version %d%s", version,
2845 VTY_NEWLINE);
2846 return CMD_WARNING;
2847 }
paulf38a4712003-06-07 01:10:00 +00002848 rip->version_send = version;
2849 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002850
2851 return CMD_SUCCESS;
2852}
2853
2854DEFUN (no_rip_version,
2855 no_rip_version_cmd,
2856 "no version",
2857 NO_STR
2858 "Set routing protocol version\n")
2859{
2860 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002861 rip->version_send = RI_RIP_VERSION_2;
2862 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002863
2864 return CMD_SUCCESS;
2865}
2866
2867ALIAS (no_rip_version,
2868 no_rip_version_val_cmd,
2869 "no version <1-2>",
2870 NO_STR
2871 "Set routing protocol version\n"
2872 "version\n")
2873
2874DEFUN (rip_route,
2875 rip_route_cmd,
2876 "route A.B.C.D/M",
2877 "RIP static route configuration\n"
2878 "IP prefix <network>/<length>\n")
2879{
2880 int ret;
2881 struct prefix_ipv4 p;
2882 struct route_node *node;
2883
2884 ret = str2prefix_ipv4 (argv[0], &p);
2885 if (ret < 0)
2886 {
2887 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2888 return CMD_WARNING;
2889 }
2890 apply_mask_ipv4 (&p);
2891
2892 /* For router rip configuration. */
2893 node = route_node_get (rip->route, (struct prefix *) &p);
2894
2895 if (node->info)
2896 {
2897 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2898 route_unlock_node (node);
2899 return CMD_WARNING;
2900 }
2901
hasso8a676be2004-10-08 06:36:38 +00002902 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00002903
2904 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
2905
2906 return CMD_SUCCESS;
2907}
2908
2909DEFUN (no_rip_route,
2910 no_rip_route_cmd,
2911 "no route A.B.C.D/M",
2912 NO_STR
2913 "RIP static route configuration\n"
2914 "IP prefix <network>/<length>\n")
2915{
2916 int ret;
2917 struct prefix_ipv4 p;
2918 struct route_node *node;
2919
2920 ret = str2prefix_ipv4 (argv[0], &p);
2921 if (ret < 0)
2922 {
2923 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2924 return CMD_WARNING;
2925 }
2926 apply_mask_ipv4 (&p);
2927
2928 /* For router rip configuration. */
2929 node = route_node_lookup (rip->route, (struct prefix *) &p);
2930 if (! node)
2931 {
2932 vty_out (vty, "Can't find route %s.%s", argv[0],
2933 VTY_NEWLINE);
2934 return CMD_WARNING;
2935 }
2936
2937 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
2938 route_unlock_node (node);
2939
2940 node->info = NULL;
2941 route_unlock_node (node);
2942
2943 return CMD_SUCCESS;
2944}
2945
2946void
2947rip_update_default_metric ()
2948{
2949 struct route_node *np;
2950 struct rip_info *rinfo;
2951
2952 for (np = route_top (rip->table); np; np = route_next (np))
2953 if ((rinfo = np->info) != NULL)
2954 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
2955 rinfo->metric = rip->default_metric;
2956}
2957
2958DEFUN (rip_default_metric,
2959 rip_default_metric_cmd,
2960 "default-metric <1-16>",
2961 "Set a metric of redistribute routes\n"
2962 "Default metric\n")
2963{
2964 if (rip)
2965 {
2966 rip->default_metric = atoi (argv[0]);
2967 /* rip_update_default_metric (); */
2968 }
2969 return CMD_SUCCESS;
2970}
2971
2972DEFUN (no_rip_default_metric,
2973 no_rip_default_metric_cmd,
2974 "no default-metric",
2975 NO_STR
2976 "Set a metric of redistribute routes\n"
2977 "Default metric\n")
2978{
2979 if (rip)
2980 {
2981 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2982 /* rip_update_default_metric (); */
2983 }
2984 return CMD_SUCCESS;
2985}
2986
2987ALIAS (no_rip_default_metric,
2988 no_rip_default_metric_val_cmd,
2989 "no default-metric <1-16>",
2990 NO_STR
2991 "Set a metric of redistribute routes\n"
2992 "Default metric\n")
2993
2994DEFUN (rip_timers,
2995 rip_timers_cmd,
2996 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
2997 "Adjust routing timers\n"
2998 "Basic routing protocol update timers\n"
2999 "Routing table update timer value in second. Default is 30.\n"
3000 "Routing information timeout timer. Default is 180.\n"
3001 "Garbage collection timer. Default is 120.\n")
3002{
3003 unsigned long update;
3004 unsigned long timeout;
3005 unsigned long garbage;
3006 char *endptr = NULL;
3007 unsigned long RIP_TIMER_MAX = 2147483647;
3008 unsigned long RIP_TIMER_MIN = 5;
3009
3010 update = strtoul (argv[0], &endptr, 10);
3011 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3012 {
3013 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3014 return CMD_WARNING;
3015 }
3016
3017 timeout = strtoul (argv[1], &endptr, 10);
3018 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3019 {
3020 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3021 return CMD_WARNING;
3022 }
3023
3024 garbage = strtoul (argv[2], &endptr, 10);
3025 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3026 {
3027 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3028 return CMD_WARNING;
3029 }
3030
3031 /* Set each timer value. */
3032 rip->update_time = update;
3033 rip->timeout_time = timeout;
3034 rip->garbage_time = garbage;
3035
3036 /* Reset update timer thread. */
3037 rip_event (RIP_UPDATE_EVENT, 0);
3038
3039 return CMD_SUCCESS;
3040}
3041
3042DEFUN (no_rip_timers,
3043 no_rip_timers_cmd,
3044 "no timers basic",
3045 NO_STR
3046 "Adjust routing timers\n"
3047 "Basic routing protocol update timers\n")
3048{
3049 /* Set each timer value to the default. */
3050 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3051 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3052 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3053
3054 /* Reset update timer thread. */
3055 rip_event (RIP_UPDATE_EVENT, 0);
3056
3057 return CMD_SUCCESS;
3058}
hasso16705132003-05-25 14:49:19 +00003059
3060ALIAS (no_rip_timers,
3061 no_rip_timers_val_cmd,
3062 "no timers basic <0-65535> <0-65535> <0-65535>",
3063 NO_STR
3064 "Adjust routing timers\n"
3065 "Basic routing protocol update timers\n"
3066 "Routing table update timer value in second. Default is 30.\n"
3067 "Routing information timeout timer. Default is 180.\n"
3068 "Garbage collection timer. Default is 120.\n")
3069
paul718e3742002-12-13 20:15:29 +00003070
3071struct route_table *rip_distance_table;
3072
3073struct rip_distance
3074{
3075 /* Distance value for the IP source prefix. */
3076 u_char distance;
3077
3078 /* Name of the access-list to be matched. */
3079 char *access_list;
3080};
3081
3082struct rip_distance *
3083rip_distance_new ()
3084{
3085 struct rip_distance *new;
3086 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3087 memset (new, 0, sizeof (struct rip_distance));
3088 return new;
3089}
3090
3091void
3092rip_distance_free (struct rip_distance *rdistance)
3093{
3094 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3095}
3096
3097int
hasso98b718a2004-10-11 12:57:57 +00003098rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3099 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003100{
3101 int ret;
3102 struct prefix_ipv4 p;
3103 u_char distance;
3104 struct route_node *rn;
3105 struct rip_distance *rdistance;
3106
3107 ret = str2prefix_ipv4 (ip_str, &p);
3108 if (ret == 0)
3109 {
3110 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3111 return CMD_WARNING;
3112 }
3113
3114 distance = atoi (distance_str);
3115
3116 /* Get RIP distance node. */
3117 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3118 if (rn->info)
3119 {
3120 rdistance = rn->info;
3121 route_unlock_node (rn);
3122 }
3123 else
3124 {
3125 rdistance = rip_distance_new ();
3126 rn->info = rdistance;
3127 }
3128
3129 /* Set distance value. */
3130 rdistance->distance = distance;
3131
3132 /* Reset access-list configuration. */
3133 if (rdistance->access_list)
3134 {
3135 free (rdistance->access_list);
3136 rdistance->access_list = NULL;
3137 }
3138 if (access_list_str)
3139 rdistance->access_list = strdup (access_list_str);
3140
3141 return CMD_SUCCESS;
3142}
3143
3144int
hasso98b718a2004-10-11 12:57:57 +00003145rip_distance_unset (struct vty *vty, const char *distance_str,
3146 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003147{
3148 int ret;
3149 struct prefix_ipv4 p;
3150 u_char distance;
3151 struct route_node *rn;
3152 struct rip_distance *rdistance;
3153
3154 ret = str2prefix_ipv4 (ip_str, &p);
3155 if (ret == 0)
3156 {
3157 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3158 return CMD_WARNING;
3159 }
3160
3161 distance = atoi (distance_str);
3162
3163 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3164 if (! rn)
3165 {
3166 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3167 return CMD_WARNING;
3168 }
3169
3170 rdistance = rn->info;
3171
3172 if (rdistance->access_list)
3173 free (rdistance->access_list);
3174 rip_distance_free (rdistance);
3175
3176 rn->info = NULL;
3177 route_unlock_node (rn);
3178 route_unlock_node (rn);
3179
3180 return CMD_SUCCESS;
3181}
3182
3183void
3184rip_distance_reset ()
3185{
3186 struct route_node *rn;
3187 struct rip_distance *rdistance;
3188
3189 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3190 if ((rdistance = rn->info) != NULL)
3191 {
3192 if (rdistance->access_list)
3193 free (rdistance->access_list);
3194 rip_distance_free (rdistance);
3195 rn->info = NULL;
3196 route_unlock_node (rn);
3197 }
3198}
3199
3200/* Apply RIP information to distance method. */
3201u_char
3202rip_distance_apply (struct rip_info *rinfo)
3203{
3204 struct route_node *rn;
3205 struct prefix_ipv4 p;
3206 struct rip_distance *rdistance;
3207 struct access_list *alist;
3208
3209 if (! rip)
3210 return 0;
3211
3212 memset (&p, 0, sizeof (struct prefix_ipv4));
3213 p.family = AF_INET;
3214 p.prefix = rinfo->from;
3215 p.prefixlen = IPV4_MAX_BITLEN;
3216
3217 /* Check source address. */
3218 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3219 if (rn)
3220 {
3221 rdistance = rn->info;
3222 route_unlock_node (rn);
3223
3224 if (rdistance->access_list)
3225 {
3226 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3227 if (alist == NULL)
3228 return 0;
3229 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3230 return 0;
3231
3232 return rdistance->distance;
3233 }
3234 else
3235 return rdistance->distance;
3236 }
3237
3238 if (rip->distance)
3239 return rip->distance;
3240
3241 return 0;
3242}
3243
3244void
3245rip_distance_show (struct vty *vty)
3246{
3247 struct route_node *rn;
3248 struct rip_distance *rdistance;
3249 int header = 1;
3250 char buf[BUFSIZ];
3251
3252 vty_out (vty, " Distance: (default is %d)%s",
3253 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3254 VTY_NEWLINE);
3255
3256 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3257 if ((rdistance = rn->info) != NULL)
3258 {
3259 if (header)
3260 {
3261 vty_out (vty, " Address Distance List%s",
3262 VTY_NEWLINE);
3263 header = 0;
3264 }
3265 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3266 vty_out (vty, " %-20s %4d %s%s",
3267 buf, rdistance->distance,
3268 rdistance->access_list ? rdistance->access_list : "",
3269 VTY_NEWLINE);
3270 }
3271}
3272
3273DEFUN (rip_distance,
3274 rip_distance_cmd,
3275 "distance <1-255>",
3276 "Administrative distance\n"
3277 "Distance value\n")
3278{
3279 rip->distance = atoi (argv[0]);
3280 return CMD_SUCCESS;
3281}
3282
3283DEFUN (no_rip_distance,
3284 no_rip_distance_cmd,
3285 "no distance <1-255>",
3286 NO_STR
3287 "Administrative distance\n"
3288 "Distance value\n")
3289{
3290 rip->distance = 0;
3291 return CMD_SUCCESS;
3292}
3293
3294DEFUN (rip_distance_source,
3295 rip_distance_source_cmd,
3296 "distance <1-255> A.B.C.D/M",
3297 "Administrative distance\n"
3298 "Distance value\n"
3299 "IP source prefix\n")
3300{
3301 rip_distance_set (vty, argv[0], argv[1], NULL);
3302 return CMD_SUCCESS;
3303}
3304
3305DEFUN (no_rip_distance_source,
3306 no_rip_distance_source_cmd,
3307 "no distance <1-255> A.B.C.D/M",
3308 NO_STR
3309 "Administrative distance\n"
3310 "Distance value\n"
3311 "IP source prefix\n")
3312{
3313 rip_distance_unset (vty, argv[0], argv[1], NULL);
3314 return CMD_SUCCESS;
3315}
3316
3317DEFUN (rip_distance_source_access_list,
3318 rip_distance_source_access_list_cmd,
3319 "distance <1-255> A.B.C.D/M WORD",
3320 "Administrative distance\n"
3321 "Distance value\n"
3322 "IP source prefix\n"
3323 "Access list name\n")
3324{
3325 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3326 return CMD_SUCCESS;
3327}
3328
3329DEFUN (no_rip_distance_source_access_list,
3330 no_rip_distance_source_access_list_cmd,
3331 "no distance <1-255> A.B.C.D/M WORD",
3332 NO_STR
3333 "Administrative distance\n"
3334 "Distance value\n"
3335 "IP source prefix\n"
3336 "Access list name\n")
3337{
3338 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3339 return CMD_SUCCESS;
3340}
3341
3342/* Print out routes update time. */
3343void
3344rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3345{
3346 struct timeval timer_now;
3347 time_t clock;
3348 struct tm *tm;
3349#define TIME_BUF 25
3350 char timebuf [TIME_BUF];
3351 struct thread *thread;
3352
3353 gettimeofday (&timer_now, NULL);
3354
3355 if ((thread = rinfo->t_timeout) != NULL)
3356 {
3357 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3358 tm = gmtime (&clock);
3359 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3360 vty_out (vty, "%5s", timebuf);
3361 }
3362 else if ((thread = rinfo->t_garbage_collect) != NULL)
3363 {
3364 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
3365 tm = gmtime (&clock);
3366 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3367 vty_out (vty, "%5s", timebuf);
3368 }
3369}
3370
hasso8a676be2004-10-08 06:36:38 +00003371const char *
paul718e3742002-12-13 20:15:29 +00003372rip_route_type_print (int sub_type)
3373{
3374 switch (sub_type)
3375 {
3376 case RIP_ROUTE_RTE:
3377 return "n";
3378 case RIP_ROUTE_STATIC:
3379 return "s";
3380 case RIP_ROUTE_DEFAULT:
3381 return "d";
3382 case RIP_ROUTE_REDISTRIBUTE:
3383 return "r";
3384 case RIP_ROUTE_INTERFACE:
3385 return "i";
3386 default:
3387 return "?";
3388 }
3389}
3390
3391DEFUN (show_ip_rip,
3392 show_ip_rip_cmd,
3393 "show ip rip",
3394 SHOW_STR
3395 IP_STR
3396 "Show RIP routes\n")
3397{
3398 struct route_node *np;
3399 struct rip_info *rinfo;
3400
3401 if (! rip)
3402 return CMD_SUCCESS;
3403
hasso16705132003-05-25 14:49:19 +00003404 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3405 "Sub-codes:%s"
3406 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003407 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003408 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003409 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003410
3411 for (np = route_top (rip->table); np; np = route_next (np))
3412 if ((rinfo = np->info) != NULL)
3413 {
3414 int len;
3415
3416 len = vty_out (vty, "%s(%s) %s/%d",
3417 /* np->lock, For debugging. */
3418 route_info[rinfo->type].str,
3419 rip_route_type_print (rinfo->sub_type),
3420 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3421
hassoa1455d82004-03-03 19:36:24 +00003422 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003423
3424 if (len > 0)
3425 vty_out (vty, "%*s", len, " ");
3426
3427 if (rinfo->nexthop.s_addr)
3428 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3429 rinfo->metric);
3430 else
3431 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3432
3433 /* Route which exist in kernel routing table. */
3434 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3435 (rinfo->sub_type == RIP_ROUTE_RTE))
3436 {
3437 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003438 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003439 rip_vty_out_uptime (vty, rinfo);
3440 }
3441 else if (rinfo->metric == RIP_METRIC_INFINITY)
3442 {
3443 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003444 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003445 rip_vty_out_uptime (vty, rinfo);
3446 }
3447 else
hasso16705132003-05-25 14:49:19 +00003448 {
3449 vty_out (vty, "self ");
3450 vty_out (vty, "%3d", rinfo->tag);
3451 }
paul718e3742002-12-13 20:15:29 +00003452
3453 vty_out (vty, "%s", VTY_NEWLINE);
3454 }
3455 return CMD_SUCCESS;
3456}
3457
3458/* Return next event time. */
3459int
3460rip_next_thread_timer (struct thread *thread)
3461{
3462 struct timeval timer_now;
3463
3464 gettimeofday (&timer_now, NULL);
3465
3466 return thread->u.sands.tv_sec - timer_now.tv_sec;
3467}
3468
hasso16705132003-05-25 14:49:19 +00003469/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3470DEFUN (show_ip_rip_status,
3471 show_ip_rip_status_cmd,
3472 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003473 SHOW_STR
3474 IP_STR
hasso16705132003-05-25 14:49:19 +00003475 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003476 "IP routing protocol process parameters and statistics\n")
3477{
hasso52dc7ee2004-09-23 19:18:23 +00003478 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003479 struct interface *ifp;
3480 struct rip_interface *ri;
3481 extern struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003482 const char *send_version;
3483 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003484
3485 if (! rip)
3486 return CMD_SUCCESS;
3487
3488 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3489 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3490 rip->update_time);
3491 vty_out (vty, " next due in %d seconds%s",
3492 rip_next_thread_timer (rip->t_update),
3493 VTY_NEWLINE);
3494 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3495 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3496 VTY_NEWLINE);
3497
3498 /* Filtering status show. */
3499 config_show_distribute (vty);
3500
3501 /* Default metric information. */
3502 vty_out (vty, " Default redistribution metric is %d%s",
3503 rip->default_metric, VTY_NEWLINE);
3504
3505 /* Redistribute information. */
3506 vty_out (vty, " Redistributing:");
3507 config_write_rip_redistribute (vty, 0);
3508 vty_out (vty, "%s", VTY_NEWLINE);
3509
paulf38a4712003-06-07 01:10:00 +00003510 vty_out (vty, " Default version control: send version %s,",
3511 lookup(ri_version_msg,rip->version_send));
3512 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3513 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3514 else
3515 vty_out (vty, " receive version %s %s",
3516 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003517
3518 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3519
3520 for (node = listhead (iflist); node; node = nextnode (node))
3521 {
3522 ifp = getdata (node);
3523 ri = ifp->info;
3524
3525 if (ri->enable_network || ri->enable_interface)
3526 {
3527 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003528 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003529 else
3530 send_version = lookup (ri_version_msg, ri->ri_send);
3531
3532 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003533 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003534 else
3535 receive_version = lookup (ri_version_msg, ri->ri_receive);
3536
3537 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3538 send_version,
3539 receive_version,
3540 ri->key_chain ? ri->key_chain : "",
3541 VTY_NEWLINE);
3542 }
3543 }
3544
3545 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3546 config_write_rip_network (vty, 0);
3547
paul4aaff3f2003-06-07 01:04:45 +00003548 {
3549 int found_passive = 0;
3550 for (node = listhead (iflist); node; node = nextnode (node))
3551 {
3552 ifp = getdata (node);
3553 ri = ifp->info;
3554
3555 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3556 {
3557 if (!found_passive)
3558 {
3559 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3560 found_passive = 1;
3561 }
3562 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3563 }
3564 }
3565 }
3566
paul718e3742002-12-13 20:15:29 +00003567 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3568 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3569 rip_peer_display (vty);
3570
3571 rip_distance_show (vty);
3572
3573 return CMD_SUCCESS;
3574}
3575
3576/* RIP configuration write function. */
3577int
3578config_write_rip (struct vty *vty)
3579{
3580 int write = 0;
3581 struct route_node *rn;
3582 struct rip_distance *rdistance;
3583
3584 if (rip)
3585 {
3586 /* Router RIP statement. */
3587 vty_out (vty, "router rip%s", VTY_NEWLINE);
3588 write++;
3589
3590 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003591 if (rip->version_send != RI_RIP_VERSION_2
3592 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3593 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003594 VTY_NEWLINE);
3595
3596 /* RIP timer configuration. */
3597 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3598 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3599 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3600 vty_out (vty, " timers basic %lu %lu %lu%s",
3601 rip->update_time,
3602 rip->timeout_time,
3603 rip->garbage_time,
3604 VTY_NEWLINE);
3605
3606 /* Default information configuration. */
3607 if (rip->default_information)
3608 {
3609 if (rip->default_information_route_map)
3610 vty_out (vty, " default-information originate route-map %s%s",
3611 rip->default_information_route_map, VTY_NEWLINE);
3612 else
3613 vty_out (vty, " default-information originate%s",
3614 VTY_NEWLINE);
3615 }
3616
3617 /* Redistribute configuration. */
3618 config_write_rip_redistribute (vty, 1);
3619
3620 /* RIP offset-list configuration. */
3621 config_write_rip_offset_list (vty);
3622
3623 /* RIP enabled network and interface configuration. */
3624 config_write_rip_network (vty, 1);
3625
3626 /* RIP default metric configuration */
3627 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3628 vty_out (vty, " default-metric %d%s",
3629 rip->default_metric, VTY_NEWLINE);
3630
3631 /* Distribute configuration. */
3632 write += config_write_distribute (vty);
3633
hasso16705132003-05-25 14:49:19 +00003634 /* Interface routemap configuration */
3635 write += config_write_if_rmap (vty);
3636
paul718e3742002-12-13 20:15:29 +00003637 /* Distance configuration. */
3638 if (rip->distance)
3639 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3640
3641 /* RIP source IP prefix distance configuration. */
3642 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3643 if ((rdistance = rn->info) != NULL)
3644 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3645 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3646 rdistance->access_list ? rdistance->access_list : "",
3647 VTY_NEWLINE);
3648
3649 /* RIP static route configuration. */
3650 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3651 if (rn->info)
3652 vty_out (vty, " route %s/%d%s",
3653 inet_ntoa (rn->p.u.prefix4),
3654 rn->p.prefixlen,
3655 VTY_NEWLINE);
3656
3657 }
3658 return write;
3659}
3660
3661/* RIP node structure. */
3662struct cmd_node rip_node =
3663{
3664 RIP_NODE,
3665 "%s(config-router)# ",
3666 1
3667};
3668
3669/* Distribute-list update functions. */
3670void
3671rip_distribute_update (struct distribute *dist)
3672{
3673 struct interface *ifp;
3674 struct rip_interface *ri;
3675 struct access_list *alist;
3676 struct prefix_list *plist;
3677
3678 if (! dist->ifname)
3679 return;
3680
3681 ifp = if_lookup_by_name (dist->ifname);
3682 if (ifp == NULL)
3683 return;
3684
3685 ri = ifp->info;
3686
3687 if (dist->list[DISTRIBUTE_IN])
3688 {
3689 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3690 if (alist)
3691 ri->list[RIP_FILTER_IN] = alist;
3692 else
3693 ri->list[RIP_FILTER_IN] = NULL;
3694 }
3695 else
3696 ri->list[RIP_FILTER_IN] = NULL;
3697
3698 if (dist->list[DISTRIBUTE_OUT])
3699 {
3700 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3701 if (alist)
3702 ri->list[RIP_FILTER_OUT] = alist;
3703 else
3704 ri->list[RIP_FILTER_OUT] = NULL;
3705 }
3706 else
3707 ri->list[RIP_FILTER_OUT] = NULL;
3708
3709 if (dist->prefix[DISTRIBUTE_IN])
3710 {
3711 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3712 if (plist)
3713 ri->prefix[RIP_FILTER_IN] = plist;
3714 else
3715 ri->prefix[RIP_FILTER_IN] = NULL;
3716 }
3717 else
3718 ri->prefix[RIP_FILTER_IN] = NULL;
3719
3720 if (dist->prefix[DISTRIBUTE_OUT])
3721 {
3722 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3723 if (plist)
3724 ri->prefix[RIP_FILTER_OUT] = plist;
3725 else
3726 ri->prefix[RIP_FILTER_OUT] = NULL;
3727 }
3728 else
3729 ri->prefix[RIP_FILTER_OUT] = NULL;
3730}
3731
3732void
3733rip_distribute_update_interface (struct interface *ifp)
3734{
3735 struct distribute *dist;
3736
3737 dist = distribute_lookup (ifp->name);
3738 if (dist)
3739 rip_distribute_update (dist);
3740}
3741
3742/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003743/* ARGSUSED */
paul718e3742002-12-13 20:15:29 +00003744void
paul02ff83c2004-06-11 11:27:03 +00003745rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003746{
3747 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003748 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003749
3750 for (node = listhead (iflist); node; nextnode (node))
3751 {
3752 ifp = getdata (node);
3753 rip_distribute_update_interface (ifp);
3754 }
3755}
paul11dde9c2004-05-31 14:00:00 +00003756/* ARGSUSED */
3757void
3758rip_distribute_update_all_wrapper(struct access_list *notused)
3759{
paul02ff83c2004-06-11 11:27:03 +00003760 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003761}
paul718e3742002-12-13 20:15:29 +00003762
3763/* Delete all added rip route. */
3764void
3765rip_clean ()
3766{
3767 int i;
3768 struct route_node *rp;
3769 struct rip_info *rinfo;
3770
3771 if (rip)
3772 {
3773 /* Clear RIP routes */
3774 for (rp = route_top (rip->table); rp; rp = route_next (rp))
3775 if ((rinfo = rp->info) != NULL)
3776 {
3777 if (rinfo->type == ZEBRA_ROUTE_RIP &&
3778 rinfo->sub_type == RIP_ROUTE_RTE)
3779 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
3780 &rinfo->nexthop, rinfo->metric);
3781
3782 RIP_TIMER_OFF (rinfo->t_timeout);
3783 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3784
3785 rp->info = NULL;
3786 route_unlock_node (rp);
3787
3788 rip_info_free (rinfo);
3789 }
3790
3791 /* Cancel RIP related timers. */
3792 RIP_TIMER_OFF (rip->t_update);
3793 RIP_TIMER_OFF (rip->t_triggered_update);
3794 RIP_TIMER_OFF (rip->t_triggered_interval);
3795
3796 /* Cancel read thread. */
3797 if (rip->t_read)
3798 {
3799 thread_cancel (rip->t_read);
3800 rip->t_read = NULL;
3801 }
3802
3803 /* Close RIP socket. */
3804 if (rip->sock >= 0)
3805 {
3806 close (rip->sock);
3807 rip->sock = -1;
3808 }
3809
3810 /* Static RIP route configuration. */
3811 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3812 if (rp->info)
3813 {
3814 rp->info = NULL;
3815 route_unlock_node (rp);
3816 }
3817
3818 /* RIP neighbor configuration. */
3819 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3820 if (rp->info)
3821 {
3822 rp->info = NULL;
3823 route_unlock_node (rp);
3824 }
3825
3826 /* Redistribute related clear. */
3827 if (rip->default_information_route_map)
3828 free (rip->default_information_route_map);
3829
3830 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3831 if (rip->route_map[i].name)
3832 free (rip->route_map[i].name);
3833
3834 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3835 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3836 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3837
3838 XFREE (MTYPE_RIP, rip);
3839 rip = NULL;
3840 }
3841
3842 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003843 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003844 rip_offset_clean ();
3845 rip_interface_clean ();
3846 rip_distance_reset ();
3847 rip_redistribute_clean ();
3848}
3849
3850/* Reset all values to the default settings. */
3851void
3852rip_reset ()
3853{
3854 /* Reset global counters. */
3855 rip_global_route_changes = 0;
3856 rip_global_queries = 0;
3857
3858 /* Call ripd related reset functions. */
3859 rip_debug_reset ();
3860 rip_route_map_reset ();
3861
3862 /* Call library reset functions. */
3863 vty_reset ();
3864 access_list_reset ();
3865 prefix_list_reset ();
3866
3867 distribute_list_reset ();
3868
3869 rip_interface_reset ();
3870 rip_distance_reset ();
3871
3872 rip_zclient_reset ();
3873}
3874
hasso16705132003-05-25 14:49:19 +00003875void
3876rip_if_rmap_update (struct if_rmap *if_rmap)
3877{
3878 struct interface *ifp;
3879 struct rip_interface *ri;
3880 struct route_map *rmap;
3881
3882 ifp = if_lookup_by_name (if_rmap->ifname);
3883 if (ifp == NULL)
3884 return;
3885
3886 ri = ifp->info;
3887
3888 if (if_rmap->routemap[IF_RMAP_IN])
3889 {
3890 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
3891 if (rmap)
3892 ri->routemap[IF_RMAP_IN] = rmap;
3893 else
3894 ri->routemap[IF_RMAP_IN] = NULL;
3895 }
3896 else
3897 ri->routemap[RIP_FILTER_IN] = NULL;
3898
3899 if (if_rmap->routemap[IF_RMAP_OUT])
3900 {
3901 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
3902 if (rmap)
3903 ri->routemap[IF_RMAP_OUT] = rmap;
3904 else
3905 ri->routemap[IF_RMAP_OUT] = NULL;
3906 }
3907 else
3908 ri->routemap[RIP_FILTER_OUT] = NULL;
3909}
3910
3911void
3912rip_if_rmap_update_interface (struct interface *ifp)
3913{
3914 struct if_rmap *if_rmap;
3915
3916 if_rmap = if_rmap_lookup (ifp->name);
3917 if (if_rmap)
3918 rip_if_rmap_update (if_rmap);
3919}
3920
3921void
3922rip_routemap_update_redistribute (void)
3923{
3924 int i;
3925
3926 if (rip)
3927 {
3928 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3929 {
3930 if (rip->route_map[i].name)
3931 rip->route_map[i].map =
3932 route_map_lookup_by_name (rip->route_map[i].name);
3933 }
3934 }
3935}
3936
paul11dde9c2004-05-31 14:00:00 +00003937/* ARGSUSED */
hasso16705132003-05-25 14:49:19 +00003938void
hasso98b718a2004-10-11 12:57:57 +00003939rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00003940{
3941 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00003942 struct listnode *node;
hasso16705132003-05-25 14:49:19 +00003943
3944 for (node = listhead (iflist); node; nextnode (node))
3945 {
3946 ifp = getdata (node);
3947 rip_if_rmap_update_interface (ifp);
3948 }
3949
3950 rip_routemap_update_redistribute ();
3951}
3952
paul718e3742002-12-13 20:15:29 +00003953/* Allocate new rip structure and set default value. */
3954void
3955rip_init ()
3956{
3957 /* Randomize for triggered update random(). */
3958 srand (time (NULL));
3959
3960 /* Install top nodes. */
3961 install_node (&rip_node, config_write_rip);
3962
3963 /* Install rip commands. */
3964 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003965 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003966 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00003967 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00003968 install_element (CONFIG_NODE, &router_rip_cmd);
3969 install_element (CONFIG_NODE, &no_router_rip_cmd);
3970
3971 install_default (RIP_NODE);
3972 install_element (RIP_NODE, &rip_version_cmd);
3973 install_element (RIP_NODE, &no_rip_version_cmd);
3974 install_element (RIP_NODE, &no_rip_version_val_cmd);
3975 install_element (RIP_NODE, &rip_default_metric_cmd);
3976 install_element (RIP_NODE, &no_rip_default_metric_cmd);
3977 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
3978 install_element (RIP_NODE, &rip_timers_cmd);
3979 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00003980 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003981 install_element (RIP_NODE, &rip_route_cmd);
3982 install_element (RIP_NODE, &no_rip_route_cmd);
3983 install_element (RIP_NODE, &rip_distance_cmd);
3984 install_element (RIP_NODE, &no_rip_distance_cmd);
3985 install_element (RIP_NODE, &rip_distance_source_cmd);
3986 install_element (RIP_NODE, &no_rip_distance_source_cmd);
3987 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
3988 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
3989
3990 /* Debug related init. */
3991 rip_debug_init ();
3992
paul718e3742002-12-13 20:15:29 +00003993 /* SNMP init. */
3994#ifdef HAVE_SNMP
3995 rip_snmp_init ();
3996#endif /* HAVE_SNMP */
3997
3998 /* Access list install. */
3999 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004000 access_list_add_hook (rip_distribute_update_all_wrapper);
4001 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004002
4003 /* Prefix list initialize.*/
4004 prefix_list_init ();
4005 prefix_list_add_hook (rip_distribute_update_all);
4006 prefix_list_delete_hook (rip_distribute_update_all);
4007
4008 /* Distribute list install. */
4009 distribute_list_init (RIP_NODE);
4010 distribute_list_add_hook (rip_distribute_update);
4011 distribute_list_delete_hook (rip_distribute_update);
4012
hasso16705132003-05-25 14:49:19 +00004013 /* Route-map */
4014 rip_route_map_init ();
4015 rip_offset_init ();
4016
4017 route_map_add_hook (rip_routemap_update);
4018 route_map_delete_hook (rip_routemap_update);
4019
4020 if_rmap_init (RIP_NODE);
4021 if_rmap_hook_add (rip_if_rmap_update);
4022 if_rmap_hook_delete (rip_if_rmap_update);
4023
paul718e3742002-12-13 20:15:29 +00004024 /* Distance control. */
4025 rip_distance_table = route_table_init ();
4026}