blob: b00241c9b031e269abd78d1d3cf4df3a99bbab70 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIP version 1 and 2.
vincentfbf5d032005-09-29 11:25:50 +00002 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "command.h"
27#include "prefix.h"
28#include "table.h"
29#include "thread.h"
30#include "memory.h"
31#include "log.h"
32#include "stream.h"
33#include "filter.h"
34#include "sockunion.h"
hasso1af81932004-09-26 16:11:14 +000035#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000036#include "routemap.h"
hasso16705132003-05-25 14:49:19 +000037#include "if_rmap.h"
paul718e3742002-12-13 20:15:29 +000038#include "plist.h"
39#include "distribute.h"
vincentc1a03d42005-09-28 15:47:44 +000040#include "md5.h"
paul718e3742002-12-13 20:15:29 +000041#include "keychain.h"
pauledd7c242003-06-04 13:59:38 +000042#include "privs.h"
paul718e3742002-12-13 20:15:29 +000043
44#include "ripd/ripd.h"
45#include "ripd/rip_debug.h"
46
paul0b3acf42004-09-17 08:39:08 +000047/* UDP receive buffer size */
48#define RIP_UDP_RCV_BUF 41600
49
50/* privileges global */
pauledd7c242003-06-04 13:59:38 +000051extern struct zebra_privs_t ripd_privs;
52
paul718e3742002-12-13 20:15:29 +000053/* RIP Structure. */
54struct rip *rip = NULL;
55
56/* RIP neighbor address table. */
57struct route_table *rip_neighbor_table;
58
59/* RIP route changes. */
60long rip_global_route_changes = 0;
61
62/* RIP queries. */
63long rip_global_queries = 0;
David Lamparter6b0655a2014-06-04 06:53:35 +020064
paul718e3742002-12-13 20:15:29 +000065/* Prototypes. */
pauldc63bfd2005-10-25 23:31:05 +000066static void rip_event (enum rip_event, int);
67static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
68static int rip_triggered_update (struct thread *);
69static int rip_update_jitter (unsigned long);
David Lamparter6b0655a2014-06-04 06:53:35 +020070
paul718e3742002-12-13 20:15:29 +000071/* RIP output routes type. */
72enum
73{
74 rip_all_route,
75 rip_changed_route
76};
David Lamparter6b0655a2014-06-04 06:53:35 +020077
paul718e3742002-12-13 20:15:29 +000078/* RIP command strings. */
Stephen Hemminger1423c802008-08-14 17:59:25 +010079static const struct message rip_msg[] =
paul718e3742002-12-13 20:15:29 +000080{
81 {RIP_REQUEST, "REQUEST"},
82 {RIP_RESPONSE, "RESPONSE"},
83 {RIP_TRACEON, "TRACEON"},
84 {RIP_TRACEOFF, "TRACEOFF"},
85 {RIP_POLL, "POLL"},
86 {RIP_POLL_ENTRY, "POLL ENTRY"},
Stephen Hemminger1423c802008-08-14 17:59:25 +010087 {0, NULL},
paul718e3742002-12-13 20:15:29 +000088};
David Lamparter6b0655a2014-06-04 06:53:35 +020089
paul718e3742002-12-13 20:15:29 +000090/* Utility function to set boradcast option to the socket. */
pauldc63bfd2005-10-25 23:31:05 +000091static int
paul718e3742002-12-13 20:15:29 +000092sockopt_broadcast (int sock)
93{
94 int ret;
95 int on = 1;
96
97 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
98 if (ret < 0)
99 {
100 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
101 return -1;
102 }
103 return 0;
104}
105
pauldc63bfd2005-10-25 23:31:05 +0000106static int
paul718e3742002-12-13 20:15:29 +0000107rip_route_rte (struct rip_info *rinfo)
108{
109 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
110}
111
pauldc63bfd2005-10-25 23:31:05 +0000112static struct rip_info *
Stephen Hemminger393deb92008-08-18 14:13:29 -0700113rip_info_new (void)
paul718e3742002-12-13 20:15:29 +0000114{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700115 return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
paul718e3742002-12-13 20:15:29 +0000116}
117
118void
119rip_info_free (struct rip_info *rinfo)
120{
121 XFREE (MTYPE_RIP_INFO, rinfo);
122}
123
124/* RIP route garbage collect timer. */
pauldc63bfd2005-10-25 23:31:05 +0000125static int
paul718e3742002-12-13 20:15:29 +0000126rip_garbage_collect (struct thread *t)
127{
128 struct rip_info *rinfo;
129 struct route_node *rp;
130
131 rinfo = THREAD_ARG (t);
132 rinfo->t_garbage_collect = NULL;
133
134 /* Off timeout timer. */
135 RIP_TIMER_OFF (rinfo->t_timeout);
136
137 /* Get route_node pointer. */
138 rp = rinfo->rp;
139
140 /* Unlock route_node. */
Lu Fengb397cf42014-07-18 06:13:18 +0000141 listnode_delete (rp->info, rinfo);
142 if (list_isempty ((struct list *)rp->info))
143 {
144 list_free (rp->info);
145 rp->info = NULL;
146 route_unlock_node (rp);
147 }
paul718e3742002-12-13 20:15:29 +0000148
149 /* Free RIP routing information. */
150 rip_info_free (rinfo);
151
152 return 0;
153}
154
Lu Fengb397cf42014-07-18 06:13:18 +0000155static void rip_timeout_update (struct rip_info *rinfo);
156
157/* Add new route to the ECMP list.
158 * RETURN: the new entry added in the list
159 */
160struct rip_info *
161rip_ecmp_add (struct rip_info *rinfo_new)
162{
163 struct route_node *rp = rinfo_new->rp;
164 struct rip_info *rinfo = NULL;
165 struct list *list = NULL;
166
167 if (rp->info == NULL)
168 rp->info = list_new ();
169 list = (struct list *)rp->info;
170
171 rinfo = rip_info_new ();
172 memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
173 listnode_add (list, rinfo);
174
175 if (rip_route_rte (rinfo))
176 {
177 rip_timeout_update (rinfo);
178 rip_zebra_ipv4_add (rp);
179 }
180
181 /* Set the route change flag on the first entry. */
182 rinfo = listgetdata (listhead (list));
183 SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
184
185 /* Signal the output process to trigger an update (see section 2.5). */
186 rip_event (RIP_TRIGGERED_UPDATE, 0);
187
188 return rinfo;
189}
190
191/* Replace the ECMP list with the new route.
192 * RETURN: the new entry added in the list
193 */
194struct rip_info *
195rip_ecmp_replace (struct rip_info *rinfo_new)
196{
197 struct route_node *rp = rinfo_new->rp;
198 struct list *list = (struct list *)rp->info;
199 struct rip_info *rinfo = NULL, *tmp_rinfo = NULL;
200 struct listnode *node = NULL, *nextnode = NULL;
201
202 if (list == NULL || listcount (list) == 0)
203 return rip_ecmp_add (rinfo_new);
204
205 /* Get the first entry */
206 rinfo = listgetdata (listhead (list));
207
208 /* Learnt route replaced by a local one. Delete it from zebra. */
209 if (rip_route_rte (rinfo) && !rip_route_rte (rinfo_new))
210 if (CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
211 rip_zebra_ipv4_delete (rp);
212
213 /* Re-use the first entry, and delete the others. */
214 for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
215 if (tmp_rinfo != rinfo)
216 {
217 RIP_TIMER_OFF (tmp_rinfo->t_timeout);
218 RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
219 list_delete_node (list, node);
220 rip_info_free (tmp_rinfo);
221 }
222
223 RIP_TIMER_OFF (rinfo->t_timeout);
224 RIP_TIMER_OFF (rinfo->t_garbage_collect);
225 memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
226
227 if (rip_route_rte (rinfo))
228 {
229 rip_timeout_update (rinfo);
230 /* The ADD message implies an update. */
231 rip_zebra_ipv4_add (rp);
232 }
233
234 /* Set the route change flag. */
235 SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
236
237 /* Signal the output process to trigger an update (see section 2.5). */
238 rip_event (RIP_TRIGGERED_UPDATE, 0);
239
240 return rinfo;
241}
242
243/* Delete one route from the ECMP list.
244 * RETURN:
245 * null - the entry is freed, and other entries exist in the list
246 * the entry - the entry is the last one in the list; its metric is set
247 * to INFINITY, and the garbage collector is started for it
248 */
249struct rip_info *
250rip_ecmp_delete (struct rip_info *rinfo)
251{
252 struct route_node *rp = rinfo->rp;
253 struct list *list = (struct list *)rp->info;
254
255 RIP_TIMER_OFF (rinfo->t_timeout);
256
257 if (listcount (list) > 1)
258 {
259 /* Some other ECMP entries still exist. Just delete this entry. */
260 RIP_TIMER_OFF (rinfo->t_garbage_collect);
261 listnode_delete (list, rinfo);
262 if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
263 /* The ADD message implies the update. */
264 rip_zebra_ipv4_add (rp);
265 rip_info_free (rinfo);
266 rinfo = NULL;
267 }
268 else
269 {
270 assert (rinfo == listgetdata (listhead (list)));
271
272 /* This is the only entry left in the list. We must keep it in
273 * the list for garbage collection time, with INFINITY metric. */
274
275 rinfo->metric = RIP_METRIC_INFINITY;
276 RIP_TIMER_ON (rinfo->t_garbage_collect,
277 rip_garbage_collect, rip->garbage_time);
278
279 if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
280 rip_zebra_ipv4_delete (rp);
281 }
282
283 /* Set the route change flag on the first entry. */
284 rinfo = listgetdata (listhead (list));
285 SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
286
287 /* Signal the output process to trigger an update (see section 2.5). */
288 rip_event (RIP_TRIGGERED_UPDATE, 0);
289
290 return rinfo;
291}
292
paul718e3742002-12-13 20:15:29 +0000293/* Timeout RIP routes. */
pauldc63bfd2005-10-25 23:31:05 +0000294static int
paul718e3742002-12-13 20:15:29 +0000295rip_timeout (struct thread *t)
296{
Lu Fengb397cf42014-07-18 06:13:18 +0000297 rip_ecmp_delete ((struct rip_info *)THREAD_ARG (t));
paul718e3742002-12-13 20:15:29 +0000298 return 0;
299}
300
pauldc63bfd2005-10-25 23:31:05 +0000301static void
paul718e3742002-12-13 20:15:29 +0000302rip_timeout_update (struct rip_info *rinfo)
303{
304 if (rinfo->metric != RIP_METRIC_INFINITY)
305 {
306 RIP_TIMER_OFF (rinfo->t_timeout);
307 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
308 }
309}
310
pauldc63bfd2005-10-25 23:31:05 +0000311static int
paul718e3742002-12-13 20:15:29 +0000312rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
313{
314 struct distribute *dist;
315 struct access_list *alist;
316 struct prefix_list *plist;
317
318 /* Input distribute-list filtering. */
319 if (ri->list[RIP_FILTER_IN])
320 {
321 if (access_list_apply (ri->list[RIP_FILTER_IN],
322 (struct prefix *) p) == FILTER_DENY)
323 {
324 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000325 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000326 inet_ntoa (p->prefix), p->prefixlen);
327 return -1;
328 }
329 }
330 if (ri->prefix[RIP_FILTER_IN])
331 {
332 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
333 (struct prefix *) p) == PREFIX_DENY)
334 {
335 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000336 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000337 inet_ntoa (p->prefix), p->prefixlen);
338 return -1;
339 }
340 }
341
342 /* All interface filter check. */
343 dist = distribute_lookup (NULL);
344 if (dist)
345 {
346 if (dist->list[DISTRIBUTE_IN])
347 {
348 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
349
350 if (alist)
351 {
352 if (access_list_apply (alist,
353 (struct prefix *) p) == FILTER_DENY)
354 {
355 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000356 zlog_debug ("%s/%d filtered by distribute in",
paul718e3742002-12-13 20:15:29 +0000357 inet_ntoa (p->prefix), p->prefixlen);
358 return -1;
359 }
360 }
361 }
362 if (dist->prefix[DISTRIBUTE_IN])
363 {
364 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
365
366 if (plist)
367 {
368 if (prefix_list_apply (plist,
369 (struct prefix *) p) == PREFIX_DENY)
370 {
371 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000372 zlog_debug ("%s/%d filtered by prefix-list in",
paul718e3742002-12-13 20:15:29 +0000373 inet_ntoa (p->prefix), p->prefixlen);
374 return -1;
375 }
376 }
377 }
378 }
379 return 0;
380}
381
pauldc63bfd2005-10-25 23:31:05 +0000382static int
paul718e3742002-12-13 20:15:29 +0000383rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
384{
385 struct distribute *dist;
386 struct access_list *alist;
387 struct prefix_list *plist;
388
389 if (ri->list[RIP_FILTER_OUT])
390 {
391 if (access_list_apply (ri->list[RIP_FILTER_OUT],
392 (struct prefix *) p) == FILTER_DENY)
393 {
394 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000395 zlog_debug ("%s/%d is filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000396 inet_ntoa (p->prefix), p->prefixlen);
397 return -1;
398 }
399 }
400 if (ri->prefix[RIP_FILTER_OUT])
401 {
402 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
403 (struct prefix *) p) == PREFIX_DENY)
404 {
405 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000406 zlog_debug ("%s/%d is filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000407 inet_ntoa (p->prefix), p->prefixlen);
408 return -1;
409 }
410 }
411
412 /* All interface filter check. */
413 dist = distribute_lookup (NULL);
414 if (dist)
415 {
416 if (dist->list[DISTRIBUTE_OUT])
417 {
418 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
419
420 if (alist)
421 {
422 if (access_list_apply (alist,
423 (struct prefix *) p) == FILTER_DENY)
424 {
425 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000426 zlog_debug ("%s/%d filtered by distribute out",
paul718e3742002-12-13 20:15:29 +0000427 inet_ntoa (p->prefix), p->prefixlen);
428 return -1;
429 }
430 }
431 }
432 if (dist->prefix[DISTRIBUTE_OUT])
433 {
434 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
435
436 if (plist)
437 {
438 if (prefix_list_apply (plist,
439 (struct prefix *) p) == PREFIX_DENY)
440 {
441 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000442 zlog_debug ("%s/%d filtered by prefix-list out",
paul718e3742002-12-13 20:15:29 +0000443 inet_ntoa (p->prefix), p->prefixlen);
444 return -1;
445 }
446 }
447 }
448 }
449 return 0;
450}
451
452/* Check nexthop address validity. */
453static int
454rip_nexthop_check (struct in_addr *addr)
455{
hasso52dc7ee2004-09-23 19:18:23 +0000456 struct listnode *node;
457 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000458 struct interface *ifp;
459 struct connected *ifc;
460 struct prefix *p;
461
462 /* If nexthop address matches local configured address then it is
463 invalid nexthop. */
paul1eb8ef22005-04-07 07:30:20 +0000464 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000465 {
paul1eb8ef22005-04-07 07:30:20 +0000466 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
paul718e3742002-12-13 20:15:29 +0000467 {
paul718e3742002-12-13 20:15:29 +0000468 p = ifc->address;
469
470 if (p->family == AF_INET
471 && IPV4_ADDR_SAME (&p->u.prefix4, addr))
472 return -1;
473 }
474 }
475 return 0;
476}
477
478/* RIP add route to routing table. */
pauldc63bfd2005-10-25 23:31:05 +0000479static void
paul718e3742002-12-13 20:15:29 +0000480rip_rte_process (struct rte *rte, struct sockaddr_in *from,
paula87552c2004-05-03 20:00:17 +0000481 struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000482{
483 int ret;
484 struct prefix_ipv4 p;
485 struct route_node *rp;
Lu Fengb397cf42014-07-18 06:13:18 +0000486 struct rip_info *rinfo = NULL, newinfo;
paul718e3742002-12-13 20:15:29 +0000487 struct rip_interface *ri;
488 struct in_addr *nexthop;
paul718e3742002-12-13 20:15:29 +0000489 int same = 0;
vincentfbf5d032005-09-29 11:25:50 +0000490 unsigned char old_dist, new_dist;
Lu Fengb397cf42014-07-18 06:13:18 +0000491 struct list *list = NULL;
492 struct listnode *node = NULL;
paul718e3742002-12-13 20:15:29 +0000493
494 /* Make prefix structure. */
495 memset (&p, 0, sizeof (struct prefix_ipv4));
496 p.family = AF_INET;
497 p.prefix = rte->prefix;
498 p.prefixlen = ip_masklen (rte->mask);
499
500 /* Make sure mask is applied. */
501 apply_mask_ipv4 (&p);
502
503 /* Apply input filters. */
504 ri = ifp->info;
505
506 ret = rip_incoming_filter (&p, ri);
507 if (ret < 0)
508 return;
509
Lu Fengb397cf42014-07-18 06:13:18 +0000510 memset (&newinfo, 0, sizeof (newinfo));
511 newinfo.type = ZEBRA_ROUTE_RIP;
512 newinfo.sub_type = RIP_ROUTE_RTE;
513 newinfo.nexthop = rte->nexthop;
514 newinfo.from = from->sin_addr;
515 newinfo.ifindex = ifp->ifindex;
516 newinfo.metric = rte->metric;
517 newinfo.metric_out = rte->metric; /* XXX */
518 newinfo.tag = ntohs (rte->tag); /* XXX */
519
hasso16705132003-05-25 14:49:19 +0000520 /* Modify entry according to the interface routemap. */
521 if (ri->routemap[RIP_FILTER_IN])
522 {
523 int ret;
hasso16705132003-05-25 14:49:19 +0000524
525 /* The object should be of the type of rip_info */
paula87552c2004-05-03 20:00:17 +0000526 ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
527 (struct prefix *) &p, RMAP_RIP, &newinfo);
hasso16705132003-05-25 14:49:19 +0000528
529 if (ret == RMAP_DENYMATCH)
paula87552c2004-05-03 20:00:17 +0000530 {
531 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000532 zlog_debug ("RIP %s/%d is filtered by route-map in",
paula87552c2004-05-03 20:00:17 +0000533 inet_ntoa (p.prefix), p.prefixlen);
534 return;
535 }
hasso16705132003-05-25 14:49:19 +0000536
537 /* Get back the object */
paula87552c2004-05-03 20:00:17 +0000538 rte->nexthop = newinfo.nexthop_out;
539 rte->tag = htons (newinfo.tag_out); /* XXX */
540 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
hasso16705132003-05-25 14:49:19 +0000541 }
542
paul718e3742002-12-13 20:15:29 +0000543 /* Once the entry has been validated, update the metric by
544 adding the cost of the network on wich the message
545 arrived. If the result is greater than infinity, use infinity
546 (RFC2453 Sec. 3.9.2) */
547 /* Zebra ripd can handle offset-list in. */
548 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
549
550 /* If offset-list does not modify the metric use interface's
551 metric. */
paula87552c2004-05-03 20:00:17 +0000552 if (!ret)
Lu Feng7b3b98a2014-04-14 08:09:29 +0000553 rte->metric += ifp->metric ? ifp->metric : 1;
paul718e3742002-12-13 20:15:29 +0000554
555 if (rte->metric > RIP_METRIC_INFINITY)
556 rte->metric = RIP_METRIC_INFINITY;
557
558 /* Set nexthop pointer. */
559 if (rte->nexthop.s_addr == 0)
560 nexthop = &from->sin_addr;
561 else
562 nexthop = &rte->nexthop;
563
hasso16705132003-05-25 14:49:19 +0000564 /* Check if nexthop address is myself, then do nothing. */
paul718e3742002-12-13 20:15:29 +0000565 if (rip_nexthop_check (nexthop) < 0)
566 {
567 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +0000568 zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
paul718e3742002-12-13 20:15:29 +0000569 return;
570 }
571
572 /* Get index for the prefix. */
573 rp = route_node_get (rip->table, (struct prefix *) &p);
574
Lu Fengb397cf42014-07-18 06:13:18 +0000575 newinfo.rp = rp;
576 newinfo.nexthop = *nexthop;
577 newinfo.metric = rte->metric;
578 newinfo.tag = ntohs (rte->tag);
579 newinfo.distance = rip_distance_apply (&newinfo);
580
581 new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT;
582
paul718e3742002-12-13 20:15:29 +0000583 /* Check to see whether there is already RIP route on the table. */
Lu Fengb397cf42014-07-18 06:13:18 +0000584 if ((list = rp->info) != NULL)
585 for (ALL_LIST_ELEMENTS_RO (list, node, rinfo))
586 {
587 /* Need to compare with redistributed entry or local entry */
588 if (!rip_route_rte (rinfo))
589 break;
590
591 if (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) &&
592 IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
593 break;
594
595 if (!listnextnode (node))
596 {
597 /* Not found in the list */
598
599 if (rte->metric > rinfo->metric)
600 {
601 /* New route has a greater metric. Discard it. */
602 route_unlock_node (rp);
603 return;
604 }
605
606 if (rte->metric < rinfo->metric)
607 /* New route has a smaller metric. Replace the ECMP list
608 * with the new one in below. */
609 break;
610
611 /* Metrics are same. We compare the distances. */
612 old_dist = rinfo->distance ? \
613 rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
614
615 if (new_dist > old_dist)
616 {
617 /* New route has a greater distance. Discard it. */
618 route_unlock_node (rp);
619 return;
620 }
621
622 if (new_dist < old_dist)
623 /* New route has a smaller distance. Replace the ECMP list
624 * with the new one in below. */
625 break;
626
627 /* Metrics and distances are both same. Keep "rinfo" null and
628 * the new route is added in the ECMP list in below. */
629 }
630 }
paul718e3742002-12-13 20:15:29 +0000631
632 if (rinfo)
633 {
paul718e3742002-12-13 20:15:29 +0000634 /* Local static route. */
635 if (rinfo->type == ZEBRA_ROUTE_RIP
paula87552c2004-05-03 20:00:17 +0000636 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
637 (rinfo->sub_type == RIP_ROUTE_DEFAULT))
638 && rinfo->metric != RIP_METRIC_INFINITY)
vincentfbf5d032005-09-29 11:25:50 +0000639 {
640 route_unlock_node (rp);
641 return;
642 }
643
644 /* Redistributed route check. */
645 if (rinfo->type != ZEBRA_ROUTE_RIP
646 && rinfo->metric != RIP_METRIC_INFINITY)
647 {
vincentfbf5d032005-09-29 11:25:50 +0000648 old_dist = rinfo->distance;
David Lamparterb68da442013-02-28 22:17:00 +0100649 /* Only routes directly connected to an interface (nexthop == 0)
650 * may have a valid NULL distance */
651 if (rinfo->nexthop.s_addr != 0)
vincent7a383332006-01-30 18:12:42 +0000652 old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
vincentfbf5d032005-09-29 11:25:50 +0000653 /* If imported route does not have STRICT precedence,
654 mark it as a ghost */
Lu Fengb397cf42014-07-18 06:13:18 +0000655 if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY)
656 rip_ecmp_replace (&newinfo);
657
658 route_unlock_node (rp);
659 return;
vincentfbf5d032005-09-29 11:25:50 +0000660 }
paul718e3742002-12-13 20:15:29 +0000661 }
paula87552c2004-05-03 20:00:17 +0000662
663 if (!rinfo)
paul718e3742002-12-13 20:15:29 +0000664 {
Lu Fengb397cf42014-07-18 06:13:18 +0000665 if (rp->info)
666 route_unlock_node (rp);
667
paul718e3742002-12-13 20:15:29 +0000668 /* Now, check to see whether there is already an explicit route
paula87552c2004-05-03 20:00:17 +0000669 for the destination prefix. If there is no such route, add
670 this route to the routing table, unless the metric is
671 infinity (there is no point in adding a route which
672 unusable). */
paul718e3742002-12-13 20:15:29 +0000673 if (rte->metric != RIP_METRIC_INFINITY)
Lu Fengb397cf42014-07-18 06:13:18 +0000674 rip_ecmp_add (&newinfo);
paul718e3742002-12-13 20:15:29 +0000675 }
676 else
677 {
678 /* Route is there but we are not sure the route is RIP or not. */
paula87552c2004-05-03 20:00:17 +0000679
paul718e3742002-12-13 20:15:29 +0000680 /* If there is an existing route, compare the next hop address
paula87552c2004-05-03 20:00:17 +0000681 to the address of the router from which the datagram came.
682 If this datagram is from the same router as the existing
683 route, reinitialize the timeout. */
hasso16705132003-05-25 14:49:19 +0000684 same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
paula87552c2004-05-03 20:00:17 +0000685 && (rinfo->ifindex == ifp->ifindex));
paul718e3742002-12-13 20:15:29 +0000686
Lu Fengb397cf42014-07-18 06:13:18 +0000687 old_dist = rinfo->distance ? \
688 rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
paulb94f9db2004-05-01 20:45:38 +0000689
paul718e3742002-12-13 20:15:29 +0000690 /* Next, compare the metrics. If the datagram is from the same
paula87552c2004-05-03 20:00:17 +0000691 router as the existing route, and the new metric is different
692 than the old one; or, if the new metric is lower than the old
693 one, or if the tag has been changed; or if there is a route
694 with a lower administrave distance; or an update of the
695 distance on the actual route; do the following actions: */
696 if ((same && rinfo->metric != rte->metric)
697 || (rte->metric < rinfo->metric)
698 || ((same)
699 && (rinfo->metric == rte->metric)
Lu Fengb397cf42014-07-18 06:13:18 +0000700 && (newinfo.tag != rinfo->tag))
701 || (old_dist > new_dist)
702 || ((old_dist != new_dist) && same))
paula87552c2004-05-03 20:00:17 +0000703 {
Lu Fengb397cf42014-07-18 06:13:18 +0000704 if (listcount (list) == 1)
paula87552c2004-05-03 20:00:17 +0000705 {
Lu Fengb397cf42014-07-18 06:13:18 +0000706 if (newinfo.metric != RIP_METRIC_INFINITY)
707 rip_ecmp_replace (&newinfo);
708 else
709 rip_ecmp_delete (rinfo);
paula87552c2004-05-03 20:00:17 +0000710 }
711 else
712 {
Lu Fengb397cf42014-07-18 06:13:18 +0000713 if (newinfo.metric < rinfo->metric)
714 rip_ecmp_replace (&newinfo);
715 else if (newinfo.metric > rinfo->metric)
716 rip_ecmp_delete (rinfo);
717 else if (new_dist < old_dist)
718 rip_ecmp_replace (&newinfo);
719 else if (new_dist > old_dist)
720 rip_ecmp_delete (rinfo);
721 else
722 {
723 int update = CHECK_FLAG (rinfo->flags, RIP_RTF_FIB) ? 1 : 0;
724
725 assert (newinfo.metric != RIP_METRIC_INFINITY);
726
727 RIP_TIMER_OFF (rinfo->t_timeout);
728 RIP_TIMER_OFF (rinfo->t_garbage_collect);
729 memcpy (rinfo, &newinfo, sizeof (struct rip_info));
730 rip_timeout_update (rinfo);
731
732 if (update)
733 rip_zebra_ipv4_add (rp);
734
735 /* - Set the route change flag on the first entry. */
736 rinfo = listgetdata (listhead (list));
737 SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
738 rip_event (RIP_TRIGGERED_UPDATE, 0);
739 }
paula87552c2004-05-03 20:00:17 +0000740 }
741 }
Lu Fengb397cf42014-07-18 06:13:18 +0000742 else /* same & no change */
743 rip_timeout_update (rinfo);
744
paul718e3742002-12-13 20:15:29 +0000745 /* Unlock tempolary lock of the route. */
746 route_unlock_node (rp);
747 }
748}
749
750/* Dump RIP packet */
pauldc63bfd2005-10-25 23:31:05 +0000751static void
hasso8a676be2004-10-08 06:36:38 +0000752rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000753{
754 caddr_t lim;
755 struct rte *rte;
hasso8a676be2004-10-08 06:36:38 +0000756 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000757 char pbuf[BUFSIZ], nbuf[BUFSIZ];
758 u_char netmask = 0;
759 u_char *p;
760
761 /* Set command string. */
762 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
763 command_str = lookup (rip_msg, packet->command);
764 else
765 command_str = "unknown";
766
767 /* Dump packet header. */
ajs5d6c3772004-12-08 19:24:06 +0000768 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000769 sndrcv, command_str, packet->version, size);
770
771 /* Dump each routing table entry. */
772 rte = packet->rte;
773
774 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
775 {
776 if (packet->version == RIPv2)
777 {
778 netmask = ip_masklen (rte->mask);
779
paulca5e5162004-06-06 22:06:33 +0000780 if (rte->family == htons (RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +0000781 {
paulca5e5162004-06-06 22:06:33 +0000782 if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000783 {
784 p = (u_char *)&rte->prefix;
785
ajs5d6c3772004-12-08 19:24:06 +0000786 zlog_debug (" family 0x%X type %d auth string: %s",
paul718e3742002-12-13 20:15:29 +0000787 ntohs (rte->family), ntohs (rte->tag), p);
788 }
paulca5e5162004-06-06 22:06:33 +0000789 else if (rte->tag == htons (RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000790 {
791 struct rip_md5_info *md5;
792
793 md5 = (struct rip_md5_info *) &packet->rte;
794
ajs5d6c3772004-12-08 19:24:06 +0000795 zlog_debug (" family 0x%X type %d (MD5 authentication)",
paul718e3742002-12-13 20:15:29 +0000796 ntohs (md5->family), ntohs (md5->type));
ajs5d6c3772004-12-08 19:24:06 +0000797 zlog_debug (" RIP-2 packet len %d Key ID %d"
paulca5e5162004-06-06 22:06:33 +0000798 " Auth Data len %d",
799 ntohs (md5->packet_len), md5->keyid,
800 md5->auth_len);
ajs5d6c3772004-12-08 19:24:06 +0000801 zlog_debug (" Sequence Number %ld",
paulca5e5162004-06-06 22:06:33 +0000802 (u_long) ntohl (md5->sequence));
paul718e3742002-12-13 20:15:29 +0000803 }
paulca5e5162004-06-06 22:06:33 +0000804 else if (rte->tag == htons (RIP_AUTH_DATA))
paul718e3742002-12-13 20:15:29 +0000805 {
806 p = (u_char *)&rte->prefix;
807
ajs5d6c3772004-12-08 19:24:06 +0000808 zlog_debug (" family 0x%X type %d (MD5 data)",
paul718e3742002-12-13 20:15:29 +0000809 ntohs (rte->family), ntohs (rte->tag));
ajs5d6c3772004-12-08 19:24:06 +0000810 zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
paul718e3742002-12-13 20:15:29 +0000811 "%02X%02X%02X%02X%02X%02X%02X",
paulca5e5162004-06-06 22:06:33 +0000812 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
813 p[7], p[9], p[10], p[11], p[12], p[13],
814 p[14], p[15]);
paul718e3742002-12-13 20:15:29 +0000815 }
816 else
817 {
ajs5d6c3772004-12-08 19:24:06 +0000818 zlog_debug (" family 0x%X type %d (Unknown auth type)",
paul718e3742002-12-13 20:15:29 +0000819 ntohs (rte->family), ntohs (rte->tag));
820 }
821 }
822 else
ajs5d6c3772004-12-08 19:24:06 +0000823 zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
paulca5e5162004-06-06 22:06:33 +0000824 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
825 netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
826 BUFSIZ), ntohs (rte->family),
827 ntohs (rte->tag), (u_long) ntohl (rte->metric));
paul718e3742002-12-13 20:15:29 +0000828 }
829 else
830 {
ajs5d6c3772004-12-08 19:24:06 +0000831 zlog_debug (" %s family %d tag %d metric %ld",
paul718e3742002-12-13 20:15:29 +0000832 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
833 ntohs (rte->family), ntohs (rte->tag),
834 (u_long)ntohl (rte->metric));
835 }
836 }
837}
838
839/* Check if the destination address is valid (unicast; not net 0
840 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
841 check net 0 because we accept default route. */
pauldc63bfd2005-10-25 23:31:05 +0000842static int
paul718e3742002-12-13 20:15:29 +0000843rip_destination_check (struct in_addr addr)
844{
845 u_int32_t destination;
846
847 /* Convert to host byte order. */
848 destination = ntohl (addr.s_addr);
849
850 if (IPV4_NET127 (destination))
851 return 0;
852
853 /* Net 0 may match to the default route. */
854 if (IPV4_NET0 (destination) && destination != 0)
855 return 0;
856
857 /* Unicast address must belong to class A, B, C. */
858 if (IN_CLASSA (destination))
859 return 1;
860 if (IN_CLASSB (destination))
861 return 1;
862 if (IN_CLASSC (destination))
863 return 1;
864
865 return 0;
866}
867
868/* RIP version 2 authentication. */
pauldc63bfd2005-10-25 23:31:05 +0000869static int
paul718e3742002-12-13 20:15:29 +0000870rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
871 struct interface *ifp)
872{
873 struct rip_interface *ri;
874 char *auth_str;
875
876 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000877 zlog_debug ("RIPv2 simple password authentication from %s",
paul718e3742002-12-13 20:15:29 +0000878 inet_ntoa (from->sin_addr));
879
880 ri = ifp->info;
881
882 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
paulca5e5162004-06-06 22:06:33 +0000883 || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
paul718e3742002-12-13 20:15:29 +0000884 return 0;
885
886 /* Simple password authentication. */
887 if (ri->auth_str)
888 {
889 auth_str = (char *) &rte->prefix;
890
891 if (strncmp (auth_str, ri->auth_str, 16) == 0)
892 return 1;
893 }
894 if (ri->key_chain)
895 {
896 struct keychain *keychain;
897 struct key *key;
898
899 keychain = keychain_lookup (ri->key_chain);
900 if (keychain == NULL)
901 return 0;
902
903 key = key_match_for_accept (keychain, (char *) &rte->prefix);
904 if (key)
905 return 1;
906 }
907 return 0;
908}
909
910/* RIP version 2 authentication with MD5. */
pauldc63bfd2005-10-25 23:31:05 +0000911static int
paul718e3742002-12-13 20:15:29 +0000912rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
paulca5e5162004-06-06 22:06:33 +0000913 int length, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000914{
915 struct rip_interface *ri;
916 struct rip_md5_info *md5;
917 struct rip_md5_data *md5data;
918 struct keychain *keychain;
919 struct key *key;
vincentc1a03d42005-09-28 15:47:44 +0000920 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000921 u_char digest[RIP_AUTH_MD5_SIZE];
922 u_int16_t packet_len;
paul98fd1e62006-01-17 17:26:25 +0000923 char auth_str[RIP_AUTH_MD5_SIZE];
paul718e3742002-12-13 20:15:29 +0000924
925 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000926 zlog_debug ("RIPv2 MD5 authentication from %s",
paulca5e5162004-06-06 22:06:33 +0000927 inet_ntoa (from->sin_addr));
paul718e3742002-12-13 20:15:29 +0000928
929 ri = ifp->info;
930 md5 = (struct rip_md5_info *) &packet->rte;
931
932 /* Check auth type. */
paulca5e5162004-06-06 22:06:33 +0000933 if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
paul718e3742002-12-13 20:15:29 +0000934 return 0;
935
paulca5e5162004-06-06 22:06:33 +0000936 /* If the authentication length is less than 16, then it must be wrong for
937 * any interpretation of rfc2082. Some implementations also interpret
938 * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
paul98fd1e62006-01-17 17:26:25 +0000939 */
paulca5e5162004-06-06 22:06:33 +0000940 if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
941 || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
paulc2bfbcc2004-06-04 01:42:38 +0000942 {
943 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000944 zlog_debug ("RIPv2 MD5 authentication, strange authentication "
paulca5e5162004-06-06 22:06:33 +0000945 "length field %d", md5->auth_len);
paul718e3742002-12-13 20:15:29 +0000946 return 0;
paulc2bfbcc2004-06-04 01:42:38 +0000947 }
paul718e3742002-12-13 20:15:29 +0000948
paulca5e5162004-06-06 22:06:33 +0000949 /* grab and verify check packet length */
950 packet_len = ntohs (md5->packet_len);
951
952 if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
953 {
954 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +0000955 zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
paulca5e5162004-06-06 22:06:33 +0000956 "greater than received length %d!",
957 md5->packet_len, length);
958 return 0;
959 }
960
961 /* retrieve authentication data */
962 md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
paul98fd1e62006-01-17 17:26:25 +0000963
964 memset (auth_str, 0, RIP_AUTH_MD5_SIZE);
paulca5e5162004-06-06 22:06:33 +0000965
paul718e3742002-12-13 20:15:29 +0000966 if (ri->key_chain)
967 {
968 keychain = keychain_lookup (ri->key_chain);
969 if (keychain == NULL)
970 return 0;
971
972 key = key_lookup_for_accept (keychain, md5->keyid);
973 if (key == NULL)
974 return 0;
975
paul98fd1e62006-01-17 17:26:25 +0000976 strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000977 }
paul98fd1e62006-01-17 17:26:25 +0000978 else if (ri->auth_str)
979 strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000980
Paul Jakmafa93b162008-05-29 19:03:08 +0000981 if (auth_str[0] == 0)
paul718e3742002-12-13 20:15:29 +0000982 return 0;
paul98fd1e62006-01-17 17:26:25 +0000983
paul718e3742002-12-13 20:15:29 +0000984 /* MD5 digest authentication. */
vincentc1a03d42005-09-28 15:47:44 +0000985 memset (&ctx, 0, sizeof(ctx));
986 MD5Init(&ctx);
paul98fd1e62006-01-17 17:26:25 +0000987 MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
988 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
vincentc1a03d42005-09-28 15:47:44 +0000989 MD5Final(digest, &ctx);
paul98fd1e62006-01-17 17:26:25 +0000990
991 if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
paul718e3742002-12-13 20:15:29 +0000992 return packet_len;
993 else
994 return 0;
995}
996
paulb14ee002005-02-04 23:42:41 +0000997/* Pick correct auth string for sends, prepare auth_str buffer for use.
998 * (left justified and padded).
999 *
1000 * presumes one of ri or key is valid, and that the auth strings they point
1001 * to are nul terminated. If neither are present, auth_str will be fully
1002 * zero padded.
1003 *
1004 */
1005static void
1006rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
1007 char *auth_str, int len)
paul718e3742002-12-13 20:15:29 +00001008{
paulb14ee002005-02-04 23:42:41 +00001009 assert (ri || key);
paul718e3742002-12-13 20:15:29 +00001010
paulb14ee002005-02-04 23:42:41 +00001011 memset (auth_str, 0, len);
1012 if (key && key->string)
1013 strncpy (auth_str, key->string, len);
1014 else if (ri->auth_str)
1015 strncpy (auth_str, ri->auth_str, len);
paul718e3742002-12-13 20:15:29 +00001016
paulb14ee002005-02-04 23:42:41 +00001017 return;
1018}
paul718e3742002-12-13 20:15:29 +00001019
paulb14ee002005-02-04 23:42:41 +00001020/* Write RIPv2 simple password authentication information
1021 *
1022 * auth_str is presumed to be 2 bytes and correctly prepared
1023 * (left justified and zero padded).
1024 */
1025static void
1026rip_auth_simple_write (struct stream *s, char *auth_str, int len)
1027{
1028 assert (s && len == RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00001029
paulb14ee002005-02-04 23:42:41 +00001030 stream_putw (s, RIP_FAMILY_AUTH);
1031 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1032 stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
1033
1034 return;
1035}
1036
1037/* write RIPv2 MD5 "authentication header"
1038 * (uses the auth key data field)
1039 *
1040 * Digest offset field is set to 0.
1041 *
1042 * returns: offset of the digest offset field, which must be set when
1043 * length to the auth-data MD5 digest is known.
1044 */
1045static size_t
1046rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
1047 struct key *key)
1048{
paul98fd1e62006-01-17 17:26:25 +00001049 size_t doff = 0;
paulb14ee002005-02-04 23:42:41 +00001050
1051 assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
paul718e3742002-12-13 20:15:29 +00001052
1053 /* MD5 authentication. */
paulca5e5162004-06-06 22:06:33 +00001054 stream_putw (s, RIP_FAMILY_AUTH);
paul718e3742002-12-13 20:15:29 +00001055 stream_putw (s, RIP_AUTH_MD5);
1056
paulb14ee002005-02-04 23:42:41 +00001057 /* MD5 AH digest offset field.
1058 *
1059 * Set to placeholder value here, to true value when RIP-2 Packet length
1060 * is known. Actual value is set in .....().
1061 */
paul98fd1e62006-01-17 17:26:25 +00001062 doff = stream_get_endp(s);
paulb14ee002005-02-04 23:42:41 +00001063 stream_putw (s, 0);
paul718e3742002-12-13 20:15:29 +00001064
1065 /* Key ID. */
1066 if (key)
1067 stream_putc (s, key->index % 256);
1068 else
1069 stream_putc (s, 1);
1070
paulca5e5162004-06-06 22:06:33 +00001071 /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1072 * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1073 * to be configurable.
1074 */
1075 stream_putc (s, ri->md5_auth_len);
paul718e3742002-12-13 20:15:29 +00001076
1077 /* Sequence Number (non-decreasing). */
1078 /* RFC2080: The value used in the sequence number is
1079 arbitrary, but two suggestions are the time of the
1080 message's creation or a simple message counter. */
1081 stream_putl (s, time (NULL));
1082
1083 /* Reserved field must be zero. */
1084 stream_putl (s, 0);
1085 stream_putl (s, 0);
1086
paul98fd1e62006-01-17 17:26:25 +00001087 return doff;
paulb14ee002005-02-04 23:42:41 +00001088}
paul718e3742002-12-13 20:15:29 +00001089
paulb14ee002005-02-04 23:42:41 +00001090/* If authentication is in used, write the appropriate header
1091 * returns stream offset to which length must later be written
1092 * or 0 if this is not required
1093 */
1094static size_t
1095rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1096 struct key *key, char *auth_str, int len)
1097{
1098 assert (ri->auth_type != RIP_NO_AUTH);
1099
1100 switch (ri->auth_type)
1101 {
1102 case RIP_AUTH_SIMPLE_PASSWORD:
1103 rip_auth_prepare_str_send (ri, key, auth_str, len);
1104 rip_auth_simple_write (s, auth_str, len);
1105 return 0;
1106 case RIP_AUTH_MD5:
1107 return rip_auth_md5_ah_write (s, ri, key);
1108 }
1109 assert (1);
paul98fd1e62006-01-17 17:26:25 +00001110 return 0;
paulb14ee002005-02-04 23:42:41 +00001111}
1112
1113/* Write RIPv2 MD5 authentication data trailer */
1114static void
1115rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1116 char *auth_str, int authlen)
1117{
1118 unsigned long len;
vincentc1a03d42005-09-28 15:47:44 +00001119 MD5_CTX ctx;
paulb14ee002005-02-04 23:42:41 +00001120 unsigned char digest[RIP_AUTH_MD5_SIZE];
1121
1122 /* Make it sure this interface is configured as MD5
1123 authentication. */
1124 assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1125 assert (doff > 0);
1126
1127 /* Get packet length. */
1128 len = stream_get_endp(s);
1129
1130 /* Check packet length. */
1131 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1132 {
1133 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1134 return;
1135 }
1136
1137 /* Set the digest offset length in the header */
1138 stream_putw_at (s, doff, len);
1139
paul718e3742002-12-13 20:15:29 +00001140 /* Set authentication data. */
paulca5e5162004-06-06 22:06:33 +00001141 stream_putw (s, RIP_FAMILY_AUTH);
1142 stream_putw (s, RIP_AUTH_DATA);
paul718e3742002-12-13 20:15:29 +00001143
1144 /* Generate a digest for the RIP packet. */
vincentc1a03d42005-09-28 15:47:44 +00001145 memset(&ctx, 0, sizeof(ctx));
1146 MD5Init(&ctx);
paul98fd1e62006-01-17 17:26:25 +00001147 MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s));
vincentc1a03d42005-09-28 15:47:44 +00001148 MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1149 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +00001150
1151 /* Copy the digest to the packet. */
1152 stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1153}
1154
1155/* RIP routing information. */
pauldc63bfd2005-10-25 23:31:05 +00001156static void
paul718e3742002-12-13 20:15:29 +00001157rip_response_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001158 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001159{
1160 caddr_t lim;
1161 struct rte *rte;
paul727d1042002-12-13 20:50:29 +00001162 struct prefix_ipv4 ifaddr;
1163 struct prefix_ipv4 ifaddrclass;
paul727d1042002-12-13 20:50:29 +00001164 int subnetted;
paul718e3742002-12-13 20:15:29 +00001165
paul727d1042002-12-13 20:50:29 +00001166 /* We don't know yet. */
1167 subnetted = -1;
1168
paul718e3742002-12-13 20:15:29 +00001169 /* The Response must be ignored if it is not from the RIP
1170 port. (RFC2453 - Sec. 3.9.2)*/
paulca5e5162004-06-06 22:06:33 +00001171 if (from->sin_port != htons(RIP_PORT_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001172 {
1173 zlog_info ("response doesn't come from RIP port: %d",
1174 from->sin_port);
1175 rip_peer_bad_packet (from);
1176 return;
1177 }
1178
1179 /* The datagram's IPv4 source address should be checked to see
1180 whether the datagram is from a valid neighbor; the source of the
ajs35a60c22005-10-30 23:51:32 +00001181 datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */
1182 if (if_lookup_address(from->sin_addr) == NULL)
paul718e3742002-12-13 20:15:29 +00001183 {
1184 zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1185 inet_ntoa (from->sin_addr));
1186 rip_peer_bad_packet (from);
1187 return;
1188 }
1189
1190 /* It is also worth checking to see whether the response is from one
1191 of the router's own addresses. */
1192
1193 ; /* Alredy done in rip_read () */
1194
1195 /* Update RIP peer. */
1196 rip_peer_update (from, packet->version);
1197
1198 /* Set RTE pointer. */
1199 rte = packet->rte;
1200
1201 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1202 {
1203 /* RIPv2 authentication check. */
1204 /* If the Address Family Identifier of the first (and only the
1205 first) entry in the message is 0xFFFF, then the remainder of
1206 the entry contains the authentication. */
1207 /* If the packet gets here it means authentication enabled */
1208 /* Check is done in rip_read(). So, just skipping it */
1209 if (packet->version == RIPv2 &&
1210 rte == packet->rte &&
paulca5e5162004-06-06 22:06:33 +00001211 rte->family == htons(RIP_FAMILY_AUTH))
paul718e3742002-12-13 20:15:29 +00001212 continue;
1213
paulca5e5162004-06-06 22:06:33 +00001214 if (rte->family != htons(AF_INET))
paul718e3742002-12-13 20:15:29 +00001215 {
1216 /* Address family check. RIP only supports AF_INET. */
1217 zlog_info ("Unsupported family %d from %s.",
1218 ntohs (rte->family), inet_ntoa (from->sin_addr));
1219 continue;
1220 }
1221
1222 /* - is the destination address valid (e.g., unicast; not net 0
1223 or 127) */
1224 if (! rip_destination_check (rte->prefix))
1225 {
1226 zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1227 rip_peer_bad_route (from);
1228 continue;
1229 }
1230
1231 /* Convert metric value to host byte order. */
1232 rte->metric = ntohl (rte->metric);
1233
1234 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1235 if (! (rte->metric >= 1 && rte->metric <= 16))
1236 {
1237 zlog_info ("Route's metric is not in the 1-16 range.");
1238 rip_peer_bad_route (from);
1239 continue;
1240 }
1241
1242 /* RIPv1 does not have nexthop value. */
1243 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1244 {
1245 zlog_info ("RIPv1 packet with nexthop value %s",
1246 inet_ntoa (rte->nexthop));
1247 rip_peer_bad_route (from);
1248 continue;
1249 }
1250
1251 /* That is, if the provided information is ignored, a possibly
1252 sub-optimal, but absolutely valid, route may be taken. If
1253 the received Next Hop is not directly reachable, it should be
1254 treated as 0.0.0.0. */
1255 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1256 {
1257 u_int32_t addrval;
1258
1259 /* Multicast address check. */
1260 addrval = ntohl (rte->nexthop.s_addr);
1261 if (IN_CLASSD (addrval))
1262 {
1263 zlog_info ("Nexthop %s is multicast address, skip this rte",
1264 inet_ntoa (rte->nexthop));
1265 continue;
1266 }
1267
1268 if (! if_lookup_address (rte->nexthop))
1269 {
1270 struct route_node *rn;
1271 struct rip_info *rinfo;
1272
1273 rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1274
1275 if (rn)
1276 {
1277 rinfo = rn->info;
1278
1279 if (rinfo->type == ZEBRA_ROUTE_RIP
1280 && rinfo->sub_type == RIP_ROUTE_RTE)
1281 {
1282 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001283 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 +00001284 rte->nexthop = rinfo->from;
1285 }
1286 else
1287 {
1288 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001289 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 +00001290 rte->nexthop.s_addr = 0;
1291 }
1292
1293 route_unlock_node (rn);
1294 }
1295 else
1296 {
1297 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001298 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 +00001299 rte->nexthop.s_addr = 0;
1300 }
1301
1302 }
1303 }
1304
1305 /* For RIPv1, there won't be a valid netmask.
1306
1307 This is a best guess at the masks. If everyone was using old
1308 Ciscos before the 'ip subnet zero' option, it would be almost
1309 right too :-)
1310
1311 Cisco summarize ripv1 advertisments to the classful boundary
1312 (/16 for class B's) except when the RIP packet does to inside
1313 the classful network in question. */
1314
1315 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1316 || (packet->version == RIPv2
1317 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1318 {
1319 u_int32_t destination;
1320
paul727d1042002-12-13 20:50:29 +00001321 if (subnetted == -1)
paulc49ad8f2004-10-22 10:27:28 +00001322 {
1323 memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1324 memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1325 apply_classful_mask_ipv4 (&ifaddrclass);
1326 subnetted = 0;
1327 if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1328 subnetted = 1;
1329 }
paul727d1042002-12-13 20:50:29 +00001330
paul718e3742002-12-13 20:15:29 +00001331 destination = ntohl (rte->prefix.s_addr);
1332
paul727d1042002-12-13 20:50:29 +00001333 if (IN_CLASSA (destination))
paul718e3742002-12-13 20:15:29 +00001334 masklen2ip (8, &rte->mask);
paul727d1042002-12-13 20:50:29 +00001335 else if (IN_CLASSB (destination))
1336 masklen2ip (16, &rte->mask);
1337 else if (IN_CLASSC (destination))
1338 masklen2ip (24, &rte->mask);
1339
1340 if (subnetted == 1)
1341 masklen2ip (ifaddrclass.prefixlen,
1342 (struct in_addr *) &destination);
1343 if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1344 ifaddrclass.prefix.s_addr))
1345 {
1346 masklen2ip (ifaddr.prefixlen, &rte->mask);
1347 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1348 masklen2ip (32, &rte->mask);
1349 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001350 zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
paul727d1042002-12-13 20:50:29 +00001351 }
1352 else
1353 {
1354 if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1355 continue;
1356 }
1357
1358 if (IS_RIP_DEBUG_EVENT)
1359 {
ajs5d6c3772004-12-08 19:24:06 +00001360 zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1361 zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
paul718e3742002-12-13 20:15:29 +00001362 }
1363 }
1364
1365 /* In case of RIPv2, if prefix in RTE is not netmask applied one
1366 ignore the entry. */
1367 if ((packet->version == RIPv2)
1368 && (rte->mask.s_addr != 0)
1369 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1370 {
1371 zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1372 inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1373 rip_peer_bad_route (from);
1374 continue;
1375 }
1376
1377 /* Default route's netmask is ignored. */
1378 if (packet->version == RIPv2
1379 && (rte->prefix.s_addr == 0)
1380 && (rte->mask.s_addr != 0))
1381 {
1382 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001383 zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
paul718e3742002-12-13 20:15:29 +00001384 rte->mask.s_addr = 0;
1385 }
1386
1387 /* Routing table updates. */
paulc49ad8f2004-10-22 10:27:28 +00001388 rip_rte_process (rte, from, ifc->ifp);
paul718e3742002-12-13 20:15:29 +00001389 }
1390}
1391
paula4e987e2005-06-03 17:46:49 +00001392/* Make socket for RIP protocol. */
paulf69bd9d2005-06-03 18:01:50 +00001393static int
paul2c61ae32005-08-16 15:22:14 +00001394rip_create_socket (struct sockaddr_in *from)
paula4e987e2005-06-03 17:46:49 +00001395{
1396 int ret;
1397 int sock;
1398 struct sockaddr_in addr;
paulf69bd9d2005-06-03 18:01:50 +00001399
paul2c61ae32005-08-16 15:22:14 +00001400 memset (&addr, 0, sizeof (struct sockaddr_in));
1401
1402 if (!from)
paulf69bd9d2005-06-03 18:01:50 +00001403 {
paulf69bd9d2005-06-03 18:01:50 +00001404 addr.sin_family = AF_INET;
1405 addr.sin_addr.s_addr = INADDR_ANY;
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001406#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
paul2c61ae32005-08-16 15:22:14 +00001407 addr.sin_len = sizeof (struct sockaddr_in);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001408#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
jardin38d3c162005-10-19 19:29:59 +00001409 } else {
1410 memcpy(&addr, from, sizeof(addr));
paulf69bd9d2005-06-03 18:01:50 +00001411 }
1412
paul2c61ae32005-08-16 15:22:14 +00001413 /* sending port must always be the RIP port */
1414 addr.sin_port = htons (RIP_PORT_DEFAULT);
1415
paula4e987e2005-06-03 17:46:49 +00001416 /* Make datagram socket. */
1417 sock = socket (AF_INET, SOCK_DGRAM, 0);
1418 if (sock < 0)
1419 {
1420 zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1421 exit (1);
1422 }
1423
1424 sockopt_broadcast (sock);
1425 sockopt_reuseaddr (sock);
1426 sockopt_reuseport (sock);
paula4e987e2005-06-03 17:46:49 +00001427#ifdef RIP_RECVMSG
1428 setsockopt_pktinfo (sock);
1429#endif /* RIP_RECVMSG */
Stephen Hemminger78b31d52009-07-21 16:27:26 -07001430#ifdef IPTOS_PREC_INTERNETCONTROL
1431 setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
1432#endif
paula4e987e2005-06-03 17:46:49 +00001433
1434 if (ripd_privs.change (ZPRIVS_RAISE))
1435 zlog_err ("rip_create_socket: could not raise privs");
paulf69bd9d2005-06-03 18:01:50 +00001436 setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1437 if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1438
paula4e987e2005-06-03 17:46:49 +00001439 {
1440 int save_errno = errno;
1441 if (ripd_privs.change (ZPRIVS_LOWER))
1442 zlog_err ("rip_create_socket: could not lower privs");
paul2c61ae32005-08-16 15:22:14 +00001443
1444 zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1445 sock, inet_ntoa(addr.sin_addr),
1446 (int) ntohs(addr.sin_port),
1447 safe_strerror(save_errno));
1448
paulf69bd9d2005-06-03 18:01:50 +00001449 close (sock);
paula4e987e2005-06-03 17:46:49 +00001450 return ret;
1451 }
paulf69bd9d2005-06-03 18:01:50 +00001452
paula4e987e2005-06-03 17:46:49 +00001453 if (ripd_privs.change (ZPRIVS_LOWER))
1454 zlog_err ("rip_create_socket: could not lower privs");
1455
1456 return sock;
1457}
1458
paulc49ad8f2004-10-22 10:27:28 +00001459/* RIP packet send to destination address, on interface denoted by
1460 * by connected argument. NULL to argument denotes destination should be
1461 * should be RIP multicast group
1462 */
pauldc63bfd2005-10-25 23:31:05 +00001463static int
paulc49ad8f2004-10-22 10:27:28 +00001464rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1465 struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001466{
paul931cd542004-01-23 15:31:42 +00001467 int ret, send_sock;
paul718e3742002-12-13 20:15:29 +00001468 struct sockaddr_in sin;
paulc49ad8f2004-10-22 10:27:28 +00001469
1470 assert (ifc != NULL);
1471
paul931cd542004-01-23 15:31:42 +00001472 if (IS_RIP_DEBUG_PACKET)
1473 {
paulf69bd9d2005-06-03 18:01:50 +00001474#define ADDRESS_SIZE 20
1475 char dst[ADDRESS_SIZE];
1476 dst[ADDRESS_SIZE - 1] = '\0';
1477
paul931cd542004-01-23 15:31:42 +00001478 if (to)
1479 {
paulf69bd9d2005-06-03 18:01:50 +00001480 strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001481 }
1482 else
1483 {
1484 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paulf69bd9d2005-06-03 18:01:50 +00001485 strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
paul931cd542004-01-23 15:31:42 +00001486 }
paulf69bd9d2005-06-03 18:01:50 +00001487#undef ADDRESS_SIZE
ajs5d6c3772004-12-08 19:24:06 +00001488 zlog_debug("rip_send_packet %s > %s (%s)",
paulc49ad8f2004-10-22 10:27:28 +00001489 inet_ntoa(ifc->address->u.prefix4),
1490 dst, ifc->ifp->name);
paul931cd542004-01-23 15:31:42 +00001491 }
paulf69bd9d2005-06-03 18:01:50 +00001492
paulc49ad8f2004-10-22 10:27:28 +00001493 if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
paul931cd542004-01-23 15:31:42 +00001494 {
1495 /*
1496 * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1497 * with multiple addresses on the same subnet: the first address
1498 * on the subnet is configured "primary", and all subsequent addresses
1499 * on that subnet are treated as "secondary" addresses.
1500 * In order to avoid routing-table bloat on other rip listeners,
1501 * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1502 * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1503 * flag is set, we would end up sending a packet for a "secondary"
1504 * source address on non-linux systems.
1505 */
1506 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001507 zlog_debug("duplicate dropped");
paul931cd542004-01-23 15:31:42 +00001508 return 0;
1509 }
1510
paul718e3742002-12-13 20:15:29 +00001511 /* Make destination address. */
1512 memset (&sin, 0, sizeof (struct sockaddr_in));
1513 sin.sin_family = AF_INET;
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001514#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
paul718e3742002-12-13 20:15:29 +00001515 sin.sin_len = sizeof (struct sockaddr_in);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001516#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
paul718e3742002-12-13 20:15:29 +00001517
1518 /* When destination is specified, use it's port and address. */
1519 if (to)
1520 {
paul718e3742002-12-13 20:15:29 +00001521 sin.sin_port = to->sin_port;
1522 sin.sin_addr = to->sin_addr;
paul931cd542004-01-23 15:31:42 +00001523 send_sock = rip->sock;
paul718e3742002-12-13 20:15:29 +00001524 }
1525 else
1526 {
paul2c61ae32005-08-16 15:22:14 +00001527 struct sockaddr_in from;
1528
paul718e3742002-12-13 20:15:29 +00001529 sin.sin_port = htons (RIP_PORT_DEFAULT);
1530 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
paul2c61ae32005-08-16 15:22:14 +00001531
1532 /* multicast send should bind to local interface address */
Nick Hilliardbb2315f2012-08-18 15:10:57 +00001533 memset (&from, 0, sizeof (from));
paul2c61ae32005-08-16 15:22:14 +00001534 from.sin_family = AF_INET;
1535 from.sin_port = htons (RIP_PORT_DEFAULT);
1536 from.sin_addr = ifc->address->u.prefix4;
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001537#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
paul2c61ae32005-08-16 15:22:14 +00001538 from.sin_len = sizeof (struct sockaddr_in);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001539#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
paul2c61ae32005-08-16 15:22:14 +00001540
paul931cd542004-01-23 15:31:42 +00001541 /*
1542 * we have to open a new socket for each packet because this
1543 * is the most portable way to bind to a different source
1544 * ipv4 address for each packet.
1545 */
paul2c61ae32005-08-16 15:22:14 +00001546 if ( (send_sock = rip_create_socket (&from)) < 0)
paul931cd542004-01-23 15:31:42 +00001547 {
paulf69bd9d2005-06-03 18:01:50 +00001548 zlog_warn("rip_send_packet could not create socket.");
paul931cd542004-01-23 15:31:42 +00001549 return -1;
paulf69bd9d2005-06-03 18:01:50 +00001550 }
paulc49ad8f2004-10-22 10:27:28 +00001551 rip_interface_multicast_set (send_sock, ifc);
paul718e3742002-12-13 20:15:29 +00001552 }
1553
paul931cd542004-01-23 15:31:42 +00001554 ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
paul718e3742002-12-13 20:15:29 +00001555 sizeof (struct sockaddr_in));
1556
1557 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001558 zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
paulcc1131a2003-10-15 23:20:17 +00001559 ntohs (sin.sin_port));
paul718e3742002-12-13 20:15:29 +00001560
1561 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001562 zlog_warn ("can't send packet : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001563
paul931cd542004-01-23 15:31:42 +00001564 if (!to)
1565 close(send_sock);
1566
paul718e3742002-12-13 20:15:29 +00001567 return ret;
1568}
1569
1570/* Add redistributed route to RIP table. */
1571void
1572rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
vincentfbf5d032005-09-29 11:25:50 +00001573 unsigned int ifindex, struct in_addr *nexthop,
1574 unsigned int metric, unsigned char distance)
paul718e3742002-12-13 20:15:29 +00001575{
1576 int ret;
Lu Fengb397cf42014-07-18 06:13:18 +00001577 struct route_node *rp = NULL;
1578 struct rip_info *rinfo = NULL, newinfo;
1579 struct list *list = NULL;
paul718e3742002-12-13 20:15:29 +00001580
1581 /* Redistribute route */
1582 ret = rip_destination_check (p->prefix);
1583 if (! ret)
1584 return;
1585
1586 rp = route_node_get (rip->table, (struct prefix *) p);
1587
Lu Fengb397cf42014-07-18 06:13:18 +00001588 memset (&newinfo, 0, sizeof (struct rip_info));
1589 newinfo.type = type;
1590 newinfo.sub_type = sub_type;
1591 newinfo.ifindex = ifindex;
1592 newinfo.metric = 1;
1593 newinfo.external_metric = metric;
1594 newinfo.distance = distance;
1595 newinfo.rp = rp;
1596 if (nexthop)
1597 newinfo.nexthop = *nexthop;
paul718e3742002-12-13 20:15:29 +00001598
Lu Fengb397cf42014-07-18 06:13:18 +00001599 if ((list = rp->info) != NULL && listcount (list) != 0)
paul718e3742002-12-13 20:15:29 +00001600 {
Lu Fengb397cf42014-07-18 06:13:18 +00001601 rinfo = listgetdata (listhead (list));
1602
paul718e3742002-12-13 20:15:29 +00001603 if (rinfo->type == ZEBRA_ROUTE_CONNECT
1604 && rinfo->sub_type == RIP_ROUTE_INTERFACE
1605 && rinfo->metric != RIP_METRIC_INFINITY)
1606 {
1607 route_unlock_node (rp);
1608 return;
1609 }
1610
1611 /* Manually configured RIP route check. */
1612 if (rinfo->type == ZEBRA_ROUTE_RIP
hasso16705132003-05-25 14:49:19 +00001613 && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1614 (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
paul718e3742002-12-13 20:15:29 +00001615 {
hasso16705132003-05-25 14:49:19 +00001616 if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1617 (sub_type != RIP_ROUTE_DEFAULT)))
paul718e3742002-12-13 20:15:29 +00001618 {
1619 route_unlock_node (rp);
1620 return;
1621 }
1622 }
1623
Lu Fengb397cf42014-07-18 06:13:18 +00001624 rinfo = rip_ecmp_replace (&newinfo);
1625 route_unlock_node (rp);
paul718e3742002-12-13 20:15:29 +00001626 }
Lu Fengb397cf42014-07-18 06:13:18 +00001627 else
1628 rinfo = rip_ecmp_add (&newinfo);
paul718e3742002-12-13 20:15:29 +00001629
hasso16705132003-05-25 14:49:19 +00001630 if (IS_RIP_DEBUG_EVENT) {
1631 if (!nexthop)
ajs5d6c3772004-12-08 19:24:06 +00001632 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso16705132003-05-25 14:49:19 +00001633 inet_ntoa(p->prefix), p->prefixlen,
1634 ifindex2ifname(ifindex));
1635 else
ajs5d6c3772004-12-08 19:24:06 +00001636 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso16705132003-05-25 14:49:19 +00001637 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1638 ifindex2ifname(ifindex));
1639 }
1640
paul718e3742002-12-13 20:15:29 +00001641 rip_event (RIP_TRIGGERED_UPDATE, 0);
1642}
1643
1644/* Delete redistributed route from RIP table. */
1645void
1646rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1647 unsigned int ifindex)
1648{
1649 int ret;
1650 struct route_node *rp;
1651 struct rip_info *rinfo;
1652
1653 ret = rip_destination_check (p->prefix);
1654 if (! ret)
1655 return;
1656
1657 rp = route_node_lookup (rip->table, (struct prefix *) p);
1658 if (rp)
1659 {
Lu Fengb397cf42014-07-18 06:13:18 +00001660 struct list *list = rp->info;
paul718e3742002-12-13 20:15:29 +00001661
Lu Fengb397cf42014-07-18 06:13:18 +00001662 if (list != NULL && listcount (list) != 0)
1663 {
1664 rinfo = listgetdata (listhead (list));
1665 if (rinfo != NULL
1666 && rinfo->type == type
1667 && rinfo->sub_type == sub_type
1668 && rinfo->ifindex == ifindex)
1669 {
1670 /* Perform poisoned reverse. */
1671 rinfo->metric = RIP_METRIC_INFINITY;
1672 RIP_TIMER_ON (rinfo->t_garbage_collect,
1673 rip_garbage_collect, rip->garbage_time);
1674 RIP_TIMER_OFF (rinfo->t_timeout);
1675 rinfo->flags |= RIP_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +00001676
Lu Fengb397cf42014-07-18 06:13:18 +00001677 if (IS_RIP_DEBUG_EVENT)
1678 zlog_debug ("Poisone %s/%d on the interface %s with an "
1679 "infinity metric [delete]",
1680 inet_ntoa(p->prefix), p->prefixlen,
1681 ifindex2ifname(ifindex));
hasso16705132003-05-25 14:49:19 +00001682
Lu Fengb397cf42014-07-18 06:13:18 +00001683 rip_event (RIP_TRIGGERED_UPDATE, 0);
1684 }
1685 }
1686 route_unlock_node (rp);
paul718e3742002-12-13 20:15:29 +00001687 }
1688}
1689
1690/* Response to request called from rip_read ().*/
pauldc63bfd2005-10-25 23:31:05 +00001691static void
paul718e3742002-12-13 20:15:29 +00001692rip_request_process (struct rip_packet *packet, int size,
paulc49ad8f2004-10-22 10:27:28 +00001693 struct sockaddr_in *from, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +00001694{
1695 caddr_t lim;
1696 struct rte *rte;
1697 struct prefix_ipv4 p;
1698 struct route_node *rp;
1699 struct rip_info *rinfo;
1700 struct rip_interface *ri;
1701
hasso16705132003-05-25 14:49:19 +00001702 /* Does not reponse to the requests on the loopback interfaces */
paulc49ad8f2004-10-22 10:27:28 +00001703 if (if_is_loopback (ifc->ifp))
hasso16705132003-05-25 14:49:19 +00001704 return;
1705
hasso429a0f82004-02-22 23:42:22 +00001706 /* Check RIP process is enabled on this interface. */
paulc49ad8f2004-10-22 10:27:28 +00001707 ri = ifc->ifp->info;
hasso16705132003-05-25 14:49:19 +00001708 if (! ri->running)
1709 return;
paul718e3742002-12-13 20:15:29 +00001710
1711 /* When passive interface is specified, suppress responses */
1712 if (ri->passive)
1713 return;
paulc49ad8f2004-10-22 10:27:28 +00001714
paul718e3742002-12-13 20:15:29 +00001715 /* RIP peer update. */
1716 rip_peer_update (from, packet->version);
1717
1718 lim = ((caddr_t) packet) + size;
1719 rte = packet->rte;
1720
1721 /* The Request is processed entry by entry. If there are no
1722 entries, no response is given. */
1723 if (lim == (caddr_t) rte)
1724 return;
1725
1726 /* There is one special case. If there is exactly one entry in the
1727 request, and it has an address family identifier of zero and a
1728 metric of infinity (i.e., 16), then this is a request to send the
1729 entire routing table. */
1730 if (lim == ((caddr_t) (rte + 1)) &&
1731 ntohs (rte->family) == 0 &&
1732 ntohl (rte->metric) == RIP_METRIC_INFINITY)
1733 {
paulcc1131a2003-10-15 23:20:17 +00001734 struct prefix_ipv4 saddr;
1735
1736 /* saddr will be used for determining which routes to split-horizon.
1737 Since the source address we'll pick will be on the same subnet as the
1738 destination, for the purpose of split-horizoning, we'll
1739 pretend that "from" is our source address. */
1740 saddr.family = AF_INET;
1741 saddr.prefixlen = IPV4_MAX_BITLEN;
1742 saddr.prefix = from->sin_addr;
1743
paul718e3742002-12-13 20:15:29 +00001744 /* All route with split horizon */
paulc49ad8f2004-10-22 10:27:28 +00001745 rip_output_process (ifc, from, rip_all_route, packet->version);
paul718e3742002-12-13 20:15:29 +00001746 }
1747 else
1748 {
1749 /* Examine the list of RTEs in the Request one by one. For each
1750 entry, look up the destination in the router's routing
1751 database and, if there is a route, put that route's metric in
1752 the metric field of the RTE. If there is no explicit route
1753 to the specified destination, put infinity in the metric
1754 field. Once all the entries have been filled in, change the
1755 command from Request to Response and send the datagram back
1756 to the requestor. */
1757 p.family = AF_INET;
1758
1759 for (; ((caddr_t) rte) < lim; rte++)
1760 {
1761 p.prefix = rte->prefix;
1762 p.prefixlen = ip_masklen (rte->mask);
1763 apply_mask_ipv4 (&p);
1764
1765 rp = route_node_lookup (rip->table, (struct prefix *) &p);
1766 if (rp)
1767 {
Lu Fengb397cf42014-07-18 06:13:18 +00001768 rinfo = listgetdata (listhead ((struct list *)rp->info));
paul718e3742002-12-13 20:15:29 +00001769 rte->metric = htonl (rinfo->metric);
1770 route_unlock_node (rp);
1771 }
1772 else
1773 rte->metric = htonl (RIP_METRIC_INFINITY);
1774 }
1775 packet->command = RIP_RESPONSE;
1776
paulc49ad8f2004-10-22 10:27:28 +00001777 rip_send_packet ((u_char *)packet, size, from, ifc);
paul718e3742002-12-13 20:15:29 +00001778 }
1779 rip_global_queries++;
1780}
1781
1782#if RIP_RECVMSG
1783/* Set IPv6 packet info to the socket. */
1784static int
1785setsockopt_pktinfo (int sock)
1786{
1787 int ret;
1788 int val = 1;
1789
1790 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1791 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001792 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001793 return ret;
1794}
1795
1796/* Read RIP packet by recvmsg function. */
1797int
1798rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1799 int *ifindex)
1800{
1801 int ret;
1802 struct msghdr msg;
1803 struct iovec iov;
1804 struct cmsghdr *ptr;
1805 char adata[1024];
1806
1807 msg.msg_name = (void *) from;
1808 msg.msg_namelen = sizeof (struct sockaddr_in);
1809 msg.msg_iov = &iov;
1810 msg.msg_iovlen = 1;
1811 msg.msg_control = (void *) adata;
1812 msg.msg_controllen = sizeof adata;
1813 iov.iov_base = buf;
1814 iov.iov_len = size;
1815
1816 ret = recvmsg (sock, &msg, 0);
1817 if (ret < 0)
1818 return ret;
1819
ajsb99760a2005-01-04 16:24:43 +00001820 for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
paul718e3742002-12-13 20:15:29 +00001821 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1822 {
1823 struct in_pktinfo *pktinfo;
1824 int i;
1825
1826 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1827 i = pktinfo->ipi_ifindex;
1828 }
1829 return ret;
1830}
1831
1832/* RIP packet read function. */
1833int
1834rip_read_new (struct thread *t)
1835{
1836 int ret;
1837 int sock;
1838 char buf[RIP_PACKET_MAXSIZ];
1839 struct sockaddr_in from;
1840 unsigned int ifindex;
1841
1842 /* Fetch socket then register myself. */
1843 sock = THREAD_FD (t);
1844 rip_event (RIP_READ, sock);
1845
1846 /* Read RIP packet. */
1847 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1848 if (ret < 0)
1849 {
ajs6099b3b2004-11-20 02:06:59 +00001850 zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001851 return ret;
1852 }
1853
1854 return ret;
1855}
1856#endif /* RIP_RECVMSG */
1857
1858/* First entry point of RIP packet. */
pauldc63bfd2005-10-25 23:31:05 +00001859static int
paul718e3742002-12-13 20:15:29 +00001860rip_read (struct thread *t)
1861{
1862 int sock;
1863 int ret;
1864 int rtenum;
1865 union rip_buf rip_buf;
1866 struct rip_packet *packet;
1867 struct sockaddr_in from;
paul11dde9c2004-05-31 14:00:00 +00001868 int len;
Paul Jakma3e557ae2006-09-11 02:10:40 +00001869 int vrecv;
paul11dde9c2004-05-31 14:00:00 +00001870 socklen_t fromlen;
paul718e3742002-12-13 20:15:29 +00001871 struct interface *ifp;
paulc49ad8f2004-10-22 10:27:28 +00001872 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +00001873 struct rip_interface *ri;
1874
1875 /* Fetch socket then register myself. */
1876 sock = THREAD_FD (t);
1877 rip->t_read = NULL;
1878
1879 /* Add myself to tne next event */
1880 rip_event (RIP_READ, sock);
1881
1882 /* RIPd manages only IPv4. */
1883 memset (&from, 0, sizeof (struct sockaddr_in));
1884 fromlen = sizeof (struct sockaddr_in);
1885
1886 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1887 (struct sockaddr *) &from, &fromlen);
1888 if (len < 0)
1889 {
ajs6099b3b2004-11-20 02:06:59 +00001890 zlog_info ("recvfrom failed: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001891 return len;
1892 }
1893
1894 /* Check is this packet comming from myself? */
paul31a476c2003-09-29 19:54:53 +00001895 if (if_check_address (from.sin_addr))
paul718e3742002-12-13 20:15:29 +00001896 {
1897 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00001898 zlog_debug ("ignore packet comes from myself");
paul718e3742002-12-13 20:15:29 +00001899 return -1;
1900 }
1901
1902 /* Which interface is this packet comes from. */
1903 ifp = if_lookup_address (from.sin_addr);
paulc49ad8f2004-10-22 10:27:28 +00001904
paul718e3742002-12-13 20:15:29 +00001905 /* RIP packet received */
1906 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001907 zlog_debug ("RECV packet from %s port %d on %s",
paul718e3742002-12-13 20:15:29 +00001908 inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1909 ifp ? ifp->name : "unknown");
1910
1911 /* If this packet come from unknown interface, ignore it. */
1912 if (ifp == NULL)
1913 {
ajs766a0ca2004-12-15 14:55:51 +00001914 zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1915 inet_ntoa(from.sin_addr), ntohs (from.sin_port));
paulc49ad8f2004-10-22 10:27:28 +00001916 return -1;
1917 }
1918
1919 ifc = connected_lookup_address (ifp, from.sin_addr);
1920
1921 if (ifc == NULL)
1922 {
ajs766a0ca2004-12-15 14:55:51 +00001923 zlog_info ("rip_read: cannot find connected address for packet from %s "
1924 "port %d on interface %s",
1925 inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
paul718e3742002-12-13 20:15:29 +00001926 return -1;
1927 }
1928
1929 /* Packet length check. */
1930 if (len < RIP_PACKET_MINSIZ)
1931 {
1932 zlog_warn ("packet size %d is smaller than minimum size %d",
1933 len, RIP_PACKET_MINSIZ);
1934 rip_peer_bad_packet (&from);
1935 return len;
1936 }
1937 if (len > RIP_PACKET_MAXSIZ)
1938 {
1939 zlog_warn ("packet size %d is larger than max size %d",
1940 len, RIP_PACKET_MAXSIZ);
1941 rip_peer_bad_packet (&from);
1942 return len;
1943 }
1944
1945 /* Packet alignment check. */
1946 if ((len - RIP_PACKET_MINSIZ) % 20)
1947 {
1948 zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1949 rip_peer_bad_packet (&from);
1950 return len;
1951 }
1952
1953 /* Set RTE number. */
1954 rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1955
1956 /* For easy to handle. */
1957 packet = &rip_buf.rip_packet;
1958
1959 /* RIP version check. */
1960 if (packet->version == 0)
1961 {
1962 zlog_info ("version 0 with command %d received.", packet->command);
1963 rip_peer_bad_packet (&from);
1964 return -1;
1965 }
1966
1967 /* Dump RIP packet. */
1968 if (IS_RIP_DEBUG_RECV)
1969 rip_packet_dump (packet, len, "RECV");
1970
1971 /* RIP version adjust. This code should rethink now. RFC1058 says
1972 that "Version 1 implementations are to ignore this extra data and
1973 process only the fields specified in this document.". So RIPv3
1974 packet should be treated as RIPv1 ignoring must be zero field. */
1975 if (packet->version > RIPv2)
1976 packet->version = RIPv2;
1977
1978 /* Is RIP running or is this RIP neighbor ?*/
1979 ri = ifp->info;
1980 if (! ri->running && ! rip_neighbor_lookup (&from))
1981 {
1982 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00001983 zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
paul718e3742002-12-13 20:15:29 +00001984 rip_peer_bad_packet (&from);
1985 return -1;
1986 }
1987
Paul Jakma15a2b082006-05-04 07:36:34 +00001988 /* RIP Version check. RFC2453, 4.6 and 5.1 */
Paul Jakma3e557ae2006-09-11 02:10:40 +00001989 vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1990 rip->version_recv : ri->ri_receive);
Paul Jakma15a2b082006-05-04 07:36:34 +00001991 if ((packet->version == RIPv1) && !(vrecv & RIPv1))
paul718e3742002-12-13 20:15:29 +00001992 {
Paul Jakma15a2b082006-05-04 07:36:34 +00001993 if (IS_RIP_DEBUG_PACKET)
1994 zlog_debug (" packet's v%d doesn't fit to if version spec",
1995 packet->version);
1996 rip_peer_bad_packet (&from);
1997 return -1;
paul718e3742002-12-13 20:15:29 +00001998 }
Paul Jakma15a2b082006-05-04 07:36:34 +00001999 if ((packet->version == RIPv2) && !(vrecv & RIPv2))
2000 {
2001 if (IS_RIP_DEBUG_PACKET)
2002 zlog_debug (" packet's v%d doesn't fit to if version spec",
2003 packet->version);
2004 rip_peer_bad_packet (&from);
2005 return -1;
2006 }
2007
paul718e3742002-12-13 20:15:29 +00002008 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
2009 messages, then RIP-1 and unauthenticated RIP-2 messages will be
2010 accepted; authenticated RIP-2 messages shall be discarded. */
paul718e3742002-12-13 20:15:29 +00002011 if ((ri->auth_type == RIP_NO_AUTH)
2012 && rtenum
paulca5e5162004-06-06 22:06:33 +00002013 && (packet->version == RIPv2)
2014 && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
paul718e3742002-12-13 20:15:29 +00002015 {
2016 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002017 zlog_debug ("packet RIPv%d is dropped because authentication disabled",
paul718e3742002-12-13 20:15:29 +00002018 packet->version);
2019 rip_peer_bad_packet (&from);
2020 return -1;
2021 }
Paul Jakma15a2b082006-05-04 07:36:34 +00002022
2023 /* RFC:
2024 If the router is configured to authenticate RIP-2 messages, then
paul718e3742002-12-13 20:15:29 +00002025 RIP-1 messages and RIP-2 messages which pass authentication
2026 testing shall be accepted; unauthenticated and failed
2027 authentication RIP-2 messages shall be discarded. For maximum
2028 security, RIP-1 messages should be ignored when authentication is
2029 in use (see section 4.1); otherwise, the routing information from
2030 authenticated messages will be propagated by RIP-1 routers in an
Paul Jakma15a2b082006-05-04 07:36:34 +00002031 unauthenticated manner.
2032 */
2033 /* We make an exception for RIPv1 REQUEST packets, to which we'll
2034 * always reply regardless of authentication settings, because:
2035 *
2036 * - if there other authorised routers on-link, the REQUESTor can
2037 * passively obtain the routing updates anyway
2038 * - if there are no other authorised routers on-link, RIP can
2039 * easily be disabled for the link to prevent giving out information
2040 * on state of this routers RIP routing table..
2041 *
2042 * I.e. if RIPv1 has any place anymore these days, it's as a very
2043 * simple way to distribute routing information (e.g. to embedded
2044 * hosts / appliances) and the ability to give out RIPv1
2045 * routing-information freely, while still requiring RIPv2
2046 * authentication for any RESPONSEs might be vaguely useful.
2047 */
2048 if (ri->auth_type != RIP_NO_AUTH
2049 && packet->version == RIPv1)
paul718e3742002-12-13 20:15:29 +00002050 {
Paul Jakma15a2b082006-05-04 07:36:34 +00002051 /* Discard RIPv1 messages other than REQUESTs */
2052 if (packet->command != RIP_REQUEST)
2053 {
2054 if (IS_RIP_DEBUG_PACKET)
2055 zlog_debug ("RIPv1" " dropped because authentication enabled");
2056 rip_peer_bad_packet (&from);
2057 return -1;
2058 }
2059 }
2060 else if (ri->auth_type != RIP_NO_AUTH)
2061 {
2062 const char *auth_desc;
2063
2064 if (rtenum == 0)
2065 {
2066 /* There definitely is no authentication in the packet. */
2067 if (IS_RIP_DEBUG_PACKET)
2068 zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
2069 rip_peer_bad_packet (&from);
2070 return -1;
2071 }
2072
2073 /* First RTE must be an Authentication Family RTE */
2074 if (packet->rte->family != htons(RIP_FAMILY_AUTH))
2075 {
2076 if (IS_RIP_DEBUG_PACKET)
2077 zlog_debug ("RIPv2" " dropped because authentication enabled");
paul718e3742002-12-13 20:15:29 +00002078 rip_peer_bad_packet (&from);
2079 return -1;
Paul Jakma15a2b082006-05-04 07:36:34 +00002080 }
2081
paul718e3742002-12-13 20:15:29 +00002082 /* Check RIPv2 authentication. */
Paul Jakma15a2b082006-05-04 07:36:34 +00002083 switch (ntohs(packet->rte->tag))
2084 {
2085 case RIP_AUTH_SIMPLE_PASSWORD:
2086 auth_desc = "simple";
2087 ret = rip_auth_simple_password (packet->rte, &from, ifp);
2088 break;
2089
2090 case RIP_AUTH_MD5:
2091 auth_desc = "MD5";
2092 ret = rip_auth_md5 (packet, &from, len, ifp);
2093 /* Reset RIP packet length to trim MD5 data. */
2094 len = ret;
2095 break;
2096
2097 default:
2098 ret = 0;
2099 auth_desc = "unknown type";
2100 if (IS_RIP_DEBUG_PACKET)
2101 zlog_debug ("RIPv2 Unknown authentication type %d",
2102 ntohs (packet->rte->tag));
2103 }
2104
2105 if (ret)
2106 {
2107 if (IS_RIP_DEBUG_PACKET)
2108 zlog_debug ("RIPv2 %s authentication success", auth_desc);
2109 }
2110 else
2111 {
2112 if (IS_RIP_DEBUG_PACKET)
2113 zlog_debug ("RIPv2 %s authentication failure", auth_desc);
2114 rip_peer_bad_packet (&from);
2115 return -1;
2116 }
paul718e3742002-12-13 20:15:29 +00002117 }
2118
2119 /* Process each command. */
2120 switch (packet->command)
2121 {
2122 case RIP_RESPONSE:
paulc49ad8f2004-10-22 10:27:28 +00002123 rip_response_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002124 break;
2125 case RIP_REQUEST:
2126 case RIP_POLL:
paulc49ad8f2004-10-22 10:27:28 +00002127 rip_request_process (packet, len, &from, ifc);
paul718e3742002-12-13 20:15:29 +00002128 break;
2129 case RIP_TRACEON:
2130 case RIP_TRACEOFF:
2131 zlog_info ("Obsolete command %s received, please sent it to routed",
2132 lookup (rip_msg, packet->command));
2133 rip_peer_bad_packet (&from);
2134 break;
2135 case RIP_POLL_ENTRY:
2136 zlog_info ("Obsolete command %s received",
2137 lookup (rip_msg, packet->command));
2138 rip_peer_bad_packet (&from);
2139 break;
2140 default:
2141 zlog_info ("Unknown RIP command %d received", packet->command);
2142 rip_peer_bad_packet (&from);
2143 break;
2144 }
2145
2146 return len;
2147}
2148
paul718e3742002-12-13 20:15:29 +00002149/* Write routing table entry to the stream and return next index of
2150 the routing table entry in the stream. */
pauldc63bfd2005-10-25 23:31:05 +00002151static int
paul718e3742002-12-13 20:15:29 +00002152rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
paulb14ee002005-02-04 23:42:41 +00002153 u_char version, struct rip_info *rinfo)
paul718e3742002-12-13 20:15:29 +00002154{
2155 struct in_addr mask;
paul718e3742002-12-13 20:15:29 +00002156
2157 /* Write routing table entry. */
2158 if (version == RIPv1)
2159 {
2160 stream_putw (s, AF_INET);
2161 stream_putw (s, 0);
2162 stream_put_ipv4 (s, p->prefix.s_addr);
2163 stream_put_ipv4 (s, 0);
2164 stream_put_ipv4 (s, 0);
2165 stream_putl (s, rinfo->metric_out);
2166 }
2167 else
2168 {
2169 masklen2ip (p->prefixlen, &mask);
2170
2171 stream_putw (s, AF_INET);
hasso16705132003-05-25 14:49:19 +00002172 stream_putw (s, rinfo->tag_out);
paul718e3742002-12-13 20:15:29 +00002173 stream_put_ipv4 (s, p->prefix.s_addr);
2174 stream_put_ipv4 (s, mask.s_addr);
2175 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2176 stream_putl (s, rinfo->metric_out);
2177 }
2178
2179 return ++num;
2180}
2181
2182/* Send update to the ifp or spcified neighbor. */
2183void
paulc49ad8f2004-10-22 10:27:28 +00002184rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2185 int route_type, u_char version)
paul718e3742002-12-13 20:15:29 +00002186{
2187 int ret;
2188 struct stream *s;
2189 struct route_node *rp;
2190 struct rip_info *rinfo;
2191 struct rip_interface *ri;
2192 struct prefix_ipv4 *p;
2193 struct prefix_ipv4 classfull;
paul727d1042002-12-13 20:50:29 +00002194 struct prefix_ipv4 ifaddrclass;
paulb14ee002005-02-04 23:42:41 +00002195 struct key *key = NULL;
2196 /* this might need to made dynamic if RIP ever supported auth methods
2197 with larger key string sizes */
2198 char auth_str[RIP_AUTH_SIMPLE_SIZE];
pauldc63bfd2005-10-25 23:31:05 +00002199 size_t doff = 0; /* offset of digest offset field */
paul2c61ae32005-08-16 15:22:14 +00002200 int num = 0;
paul718e3742002-12-13 20:15:29 +00002201 int rtemax;
paul01d09082003-06-08 21:22:18 +00002202 int subnetted = 0;
Lu Fengb397cf42014-07-18 06:13:18 +00002203 struct list *list = NULL;
2204 struct listnode *listnode = NULL;
paul718e3742002-12-13 20:15:29 +00002205
2206 /* Logging output event. */
2207 if (IS_RIP_DEBUG_EVENT)
2208 {
2209 if (to)
ajs5d6c3772004-12-08 19:24:06 +00002210 zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
paul718e3742002-12-13 20:15:29 +00002211 else
ajs5d6c3772004-12-08 19:24:06 +00002212 zlog_debug ("update routes on interface %s ifindex %d",
paulc49ad8f2004-10-22 10:27:28 +00002213 ifc->ifp->name, ifc->ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002214 }
2215
2216 /* Set output stream. */
2217 s = rip->obuf;
2218
2219 /* Reset stream and RTE counter. */
2220 stream_reset (s);
Lu Feng342a31b2014-06-25 07:43:15 +00002221 rtemax = RIP_MAX_RTE;
paul718e3742002-12-13 20:15:29 +00002222
2223 /* Get RIP interface. */
paulc49ad8f2004-10-22 10:27:28 +00002224 ri = ifc->ifp->info;
paul718e3742002-12-13 20:15:29 +00002225
2226 /* If output interface is in simple password authentication mode, we
2227 need space for authentication data. */
2228 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2229 rtemax -= 1;
2230
2231 /* If output interface is in MD5 authentication mode, we need space
2232 for authentication header and data. */
2233 if (ri->auth_type == RIP_AUTH_MD5)
2234 rtemax -= 2;
2235
2236 /* If output interface is in simple password authentication mode
2237 and string or keychain is specified we need space for auth. data */
paulb14ee002005-02-04 23:42:41 +00002238 if (ri->auth_type != RIP_NO_AUTH)
paul718e3742002-12-13 20:15:29 +00002239 {
2240 if (ri->key_chain)
2241 {
2242 struct keychain *keychain;
2243
2244 keychain = keychain_lookup (ri->key_chain);
2245 if (keychain)
paulb14ee002005-02-04 23:42:41 +00002246 key = key_lookup_for_send (keychain);
paul718e3742002-12-13 20:15:29 +00002247 }
paulb14ee002005-02-04 23:42:41 +00002248 /* to be passed to auth functions later */
2249 rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002250 }
2251
paul727d1042002-12-13 20:50:29 +00002252 if (version == RIPv1)
2253 {
paulc49ad8f2004-10-22 10:27:28 +00002254 memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
paul727d1042002-12-13 20:50:29 +00002255 apply_classful_mask_ipv4 (&ifaddrclass);
2256 subnetted = 0;
paulc49ad8f2004-10-22 10:27:28 +00002257 if (ifc->address->prefixlen > ifaddrclass.prefixlen)
paul01d09082003-06-08 21:22:18 +00002258 subnetted = 1;
paul727d1042002-12-13 20:50:29 +00002259 }
2260
paul718e3742002-12-13 20:15:29 +00002261 for (rp = route_top (rip->table); rp; rp = route_next (rp))
Lu Fengb397cf42014-07-18 06:13:18 +00002262 if ((list = rp->info) != NULL && listcount (list) != 0)
paul718e3742002-12-13 20:15:29 +00002263 {
Lu Fengb397cf42014-07-18 06:13:18 +00002264 rinfo = listgetdata (listhead (list));
paul727d1042002-12-13 20:50:29 +00002265 /* For RIPv1, if we are subnetted, output subnets in our network */
2266 /* that have the same mask as the output "interface". For other */
2267 /* networks, only the classfull version is output. */
paul718e3742002-12-13 20:15:29 +00002268
2269 if (version == RIPv1)
2270 {
paul727d1042002-12-13 20:50:29 +00002271 p = (struct prefix_ipv4 *) &rp->p;
paul718e3742002-12-13 20:15:29 +00002272
2273 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002274 zlog_debug("RIPv1 mask check, %s/%d considered for output",
paul727d1042002-12-13 20:50:29 +00002275 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002276
paul727d1042002-12-13 20:50:29 +00002277 if (subnetted &&
2278 prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2279 {
paulc49ad8f2004-10-22 10:27:28 +00002280 if ((ifc->address->prefixlen != rp->p.prefixlen) &&
paul727d1042002-12-13 20:50:29 +00002281 (rp->p.prefixlen != 32))
2282 continue;
2283 }
2284 else
2285 {
2286 memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2287 apply_classful_mask_ipv4(&classfull);
2288 if (rp->p.u.prefix4.s_addr != 0 &&
2289 classfull.prefixlen != rp->p.prefixlen)
2290 continue;
2291 }
paul718e3742002-12-13 20:15:29 +00002292 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002293 zlog_debug("RIPv1 mask check, %s/%d made it through",
paul727d1042002-12-13 20:50:29 +00002294 inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
paul718e3742002-12-13 20:15:29 +00002295 }
2296 else
2297 p = (struct prefix_ipv4 *) &rp->p;
2298
2299 /* Apply output filters. */
2300 ret = rip_outgoing_filter (p, ri);
2301 if (ret < 0)
2302 continue;
2303
2304 /* Changed route only output. */
2305 if (route_type == rip_changed_route &&
2306 (! (rinfo->flags & RIP_RTF_CHANGED)))
2307 continue;
2308
2309 /* Split horizon. */
2310 /* if (split_horizon == rip_split_horizon) */
hasso16705132003-05-25 14:49:19 +00002311 if (ri->split_horizon == RIP_SPLIT_HORIZON)
paul718e3742002-12-13 20:15:29 +00002312 {
paul42d14d92003-11-17 09:15:18 +00002313 /*
2314 * We perform split horizon for RIP and connected route.
2315 * For rip routes, we want to suppress the route if we would
2316 * end up sending the route back on the interface that we
2317 * learned it from, with a higher metric. For connected routes,
2318 * we suppress the route if the prefix is a subset of the
2319 * source address that we are going to use for the packet
2320 * (in order to handle the case when multiple subnets are
2321 * configured on the same interface).
2322 */
Lu Fengb397cf42014-07-18 06:13:18 +00002323 int suppress = 0;
2324 struct rip_info *tmp_rinfo = NULL;
2325
2326 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
2327 if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2328 tmp_rinfo->ifindex == ifc->ifp->ifindex)
2329 {
2330 suppress = 1;
2331 break;
2332 }
2333
2334 if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002335 prefix_match((struct prefix *)p, ifc->address))
Lu Fengb397cf42014-07-18 06:13:18 +00002336 suppress = 1;
2337
2338 if (suppress)
paul718e3742002-12-13 20:15:29 +00002339 continue;
2340 }
2341
2342 /* Preparation for route-map. */
2343 rinfo->metric_set = 0;
2344 rinfo->nexthop_out.s_addr = 0;
2345 rinfo->metric_out = rinfo->metric;
hasso16705132003-05-25 14:49:19 +00002346 rinfo->tag_out = rinfo->tag;
paulc49ad8f2004-10-22 10:27:28 +00002347 rinfo->ifindex_out = ifc->ifp->ifindex;
paul718e3742002-12-13 20:15:29 +00002348
hasso16705132003-05-25 14:49:19 +00002349 /* In order to avoid some local loops,
2350 * if the RIP route has a nexthop via this interface, keep the nexthop,
2351 * otherwise set it to 0. The nexthop should not be propagated
2352 * beyond the local broadcast/multicast area in order
2353 * to avoid an IGP multi-level recursive look-up.
2354 * see (4.4)
2355 */
paulc49ad8f2004-10-22 10:27:28 +00002356 if (rinfo->ifindex == ifc->ifp->ifindex)
paul718e3742002-12-13 20:15:29 +00002357 rinfo->nexthop_out = rinfo->nexthop;
hasso16705132003-05-25 14:49:19 +00002358
2359 /* Interface route-map */
2360 if (ri->routemap[RIP_FILTER_OUT])
2361 {
2362 ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2363 (struct prefix *) p, RMAP_RIP,
2364 rinfo);
2365
2366 if (ret == RMAP_DENYMATCH)
2367 {
2368 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002369 zlog_debug ("RIP %s/%d is filtered by route-map out",
hasso16705132003-05-25 14:49:19 +00002370 inet_ntoa (p->prefix), p->prefixlen);
2371 continue;
2372 }
2373 }
paul718e3742002-12-13 20:15:29 +00002374
hasso16705132003-05-25 14:49:19 +00002375 /* Apply redistribute route map - continue, if deny */
paul718e3742002-12-13 20:15:29 +00002376 if (rip->route_map[rinfo->type].name
2377 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2378 {
2379 ret = route_map_apply (rip->route_map[rinfo->type].map,
2380 (struct prefix *)p, RMAP_RIP, rinfo);
2381
2382 if (ret == RMAP_DENYMATCH)
2383 {
2384 if (IS_RIP_DEBUG_PACKET)
ajs5d6c3772004-12-08 19:24:06 +00002385 zlog_debug ("%s/%d is filtered by route-map",
paul718e3742002-12-13 20:15:29 +00002386 inet_ntoa (p->prefix), p->prefixlen);
2387 continue;
2388 }
2389 }
2390
2391 /* When route-map does not set metric. */
2392 if (! rinfo->metric_set)
2393 {
2394 /* If redistribute metric is set. */
2395 if (rip->route_map[rinfo->type].metric_config
2396 && rinfo->metric != RIP_METRIC_INFINITY)
2397 {
2398 rinfo->metric_out = rip->route_map[rinfo->type].metric;
2399 }
2400 else
2401 {
2402 /* If the route is not connected or localy generated
2403 one, use default-metric value*/
2404 if (rinfo->type != ZEBRA_ROUTE_RIP
2405 && rinfo->type != ZEBRA_ROUTE_CONNECT
2406 && rinfo->metric != RIP_METRIC_INFINITY)
2407 rinfo->metric_out = rip->default_metric;
2408 }
2409 }
2410
2411 /* Apply offset-list */
2412 if (rinfo->metric != RIP_METRIC_INFINITY)
paulc49ad8f2004-10-22 10:27:28 +00002413 rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00002414
2415 if (rinfo->metric_out > RIP_METRIC_INFINITY)
2416 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002417
2418 /* Perform split-horizon with poisoned reverse
2419 * for RIP and connected routes.
2420 **/
2421 if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
paul42d14d92003-11-17 09:15:18 +00002422 /*
2423 * We perform split horizon for RIP and connected route.
2424 * For rip routes, we want to suppress the route if we would
2425 * end up sending the route back on the interface that we
2426 * learned it from, with a higher metric. For connected routes,
2427 * we suppress the route if the prefix is a subset of the
2428 * source address that we are going to use for the packet
2429 * (in order to handle the case when multiple subnets are
2430 * configured on the same interface).
2431 */
Lu Fengb397cf42014-07-18 06:13:18 +00002432 struct rip_info *tmp_rinfo = NULL;
2433
2434 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
2435 if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
2436 tmp_rinfo->ifindex == ifc->ifp->ifindex)
2437 rinfo->metric_out = RIP_METRIC_INFINITY;
2438 if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT &&
paulc49ad8f2004-10-22 10:27:28 +00002439 prefix_match((struct prefix *)p, ifc->address))
Lu Fengb397cf42014-07-18 06:13:18 +00002440 rinfo->metric_out = RIP_METRIC_INFINITY;
hasso16705132003-05-25 14:49:19 +00002441 }
paulb14ee002005-02-04 23:42:41 +00002442
2443 /* Prepare preamble, auth headers, if needs be */
2444 if (num == 0)
2445 {
2446 stream_putc (s, RIP_RESPONSE);
2447 stream_putc (s, version);
2448 stream_putw (s, 0);
2449
paul0cb8a012005-05-29 11:27:24 +00002450 /* auth header for !v1 && !no_auth */
2451 if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
paulb14ee002005-02-04 23:42:41 +00002452 doff = rip_auth_header_write (s, ri, key, auth_str,
2453 RIP_AUTH_SIMPLE_SIZE);
2454 }
2455
paul718e3742002-12-13 20:15:29 +00002456 /* Write RTE to the stream. */
paulb14ee002005-02-04 23:42:41 +00002457 num = rip_write_rte (num, s, p, version, rinfo);
paul718e3742002-12-13 20:15:29 +00002458 if (num == rtemax)
2459 {
2460 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002461 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002462
2463 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
paulc49ad8f2004-10-22 10:27:28 +00002464 to, ifc);
paul718e3742002-12-13 20:15:29 +00002465
2466 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2467 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2468 stream_get_endp(s), "SEND");
2469 num = 0;
2470 stream_reset (s);
2471 }
2472 }
2473
2474 /* Flush unwritten RTE. */
2475 if (num != 0)
2476 {
2477 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
paulb14ee002005-02-04 23:42:41 +00002478 rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
paul718e3742002-12-13 20:15:29 +00002479
paulc49ad8f2004-10-22 10:27:28 +00002480 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
paul718e3742002-12-13 20:15:29 +00002481
2482 if (ret >= 0 && IS_RIP_DEBUG_SEND)
2483 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2484 stream_get_endp (s), "SEND");
2485 num = 0;
2486 stream_reset (s);
2487 }
2488
2489 /* Statistics updates. */
2490 ri->sent_updates++;
2491}
2492
2493/* Send RIP packet to the interface. */
pauldc63bfd2005-10-25 23:31:05 +00002494static void
paulc49ad8f2004-10-22 10:27:28 +00002495rip_update_interface (struct connected *ifc, u_char version, int route_type)
paul718e3742002-12-13 20:15:29 +00002496{
paul718e3742002-12-13 20:15:29 +00002497 struct sockaddr_in to;
2498
2499 /* When RIP version is 2 and multicast enable interface. */
paulc49ad8f2004-10-22 10:27:28 +00002500 if (version == RIPv2 && if_is_multicast (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002501 {
2502 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002503 zlog_debug ("multicast announce on %s ", ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002504
paulc49ad8f2004-10-22 10:27:28 +00002505 rip_output_process (ifc, NULL, route_type, version);
paul718e3742002-12-13 20:15:29 +00002506 return;
2507 }
paulc49ad8f2004-10-22 10:27:28 +00002508
paul718e3742002-12-13 20:15:29 +00002509 /* If we can't send multicast packet, send it with unicast. */
paulc49ad8f2004-10-22 10:27:28 +00002510 if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
paul718e3742002-12-13 20:15:29 +00002511 {
paulc49ad8f2004-10-22 10:27:28 +00002512 if (ifc->address->family == AF_INET)
2513 {
2514 /* Destination address and port setting. */
2515 memset (&to, 0, sizeof (struct sockaddr_in));
2516 if (ifc->destination)
Andrew J. Schorre4529632006-12-12 19:18:21 +00002517 /* use specified broadcast or peer destination addr */
paulc49ad8f2004-10-22 10:27:28 +00002518 to.sin_addr = ifc->destination->u.prefix4;
Andrew J. Schorre4529632006-12-12 19:18:21 +00002519 else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
paulc49ad8f2004-10-22 10:27:28 +00002520 /* calculate the appropriate broadcast address */
2521 to.sin_addr.s_addr =
2522 ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2523 ifc->address->prefixlen);
Andrew J. Schorre4529632006-12-12 19:18:21 +00002524 else
2525 /* do not know where to send the packet */
2526 return;
paulc49ad8f2004-10-22 10:27:28 +00002527 to.sin_port = htons (RIP_PORT_DEFAULT);
paul718e3742002-12-13 20:15:29 +00002528
paulc49ad8f2004-10-22 10:27:28 +00002529 if (IS_RIP_DEBUG_EVENT)
Andrew J. Schorre4529632006-12-12 19:18:21 +00002530 zlog_debug("%s announce to %s on %s",
2531 CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
2532 inet_ntoa (to.sin_addr), ifc->ifp->name);
paul718e3742002-12-13 20:15:29 +00002533
paulc49ad8f2004-10-22 10:27:28 +00002534 rip_output_process (ifc, &to, route_type, version);
2535 }
paul718e3742002-12-13 20:15:29 +00002536 }
2537}
2538
2539/* Update send to all interface and neighbor. */
pauldc63bfd2005-10-25 23:31:05 +00002540static void
paul718e3742002-12-13 20:15:29 +00002541rip_update_process (int route_type)
2542{
paul1eb8ef22005-04-07 07:30:20 +00002543 struct listnode *node;
2544 struct listnode *ifnode, *ifnnode;
paulcc1131a2003-10-15 23:20:17 +00002545 struct connected *connected;
paul718e3742002-12-13 20:15:29 +00002546 struct interface *ifp;
2547 struct rip_interface *ri;
2548 struct route_node *rp;
2549 struct sockaddr_in to;
2550 struct prefix_ipv4 *p;
2551
2552 /* Send RIP update to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00002553 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00002554 {
paul718e3742002-12-13 20:15:29 +00002555 if (if_is_loopback (ifp))
2556 continue;
2557
paul2e3b2e42002-12-13 21:03:13 +00002558 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +00002559 continue;
2560
2561 /* Fetch RIP interface information. */
2562 ri = ifp->info;
2563
2564 /* When passive interface is specified, suppress announce to the
2565 interface. */
2566 if (ri->passive)
2567 continue;
2568
2569 if (ri->running)
2570 {
Andrew J. Schorrb9d92882006-04-28 16:22:36 +00002571 /*
2572 * If there is no version configuration in the interface,
2573 * use rip's version setting.
2574 */
2575 int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2576 rip->version_send : ri->ri_send);
2577
paul718e3742002-12-13 20:15:29 +00002578 if (IS_RIP_DEBUG_EVENT)
Andrew J. Schorrb9d92882006-04-28 16:22:36 +00002579 zlog_debug("SEND UPDATE to %s ifindex %d",
2580 (ifp->name ? ifp->name : "_unknown_"), ifp->ifindex);
paul718e3742002-12-13 20:15:29 +00002581
paulcc1131a2003-10-15 23:20:17 +00002582 /* send update on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002583 for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002584 {
Andrew J. Schorrb9d92882006-04-28 16:22:36 +00002585 if (connected->address->family == AF_INET)
2586 {
2587 if (vsend & RIPv1)
2588 rip_update_interface (connected, RIPv1, route_type);
2589 if ((vsend & RIPv2) && if_is_multicast(ifp))
2590 rip_update_interface (connected, RIPv2, route_type);
2591 }
2592 }
paul718e3742002-12-13 20:15:29 +00002593 }
2594 }
2595
2596 /* RIP send updates to each neighbor. */
2597 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2598 if (rp->info != NULL)
2599 {
2600 p = (struct prefix_ipv4 *) &rp->p;
2601
2602 ifp = if_lookup_address (p->prefix);
2603 if (! ifp)
2604 {
paulc49ad8f2004-10-22 10:27:28 +00002605 zlog_warn ("Neighbor %s doesnt have connected interface!",
paul718e3742002-12-13 20:15:29 +00002606 inet_ntoa (p->prefix));
2607 continue;
2608 }
paulc49ad8f2004-10-22 10:27:28 +00002609
2610 if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2611 {
2612 zlog_warn ("Neighbor %s doesnt have connected network",
2613 inet_ntoa (p->prefix));
2614 continue;
2615 }
2616
paul718e3742002-12-13 20:15:29 +00002617 /* Set destination address and port */
2618 memset (&to, 0, sizeof (struct sockaddr_in));
2619 to.sin_addr = p->prefix;
2620 to.sin_port = htons (RIP_PORT_DEFAULT);
2621
2622 /* RIP version is rip's configuration. */
paulc49ad8f2004-10-22 10:27:28 +00002623 rip_output_process (connected, &to, route_type, rip->version_send);
paul718e3742002-12-13 20:15:29 +00002624 }
2625}
2626
2627/* RIP's periodical timer. */
pauldc63bfd2005-10-25 23:31:05 +00002628static int
paul718e3742002-12-13 20:15:29 +00002629rip_update (struct thread *t)
2630{
2631 /* Clear timer pointer. */
2632 rip->t_update = NULL;
2633
2634 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002635 zlog_debug ("update timer fire!");
paul718e3742002-12-13 20:15:29 +00002636
2637 /* Process update output. */
2638 rip_update_process (rip_all_route);
2639
2640 /* Triggered updates may be suppressed if a regular update is due by
2641 the time the triggered update would be sent. */
2642 if (rip->t_triggered_interval)
2643 {
2644 thread_cancel (rip->t_triggered_interval);
2645 rip->t_triggered_interval = NULL;
2646 }
2647 rip->trigger = 0;
2648
2649 /* Register myself. */
2650 rip_event (RIP_UPDATE_EVENT, 0);
2651
2652 return 0;
2653}
2654
2655/* Walk down the RIP routing table then clear changed flag. */
pauldc63bfd2005-10-25 23:31:05 +00002656static void
paul216565a2005-10-25 23:35:28 +00002657rip_clear_changed_flag (void)
paul718e3742002-12-13 20:15:29 +00002658{
2659 struct route_node *rp;
Lu Fengb397cf42014-07-18 06:13:18 +00002660 struct rip_info *rinfo = NULL;
2661 struct list *list = NULL;
2662 struct listnode *listnode = NULL;
paul718e3742002-12-13 20:15:29 +00002663
2664 for (rp = route_top (rip->table); rp; rp = route_next (rp))
Lu Fengb397cf42014-07-18 06:13:18 +00002665 if ((list = rp->info) != NULL)
2666 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
2667 {
2668 UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
2669 /* This flag can be set only on the first entry. */
2670 break;
2671 }
paul718e3742002-12-13 20:15:29 +00002672}
2673
2674/* Triggered update interval timer. */
pauldc63bfd2005-10-25 23:31:05 +00002675static int
paul718e3742002-12-13 20:15:29 +00002676rip_triggered_interval (struct thread *t)
2677{
2678 int rip_triggered_update (struct thread *);
2679
2680 rip->t_triggered_interval = NULL;
2681
2682 if (rip->trigger)
2683 {
2684 rip->trigger = 0;
2685 rip_triggered_update (t);
2686 }
2687 return 0;
2688}
2689
2690/* Execute triggered update. */
pauldc63bfd2005-10-25 23:31:05 +00002691static int
paul718e3742002-12-13 20:15:29 +00002692rip_triggered_update (struct thread *t)
2693{
2694 int interval;
2695
2696 /* Clear thred pointer. */
2697 rip->t_triggered_update = NULL;
2698
2699 /* Cancel interval timer. */
2700 if (rip->t_triggered_interval)
2701 {
2702 thread_cancel (rip->t_triggered_interval);
2703 rip->t_triggered_interval = NULL;
2704 }
2705 rip->trigger = 0;
2706
2707 /* Logging triggered update. */
2708 if (IS_RIP_DEBUG_EVENT)
ajs5d6c3772004-12-08 19:24:06 +00002709 zlog_debug ("triggered update!");
paul718e3742002-12-13 20:15:29 +00002710
2711 /* Split Horizon processing is done when generating triggered
2712 updates as well as normal updates (see section 2.6). */
2713 rip_update_process (rip_changed_route);
2714
2715 /* Once all of the triggered updates have been generated, the route
2716 change flags should be cleared. */
2717 rip_clear_changed_flag ();
2718
2719 /* After a triggered update is sent, a timer should be set for a
2720 random interval between 1 and 5 seconds. If other changes that
2721 would trigger updates occur before the timer expires, a single
2722 update is triggered when the timer expires. */
2723 interval = (random () % 5) + 1;
2724
2725 rip->t_triggered_interval =
2726 thread_add_timer (master, rip_triggered_interval, NULL, interval);
2727
2728 return 0;
2729}
2730
2731/* Withdraw redistributed route. */
2732void
2733rip_redistribute_withdraw (int type)
2734{
2735 struct route_node *rp;
Lu Fengb397cf42014-07-18 06:13:18 +00002736 struct rip_info *rinfo = NULL;
2737 struct list *list = NULL;
paul718e3742002-12-13 20:15:29 +00002738
2739 if (!rip)
2740 return;
2741
2742 for (rp = route_top (rip->table); rp; rp = route_next (rp))
Lu Fengb397cf42014-07-18 06:13:18 +00002743 if ((list = rp->info) != NULL)
paul718e3742002-12-13 20:15:29 +00002744 {
Lu Fengb397cf42014-07-18 06:13:18 +00002745 rinfo = listgetdata (listhead (list));
paul718e3742002-12-13 20:15:29 +00002746 if (rinfo->type == type
2747 && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2748 {
2749 /* Perform poisoned reverse. */
2750 rinfo->metric = RIP_METRIC_INFINITY;
2751 RIP_TIMER_ON (rinfo->t_garbage_collect,
2752 rip_garbage_collect, rip->garbage_time);
2753 RIP_TIMER_OFF (rinfo->t_timeout);
2754 rinfo->flags |= RIP_RTF_CHANGED;
2755
hasso16705132003-05-25 14:49:19 +00002756 if (IS_RIP_DEBUG_EVENT) {
2757 struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2758
ajs5d6c3772004-12-08 19:24:06 +00002759 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
hasso16705132003-05-25 14:49:19 +00002760 inet_ntoa(p->prefix), p->prefixlen,
2761 ifindex2ifname(rinfo->ifindex));
2762 }
2763
paul718e3742002-12-13 20:15:29 +00002764 rip_event (RIP_TRIGGERED_UPDATE, 0);
2765 }
2766 }
2767}
2768
2769/* Create new RIP instance and set it to global variable. */
pauldc63bfd2005-10-25 23:31:05 +00002770static int
2771rip_create (void)
paul718e3742002-12-13 20:15:29 +00002772{
Stephen Hemminger393deb92008-08-18 14:13:29 -07002773 rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
paul718e3742002-12-13 20:15:29 +00002774
2775 /* Set initial value. */
paulf38a4712003-06-07 01:10:00 +00002776 rip->version_send = RI_RIP_VERSION_2;
2777 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002778 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2779 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2780 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2781 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2782
2783 /* Initialize RIP routig table. */
2784 rip->table = route_table_init ();
2785 rip->route = route_table_init ();
2786 rip->neighbor = route_table_init ();
2787
2788 /* Make output stream. */
2789 rip->obuf = stream_new (1500);
2790
2791 /* Make socket. */
paulf69bd9d2005-06-03 18:01:50 +00002792 rip->sock = rip_create_socket (NULL);
paul718e3742002-12-13 20:15:29 +00002793 if (rip->sock < 0)
2794 return rip->sock;
2795
2796 /* Create read and timer thread. */
2797 rip_event (RIP_READ, rip->sock);
2798 rip_event (RIP_UPDATE_EVENT, 1);
2799
2800 return 0;
2801}
2802
2803/* Sned RIP request to the destination. */
2804int
2805rip_request_send (struct sockaddr_in *to, struct interface *ifp,
paul931cd542004-01-23 15:31:42 +00002806 u_char version, struct connected *connected)
paul718e3742002-12-13 20:15:29 +00002807{
2808 struct rte *rte;
2809 struct rip_packet rip_packet;
paul1eb8ef22005-04-07 07:30:20 +00002810 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002811
2812 memset (&rip_packet, 0, sizeof (rip_packet));
2813
2814 rip_packet.command = RIP_REQUEST;
2815 rip_packet.version = version;
2816 rte = rip_packet.rte;
2817 rte->metric = htonl (RIP_METRIC_INFINITY);
2818
paul931cd542004-01-23 15:31:42 +00002819 if (connected)
2820 {
2821 /*
2822 * connected is only sent for ripv1 case, or when
2823 * interface does not support multicast. Caller loops
2824 * over each connected address for this case.
2825 */
paul11dde9c2004-05-31 14:00:00 +00002826 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002827 to, connected) != sizeof (rip_packet))
paul931cd542004-01-23 15:31:42 +00002828 return -1;
2829 else
2830 return sizeof (rip_packet);
2831 }
2832
paulcc1131a2003-10-15 23:20:17 +00002833 /* send request on each connected network */
paul1eb8ef22005-04-07 07:30:20 +00002834 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
paulcc1131a2003-10-15 23:20:17 +00002835 {
2836 struct prefix_ipv4 *p;
2837
2838 p = (struct prefix_ipv4 *) connected->address;
2839
2840 if (p->family != AF_INET)
2841 continue;
2842
paul11dde9c2004-05-31 14:00:00 +00002843 if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
paulc49ad8f2004-10-22 10:27:28 +00002844 to, connected) != sizeof (rip_packet))
paulcc1131a2003-10-15 23:20:17 +00002845 return -1;
2846 }
2847 return sizeof (rip_packet);
paul718e3742002-12-13 20:15:29 +00002848}
David Lamparter6b0655a2014-06-04 06:53:35 +02002849
pauldc63bfd2005-10-25 23:31:05 +00002850static int
paul718e3742002-12-13 20:15:29 +00002851rip_update_jitter (unsigned long time)
2852{
paul239389b2004-05-05 14:09:37 +00002853#define JITTER_BOUND 4
2854 /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2855 Given that, we cannot let time be less than JITTER_BOUND seconds.
2856 The RIPv2 RFC says jitter should be small compared to
2857 update_time. We consider 1/JITTER_BOUND to be small.
2858 */
2859
2860 int jitter_input = time;
2861 int jitter;
2862
2863 if (jitter_input < JITTER_BOUND)
2864 jitter_input = JITTER_BOUND;
2865
2866 jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input));
2867
2868 return jitter/JITTER_BOUND;
paul718e3742002-12-13 20:15:29 +00002869}
2870
2871void
2872rip_event (enum rip_event event, int sock)
2873{
2874 int jitter = 0;
2875
2876 switch (event)
2877 {
2878 case RIP_READ:
2879 rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2880 break;
2881 case RIP_UPDATE_EVENT:
2882 if (rip->t_update)
2883 {
2884 thread_cancel (rip->t_update);
2885 rip->t_update = NULL;
2886 }
2887 jitter = rip_update_jitter (rip->update_time);
2888 rip->t_update =
2889 thread_add_timer (master, rip_update, NULL,
2890 sock ? 2 : rip->update_time + jitter);
2891 break;
2892 case RIP_TRIGGERED_UPDATE:
2893 if (rip->t_triggered_interval)
2894 rip->trigger = 1;
2895 else if (! rip->t_triggered_update)
2896 rip->t_triggered_update =
2897 thread_add_event (master, rip_triggered_update, NULL, 0);
2898 break;
2899 default:
2900 break;
2901 }
2902}
David Lamparter6b0655a2014-06-04 06:53:35 +02002903
paul718e3742002-12-13 20:15:29 +00002904DEFUN (router_rip,
2905 router_rip_cmd,
2906 "router rip",
2907 "Enable a routing process\n"
2908 "Routing Information Protocol (RIP)\n")
2909{
2910 int ret;
2911
2912 /* If rip is not enabled before. */
2913 if (! rip)
2914 {
2915 ret = rip_create ();
2916 if (ret < 0)
2917 {
2918 zlog_info ("Can't create RIP");
2919 return CMD_WARNING;
2920 }
2921 }
2922 vty->node = RIP_NODE;
2923 vty->index = rip;
2924
2925 return CMD_SUCCESS;
2926}
2927
2928DEFUN (no_router_rip,
2929 no_router_rip_cmd,
2930 "no router rip",
2931 NO_STR
2932 "Enable a routing process\n"
2933 "Routing Information Protocol (RIP)\n")
2934{
2935 if (rip)
2936 rip_clean ();
2937 return CMD_SUCCESS;
2938}
2939
2940DEFUN (rip_version,
2941 rip_version_cmd,
2942 "version <1-2>",
2943 "Set routing protocol version\n"
2944 "version\n")
2945{
2946 int version;
2947
2948 version = atoi (argv[0]);
2949 if (version != RIPv1 && version != RIPv2)
2950 {
2951 vty_out (vty, "invalid rip version %d%s", version,
2952 VTY_NEWLINE);
2953 return CMD_WARNING;
2954 }
paulf38a4712003-06-07 01:10:00 +00002955 rip->version_send = version;
2956 rip->version_recv = version;
paul718e3742002-12-13 20:15:29 +00002957
2958 return CMD_SUCCESS;
2959}
2960
2961DEFUN (no_rip_version,
2962 no_rip_version_cmd,
2963 "no version",
2964 NO_STR
2965 "Set routing protocol version\n")
2966{
2967 /* Set RIP version to the default. */
paulf38a4712003-06-07 01:10:00 +00002968 rip->version_send = RI_RIP_VERSION_2;
2969 rip->version_recv = RI_RIP_VERSION_1_AND_2;
paul718e3742002-12-13 20:15:29 +00002970
2971 return CMD_SUCCESS;
2972}
2973
2974ALIAS (no_rip_version,
2975 no_rip_version_val_cmd,
2976 "no version <1-2>",
2977 NO_STR
2978 "Set routing protocol version\n"
2979 "version\n")
2980
2981DEFUN (rip_route,
2982 rip_route_cmd,
2983 "route A.B.C.D/M",
2984 "RIP static route configuration\n"
2985 "IP prefix <network>/<length>\n")
2986{
2987 int ret;
2988 struct prefix_ipv4 p;
2989 struct route_node *node;
2990
2991 ret = str2prefix_ipv4 (argv[0], &p);
2992 if (ret < 0)
2993 {
2994 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2995 return CMD_WARNING;
2996 }
2997 apply_mask_ipv4 (&p);
2998
2999 /* For router rip configuration. */
3000 node = route_node_get (rip->route, (struct prefix *) &p);
3001
3002 if (node->info)
3003 {
3004 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
3005 route_unlock_node (node);
3006 return CMD_WARNING;
3007 }
3008
hasso8a676be2004-10-08 06:36:38 +00003009 node->info = (char *)"static";
paul718e3742002-12-13 20:15:29 +00003010
vincentfbf5d032005-09-29 11:25:50 +00003011 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
paul718e3742002-12-13 20:15:29 +00003012
3013 return CMD_SUCCESS;
3014}
3015
3016DEFUN (no_rip_route,
3017 no_rip_route_cmd,
3018 "no route A.B.C.D/M",
3019 NO_STR
3020 "RIP static route configuration\n"
3021 "IP prefix <network>/<length>\n")
3022{
3023 int ret;
3024 struct prefix_ipv4 p;
3025 struct route_node *node;
3026
3027 ret = str2prefix_ipv4 (argv[0], &p);
3028 if (ret < 0)
3029 {
3030 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033 apply_mask_ipv4 (&p);
3034
3035 /* For router rip configuration. */
3036 node = route_node_lookup (rip->route, (struct prefix *) &p);
3037 if (! node)
3038 {
3039 vty_out (vty, "Can't find route %s.%s", argv[0],
3040 VTY_NEWLINE);
3041 return CMD_WARNING;
3042 }
3043
3044 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
3045 route_unlock_node (node);
3046
3047 node->info = NULL;
3048 route_unlock_node (node);
3049
3050 return CMD_SUCCESS;
3051}
3052
Stephen Hemminger2c239702009-12-10 19:16:05 +03003053#if 0
pauldc63bfd2005-10-25 23:31:05 +00003054static void
paul216565a2005-10-25 23:35:28 +00003055rip_update_default_metric (void)
paul718e3742002-12-13 20:15:29 +00003056{
3057 struct route_node *np;
Lu Fengb397cf42014-07-18 06:13:18 +00003058 struct rip_info *rinfo = NULL;
3059 struct list *list = NULL;
3060 struct listnode *listnode = NULL;
paul718e3742002-12-13 20:15:29 +00003061
3062 for (np = route_top (rip->table); np; np = route_next (np))
Lu Fengb397cf42014-07-18 06:13:18 +00003063 if ((list = np->info) != NULL)
3064 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
3065 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
3066 rinfo->metric = rip->default_metric;
paul718e3742002-12-13 20:15:29 +00003067}
Stephen Hemminger2c239702009-12-10 19:16:05 +03003068#endif
paul718e3742002-12-13 20:15:29 +00003069
3070DEFUN (rip_default_metric,
3071 rip_default_metric_cmd,
3072 "default-metric <1-16>",
3073 "Set a metric of redistribute routes\n"
3074 "Default metric\n")
3075{
3076 if (rip)
3077 {
3078 rip->default_metric = atoi (argv[0]);
3079 /* rip_update_default_metric (); */
3080 }
3081 return CMD_SUCCESS;
3082}
3083
3084DEFUN (no_rip_default_metric,
3085 no_rip_default_metric_cmd,
3086 "no default-metric",
3087 NO_STR
3088 "Set a metric of redistribute routes\n"
3089 "Default metric\n")
3090{
3091 if (rip)
3092 {
3093 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3094 /* rip_update_default_metric (); */
3095 }
3096 return CMD_SUCCESS;
3097}
3098
3099ALIAS (no_rip_default_metric,
3100 no_rip_default_metric_val_cmd,
3101 "no default-metric <1-16>",
3102 NO_STR
3103 "Set a metric of redistribute routes\n"
3104 "Default metric\n")
3105
3106DEFUN (rip_timers,
3107 rip_timers_cmd,
3108 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3109 "Adjust routing timers\n"
3110 "Basic routing protocol update timers\n"
3111 "Routing table update timer value in second. Default is 30.\n"
3112 "Routing information timeout timer. Default is 180.\n"
3113 "Garbage collection timer. Default is 120.\n")
3114{
3115 unsigned long update;
3116 unsigned long timeout;
3117 unsigned long garbage;
3118 char *endptr = NULL;
3119 unsigned long RIP_TIMER_MAX = 2147483647;
3120 unsigned long RIP_TIMER_MIN = 5;
3121
3122 update = strtoul (argv[0], &endptr, 10);
3123 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3124 {
3125 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3126 return CMD_WARNING;
3127 }
3128
3129 timeout = strtoul (argv[1], &endptr, 10);
3130 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3131 {
3132 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3133 return CMD_WARNING;
3134 }
3135
3136 garbage = strtoul (argv[2], &endptr, 10);
3137 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3138 {
3139 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3140 return CMD_WARNING;
3141 }
3142
3143 /* Set each timer value. */
3144 rip->update_time = update;
3145 rip->timeout_time = timeout;
3146 rip->garbage_time = garbage;
3147
3148 /* Reset update timer thread. */
3149 rip_event (RIP_UPDATE_EVENT, 0);
3150
3151 return CMD_SUCCESS;
3152}
3153
3154DEFUN (no_rip_timers,
3155 no_rip_timers_cmd,
3156 "no timers basic",
3157 NO_STR
3158 "Adjust routing timers\n"
3159 "Basic routing protocol update timers\n")
3160{
3161 /* Set each timer value to the default. */
3162 rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3163 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3164 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3165
3166 /* Reset update timer thread. */
3167 rip_event (RIP_UPDATE_EVENT, 0);
3168
3169 return CMD_SUCCESS;
3170}
hasso16705132003-05-25 14:49:19 +00003171
3172ALIAS (no_rip_timers,
3173 no_rip_timers_val_cmd,
3174 "no timers basic <0-65535> <0-65535> <0-65535>",
3175 NO_STR
3176 "Adjust routing timers\n"
3177 "Basic routing protocol update timers\n"
3178 "Routing table update timer value in second. Default is 30.\n"
3179 "Routing information timeout timer. Default is 180.\n"
3180 "Garbage collection timer. Default is 120.\n")
3181
David Lamparter6b0655a2014-06-04 06:53:35 +02003182
paul718e3742002-12-13 20:15:29 +00003183struct route_table *rip_distance_table;
3184
3185struct rip_distance
3186{
3187 /* Distance value for the IP source prefix. */
3188 u_char distance;
3189
3190 /* Name of the access-list to be matched. */
3191 char *access_list;
3192};
3193
pauldc63bfd2005-10-25 23:31:05 +00003194static struct rip_distance *
paul216565a2005-10-25 23:35:28 +00003195rip_distance_new (void)
paul718e3742002-12-13 20:15:29 +00003196{
Stephen Hemminger393deb92008-08-18 14:13:29 -07003197 return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
paul718e3742002-12-13 20:15:29 +00003198}
3199
pauldc63bfd2005-10-25 23:31:05 +00003200static void
paul718e3742002-12-13 20:15:29 +00003201rip_distance_free (struct rip_distance *rdistance)
3202{
3203 XFREE (MTYPE_RIP_DISTANCE, rdistance);
3204}
3205
pauldc63bfd2005-10-25 23:31:05 +00003206static int
hasso98b718a2004-10-11 12:57:57 +00003207rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3208 const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003209{
3210 int ret;
3211 struct prefix_ipv4 p;
3212 u_char distance;
3213 struct route_node *rn;
3214 struct rip_distance *rdistance;
3215
3216 ret = str2prefix_ipv4 (ip_str, &p);
3217 if (ret == 0)
3218 {
3219 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3220 return CMD_WARNING;
3221 }
3222
3223 distance = atoi (distance_str);
3224
3225 /* Get RIP distance node. */
3226 rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3227 if (rn->info)
3228 {
3229 rdistance = rn->info;
3230 route_unlock_node (rn);
3231 }
3232 else
3233 {
3234 rdistance = rip_distance_new ();
3235 rn->info = rdistance;
3236 }
3237
3238 /* Set distance value. */
3239 rdistance->distance = distance;
3240
3241 /* Reset access-list configuration. */
3242 if (rdistance->access_list)
3243 {
3244 free (rdistance->access_list);
3245 rdistance->access_list = NULL;
3246 }
3247 if (access_list_str)
3248 rdistance->access_list = strdup (access_list_str);
3249
3250 return CMD_SUCCESS;
3251}
3252
pauldc63bfd2005-10-25 23:31:05 +00003253static int
hasso98b718a2004-10-11 12:57:57 +00003254rip_distance_unset (struct vty *vty, const char *distance_str,
3255 const char *ip_str, const char *access_list_str)
paul718e3742002-12-13 20:15:29 +00003256{
3257 int ret;
3258 struct prefix_ipv4 p;
3259 u_char distance;
3260 struct route_node *rn;
3261 struct rip_distance *rdistance;
3262
3263 ret = str2prefix_ipv4 (ip_str, &p);
3264 if (ret == 0)
3265 {
3266 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3267 return CMD_WARNING;
3268 }
3269
3270 distance = atoi (distance_str);
3271
3272 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3273 if (! rn)
3274 {
3275 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3276 return CMD_WARNING;
3277 }
3278
3279 rdistance = rn->info;
3280
3281 if (rdistance->access_list)
3282 free (rdistance->access_list);
3283 rip_distance_free (rdistance);
3284
3285 rn->info = NULL;
3286 route_unlock_node (rn);
3287 route_unlock_node (rn);
3288
3289 return CMD_SUCCESS;
3290}
3291
pauldc63bfd2005-10-25 23:31:05 +00003292static void
paul216565a2005-10-25 23:35:28 +00003293rip_distance_reset (void)
paul718e3742002-12-13 20:15:29 +00003294{
3295 struct route_node *rn;
3296 struct rip_distance *rdistance;
3297
3298 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3299 if ((rdistance = rn->info) != NULL)
3300 {
3301 if (rdistance->access_list)
3302 free (rdistance->access_list);
3303 rip_distance_free (rdistance);
3304 rn->info = NULL;
3305 route_unlock_node (rn);
3306 }
3307}
3308
3309/* Apply RIP information to distance method. */
3310u_char
3311rip_distance_apply (struct rip_info *rinfo)
3312{
3313 struct route_node *rn;
3314 struct prefix_ipv4 p;
3315 struct rip_distance *rdistance;
3316 struct access_list *alist;
3317
3318 if (! rip)
3319 return 0;
3320
3321 memset (&p, 0, sizeof (struct prefix_ipv4));
3322 p.family = AF_INET;
3323 p.prefix = rinfo->from;
3324 p.prefixlen = IPV4_MAX_BITLEN;
3325
3326 /* Check source address. */
3327 rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3328 if (rn)
3329 {
3330 rdistance = rn->info;
3331 route_unlock_node (rn);
3332
3333 if (rdistance->access_list)
3334 {
3335 alist = access_list_lookup (AFI_IP, rdistance->access_list);
3336 if (alist == NULL)
3337 return 0;
3338 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3339 return 0;
3340
3341 return rdistance->distance;
3342 }
3343 else
3344 return rdistance->distance;
3345 }
3346
3347 if (rip->distance)
3348 return rip->distance;
3349
3350 return 0;
3351}
3352
pauldc63bfd2005-10-25 23:31:05 +00003353static void
paul718e3742002-12-13 20:15:29 +00003354rip_distance_show (struct vty *vty)
3355{
3356 struct route_node *rn;
3357 struct rip_distance *rdistance;
3358 int header = 1;
3359 char buf[BUFSIZ];
3360
3361 vty_out (vty, " Distance: (default is %d)%s",
3362 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3363 VTY_NEWLINE);
3364
3365 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3366 if ((rdistance = rn->info) != NULL)
3367 {
3368 if (header)
3369 {
3370 vty_out (vty, " Address Distance List%s",
3371 VTY_NEWLINE);
3372 header = 0;
3373 }
3374 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3375 vty_out (vty, " %-20s %4d %s%s",
3376 buf, rdistance->distance,
3377 rdistance->access_list ? rdistance->access_list : "",
3378 VTY_NEWLINE);
3379 }
3380}
3381
3382DEFUN (rip_distance,
3383 rip_distance_cmd,
3384 "distance <1-255>",
3385 "Administrative distance\n"
3386 "Distance value\n")
3387{
3388 rip->distance = atoi (argv[0]);
3389 return CMD_SUCCESS;
3390}
3391
3392DEFUN (no_rip_distance,
3393 no_rip_distance_cmd,
3394 "no distance <1-255>",
3395 NO_STR
3396 "Administrative distance\n"
3397 "Distance value\n")
3398{
3399 rip->distance = 0;
3400 return CMD_SUCCESS;
3401}
3402
3403DEFUN (rip_distance_source,
3404 rip_distance_source_cmd,
3405 "distance <1-255> A.B.C.D/M",
3406 "Administrative distance\n"
3407 "Distance value\n"
3408 "IP source prefix\n")
3409{
3410 rip_distance_set (vty, argv[0], argv[1], NULL);
3411 return CMD_SUCCESS;
3412}
3413
3414DEFUN (no_rip_distance_source,
3415 no_rip_distance_source_cmd,
3416 "no distance <1-255> A.B.C.D/M",
3417 NO_STR
3418 "Administrative distance\n"
3419 "Distance value\n"
3420 "IP source prefix\n")
3421{
3422 rip_distance_unset (vty, argv[0], argv[1], NULL);
3423 return CMD_SUCCESS;
3424}
3425
3426DEFUN (rip_distance_source_access_list,
3427 rip_distance_source_access_list_cmd,
3428 "distance <1-255> A.B.C.D/M WORD",
3429 "Administrative distance\n"
3430 "Distance value\n"
3431 "IP source prefix\n"
3432 "Access list name\n")
3433{
3434 rip_distance_set (vty, argv[0], argv[1], argv[2]);
3435 return CMD_SUCCESS;
3436}
3437
3438DEFUN (no_rip_distance_source_access_list,
3439 no_rip_distance_source_access_list_cmd,
3440 "no distance <1-255> A.B.C.D/M WORD",
3441 NO_STR
3442 "Administrative distance\n"
3443 "Distance value\n"
3444 "IP source prefix\n"
3445 "Access list name\n")
3446{
3447 rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3448 return CMD_SUCCESS;
3449}
David Lamparter6b0655a2014-06-04 06:53:35 +02003450
paul718e3742002-12-13 20:15:29 +00003451/* Print out routes update time. */
pauldc63bfd2005-10-25 23:31:05 +00003452static void
paul718e3742002-12-13 20:15:29 +00003453rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3454{
paul718e3742002-12-13 20:15:29 +00003455 time_t clock;
3456 struct tm *tm;
3457#define TIME_BUF 25
3458 char timebuf [TIME_BUF];
3459 struct thread *thread;
3460
paul718e3742002-12-13 20:15:29 +00003461 if ((thread = rinfo->t_timeout) != NULL)
3462 {
Vincent Jardina1fdf942007-04-11 15:12:05 +00003463 clock = thread_timer_remain_second (thread);
paul718e3742002-12-13 20:15:29 +00003464 tm = gmtime (&clock);
3465 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3466 vty_out (vty, "%5s", timebuf);
3467 }
3468 else if ((thread = rinfo->t_garbage_collect) != NULL)
3469 {
Vincent Jardina1fdf942007-04-11 15:12:05 +00003470 clock = thread_timer_remain_second (thread);
paul718e3742002-12-13 20:15:29 +00003471 tm = gmtime (&clock);
3472 strftime (timebuf, TIME_BUF, "%M:%S", tm);
3473 vty_out (vty, "%5s", timebuf);
3474 }
3475}
3476
pauldc63bfd2005-10-25 23:31:05 +00003477static const char *
paul718e3742002-12-13 20:15:29 +00003478rip_route_type_print (int sub_type)
3479{
3480 switch (sub_type)
3481 {
3482 case RIP_ROUTE_RTE:
3483 return "n";
3484 case RIP_ROUTE_STATIC:
3485 return "s";
3486 case RIP_ROUTE_DEFAULT:
3487 return "d";
3488 case RIP_ROUTE_REDISTRIBUTE:
3489 return "r";
3490 case RIP_ROUTE_INTERFACE:
3491 return "i";
3492 default:
3493 return "?";
3494 }
3495}
3496
3497DEFUN (show_ip_rip,
3498 show_ip_rip_cmd,
3499 "show ip rip",
3500 SHOW_STR
3501 IP_STR
3502 "Show RIP routes\n")
3503{
3504 struct route_node *np;
Lu Fengb397cf42014-07-18 06:13:18 +00003505 struct rip_info *rinfo = NULL;
3506 struct list *list = NULL;
3507 struct listnode *listnode = NULL;
paul718e3742002-12-13 20:15:29 +00003508
3509 if (! rip)
3510 return CMD_SUCCESS;
3511
hasso16705132003-05-25 14:49:19 +00003512 vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3513 "Sub-codes:%s"
3514 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
paul718e3742002-12-13 20:15:29 +00003515 " (i) - interface%s%s"
hassoa1455d82004-03-03 19:36:24 +00003516 " Network Next Hop Metric From Tag Time%s",
hasso16705132003-05-25 14:49:19 +00003517 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003518
3519 for (np = route_top (rip->table); np; np = route_next (np))
Lu Fengb397cf42014-07-18 06:13:18 +00003520 if ((list = np->info) != NULL)
3521 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
paul718e3742002-12-13 20:15:29 +00003522 {
3523 int len;
3524
ajsf52d13c2005-10-01 17:38:06 +00003525 len = vty_out (vty, "%c(%s) %s/%d",
paul718e3742002-12-13 20:15:29 +00003526 /* np->lock, For debugging. */
ajsf52d13c2005-10-01 17:38:06 +00003527 zebra_route_char(rinfo->type),
paul718e3742002-12-13 20:15:29 +00003528 rip_route_type_print (rinfo->sub_type),
3529 inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3530
hassoa1455d82004-03-03 19:36:24 +00003531 len = 24 - len;
paul718e3742002-12-13 20:15:29 +00003532
3533 if (len > 0)
3534 vty_out (vty, "%*s", len, " ");
3535
3536 if (rinfo->nexthop.s_addr)
3537 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3538 rinfo->metric);
3539 else
3540 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3541
3542 /* Route which exist in kernel routing table. */
3543 if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3544 (rinfo->sub_type == RIP_ROUTE_RTE))
3545 {
3546 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
hasso16705132003-05-25 14:49:19 +00003547 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003548 rip_vty_out_uptime (vty, rinfo);
3549 }
3550 else if (rinfo->metric == RIP_METRIC_INFINITY)
3551 {
3552 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003553 vty_out (vty, "%3d ", rinfo->tag);
paul718e3742002-12-13 20:15:29 +00003554 rip_vty_out_uptime (vty, rinfo);
3555 }
3556 else
hasso16705132003-05-25 14:49:19 +00003557 {
vincentfbf5d032005-09-29 11:25:50 +00003558 if (rinfo->external_metric)
3559 {
3560 len = vty_out (vty, "self (%s:%d)",
ajsf52d13c2005-10-01 17:38:06 +00003561 zebra_route_string(rinfo->type),
vincentfbf5d032005-09-29 11:25:50 +00003562 rinfo->external_metric);
3563 len = 16 - len;
3564 if (len > 0)
3565 vty_out (vty, "%*s", len, " ");
3566 }
3567 else
3568 vty_out (vty, "self ");
hasso16705132003-05-25 14:49:19 +00003569 vty_out (vty, "%3d", rinfo->tag);
3570 }
paul718e3742002-12-13 20:15:29 +00003571
3572 vty_out (vty, "%s", VTY_NEWLINE);
3573 }
3574 return CMD_SUCCESS;
3575}
3576
hasso16705132003-05-25 14:49:19 +00003577/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3578DEFUN (show_ip_rip_status,
3579 show_ip_rip_status_cmd,
3580 "show ip rip status",
paul718e3742002-12-13 20:15:29 +00003581 SHOW_STR
3582 IP_STR
hasso16705132003-05-25 14:49:19 +00003583 "Show RIP routes\n"
paul718e3742002-12-13 20:15:29 +00003584 "IP routing protocol process parameters and statistics\n")
3585{
hasso52dc7ee2004-09-23 19:18:23 +00003586 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003587 struct interface *ifp;
3588 struct rip_interface *ri;
Stephen Hemminger1423c802008-08-14 17:59:25 +01003589 extern const struct message ri_version_msg[];
hasso8a676be2004-10-08 06:36:38 +00003590 const char *send_version;
3591 const char *receive_version;
paul718e3742002-12-13 20:15:29 +00003592
3593 if (! rip)
3594 return CMD_SUCCESS;
3595
3596 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3597 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3598 rip->update_time);
Andrew J. Schorra4c64822007-03-21 18:57:38 +00003599 vty_out (vty, " next due in %lu seconds%s",
3600 thread_timer_remain_second(rip->t_update),
paul718e3742002-12-13 20:15:29 +00003601 VTY_NEWLINE);
3602 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3603 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3604 VTY_NEWLINE);
3605
3606 /* Filtering status show. */
3607 config_show_distribute (vty);
3608
3609 /* Default metric information. */
3610 vty_out (vty, " Default redistribution metric is %d%s",
3611 rip->default_metric, VTY_NEWLINE);
3612
3613 /* Redistribute information. */
3614 vty_out (vty, " Redistributing:");
3615 config_write_rip_redistribute (vty, 0);
3616 vty_out (vty, "%s", VTY_NEWLINE);
3617
paulf38a4712003-06-07 01:10:00 +00003618 vty_out (vty, " Default version control: send version %s,",
3619 lookup(ri_version_msg,rip->version_send));
3620 if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3621 vty_out (vty, " receive any version %s", VTY_NEWLINE);
3622 else
3623 vty_out (vty, " receive version %s %s",
3624 lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00003625
3626 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3627
paul1eb8ef22005-04-07 07:30:20 +00003628 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00003629 {
paul718e3742002-12-13 20:15:29 +00003630 ri = ifp->info;
3631
Stephen Hemminger82f5ee12009-04-07 15:00:46 -07003632 if (!ri->running)
3633 continue;
3634
paul718e3742002-12-13 20:15:29 +00003635 if (ri->enable_network || ri->enable_interface)
3636 {
3637 if (ri->ri_send == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003638 send_version = lookup (ri_version_msg, rip->version_send);
paul718e3742002-12-13 20:15:29 +00003639 else
3640 send_version = lookup (ri_version_msg, ri->ri_send);
3641
3642 if (ri->ri_receive == RI_RIP_UNSPEC)
paulf38a4712003-06-07 01:10:00 +00003643 receive_version = lookup (ri_version_msg, rip->version_recv);
paul718e3742002-12-13 20:15:29 +00003644 else
3645 receive_version = lookup (ri_version_msg, ri->ri_receive);
3646
3647 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3648 send_version,
3649 receive_version,
3650 ri->key_chain ? ri->key_chain : "",
3651 VTY_NEWLINE);
3652 }
3653 }
3654
3655 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3656 config_write_rip_network (vty, 0);
3657
paul4aaff3f2003-06-07 01:04:45 +00003658 {
3659 int found_passive = 0;
paul1eb8ef22005-04-07 07:30:20 +00003660 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul4aaff3f2003-06-07 01:04:45 +00003661 {
paul4aaff3f2003-06-07 01:04:45 +00003662 ri = ifp->info;
3663
3664 if ((ri->enable_network || ri->enable_interface) && ri->passive)
3665 {
3666 if (!found_passive)
3667 {
3668 vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3669 found_passive = 1;
3670 }
3671 vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3672 }
3673 }
3674 }
3675
paul718e3742002-12-13 20:15:29 +00003676 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3677 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3678 rip_peer_display (vty);
3679
3680 rip_distance_show (vty);
3681
3682 return CMD_SUCCESS;
3683}
3684
3685/* RIP configuration write function. */
pauldc63bfd2005-10-25 23:31:05 +00003686static int
paul718e3742002-12-13 20:15:29 +00003687config_write_rip (struct vty *vty)
3688{
3689 int write = 0;
3690 struct route_node *rn;
3691 struct rip_distance *rdistance;
3692
3693 if (rip)
3694 {
3695 /* Router RIP statement. */
3696 vty_out (vty, "router rip%s", VTY_NEWLINE);
3697 write++;
3698
3699 /* RIP version statement. Default is RIP version 2. */
paulf38a4712003-06-07 01:10:00 +00003700 if (rip->version_send != RI_RIP_VERSION_2
3701 || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3702 vty_out (vty, " version %d%s", rip->version_send,
paul718e3742002-12-13 20:15:29 +00003703 VTY_NEWLINE);
3704
3705 /* RIP timer configuration. */
3706 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3707 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3708 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3709 vty_out (vty, " timers basic %lu %lu %lu%s",
3710 rip->update_time,
3711 rip->timeout_time,
3712 rip->garbage_time,
3713 VTY_NEWLINE);
3714
3715 /* Default information configuration. */
3716 if (rip->default_information)
3717 {
3718 if (rip->default_information_route_map)
3719 vty_out (vty, " default-information originate route-map %s%s",
3720 rip->default_information_route_map, VTY_NEWLINE);
3721 else
3722 vty_out (vty, " default-information originate%s",
3723 VTY_NEWLINE);
3724 }
3725
3726 /* Redistribute configuration. */
3727 config_write_rip_redistribute (vty, 1);
3728
3729 /* RIP offset-list configuration. */
3730 config_write_rip_offset_list (vty);
3731
3732 /* RIP enabled network and interface configuration. */
3733 config_write_rip_network (vty, 1);
3734
3735 /* RIP default metric configuration */
3736 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3737 vty_out (vty, " default-metric %d%s",
3738 rip->default_metric, VTY_NEWLINE);
3739
3740 /* Distribute configuration. */
3741 write += config_write_distribute (vty);
3742
hasso16705132003-05-25 14:49:19 +00003743 /* Interface routemap configuration */
3744 write += config_write_if_rmap (vty);
3745
paul718e3742002-12-13 20:15:29 +00003746 /* Distance configuration. */
3747 if (rip->distance)
3748 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3749
3750 /* RIP source IP prefix distance configuration. */
3751 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3752 if ((rdistance = rn->info) != NULL)
3753 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3754 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3755 rdistance->access_list ? rdistance->access_list : "",
3756 VTY_NEWLINE);
3757
3758 /* RIP static route configuration. */
3759 for (rn = route_top (rip->route); rn; rn = route_next (rn))
3760 if (rn->info)
3761 vty_out (vty, " route %s/%d%s",
3762 inet_ntoa (rn->p.u.prefix4),
3763 rn->p.prefixlen,
3764 VTY_NEWLINE);
3765
3766 }
3767 return write;
3768}
3769
3770/* RIP node structure. */
Stephen Hemminger7fc626d2008-12-01 11:10:34 -08003771static struct cmd_node rip_node =
paul718e3742002-12-13 20:15:29 +00003772{
3773 RIP_NODE,
3774 "%s(config-router)# ",
3775 1
3776};
David Lamparter6b0655a2014-06-04 06:53:35 +02003777
paul718e3742002-12-13 20:15:29 +00003778/* Distribute-list update functions. */
pauldc63bfd2005-10-25 23:31:05 +00003779static void
paul718e3742002-12-13 20:15:29 +00003780rip_distribute_update (struct distribute *dist)
3781{
3782 struct interface *ifp;
3783 struct rip_interface *ri;
3784 struct access_list *alist;
3785 struct prefix_list *plist;
3786
3787 if (! dist->ifname)
3788 return;
3789
3790 ifp = if_lookup_by_name (dist->ifname);
3791 if (ifp == NULL)
3792 return;
3793
3794 ri = ifp->info;
3795
3796 if (dist->list[DISTRIBUTE_IN])
3797 {
3798 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3799 if (alist)
3800 ri->list[RIP_FILTER_IN] = alist;
3801 else
3802 ri->list[RIP_FILTER_IN] = NULL;
3803 }
3804 else
3805 ri->list[RIP_FILTER_IN] = NULL;
3806
3807 if (dist->list[DISTRIBUTE_OUT])
3808 {
3809 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3810 if (alist)
3811 ri->list[RIP_FILTER_OUT] = alist;
3812 else
3813 ri->list[RIP_FILTER_OUT] = NULL;
3814 }
3815 else
3816 ri->list[RIP_FILTER_OUT] = NULL;
3817
3818 if (dist->prefix[DISTRIBUTE_IN])
3819 {
3820 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3821 if (plist)
3822 ri->prefix[RIP_FILTER_IN] = plist;
3823 else
3824 ri->prefix[RIP_FILTER_IN] = NULL;
3825 }
3826 else
3827 ri->prefix[RIP_FILTER_IN] = NULL;
3828
3829 if (dist->prefix[DISTRIBUTE_OUT])
3830 {
3831 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3832 if (plist)
3833 ri->prefix[RIP_FILTER_OUT] = plist;
3834 else
3835 ri->prefix[RIP_FILTER_OUT] = NULL;
3836 }
3837 else
3838 ri->prefix[RIP_FILTER_OUT] = NULL;
3839}
3840
3841void
3842rip_distribute_update_interface (struct interface *ifp)
3843{
3844 struct distribute *dist;
3845
3846 dist = distribute_lookup (ifp->name);
3847 if (dist)
3848 rip_distribute_update (dist);
3849}
3850
3851/* Update all interface's distribute list. */
paul02ff83c2004-06-11 11:27:03 +00003852/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00003853static void
paul02ff83c2004-06-11 11:27:03 +00003854rip_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00003855{
3856 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00003857 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003858
paul1eb8ef22005-04-07 07:30:20 +00003859 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3860 rip_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00003861}
paul11dde9c2004-05-31 14:00:00 +00003862/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00003863static void
paul11dde9c2004-05-31 14:00:00 +00003864rip_distribute_update_all_wrapper(struct access_list *notused)
3865{
paul02ff83c2004-06-11 11:27:03 +00003866 rip_distribute_update_all(NULL);
paul11dde9c2004-05-31 14:00:00 +00003867}
David Lamparter6b0655a2014-06-04 06:53:35 +02003868
paul718e3742002-12-13 20:15:29 +00003869/* Delete all added rip route. */
3870void
paul216565a2005-10-25 23:35:28 +00003871rip_clean (void)
paul718e3742002-12-13 20:15:29 +00003872{
3873 int i;
3874 struct route_node *rp;
Lu Fengb397cf42014-07-18 06:13:18 +00003875 struct rip_info *rinfo = NULL;
3876 struct list *list = NULL;
3877 struct listnode *listnode = NULL;
paul718e3742002-12-13 20:15:29 +00003878
3879 if (rip)
3880 {
3881 /* Clear RIP routes */
3882 for (rp = route_top (rip->table); rp; rp = route_next (rp))
Lu Fengb397cf42014-07-18 06:13:18 +00003883 if ((list = rp->info) != NULL)
3884 {
3885 rinfo = listgetdata (listhead (list));
3886 if (rip_route_rte (rinfo))
3887 rip_zebra_ipv4_delete (rp);
paul718e3742002-12-13 20:15:29 +00003888
Lu Fengb397cf42014-07-18 06:13:18 +00003889 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
3890 {
3891 RIP_TIMER_OFF (rinfo->t_timeout);
3892 RIP_TIMER_OFF (rinfo->t_garbage_collect);
3893 rip_info_free (rinfo);
3894 }
3895 list_delete (list);
3896 rp->info = NULL;
3897 route_unlock_node (rp);
3898 }
paul718e3742002-12-13 20:15:29 +00003899
3900 /* Cancel RIP related timers. */
3901 RIP_TIMER_OFF (rip->t_update);
3902 RIP_TIMER_OFF (rip->t_triggered_update);
3903 RIP_TIMER_OFF (rip->t_triggered_interval);
3904
3905 /* Cancel read thread. */
3906 if (rip->t_read)
3907 {
3908 thread_cancel (rip->t_read);
3909 rip->t_read = NULL;
3910 }
3911
3912 /* Close RIP socket. */
3913 if (rip->sock >= 0)
3914 {
3915 close (rip->sock);
3916 rip->sock = -1;
3917 }
3918
3919 /* Static RIP route configuration. */
3920 for (rp = route_top (rip->route); rp; rp = route_next (rp))
3921 if (rp->info)
3922 {
3923 rp->info = NULL;
3924 route_unlock_node (rp);
3925 }
3926
3927 /* RIP neighbor configuration. */
3928 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
3929 if (rp->info)
3930 {
3931 rp->info = NULL;
3932 route_unlock_node (rp);
3933 }
3934
3935 /* Redistribute related clear. */
3936 if (rip->default_information_route_map)
3937 free (rip->default_information_route_map);
3938
3939 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3940 if (rip->route_map[i].name)
3941 free (rip->route_map[i].name);
3942
3943 XFREE (MTYPE_ROUTE_TABLE, rip->table);
3944 XFREE (MTYPE_ROUTE_TABLE, rip->route);
3945 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
3946
3947 XFREE (MTYPE_RIP, rip);
3948 rip = NULL;
3949 }
3950
3951 rip_clean_network ();
paul4aaff3f2003-06-07 01:04:45 +00003952 rip_passive_nondefault_clean ();
paul718e3742002-12-13 20:15:29 +00003953 rip_offset_clean ();
3954 rip_interface_clean ();
3955 rip_distance_reset ();
3956 rip_redistribute_clean ();
3957}
3958
3959/* Reset all values to the default settings. */
3960void
paul216565a2005-10-25 23:35:28 +00003961rip_reset (void)
paul718e3742002-12-13 20:15:29 +00003962{
3963 /* Reset global counters. */
3964 rip_global_route_changes = 0;
3965 rip_global_queries = 0;
3966
3967 /* Call ripd related reset functions. */
3968 rip_debug_reset ();
3969 rip_route_map_reset ();
3970
3971 /* Call library reset functions. */
3972 vty_reset ();
3973 access_list_reset ();
3974 prefix_list_reset ();
3975
3976 distribute_list_reset ();
3977
3978 rip_interface_reset ();
3979 rip_distance_reset ();
3980
3981 rip_zclient_reset ();
3982}
3983
pauldc63bfd2005-10-25 23:31:05 +00003984static void
hasso16705132003-05-25 14:49:19 +00003985rip_if_rmap_update (struct if_rmap *if_rmap)
3986{
3987 struct interface *ifp;
3988 struct rip_interface *ri;
3989 struct route_map *rmap;
3990
3991 ifp = if_lookup_by_name (if_rmap->ifname);
3992 if (ifp == NULL)
3993 return;
3994
3995 ri = ifp->info;
3996
3997 if (if_rmap->routemap[IF_RMAP_IN])
3998 {
3999 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
4000 if (rmap)
4001 ri->routemap[IF_RMAP_IN] = rmap;
4002 else
4003 ri->routemap[IF_RMAP_IN] = NULL;
4004 }
4005 else
4006 ri->routemap[RIP_FILTER_IN] = NULL;
4007
4008 if (if_rmap->routemap[IF_RMAP_OUT])
4009 {
4010 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
4011 if (rmap)
4012 ri->routemap[IF_RMAP_OUT] = rmap;
4013 else
4014 ri->routemap[IF_RMAP_OUT] = NULL;
4015 }
4016 else
4017 ri->routemap[RIP_FILTER_OUT] = NULL;
4018}
4019
4020void
4021rip_if_rmap_update_interface (struct interface *ifp)
4022{
4023 struct if_rmap *if_rmap;
4024
4025 if_rmap = if_rmap_lookup (ifp->name);
4026 if (if_rmap)
4027 rip_if_rmap_update (if_rmap);
4028}
4029
pauldc63bfd2005-10-25 23:31:05 +00004030static void
hasso16705132003-05-25 14:49:19 +00004031rip_routemap_update_redistribute (void)
4032{
4033 int i;
4034
4035 if (rip)
4036 {
4037 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
4038 {
4039 if (rip->route_map[i].name)
4040 rip->route_map[i].map =
4041 route_map_lookup_by_name (rip->route_map[i].name);
4042 }
4043 }
4044}
4045
paul11dde9c2004-05-31 14:00:00 +00004046/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +00004047static void
hasso98b718a2004-10-11 12:57:57 +00004048rip_routemap_update (const char *notused)
hasso16705132003-05-25 14:49:19 +00004049{
4050 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00004051 struct listnode *node, *nnode;
hasso16705132003-05-25 14:49:19 +00004052
paul1eb8ef22005-04-07 07:30:20 +00004053 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
4054 rip_if_rmap_update_interface (ifp);
hasso16705132003-05-25 14:49:19 +00004055
4056 rip_routemap_update_redistribute ();
4057}
4058
paul718e3742002-12-13 20:15:29 +00004059/* Allocate new rip structure and set default value. */
4060void
pauldc63bfd2005-10-25 23:31:05 +00004061rip_init (void)
paul718e3742002-12-13 20:15:29 +00004062{
4063 /* Randomize for triggered update random(). */
4064 srand (time (NULL));
4065
4066 /* Install top nodes. */
4067 install_node (&rip_node, config_write_rip);
4068
4069 /* Install rip commands. */
4070 install_element (VIEW_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004071 install_element (VIEW_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004072 install_element (ENABLE_NODE, &show_ip_rip_cmd);
hasso16705132003-05-25 14:49:19 +00004073 install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
paul718e3742002-12-13 20:15:29 +00004074 install_element (CONFIG_NODE, &router_rip_cmd);
4075 install_element (CONFIG_NODE, &no_router_rip_cmd);
4076
4077 install_default (RIP_NODE);
4078 install_element (RIP_NODE, &rip_version_cmd);
4079 install_element (RIP_NODE, &no_rip_version_cmd);
4080 install_element (RIP_NODE, &no_rip_version_val_cmd);
4081 install_element (RIP_NODE, &rip_default_metric_cmd);
4082 install_element (RIP_NODE, &no_rip_default_metric_cmd);
4083 install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4084 install_element (RIP_NODE, &rip_timers_cmd);
4085 install_element (RIP_NODE, &no_rip_timers_cmd);
hasso16705132003-05-25 14:49:19 +00004086 install_element (RIP_NODE, &no_rip_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00004087 install_element (RIP_NODE, &rip_route_cmd);
4088 install_element (RIP_NODE, &no_rip_route_cmd);
4089 install_element (RIP_NODE, &rip_distance_cmd);
4090 install_element (RIP_NODE, &no_rip_distance_cmd);
4091 install_element (RIP_NODE, &rip_distance_source_cmd);
4092 install_element (RIP_NODE, &no_rip_distance_source_cmd);
4093 install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4094 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
4095
4096 /* Debug related init. */
4097 rip_debug_init ();
4098
paul718e3742002-12-13 20:15:29 +00004099 /* SNMP init. */
4100#ifdef HAVE_SNMP
4101 rip_snmp_init ();
4102#endif /* HAVE_SNMP */
4103
4104 /* Access list install. */
4105 access_list_init ();
paul11dde9c2004-05-31 14:00:00 +00004106 access_list_add_hook (rip_distribute_update_all_wrapper);
4107 access_list_delete_hook (rip_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00004108
4109 /* Prefix list initialize.*/
4110 prefix_list_init ();
4111 prefix_list_add_hook (rip_distribute_update_all);
4112 prefix_list_delete_hook (rip_distribute_update_all);
4113
4114 /* Distribute list install. */
4115 distribute_list_init (RIP_NODE);
4116 distribute_list_add_hook (rip_distribute_update);
4117 distribute_list_delete_hook (rip_distribute_update);
4118
hasso16705132003-05-25 14:49:19 +00004119 /* Route-map */
4120 rip_route_map_init ();
4121 rip_offset_init ();
4122
4123 route_map_add_hook (rip_routemap_update);
4124 route_map_delete_hook (rip_routemap_update);
4125
4126 if_rmap_init (RIP_NODE);
4127 if_rmap_hook_add (rip_if_rmap_update);
4128 if_rmap_hook_delete (rip_if_rmap_update);
4129
paul718e3742002-12-13 20:15:29 +00004130 /* Distance control. */
4131 rip_distance_table = route_table_init ();
4132}