Annotation of embedaddon/quagga/ripd/ripd.c, revision 1.1.1.3
1.1 misho 1: /* RIP version 1 and 2.
2: * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
3: * 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"
35: #include "sockopt.h"
36: #include "routemap.h"
37: #include "if_rmap.h"
38: #include "plist.h"
39: #include "distribute.h"
40: #include "md5.h"
41: #include "keychain.h"
42: #include "privs.h"
43:
44: #include "ripd/ripd.h"
45: #include "ripd/rip_debug.h"
46:
47: /* UDP receive buffer size */
48: #define RIP_UDP_RCV_BUF 41600
49:
50: /* privileges global */
51: extern struct zebra_privs_t ripd_privs;
52:
53: /* RIP Structure. */
54: struct rip *rip = NULL;
55:
56: /* RIP neighbor address table. */
57: struct route_table *rip_neighbor_table;
58:
59: /* RIP route changes. */
60: long rip_global_route_changes = 0;
61:
62: /* RIP queries. */
63: long rip_global_queries = 0;
1.1.1.3 ! misho 64:
1.1 misho 65: /* Prototypes. */
66: static void rip_event (enum rip_event, int);
67: static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
68: static int rip_triggered_update (struct thread *);
69: static int rip_update_jitter (unsigned long);
1.1.1.3 ! misho 70:
1.1 misho 71: /* RIP output routes type. */
72: enum
73: {
74: rip_all_route,
75: rip_changed_route
76: };
1.1.1.3 ! misho 77:
1.1 misho 78: /* RIP command strings. */
79: static const struct message rip_msg[] =
80: {
81: {RIP_REQUEST, "REQUEST"},
82: {RIP_RESPONSE, "RESPONSE"},
83: {RIP_TRACEON, "TRACEON"},
84: {RIP_TRACEOFF, "TRACEOFF"},
85: {RIP_POLL, "POLL"},
86: {RIP_POLL_ENTRY, "POLL ENTRY"},
87: {0, NULL},
88: };
1.1.1.3 ! misho 89:
1.1 misho 90: /* Utility function to set boradcast option to the socket. */
91: static int
92: sockopt_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:
106: static int
107: rip_route_rte (struct rip_info *rinfo)
108: {
109: return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
110: }
111:
112: static struct rip_info *
113: rip_info_new (void)
114: {
115: return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
116: }
117:
118: void
119: rip_info_free (struct rip_info *rinfo)
120: {
121: XFREE (MTYPE_RIP_INFO, rinfo);
122: }
123:
124: /* RIP route garbage collect timer. */
125: static int
126: rip_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. */
1.1.1.3 ! misho 141: 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: }
1.1 misho 148:
149: /* Free RIP routing information. */
150: rip_info_free (rinfo);
151:
152: return 0;
153: }
154:
1.1.1.3 ! misho 155: static 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, or NULL if it is not the first
! 159: * entry and ECMP is not allowed.
! 160: */
! 161: struct rip_info *
! 162: rip_ecmp_add (struct rip_info *rinfo_new)
1.1 misho 163: {
1.1.1.3 ! misho 164: struct route_node *rp = rinfo_new->rp;
! 165: struct rip_info *rinfo = NULL;
! 166: struct list *list = NULL;
! 167:
! 168: if (rp->info == NULL)
! 169: rp->info = list_new ();
! 170: list = (struct list *)rp->info;
! 171:
! 172: /* If ECMP is not allowed and some entry already exists in the list,
! 173: * do nothing. */
! 174: if (listcount (list) && !rip->ecmp)
! 175: return NULL;
1.1 misho 176:
1.1.1.3 ! misho 177: rinfo = rip_info_new ();
! 178: memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
! 179: listnode_add (list, rinfo);
! 180:
! 181: if (rip_route_rte (rinfo))
! 182: {
! 183: rip_timeout_update (rinfo);
! 184: rip_zebra_ipv4_add (rp);
! 185: }
! 186:
! 187: /* Set the route change flag on the first entry. */
! 188: rinfo = listgetdata (listhead (list));
! 189: SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 190:
! 191: /* Signal the output process to trigger an update (see section 2.5). */
! 192: rip_event (RIP_TRIGGERED_UPDATE, 0);
! 193:
! 194: return rinfo;
! 195: }
! 196:
! 197: /* Replace the ECMP list with the new route.
! 198: * RETURN: the new entry added in the list
! 199: */
! 200: struct rip_info *
! 201: rip_ecmp_replace (struct rip_info *rinfo_new)
! 202: {
! 203: struct route_node *rp = rinfo_new->rp;
! 204: struct list *list = (struct list *)rp->info;
! 205: struct rip_info *rinfo = NULL, *tmp_rinfo = NULL;
! 206: struct listnode *node = NULL, *nextnode = NULL;
! 207:
! 208: if (list == NULL || listcount (list) == 0)
! 209: return rip_ecmp_add (rinfo_new);
! 210:
! 211: /* Get the first entry */
! 212: rinfo = listgetdata (listhead (list));
! 213:
! 214: /* Learnt route replaced by a local one. Delete it from zebra. */
! 215: if (rip_route_rte (rinfo) && !rip_route_rte (rinfo_new))
! 216: if (CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
! 217: rip_zebra_ipv4_delete (rp);
! 218:
! 219: /* Re-use the first entry, and delete the others. */
! 220: for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
! 221: if (tmp_rinfo != rinfo)
! 222: {
! 223: RIP_TIMER_OFF (tmp_rinfo->t_timeout);
! 224: RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
! 225: list_delete_node (list, node);
! 226: rip_info_free (tmp_rinfo);
! 227: }
! 228:
! 229: RIP_TIMER_OFF (rinfo->t_timeout);
! 230: RIP_TIMER_OFF (rinfo->t_garbage_collect);
! 231: memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
! 232:
! 233: if (rip_route_rte (rinfo))
! 234: {
! 235: rip_timeout_update (rinfo);
! 236: /* The ADD message implies an update. */
! 237: rip_zebra_ipv4_add (rp);
! 238: }
! 239:
! 240: /* Set the route change flag. */
! 241: SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 242:
! 243: /* Signal the output process to trigger an update (see section 2.5). */
! 244: rip_event (RIP_TRIGGERED_UPDATE, 0);
! 245:
! 246: return rinfo;
! 247: }
! 248:
! 249: /* Delete one route from the ECMP list.
! 250: * RETURN:
! 251: * null - the entry is freed, and other entries exist in the list
! 252: * the entry - the entry is the last one in the list; its metric is set
! 253: * to INFINITY, and the garbage collector is started for it
! 254: */
! 255: struct rip_info *
! 256: rip_ecmp_delete (struct rip_info *rinfo)
! 257: {
! 258: struct route_node *rp = rinfo->rp;
! 259: struct list *list = (struct list *)rp->info;
! 260:
! 261: RIP_TIMER_OFF (rinfo->t_timeout);
! 262:
! 263: if (listcount (list) > 1)
! 264: {
! 265: /* Some other ECMP entries still exist. Just delete this entry. */
! 266: RIP_TIMER_OFF (rinfo->t_garbage_collect);
! 267: listnode_delete (list, rinfo);
! 268: if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
! 269: /* The ADD message implies the update. */
! 270: rip_zebra_ipv4_add (rp);
! 271: rip_info_free (rinfo);
! 272: rinfo = NULL;
! 273: }
! 274: else
! 275: {
! 276: assert (rinfo == listgetdata (listhead (list)));
1.1 misho 277:
1.1.1.3 ! misho 278: /* This is the only entry left in the list. We must keep it in
! 279: * the list for garbage collection time, with INFINITY metric. */
1.1 misho 280:
1.1.1.3 ! misho 281: rinfo->metric = RIP_METRIC_INFINITY;
! 282: RIP_TIMER_ON (rinfo->t_garbage_collect,
! 283: rip_garbage_collect, rip->garbage_time);
1.1 misho 284:
1.1.1.3 ! misho 285: if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
! 286: rip_zebra_ipv4_delete (rp);
! 287: }
! 288:
! 289: /* Set the route change flag on the first entry. */
! 290: rinfo = listgetdata (listhead (list));
! 291: SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 292:
! 293: /* Signal the output process to trigger an update (see section 2.5). */
1.1 misho 294: rip_event (RIP_TRIGGERED_UPDATE, 0);
295:
1.1.1.3 ! misho 296: return rinfo;
! 297: }
! 298:
! 299: /* Timeout RIP routes. */
! 300: static int
! 301: rip_timeout (struct thread *t)
! 302: {
! 303: rip_ecmp_delete ((struct rip_info *)THREAD_ARG (t));
1.1 misho 304: return 0;
305: }
306:
307: static void
308: rip_timeout_update (struct rip_info *rinfo)
309: {
310: if (rinfo->metric != RIP_METRIC_INFINITY)
311: {
312: RIP_TIMER_OFF (rinfo->t_timeout);
313: RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
314: }
315: }
316:
317: static int
318: rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
319: {
320: struct distribute *dist;
321: struct access_list *alist;
322: struct prefix_list *plist;
323:
324: /* Input distribute-list filtering. */
325: if (ri->list[RIP_FILTER_IN])
326: {
327: if (access_list_apply (ri->list[RIP_FILTER_IN],
328: (struct prefix *) p) == FILTER_DENY)
329: {
330: if (IS_RIP_DEBUG_PACKET)
331: zlog_debug ("%s/%d filtered by distribute in",
332: inet_ntoa (p->prefix), p->prefixlen);
333: return -1;
334: }
335: }
336: if (ri->prefix[RIP_FILTER_IN])
337: {
338: if (prefix_list_apply (ri->prefix[RIP_FILTER_IN],
339: (struct prefix *) p) == PREFIX_DENY)
340: {
341: if (IS_RIP_DEBUG_PACKET)
342: zlog_debug ("%s/%d filtered by prefix-list in",
343: inet_ntoa (p->prefix), p->prefixlen);
344: return -1;
345: }
346: }
347:
348: /* All interface filter check. */
349: dist = distribute_lookup (NULL);
350: if (dist)
351: {
352: if (dist->list[DISTRIBUTE_IN])
353: {
354: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
355:
356: if (alist)
357: {
358: if (access_list_apply (alist,
359: (struct prefix *) p) == FILTER_DENY)
360: {
361: if (IS_RIP_DEBUG_PACKET)
362: zlog_debug ("%s/%d filtered by distribute in",
363: inet_ntoa (p->prefix), p->prefixlen);
364: return -1;
365: }
366: }
367: }
368: if (dist->prefix[DISTRIBUTE_IN])
369: {
370: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
371:
372: if (plist)
373: {
374: if (prefix_list_apply (plist,
375: (struct prefix *) p) == PREFIX_DENY)
376: {
377: if (IS_RIP_DEBUG_PACKET)
378: zlog_debug ("%s/%d filtered by prefix-list in",
379: inet_ntoa (p->prefix), p->prefixlen);
380: return -1;
381: }
382: }
383: }
384: }
385: return 0;
386: }
387:
388: static int
389: rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri)
390: {
391: struct distribute *dist;
392: struct access_list *alist;
393: struct prefix_list *plist;
394:
395: if (ri->list[RIP_FILTER_OUT])
396: {
397: if (access_list_apply (ri->list[RIP_FILTER_OUT],
398: (struct prefix *) p) == FILTER_DENY)
399: {
400: if (IS_RIP_DEBUG_PACKET)
401: zlog_debug ("%s/%d is filtered by distribute out",
402: inet_ntoa (p->prefix), p->prefixlen);
403: return -1;
404: }
405: }
406: if (ri->prefix[RIP_FILTER_OUT])
407: {
408: if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],
409: (struct prefix *) p) == PREFIX_DENY)
410: {
411: if (IS_RIP_DEBUG_PACKET)
412: zlog_debug ("%s/%d is filtered by prefix-list out",
413: inet_ntoa (p->prefix), p->prefixlen);
414: return -1;
415: }
416: }
417:
418: /* All interface filter check. */
419: dist = distribute_lookup (NULL);
420: if (dist)
421: {
422: if (dist->list[DISTRIBUTE_OUT])
423: {
424: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
425:
426: if (alist)
427: {
428: if (access_list_apply (alist,
429: (struct prefix *) p) == FILTER_DENY)
430: {
431: if (IS_RIP_DEBUG_PACKET)
432: zlog_debug ("%s/%d filtered by distribute out",
433: inet_ntoa (p->prefix), p->prefixlen);
434: return -1;
435: }
436: }
437: }
438: if (dist->prefix[DISTRIBUTE_OUT])
439: {
440: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
441:
442: if (plist)
443: {
444: if (prefix_list_apply (plist,
445: (struct prefix *) p) == PREFIX_DENY)
446: {
447: if (IS_RIP_DEBUG_PACKET)
448: zlog_debug ("%s/%d filtered by prefix-list out",
449: inet_ntoa (p->prefix), p->prefixlen);
450: return -1;
451: }
452: }
453: }
454: }
455: return 0;
456: }
457:
458: /* Check nexthop address validity. */
459: static int
460: rip_nexthop_check (struct in_addr *addr)
461: {
462: struct listnode *node;
463: struct listnode *cnode;
464: struct interface *ifp;
465: struct connected *ifc;
466: struct prefix *p;
467:
468: /* If nexthop address matches local configured address then it is
469: invalid nexthop. */
470: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
471: {
472: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
473: {
474: p = ifc->address;
475:
476: if (p->family == AF_INET
477: && IPV4_ADDR_SAME (&p->u.prefix4, addr))
478: return -1;
479: }
480: }
481: return 0;
482: }
483:
484: /* RIP add route to routing table. */
485: static void
486: rip_rte_process (struct rte *rte, struct sockaddr_in *from,
487: struct interface *ifp)
488: {
489: int ret;
490: struct prefix_ipv4 p;
491: struct route_node *rp;
1.1.1.3 ! misho 492: struct rip_info *rinfo = NULL, newinfo;
1.1 misho 493: struct rip_interface *ri;
494: struct in_addr *nexthop;
495: int same = 0;
496: unsigned char old_dist, new_dist;
1.1.1.3 ! misho 497: struct list *list = NULL;
! 498: struct listnode *node = NULL;
1.1 misho 499:
500: /* Make prefix structure. */
501: memset (&p, 0, sizeof (struct prefix_ipv4));
502: p.family = AF_INET;
503: p.prefix = rte->prefix;
504: p.prefixlen = ip_masklen (rte->mask);
505:
506: /* Make sure mask is applied. */
507: apply_mask_ipv4 (&p);
508:
509: /* Apply input filters. */
510: ri = ifp->info;
511:
512: ret = rip_incoming_filter (&p, ri);
513: if (ret < 0)
514: return;
515:
1.1.1.3 ! misho 516: memset (&newinfo, 0, sizeof (newinfo));
! 517: newinfo.type = ZEBRA_ROUTE_RIP;
! 518: newinfo.sub_type = RIP_ROUTE_RTE;
! 519: newinfo.nexthop = rte->nexthop;
! 520: newinfo.from = from->sin_addr;
! 521: newinfo.ifindex = ifp->ifindex;
! 522: newinfo.metric = rte->metric;
! 523: newinfo.metric_out = rte->metric; /* XXX */
! 524: newinfo.tag = ntohs (rte->tag); /* XXX */
! 525:
1.1 misho 526: /* Modify entry according to the interface routemap. */
527: if (ri->routemap[RIP_FILTER_IN])
528: {
529: int ret;
530:
531: /* The object should be of the type of rip_info */
532: ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
533: (struct prefix *) &p, RMAP_RIP, &newinfo);
534:
535: if (ret == RMAP_DENYMATCH)
536: {
537: if (IS_RIP_DEBUG_PACKET)
538: zlog_debug ("RIP %s/%d is filtered by route-map in",
539: inet_ntoa (p.prefix), p.prefixlen);
540: return;
541: }
542:
543: /* Get back the object */
544: rte->nexthop = newinfo.nexthop_out;
545: rte->tag = htons (newinfo.tag_out); /* XXX */
546: rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
547: }
548:
549: /* Once the entry has been validated, update the metric by
550: adding the cost of the network on wich the message
551: arrived. If the result is greater than infinity, use infinity
552: (RFC2453 Sec. 3.9.2) */
553: /* Zebra ripd can handle offset-list in. */
554: ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
555:
556: /* If offset-list does not modify the metric use interface's
557: metric. */
558: if (!ret)
1.1.1.3 ! misho 559: rte->metric += ifp->metric ? ifp->metric : 1;
1.1 misho 560:
561: if (rte->metric > RIP_METRIC_INFINITY)
562: rte->metric = RIP_METRIC_INFINITY;
563:
564: /* Set nexthop pointer. */
565: if (rte->nexthop.s_addr == 0)
566: nexthop = &from->sin_addr;
567: else
568: nexthop = &rte->nexthop;
569:
570: /* Check if nexthop address is myself, then do nothing. */
571: if (rip_nexthop_check (nexthop) < 0)
572: {
573: if (IS_RIP_DEBUG_PACKET)
574: zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
575: return;
576: }
577:
578: /* Get index for the prefix. */
579: rp = route_node_get (rip->table, (struct prefix *) &p);
580:
1.1.1.3 ! misho 581: newinfo.rp = rp;
! 582: newinfo.nexthop = *nexthop;
! 583: newinfo.metric = rte->metric;
! 584: newinfo.tag = ntohs (rte->tag);
! 585: newinfo.distance = rip_distance_apply (&newinfo);
! 586:
! 587: new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT;
! 588:
1.1 misho 589: /* Check to see whether there is already RIP route on the table. */
1.1.1.3 ! misho 590: if ((list = rp->info) != NULL)
! 591: for (ALL_LIST_ELEMENTS_RO (list, node, rinfo))
! 592: {
! 593: /* Need to compare with redistributed entry or local entry */
! 594: if (!rip_route_rte (rinfo))
! 595: break;
! 596:
! 597: if (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) &&
! 598: IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
! 599: break;
! 600:
! 601: if (!listnextnode (node))
! 602: {
! 603: /* Not found in the list */
! 604:
! 605: if (rte->metric > rinfo->metric)
! 606: {
! 607: /* New route has a greater metric. Discard it. */
! 608: route_unlock_node (rp);
! 609: return;
! 610: }
! 611:
! 612: if (rte->metric < rinfo->metric)
! 613: /* New route has a smaller metric. Replace the ECMP list
! 614: * with the new one in below. */
! 615: break;
! 616:
! 617: /* Metrics are same. We compare the distances. */
! 618: old_dist = rinfo->distance ? \
! 619: rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
! 620:
! 621: if (new_dist > old_dist)
! 622: {
! 623: /* New route has a greater distance. Discard it. */
! 624: route_unlock_node (rp);
! 625: return;
! 626: }
! 627:
! 628: if (new_dist < old_dist)
! 629: /* New route has a smaller distance. Replace the ECMP list
! 630: * with the new one in below. */
! 631: break;
! 632:
! 633: /* Metrics and distances are both same. Keep "rinfo" null and
! 634: * the new route is added in the ECMP list in below. */
! 635: }
! 636: }
1.1 misho 637:
638: if (rinfo)
639: {
640: /* Local static route. */
641: if (rinfo->type == ZEBRA_ROUTE_RIP
642: && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
643: (rinfo->sub_type == RIP_ROUTE_DEFAULT))
644: && rinfo->metric != RIP_METRIC_INFINITY)
645: {
646: route_unlock_node (rp);
647: return;
648: }
649:
650: /* Redistributed route check. */
651: if (rinfo->type != ZEBRA_ROUTE_RIP
652: && rinfo->metric != RIP_METRIC_INFINITY)
653: {
654: old_dist = rinfo->distance;
1.1.1.3 ! misho 655: /* Only routes directly connected to an interface (nexthop == 0)
! 656: * may have a valid NULL distance */
! 657: if (rinfo->nexthop.s_addr != 0)
1.1 misho 658: old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
659: /* If imported route does not have STRICT precedence,
660: mark it as a ghost */
1.1.1.3 ! misho 661: if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY)
! 662: rip_ecmp_replace (&newinfo);
! 663:
! 664: route_unlock_node (rp);
! 665: return;
1.1 misho 666: }
667: }
668:
669: if (!rinfo)
670: {
1.1.1.3 ! misho 671: if (rp->info)
! 672: route_unlock_node (rp);
! 673:
1.1 misho 674: /* Now, check to see whether there is already an explicit route
675: for the destination prefix. If there is no such route, add
676: this route to the routing table, unless the metric is
677: infinity (there is no point in adding a route which
678: unusable). */
679: if (rte->metric != RIP_METRIC_INFINITY)
1.1.1.3 ! misho 680: rip_ecmp_add (&newinfo);
1.1 misho 681: }
682: else
683: {
684: /* Route is there but we are not sure the route is RIP or not. */
685:
686: /* If there is an existing route, compare the next hop address
687: to the address of the router from which the datagram came.
688: If this datagram is from the same router as the existing
689: route, reinitialize the timeout. */
690: same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
691: && (rinfo->ifindex == ifp->ifindex));
692:
1.1.1.3 ! misho 693: old_dist = rinfo->distance ? \
! 694: rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
1.1 misho 695:
696: /* Next, compare the metrics. If the datagram is from the same
697: router as the existing route, and the new metric is different
698: than the old one; or, if the new metric is lower than the old
699: one, or if the tag has been changed; or if there is a route
700: with a lower administrave distance; or an update of the
701: distance on the actual route; do the following actions: */
702: if ((same && rinfo->metric != rte->metric)
703: || (rte->metric < rinfo->metric)
704: || ((same)
705: && (rinfo->metric == rte->metric)
1.1.1.3 ! misho 706: && (newinfo.tag != rinfo->tag))
! 707: || (old_dist > new_dist)
! 708: || ((old_dist != new_dist) && same))
1.1 misho 709: {
1.1.1.3 ! misho 710: if (listcount (list) == 1)
1.1 misho 711: {
1.1.1.3 ! misho 712: if (newinfo.metric != RIP_METRIC_INFINITY)
! 713: rip_ecmp_replace (&newinfo);
! 714: else
! 715: rip_ecmp_delete (rinfo);
1.1 misho 716: }
1.1.1.3 ! misho 717: else
1.1 misho 718: {
1.1.1.3 ! misho 719: if (newinfo.metric < rinfo->metric)
! 720: rip_ecmp_replace (&newinfo);
! 721: else if (newinfo.metric > rinfo->metric)
! 722: rip_ecmp_delete (rinfo);
! 723: else if (new_dist < old_dist)
! 724: rip_ecmp_replace (&newinfo);
! 725: else if (new_dist > old_dist)
! 726: rip_ecmp_delete (rinfo);
! 727: else
! 728: {
! 729: int update = CHECK_FLAG (rinfo->flags, RIP_RTF_FIB) ? 1 : 0;
1.1 misho 730:
1.1.1.3 ! misho 731: assert (newinfo.metric != RIP_METRIC_INFINITY);
1.1 misho 732:
733: RIP_TIMER_OFF (rinfo->t_timeout);
1.1.1.3 ! misho 734: RIP_TIMER_OFF (rinfo->t_garbage_collect);
! 735: memcpy (rinfo, &newinfo, sizeof (struct rip_info));
! 736: rip_timeout_update (rinfo);
! 737:
! 738: if (update)
! 739: rip_zebra_ipv4_add (rp);
! 740:
! 741: /* - Set the route change flag on the first entry. */
! 742: rinfo = listgetdata (listhead (list));
! 743: SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 744: rip_event (RIP_TRIGGERED_UPDATE, 0);
1.1 misho 745: }
746: }
747: }
1.1.1.3 ! misho 748: else /* same & no change */
! 749: rip_timeout_update (rinfo);
! 750:
1.1 misho 751: /* Unlock tempolary lock of the route. */
752: route_unlock_node (rp);
753: }
754: }
755:
756: /* Dump RIP packet */
757: static void
758: rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
759: {
760: caddr_t lim;
761: struct rte *rte;
762: const char *command_str;
763: char pbuf[BUFSIZ], nbuf[BUFSIZ];
764: u_char netmask = 0;
765: u_char *p;
766:
767: /* Set command string. */
768: if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
769: command_str = lookup (rip_msg, packet->command);
770: else
771: command_str = "unknown";
772:
773: /* Dump packet header. */
774: zlog_debug ("%s %s version %d packet size %d",
775: sndrcv, command_str, packet->version, size);
776:
777: /* Dump each routing table entry. */
778: rte = packet->rte;
779:
780: for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
781: {
782: if (packet->version == RIPv2)
783: {
784: netmask = ip_masklen (rte->mask);
785:
786: if (rte->family == htons (RIP_FAMILY_AUTH))
787: {
788: if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
789: {
790: p = (u_char *)&rte->prefix;
791:
792: zlog_debug (" family 0x%X type %d auth string: %s",
793: ntohs (rte->family), ntohs (rte->tag), p);
794: }
795: else if (rte->tag == htons (RIP_AUTH_MD5))
796: {
797: struct rip_md5_info *md5;
798:
799: md5 = (struct rip_md5_info *) &packet->rte;
800:
801: zlog_debug (" family 0x%X type %d (MD5 authentication)",
802: ntohs (md5->family), ntohs (md5->type));
803: zlog_debug (" RIP-2 packet len %d Key ID %d"
804: " Auth Data len %d",
805: ntohs (md5->packet_len), md5->keyid,
806: md5->auth_len);
807: zlog_debug (" Sequence Number %ld",
808: (u_long) ntohl (md5->sequence));
809: }
810: else if (rte->tag == htons (RIP_AUTH_DATA))
811: {
812: p = (u_char *)&rte->prefix;
813:
814: zlog_debug (" family 0x%X type %d (MD5 data)",
815: ntohs (rte->family), ntohs (rte->tag));
816: zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
817: "%02X%02X%02X%02X%02X%02X%02X",
818: p[0], p[1], p[2], p[3], p[4], p[5], p[6],
819: p[7], p[9], p[10], p[11], p[12], p[13],
820: p[14], p[15]);
821: }
822: else
823: {
824: zlog_debug (" family 0x%X type %d (Unknown auth type)",
825: ntohs (rte->family), ntohs (rte->tag));
826: }
827: }
828: else
829: zlog_debug (" %s/%d -> %s family %d tag %d metric %ld",
830: inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
831: netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
832: BUFSIZ), ntohs (rte->family),
833: ntohs (rte->tag), (u_long) ntohl (rte->metric));
834: }
835: else
836: {
837: zlog_debug (" %s family %d tag %d metric %ld",
838: inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
839: ntohs (rte->family), ntohs (rte->tag),
840: (u_long)ntohl (rte->metric));
841: }
842: }
843: }
844:
845: /* Check if the destination address is valid (unicast; not net 0
846: or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't
847: check net 0 because we accept default route. */
848: static int
849: rip_destination_check (struct in_addr addr)
850: {
851: u_int32_t destination;
852:
853: /* Convert to host byte order. */
854: destination = ntohl (addr.s_addr);
855:
856: if (IPV4_NET127 (destination))
857: return 0;
858:
859: /* Net 0 may match to the default route. */
860: if (IPV4_NET0 (destination) && destination != 0)
861: return 0;
862:
863: /* Unicast address must belong to class A, B, C. */
864: if (IN_CLASSA (destination))
865: return 1;
866: if (IN_CLASSB (destination))
867: return 1;
868: if (IN_CLASSC (destination))
869: return 1;
870:
871: return 0;
872: }
873:
874: /* RIP version 2 authentication. */
875: static int
876: rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
877: struct interface *ifp)
878: {
879: struct rip_interface *ri;
880: char *auth_str;
881:
882: if (IS_RIP_DEBUG_EVENT)
883: zlog_debug ("RIPv2 simple password authentication from %s",
884: inet_ntoa (from->sin_addr));
885:
886: ri = ifp->info;
887:
888: if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
889: || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
890: return 0;
891:
892: /* Simple password authentication. */
893: if (ri->auth_str)
894: {
895: auth_str = (char *) &rte->prefix;
896:
897: if (strncmp (auth_str, ri->auth_str, 16) == 0)
898: return 1;
899: }
900: if (ri->key_chain)
901: {
902: struct keychain *keychain;
903: struct key *key;
904:
905: keychain = keychain_lookup (ri->key_chain);
906: if (keychain == NULL)
907: return 0;
908:
909: key = key_match_for_accept (keychain, (char *) &rte->prefix);
910: if (key)
911: return 1;
912: }
913: return 0;
914: }
915:
916: /* RIP version 2 authentication with MD5. */
917: static int
918: rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
919: int length, struct interface *ifp)
920: {
921: struct rip_interface *ri;
922: struct rip_md5_info *md5;
923: struct rip_md5_data *md5data;
924: struct keychain *keychain;
925: struct key *key;
926: MD5_CTX ctx;
927: u_char digest[RIP_AUTH_MD5_SIZE];
928: u_int16_t packet_len;
929: char auth_str[RIP_AUTH_MD5_SIZE];
930:
931: if (IS_RIP_DEBUG_EVENT)
932: zlog_debug ("RIPv2 MD5 authentication from %s",
933: inet_ntoa (from->sin_addr));
934:
935: ri = ifp->info;
936: md5 = (struct rip_md5_info *) &packet->rte;
937:
938: /* Check auth type. */
939: if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
940: return 0;
941:
942: /* If the authentication length is less than 16, then it must be wrong for
943: * any interpretation of rfc2082. Some implementations also interpret
944: * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
945: */
946: if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
947: || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
948: {
949: if (IS_RIP_DEBUG_EVENT)
950: zlog_debug ("RIPv2 MD5 authentication, strange authentication "
951: "length field %d", md5->auth_len);
952: return 0;
953: }
954:
955: /* grab and verify check packet length */
956: packet_len = ntohs (md5->packet_len);
957:
958: if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
959: {
960: if (IS_RIP_DEBUG_EVENT)
961: zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
962: "greater than received length %d!",
963: md5->packet_len, length);
964: return 0;
965: }
966:
967: /* retrieve authentication data */
968: md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
969:
970: memset (auth_str, 0, RIP_AUTH_MD5_SIZE);
971:
972: if (ri->key_chain)
973: {
974: keychain = keychain_lookup (ri->key_chain);
975: if (keychain == NULL)
976: return 0;
977:
978: key = key_lookup_for_accept (keychain, md5->keyid);
979: if (key == NULL)
980: return 0;
981:
982: strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE);
983: }
984: else if (ri->auth_str)
985: strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
986:
987: if (auth_str[0] == 0)
988: return 0;
989:
990: /* MD5 digest authentication. */
991: memset (&ctx, 0, sizeof(ctx));
992: MD5Init(&ctx);
993: MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
994: MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
995: MD5Final(digest, &ctx);
996:
997: if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
998: return packet_len;
999: else
1000: return 0;
1001: }
1002:
1003: /* Pick correct auth string for sends, prepare auth_str buffer for use.
1004: * (left justified and padded).
1005: *
1006: * presumes one of ri or key is valid, and that the auth strings they point
1007: * to are nul terminated. If neither are present, auth_str will be fully
1008: * zero padded.
1009: *
1010: */
1011: static void
1012: rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key,
1013: char *auth_str, int len)
1014: {
1015: assert (ri || key);
1016:
1017: memset (auth_str, 0, len);
1018: if (key && key->string)
1019: strncpy (auth_str, key->string, len);
1020: else if (ri->auth_str)
1021: strncpy (auth_str, ri->auth_str, len);
1022:
1023: return;
1024: }
1025:
1026: /* Write RIPv2 simple password authentication information
1027: *
1028: * auth_str is presumed to be 2 bytes and correctly prepared
1029: * (left justified and zero padded).
1030: */
1031: static void
1032: rip_auth_simple_write (struct stream *s, char *auth_str, int len)
1033: {
1034: assert (s && len == RIP_AUTH_SIMPLE_SIZE);
1035:
1036: stream_putw (s, RIP_FAMILY_AUTH);
1037: stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
1038: stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
1039:
1040: return;
1041: }
1042:
1043: /* write RIPv2 MD5 "authentication header"
1044: * (uses the auth key data field)
1045: *
1046: * Digest offset field is set to 0.
1047: *
1048: * returns: offset of the digest offset field, which must be set when
1049: * length to the auth-data MD5 digest is known.
1050: */
1051: static size_t
1052: rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
1053: struct key *key)
1054: {
1055: size_t doff = 0;
1056:
1057: assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
1058:
1059: /* MD5 authentication. */
1060: stream_putw (s, RIP_FAMILY_AUTH);
1061: stream_putw (s, RIP_AUTH_MD5);
1062:
1063: /* MD5 AH digest offset field.
1064: *
1065: * Set to placeholder value here, to true value when RIP-2 Packet length
1066: * is known. Actual value is set in .....().
1067: */
1068: doff = stream_get_endp(s);
1069: stream_putw (s, 0);
1070:
1071: /* Key ID. */
1072: if (key)
1073: stream_putc (s, key->index % 256);
1074: else
1075: stream_putc (s, 1);
1076:
1077: /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds
1078: * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
1079: * to be configurable.
1080: */
1081: stream_putc (s, ri->md5_auth_len);
1082:
1083: /* Sequence Number (non-decreasing). */
1084: /* RFC2080: The value used in the sequence number is
1085: arbitrary, but two suggestions are the time of the
1086: message's creation or a simple message counter. */
1087: stream_putl (s, time (NULL));
1088:
1089: /* Reserved field must be zero. */
1090: stream_putl (s, 0);
1091: stream_putl (s, 0);
1092:
1093: return doff;
1094: }
1095:
1096: /* If authentication is in used, write the appropriate header
1097: * returns stream offset to which length must later be written
1098: * or 0 if this is not required
1099: */
1100: static size_t
1101: rip_auth_header_write (struct stream *s, struct rip_interface *ri,
1102: struct key *key, char *auth_str, int len)
1103: {
1104: assert (ri->auth_type != RIP_NO_AUTH);
1105:
1106: switch (ri->auth_type)
1107: {
1108: case RIP_AUTH_SIMPLE_PASSWORD:
1109: rip_auth_prepare_str_send (ri, key, auth_str, len);
1110: rip_auth_simple_write (s, auth_str, len);
1111: return 0;
1112: case RIP_AUTH_MD5:
1113: return rip_auth_md5_ah_write (s, ri, key);
1114: }
1115: assert (1);
1116: return 0;
1117: }
1118:
1119: /* Write RIPv2 MD5 authentication data trailer */
1120: static void
1121: rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
1122: char *auth_str, int authlen)
1123: {
1124: unsigned long len;
1125: MD5_CTX ctx;
1126: unsigned char digest[RIP_AUTH_MD5_SIZE];
1127:
1128: /* Make it sure this interface is configured as MD5
1129: authentication. */
1130: assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
1131: assert (doff > 0);
1132:
1133: /* Get packet length. */
1134: len = stream_get_endp(s);
1135:
1136: /* Check packet length. */
1137: if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
1138: {
1139: zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
1140: return;
1141: }
1142:
1143: /* Set the digest offset length in the header */
1144: stream_putw_at (s, doff, len);
1145:
1146: /* Set authentication data. */
1147: stream_putw (s, RIP_FAMILY_AUTH);
1148: stream_putw (s, RIP_AUTH_DATA);
1149:
1150: /* Generate a digest for the RIP packet. */
1151: memset(&ctx, 0, sizeof(ctx));
1152: MD5Init(&ctx);
1153: MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s));
1154: MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
1155: MD5Final(digest, &ctx);
1156:
1157: /* Copy the digest to the packet. */
1158: stream_write (s, digest, RIP_AUTH_MD5_SIZE);
1159: }
1160:
1161: /* RIP routing information. */
1162: static void
1163: rip_response_process (struct rip_packet *packet, int size,
1164: struct sockaddr_in *from, struct connected *ifc)
1165: {
1166: caddr_t lim;
1167: struct rte *rte;
1168: struct prefix_ipv4 ifaddr;
1169: struct prefix_ipv4 ifaddrclass;
1170: int subnetted;
1.1.1.3 ! misho 1171:
! 1172: memset(&ifaddr, 0, sizeof(ifaddr));
1.1 misho 1173: /* We don't know yet. */
1174: subnetted = -1;
1175:
1176: /* The Response must be ignored if it is not from the RIP
1177: port. (RFC2453 - Sec. 3.9.2)*/
1178: if (from->sin_port != htons(RIP_PORT_DEFAULT))
1179: {
1180: zlog_info ("response doesn't come from RIP port: %d",
1181: from->sin_port);
1182: rip_peer_bad_packet (from);
1183: return;
1184: }
1185:
1186: /* The datagram's IPv4 source address should be checked to see
1187: whether the datagram is from a valid neighbor; the source of the
1188: datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */
1189: if (if_lookup_address(from->sin_addr) == NULL)
1190: {
1191: zlog_info ("This datagram doesn't came from a valid neighbor: %s",
1192: inet_ntoa (from->sin_addr));
1193: rip_peer_bad_packet (from);
1194: return;
1195: }
1196:
1197: /* It is also worth checking to see whether the response is from one
1198: of the router's own addresses. */
1199:
1200: ; /* Alredy done in rip_read () */
1201:
1202: /* Update RIP peer. */
1203: rip_peer_update (from, packet->version);
1204:
1205: /* Set RTE pointer. */
1206: rte = packet->rte;
1207:
1208: for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
1209: {
1210: /* RIPv2 authentication check. */
1211: /* If the Address Family Identifier of the first (and only the
1212: first) entry in the message is 0xFFFF, then the remainder of
1213: the entry contains the authentication. */
1214: /* If the packet gets here it means authentication enabled */
1215: /* Check is done in rip_read(). So, just skipping it */
1216: if (packet->version == RIPv2 &&
1217: rte == packet->rte &&
1218: rte->family == htons(RIP_FAMILY_AUTH))
1219: continue;
1220:
1221: if (rte->family != htons(AF_INET))
1222: {
1223: /* Address family check. RIP only supports AF_INET. */
1224: zlog_info ("Unsupported family %d from %s.",
1225: ntohs (rte->family), inet_ntoa (from->sin_addr));
1226: continue;
1227: }
1228:
1229: /* - is the destination address valid (e.g., unicast; not net 0
1230: or 127) */
1231: if (! rip_destination_check (rte->prefix))
1232: {
1233: zlog_info ("Network is net 0 or net 127 or it is not unicast network");
1234: rip_peer_bad_route (from);
1235: continue;
1236: }
1237:
1238: /* Convert metric value to host byte order. */
1239: rte->metric = ntohl (rte->metric);
1240:
1241: /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1242: if (! (rte->metric >= 1 && rte->metric <= 16))
1243: {
1244: zlog_info ("Route's metric is not in the 1-16 range.");
1245: rip_peer_bad_route (from);
1246: continue;
1247: }
1248:
1249: /* RIPv1 does not have nexthop value. */
1250: if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
1251: {
1252: zlog_info ("RIPv1 packet with nexthop value %s",
1253: inet_ntoa (rte->nexthop));
1254: rip_peer_bad_route (from);
1255: continue;
1256: }
1257:
1258: /* That is, if the provided information is ignored, a possibly
1259: sub-optimal, but absolutely valid, route may be taken. If
1260: the received Next Hop is not directly reachable, it should be
1261: treated as 0.0.0.0. */
1262: if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
1263: {
1264: u_int32_t addrval;
1265:
1266: /* Multicast address check. */
1267: addrval = ntohl (rte->nexthop.s_addr);
1268: if (IN_CLASSD (addrval))
1269: {
1270: zlog_info ("Nexthop %s is multicast address, skip this rte",
1271: inet_ntoa (rte->nexthop));
1272: continue;
1273: }
1274:
1275: if (! if_lookup_address (rte->nexthop))
1276: {
1277: struct route_node *rn;
1278: struct rip_info *rinfo;
1279:
1280: rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
1281:
1282: if (rn)
1283: {
1284: rinfo = rn->info;
1285:
1286: if (rinfo->type == ZEBRA_ROUTE_RIP
1287: && rinfo->sub_type == RIP_ROUTE_RTE)
1288: {
1289: if (IS_RIP_DEBUG_EVENT)
1290: zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
1291: rte->nexthop = rinfo->from;
1292: }
1293: else
1294: {
1295: if (IS_RIP_DEBUG_EVENT)
1296: zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1297: rte->nexthop.s_addr = 0;
1298: }
1299:
1300: route_unlock_node (rn);
1301: }
1302: else
1303: {
1304: if (IS_RIP_DEBUG_EVENT)
1305: zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
1306: rte->nexthop.s_addr = 0;
1307: }
1308:
1309: }
1310: }
1311:
1312: /* For RIPv1, there won't be a valid netmask.
1313:
1314: This is a best guess at the masks. If everyone was using old
1315: Ciscos before the 'ip subnet zero' option, it would be almost
1316: right too :-)
1317:
1318: Cisco summarize ripv1 advertisments to the classful boundary
1319: (/16 for class B's) except when the RIP packet does to inside
1320: the classful network in question. */
1321:
1322: if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
1323: || (packet->version == RIPv2
1324: && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
1325: {
1326: u_int32_t destination;
1327:
1328: if (subnetted == -1)
1329: {
1330: memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
1331: memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
1332: apply_classful_mask_ipv4 (&ifaddrclass);
1333: subnetted = 0;
1334: if (ifaddr.prefixlen > ifaddrclass.prefixlen)
1335: subnetted = 1;
1336: }
1337:
1338: destination = ntohl (rte->prefix.s_addr);
1339:
1340: if (IN_CLASSA (destination))
1341: masklen2ip (8, &rte->mask);
1342: else if (IN_CLASSB (destination))
1343: masklen2ip (16, &rte->mask);
1344: else if (IN_CLASSC (destination))
1345: masklen2ip (24, &rte->mask);
1346:
1347: if (subnetted == 1)
1348: masklen2ip (ifaddrclass.prefixlen,
1349: (struct in_addr *) &destination);
1350: if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
1351: ifaddrclass.prefix.s_addr))
1352: {
1353: masklen2ip (ifaddr.prefixlen, &rte->mask);
1354: if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1355: masklen2ip (32, &rte->mask);
1356: if (IS_RIP_DEBUG_EVENT)
1357: zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
1358: }
1359: else
1360: {
1361: if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
1362: continue;
1363: }
1364:
1365: if (IS_RIP_DEBUG_EVENT)
1366: {
1367: zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
1368: zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
1369: }
1370: }
1371:
1372: /* In case of RIPv2, if prefix in RTE is not netmask applied one
1373: ignore the entry. */
1374: if ((packet->version == RIPv2)
1375: && (rte->mask.s_addr != 0)
1376: && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
1377: {
1378: zlog_warn ("RIPv2 address %s is not mask /%d applied one",
1379: inet_ntoa (rte->prefix), ip_masklen (rte->mask));
1380: rip_peer_bad_route (from);
1381: continue;
1382: }
1383:
1384: /* Default route's netmask is ignored. */
1385: if (packet->version == RIPv2
1386: && (rte->prefix.s_addr == 0)
1387: && (rte->mask.s_addr != 0))
1388: {
1389: if (IS_RIP_DEBUG_EVENT)
1390: zlog_debug ("Default route with non-zero netmask. Set zero to netmask");
1391: rte->mask.s_addr = 0;
1392: }
1393:
1394: /* Routing table updates. */
1395: rip_rte_process (rte, from, ifc->ifp);
1396: }
1397: }
1398:
1399: /* Make socket for RIP protocol. */
1400: static int
1401: rip_create_socket (struct sockaddr_in *from)
1402: {
1403: int ret;
1404: int sock;
1405: struct sockaddr_in addr;
1406:
1407: memset (&addr, 0, sizeof (struct sockaddr_in));
1408:
1409: if (!from)
1410: {
1411: addr.sin_family = AF_INET;
1412: addr.sin_addr.s_addr = INADDR_ANY;
1413: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1414: addr.sin_len = sizeof (struct sockaddr_in);
1415: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1416: } else {
1417: memcpy(&addr, from, sizeof(addr));
1418: }
1419:
1420: /* sending port must always be the RIP port */
1421: addr.sin_port = htons (RIP_PORT_DEFAULT);
1422:
1423: /* Make datagram socket. */
1424: sock = socket (AF_INET, SOCK_DGRAM, 0);
1425: if (sock < 0)
1426: {
1427: zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
1428: exit (1);
1429: }
1430:
1431: sockopt_broadcast (sock);
1432: sockopt_reuseaddr (sock);
1433: sockopt_reuseport (sock);
1434: #ifdef RIP_RECVMSG
1435: setsockopt_pktinfo (sock);
1436: #endif /* RIP_RECVMSG */
1437: #ifdef IPTOS_PREC_INTERNETCONTROL
1438: setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
1439: #endif
1440:
1441: if (ripd_privs.change (ZPRIVS_RAISE))
1442: zlog_err ("rip_create_socket: could not raise privs");
1443: setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
1444: if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
1445:
1446: {
1447: int save_errno = errno;
1448: if (ripd_privs.change (ZPRIVS_LOWER))
1449: zlog_err ("rip_create_socket: could not lower privs");
1450:
1451: zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
1452: sock, inet_ntoa(addr.sin_addr),
1453: (int) ntohs(addr.sin_port),
1454: safe_strerror(save_errno));
1455:
1456: close (sock);
1457: return ret;
1458: }
1459:
1460: if (ripd_privs.change (ZPRIVS_LOWER))
1461: zlog_err ("rip_create_socket: could not lower privs");
1462:
1463: return sock;
1464: }
1465:
1466: /* RIP packet send to destination address, on interface denoted by
1467: * by connected argument. NULL to argument denotes destination should be
1468: * should be RIP multicast group
1469: */
1470: static int
1471: rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
1472: struct connected *ifc)
1473: {
1474: int ret, send_sock;
1475: struct sockaddr_in sin;
1476:
1477: assert (ifc != NULL);
1478:
1479: if (IS_RIP_DEBUG_PACKET)
1480: {
1481: #define ADDRESS_SIZE 20
1482: char dst[ADDRESS_SIZE];
1483: dst[ADDRESS_SIZE - 1] = '\0';
1484:
1485: if (to)
1486: {
1487: strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
1488: }
1489: else
1490: {
1491: sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1492: strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
1493: }
1494: #undef ADDRESS_SIZE
1495: zlog_debug("rip_send_packet %s > %s (%s)",
1496: inet_ntoa(ifc->address->u.prefix4),
1497: dst, ifc->ifp->name);
1498: }
1499:
1500: if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
1501: {
1502: /*
1503: * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
1504: * with multiple addresses on the same subnet: the first address
1505: * on the subnet is configured "primary", and all subsequent addresses
1506: * on that subnet are treated as "secondary" addresses.
1507: * In order to avoid routing-table bloat on other rip listeners,
1508: * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
1509: * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
1510: * flag is set, we would end up sending a packet for a "secondary"
1511: * source address on non-linux systems.
1512: */
1513: if (IS_RIP_DEBUG_PACKET)
1514: zlog_debug("duplicate dropped");
1515: return 0;
1516: }
1517:
1518: /* Make destination address. */
1519: memset (&sin, 0, sizeof (struct sockaddr_in));
1520: sin.sin_family = AF_INET;
1521: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1522: sin.sin_len = sizeof (struct sockaddr_in);
1523: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1524:
1525: /* When destination is specified, use it's port and address. */
1526: if (to)
1527: {
1528: sin.sin_port = to->sin_port;
1529: sin.sin_addr = to->sin_addr;
1530: send_sock = rip->sock;
1531: }
1532: else
1533: {
1534: struct sockaddr_in from;
1535:
1536: sin.sin_port = htons (RIP_PORT_DEFAULT);
1537: sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
1538:
1539: /* multicast send should bind to local interface address */
1.1.1.2 misho 1540: memset (&from, 0, sizeof (from));
1.1 misho 1541: from.sin_family = AF_INET;
1542: from.sin_port = htons (RIP_PORT_DEFAULT);
1543: from.sin_addr = ifc->address->u.prefix4;
1544: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1545: from.sin_len = sizeof (struct sockaddr_in);
1546: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1547:
1548: /*
1549: * we have to open a new socket for each packet because this
1550: * is the most portable way to bind to a different source
1551: * ipv4 address for each packet.
1552: */
1553: if ( (send_sock = rip_create_socket (&from)) < 0)
1554: {
1555: zlog_warn("rip_send_packet could not create socket.");
1556: return -1;
1557: }
1558: rip_interface_multicast_set (send_sock, ifc);
1559: }
1560:
1561: ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin,
1562: sizeof (struct sockaddr_in));
1563:
1564: if (IS_RIP_DEBUG_EVENT)
1565: zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
1566: ntohs (sin.sin_port));
1567:
1568: if (ret < 0)
1569: zlog_warn ("can't send packet : %s", safe_strerror (errno));
1570:
1571: if (!to)
1572: close(send_sock);
1573:
1574: return ret;
1575: }
1576:
1577: /* Add redistributed route to RIP table. */
1578: void
1579: rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
1.1.1.3 ! misho 1580: ifindex_t ifindex, struct in_addr *nexthop,
1.1 misho 1581: unsigned int metric, unsigned char distance)
1582: {
1583: int ret;
1.1.1.3 ! misho 1584: struct route_node *rp = NULL;
! 1585: struct rip_info *rinfo = NULL, newinfo;
! 1586: struct list *list = NULL;
1.1 misho 1587:
1588: /* Redistribute route */
1589: ret = rip_destination_check (p->prefix);
1590: if (! ret)
1591: return;
1592:
1593: rp = route_node_get (rip->table, (struct prefix *) p);
1594:
1.1.1.3 ! misho 1595: memset (&newinfo, 0, sizeof (struct rip_info));
! 1596: newinfo.type = type;
! 1597: newinfo.sub_type = sub_type;
! 1598: newinfo.ifindex = ifindex;
! 1599: newinfo.metric = 1;
! 1600: newinfo.external_metric = metric;
! 1601: newinfo.distance = distance;
! 1602: newinfo.rp = rp;
! 1603: if (nexthop)
! 1604: newinfo.nexthop = *nexthop;
1.1 misho 1605:
1.1.1.3 ! misho 1606: if ((list = rp->info) != NULL && listcount (list) != 0)
1.1 misho 1607: {
1.1.1.3 ! misho 1608: rinfo = listgetdata (listhead (list));
! 1609:
1.1 misho 1610: if (rinfo->type == ZEBRA_ROUTE_CONNECT
1611: && rinfo->sub_type == RIP_ROUTE_INTERFACE
1612: && rinfo->metric != RIP_METRIC_INFINITY)
1613: {
1614: route_unlock_node (rp);
1615: return;
1616: }
1617:
1618: /* Manually configured RIP route check. */
1619: if (rinfo->type == ZEBRA_ROUTE_RIP
1620: && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
1621: (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
1622: {
1623: if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
1624: (sub_type != RIP_ROUTE_DEFAULT)))
1625: {
1626: route_unlock_node (rp);
1627: return;
1628: }
1629: }
1630:
1.1.1.3 ! misho 1631: rinfo = rip_ecmp_replace (&newinfo);
! 1632: route_unlock_node (rp);
1.1 misho 1633: }
1.1.1.3 ! misho 1634: else
! 1635: rinfo = rip_ecmp_add (&newinfo);
1.1 misho 1636:
1637: if (IS_RIP_DEBUG_EVENT) {
1638: if (!nexthop)
1639: zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1640: inet_ntoa(p->prefix), p->prefixlen,
1641: ifindex2ifname(ifindex));
1642: else
1643: zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1644: inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
1645: ifindex2ifname(ifindex));
1646: }
1647:
1648: rip_event (RIP_TRIGGERED_UPDATE, 0);
1649: }
1650:
1651: /* Delete redistributed route from RIP table. */
1652: void
1653: rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
1.1.1.3 ! misho 1654: ifindex_t ifindex)
1.1 misho 1655: {
1656: int ret;
1657: struct route_node *rp;
1658: struct rip_info *rinfo;
1659:
1660: ret = rip_destination_check (p->prefix);
1661: if (! ret)
1662: return;
1663:
1664: rp = route_node_lookup (rip->table, (struct prefix *) p);
1665: if (rp)
1666: {
1.1.1.3 ! misho 1667: struct list *list = rp->info;
1.1 misho 1668:
1.1.1.3 ! misho 1669: if (list != NULL && listcount (list) != 0)
! 1670: {
! 1671: rinfo = listgetdata (listhead (list));
! 1672: if (rinfo != NULL
! 1673: && rinfo->type == type
! 1674: && rinfo->sub_type == sub_type
! 1675: && rinfo->ifindex == ifindex)
! 1676: {
! 1677: /* Perform poisoned reverse. */
! 1678: rinfo->metric = RIP_METRIC_INFINITY;
! 1679: RIP_TIMER_ON (rinfo->t_garbage_collect,
! 1680: rip_garbage_collect, rip->garbage_time);
! 1681: RIP_TIMER_OFF (rinfo->t_timeout);
! 1682: rinfo->flags |= RIP_RTF_CHANGED;
1.1 misho 1683:
1.1.1.3 ! misho 1684: if (IS_RIP_DEBUG_EVENT)
! 1685: zlog_debug ("Poisone %s/%d on the interface %s with an "
! 1686: "infinity metric [delete]",
! 1687: inet_ntoa(p->prefix), p->prefixlen,
! 1688: ifindex2ifname(ifindex));
1.1 misho 1689:
1.1.1.3 ! misho 1690: rip_event (RIP_TRIGGERED_UPDATE, 0);
! 1691: }
! 1692: }
! 1693: route_unlock_node (rp);
1.1 misho 1694: }
1695: }
1696:
1697: /* Response to request called from rip_read ().*/
1698: static void
1699: rip_request_process (struct rip_packet *packet, int size,
1700: struct sockaddr_in *from, struct connected *ifc)
1701: {
1702: caddr_t lim;
1703: struct rte *rte;
1704: struct prefix_ipv4 p;
1705: struct route_node *rp;
1706: struct rip_info *rinfo;
1707: struct rip_interface *ri;
1708:
1709: /* Does not reponse to the requests on the loopback interfaces */
1710: if (if_is_loopback (ifc->ifp))
1711: return;
1712:
1713: /* Check RIP process is enabled on this interface. */
1714: ri = ifc->ifp->info;
1715: if (! ri->running)
1716: return;
1717:
1718: /* When passive interface is specified, suppress responses */
1719: if (ri->passive)
1720: return;
1721:
1722: /* RIP peer update. */
1723: rip_peer_update (from, packet->version);
1724:
1725: lim = ((caddr_t) packet) + size;
1726: rte = packet->rte;
1727:
1728: /* The Request is processed entry by entry. If there are no
1729: entries, no response is given. */
1730: if (lim == (caddr_t) rte)
1731: return;
1732:
1733: /* There is one special case. If there is exactly one entry in the
1734: request, and it has an address family identifier of zero and a
1735: metric of infinity (i.e., 16), then this is a request to send the
1736: entire routing table. */
1737: if (lim == ((caddr_t) (rte + 1)) &&
1738: ntohs (rte->family) == 0 &&
1739: ntohl (rte->metric) == RIP_METRIC_INFINITY)
1740: {
1741: /* All route with split horizon */
1742: rip_output_process (ifc, from, rip_all_route, packet->version);
1743: }
1744: else
1745: {
1746: /* Examine the list of RTEs in the Request one by one. For each
1747: entry, look up the destination in the router's routing
1748: database and, if there is a route, put that route's metric in
1749: the metric field of the RTE. If there is no explicit route
1750: to the specified destination, put infinity in the metric
1751: field. Once all the entries have been filled in, change the
1752: command from Request to Response and send the datagram back
1753: to the requestor. */
1754: p.family = AF_INET;
1755:
1756: for (; ((caddr_t) rte) < lim; rte++)
1757: {
1758: p.prefix = rte->prefix;
1759: p.prefixlen = ip_masklen (rte->mask);
1760: apply_mask_ipv4 (&p);
1761:
1762: rp = route_node_lookup (rip->table, (struct prefix *) &p);
1763: if (rp)
1764: {
1.1.1.3 ! misho 1765: rinfo = listgetdata (listhead ((struct list *)rp->info));
1.1 misho 1766: rte->metric = htonl (rinfo->metric);
1767: route_unlock_node (rp);
1768: }
1769: else
1770: rte->metric = htonl (RIP_METRIC_INFINITY);
1771: }
1772: packet->command = RIP_RESPONSE;
1773:
1774: rip_send_packet ((u_char *)packet, size, from, ifc);
1775: }
1776: rip_global_queries++;
1777: }
1778:
1779: #if RIP_RECVMSG
1780: /* Set IPv6 packet info to the socket. */
1781: static int
1782: setsockopt_pktinfo (int sock)
1783: {
1784: int ret;
1785: int val = 1;
1786:
1787: ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
1788: if (ret < 0)
1789: zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
1790: return ret;
1791: }
1792:
1793: /* Read RIP packet by recvmsg function. */
1794: int
1795: rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
1.1.1.3 ! misho 1796: ifindex_t *ifindex)
1.1 misho 1797: {
1798: int ret;
1799: struct msghdr msg;
1800: struct iovec iov;
1801: struct cmsghdr *ptr;
1802: char adata[1024];
1803:
1804: msg.msg_name = (void *) from;
1805: msg.msg_namelen = sizeof (struct sockaddr_in);
1806: msg.msg_iov = &iov;
1807: msg.msg_iovlen = 1;
1808: msg.msg_control = (void *) adata;
1809: msg.msg_controllen = sizeof adata;
1810: iov.iov_base = buf;
1811: iov.iov_len = size;
1812:
1813: ret = recvmsg (sock, &msg, 0);
1814: if (ret < 0)
1815: return ret;
1816:
1817: for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
1818: if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)
1819: {
1820: struct in_pktinfo *pktinfo;
1821: int i;
1822:
1823: pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
1824: i = pktinfo->ipi_ifindex;
1825: }
1826: return ret;
1827: }
1828:
1829: /* RIP packet read function. */
1830: int
1831: rip_read_new (struct thread *t)
1832: {
1833: int ret;
1834: int sock;
1835: char buf[RIP_PACKET_MAXSIZ];
1836: struct sockaddr_in from;
1.1.1.3 ! misho 1837: ifindex_t ifindex;
1.1 misho 1838:
1839: /* Fetch socket then register myself. */
1840: sock = THREAD_FD (t);
1841: rip_event (RIP_READ, sock);
1842:
1843: /* Read RIP packet. */
1844: ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
1845: if (ret < 0)
1846: {
1847: zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
1848: return ret;
1849: }
1850:
1851: return ret;
1852: }
1853: #endif /* RIP_RECVMSG */
1854:
1855: /* First entry point of RIP packet. */
1856: static int
1857: rip_read (struct thread *t)
1858: {
1859: int sock;
1860: int ret;
1861: int rtenum;
1862: union rip_buf rip_buf;
1863: struct rip_packet *packet;
1864: struct sockaddr_in from;
1865: int len;
1866: int vrecv;
1867: socklen_t fromlen;
1868: struct interface *ifp;
1869: struct connected *ifc;
1870: struct rip_interface *ri;
1871:
1872: /* Fetch socket then register myself. */
1873: sock = THREAD_FD (t);
1874: rip->t_read = NULL;
1875:
1876: /* Add myself to tne next event */
1877: rip_event (RIP_READ, sock);
1878:
1879: /* RIPd manages only IPv4. */
1880: memset (&from, 0, sizeof (struct sockaddr_in));
1881: fromlen = sizeof (struct sockaddr_in);
1882:
1883: len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0,
1884: (struct sockaddr *) &from, &fromlen);
1885: if (len < 0)
1886: {
1887: zlog_info ("recvfrom failed: %s", safe_strerror (errno));
1888: return len;
1889: }
1890:
1891: /* Check is this packet comming from myself? */
1892: if (if_check_address (from.sin_addr))
1893: {
1894: if (IS_RIP_DEBUG_PACKET)
1895: zlog_debug ("ignore packet comes from myself");
1896: return -1;
1897: }
1898:
1899: /* Which interface is this packet comes from. */
1900: ifp = if_lookup_address (from.sin_addr);
1901:
1902: /* RIP packet received */
1903: if (IS_RIP_DEBUG_EVENT)
1904: zlog_debug ("RECV packet from %s port %d on %s",
1905: inet_ntoa (from.sin_addr), ntohs (from.sin_port),
1906: ifp ? ifp->name : "unknown");
1907:
1908: /* If this packet come from unknown interface, ignore it. */
1909: if (ifp == NULL)
1910: {
1911: zlog_info ("rip_read: cannot find interface for packet from %s port %d",
1912: inet_ntoa(from.sin_addr), ntohs (from.sin_port));
1913: return -1;
1914: }
1915:
1916: ifc = connected_lookup_address (ifp, from.sin_addr);
1917:
1918: if (ifc == NULL)
1919: {
1920: zlog_info ("rip_read: cannot find connected address for packet from %s "
1921: "port %d on interface %s",
1922: inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
1923: return -1;
1924: }
1925:
1926: /* Packet length check. */
1927: if (len < RIP_PACKET_MINSIZ)
1928: {
1929: zlog_warn ("packet size %d is smaller than minimum size %d",
1930: len, RIP_PACKET_MINSIZ);
1931: rip_peer_bad_packet (&from);
1932: return len;
1933: }
1934: if (len > RIP_PACKET_MAXSIZ)
1935: {
1936: zlog_warn ("packet size %d is larger than max size %d",
1937: len, RIP_PACKET_MAXSIZ);
1938: rip_peer_bad_packet (&from);
1939: return len;
1940: }
1941:
1942: /* Packet alignment check. */
1943: if ((len - RIP_PACKET_MINSIZ) % 20)
1944: {
1945: zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
1946: rip_peer_bad_packet (&from);
1947: return len;
1948: }
1949:
1950: /* Set RTE number. */
1951: rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
1952:
1953: /* For easy to handle. */
1954: packet = &rip_buf.rip_packet;
1955:
1956: /* RIP version check. */
1957: if (packet->version == 0)
1958: {
1959: zlog_info ("version 0 with command %d received.", packet->command);
1960: rip_peer_bad_packet (&from);
1961: return -1;
1962: }
1963:
1964: /* Dump RIP packet. */
1965: if (IS_RIP_DEBUG_RECV)
1966: rip_packet_dump (packet, len, "RECV");
1967:
1968: /* RIP version adjust. This code should rethink now. RFC1058 says
1969: that "Version 1 implementations are to ignore this extra data and
1970: process only the fields specified in this document.". So RIPv3
1971: packet should be treated as RIPv1 ignoring must be zero field. */
1972: if (packet->version > RIPv2)
1973: packet->version = RIPv2;
1974:
1975: /* Is RIP running or is this RIP neighbor ?*/
1976: ri = ifp->info;
1977: if (! ri->running && ! rip_neighbor_lookup (&from))
1978: {
1979: if (IS_RIP_DEBUG_EVENT)
1980: zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
1981: rip_peer_bad_packet (&from);
1982: return -1;
1983: }
1984:
1985: /* RIP Version check. RFC2453, 4.6 and 5.1 */
1986: vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
1987: rip->version_recv : ri->ri_receive);
1988: if ((packet->version == RIPv1) && !(vrecv & RIPv1))
1989: {
1990: if (IS_RIP_DEBUG_PACKET)
1991: zlog_debug (" packet's v%d doesn't fit to if version spec",
1992: packet->version);
1993: rip_peer_bad_packet (&from);
1994: return -1;
1995: }
1996: if ((packet->version == RIPv2) && !(vrecv & RIPv2))
1997: {
1998: if (IS_RIP_DEBUG_PACKET)
1999: zlog_debug (" packet's v%d doesn't fit to if version spec",
2000: packet->version);
2001: rip_peer_bad_packet (&from);
2002: return -1;
2003: }
2004:
2005: /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
2006: messages, then RIP-1 and unauthenticated RIP-2 messages will be
2007: accepted; authenticated RIP-2 messages shall be discarded. */
2008: if ((ri->auth_type == RIP_NO_AUTH)
2009: && rtenum
2010: && (packet->version == RIPv2)
2011: && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
2012: {
2013: if (IS_RIP_DEBUG_EVENT)
2014: zlog_debug ("packet RIPv%d is dropped because authentication disabled",
2015: packet->version);
2016: rip_peer_bad_packet (&from);
2017: return -1;
2018: }
2019:
2020: /* RFC:
2021: If the router is configured to authenticate RIP-2 messages, then
2022: RIP-1 messages and RIP-2 messages which pass authentication
2023: testing shall be accepted; unauthenticated and failed
2024: authentication RIP-2 messages shall be discarded. For maximum
2025: security, RIP-1 messages should be ignored when authentication is
2026: in use (see section 4.1); otherwise, the routing information from
2027: authenticated messages will be propagated by RIP-1 routers in an
2028: unauthenticated manner.
2029: */
2030: /* We make an exception for RIPv1 REQUEST packets, to which we'll
2031: * always reply regardless of authentication settings, because:
2032: *
2033: * - if there other authorised routers on-link, the REQUESTor can
2034: * passively obtain the routing updates anyway
2035: * - if there are no other authorised routers on-link, RIP can
2036: * easily be disabled for the link to prevent giving out information
2037: * on state of this routers RIP routing table..
2038: *
2039: * I.e. if RIPv1 has any place anymore these days, it's as a very
2040: * simple way to distribute routing information (e.g. to embedded
2041: * hosts / appliances) and the ability to give out RIPv1
2042: * routing-information freely, while still requiring RIPv2
2043: * authentication for any RESPONSEs might be vaguely useful.
2044: */
2045: if (ri->auth_type != RIP_NO_AUTH
2046: && packet->version == RIPv1)
2047: {
2048: /* Discard RIPv1 messages other than REQUESTs */
2049: if (packet->command != RIP_REQUEST)
2050: {
2051: if (IS_RIP_DEBUG_PACKET)
2052: zlog_debug ("RIPv1" " dropped because authentication enabled");
2053: rip_peer_bad_packet (&from);
2054: return -1;
2055: }
2056: }
2057: else if (ri->auth_type != RIP_NO_AUTH)
2058: {
2059: const char *auth_desc;
2060:
2061: if (rtenum == 0)
2062: {
2063: /* There definitely is no authentication in the packet. */
2064: if (IS_RIP_DEBUG_PACKET)
2065: zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
2066: rip_peer_bad_packet (&from);
2067: return -1;
2068: }
2069:
2070: /* First RTE must be an Authentication Family RTE */
2071: if (packet->rte->family != htons(RIP_FAMILY_AUTH))
2072: {
2073: if (IS_RIP_DEBUG_PACKET)
2074: zlog_debug ("RIPv2" " dropped because authentication enabled");
2075: rip_peer_bad_packet (&from);
2076: return -1;
2077: }
2078:
2079: /* Check RIPv2 authentication. */
2080: switch (ntohs(packet->rte->tag))
2081: {
2082: case RIP_AUTH_SIMPLE_PASSWORD:
2083: auth_desc = "simple";
2084: ret = rip_auth_simple_password (packet->rte, &from, ifp);
2085: break;
2086:
2087: case RIP_AUTH_MD5:
2088: auth_desc = "MD5";
2089: ret = rip_auth_md5 (packet, &from, len, ifp);
2090: /* Reset RIP packet length to trim MD5 data. */
2091: len = ret;
2092: break;
2093:
2094: default:
2095: ret = 0;
2096: auth_desc = "unknown type";
2097: if (IS_RIP_DEBUG_PACKET)
2098: zlog_debug ("RIPv2 Unknown authentication type %d",
2099: ntohs (packet->rte->tag));
2100: }
2101:
2102: if (ret)
2103: {
2104: if (IS_RIP_DEBUG_PACKET)
2105: zlog_debug ("RIPv2 %s authentication success", auth_desc);
2106: }
2107: else
2108: {
2109: if (IS_RIP_DEBUG_PACKET)
2110: zlog_debug ("RIPv2 %s authentication failure", auth_desc);
2111: rip_peer_bad_packet (&from);
2112: return -1;
2113: }
2114: }
2115:
2116: /* Process each command. */
2117: switch (packet->command)
2118: {
2119: case RIP_RESPONSE:
2120: rip_response_process (packet, len, &from, ifc);
2121: break;
2122: case RIP_REQUEST:
2123: case RIP_POLL:
2124: rip_request_process (packet, len, &from, ifc);
2125: break;
2126: case RIP_TRACEON:
2127: case RIP_TRACEOFF:
2128: zlog_info ("Obsolete command %s received, please sent it to routed",
2129: lookup (rip_msg, packet->command));
2130: rip_peer_bad_packet (&from);
2131: break;
2132: case RIP_POLL_ENTRY:
2133: zlog_info ("Obsolete command %s received",
2134: lookup (rip_msg, packet->command));
2135: rip_peer_bad_packet (&from);
2136: break;
2137: default:
2138: zlog_info ("Unknown RIP command %d received", packet->command);
2139: rip_peer_bad_packet (&from);
2140: break;
2141: }
2142:
2143: return len;
2144: }
2145:
2146: /* Write routing table entry to the stream and return next index of
2147: the routing table entry in the stream. */
2148: static int
2149: rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
2150: u_char version, struct rip_info *rinfo)
2151: {
2152: struct in_addr mask;
2153:
2154: /* Write routing table entry. */
2155: if (version == RIPv1)
2156: {
2157: stream_putw (s, AF_INET);
2158: stream_putw (s, 0);
2159: stream_put_ipv4 (s, p->prefix.s_addr);
2160: stream_put_ipv4 (s, 0);
2161: stream_put_ipv4 (s, 0);
2162: stream_putl (s, rinfo->metric_out);
2163: }
2164: else
2165: {
2166: masklen2ip (p->prefixlen, &mask);
2167:
2168: stream_putw (s, AF_INET);
2169: stream_putw (s, rinfo->tag_out);
2170: stream_put_ipv4 (s, p->prefix.s_addr);
2171: stream_put_ipv4 (s, mask.s_addr);
2172: stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
2173: stream_putl (s, rinfo->metric_out);
2174: }
2175:
2176: return ++num;
2177: }
2178:
2179: /* Send update to the ifp or spcified neighbor. */
2180: void
2181: rip_output_process (struct connected *ifc, struct sockaddr_in *to,
2182: int route_type, u_char version)
2183: {
2184: int ret;
2185: struct stream *s;
2186: struct route_node *rp;
2187: struct rip_info *rinfo;
2188: struct rip_interface *ri;
2189: struct prefix_ipv4 *p;
2190: struct prefix_ipv4 classfull;
2191: struct prefix_ipv4 ifaddrclass;
2192: struct key *key = NULL;
2193: /* this might need to made dynamic if RIP ever supported auth methods
2194: with larger key string sizes */
2195: char auth_str[RIP_AUTH_SIMPLE_SIZE];
2196: size_t doff = 0; /* offset of digest offset field */
2197: int num = 0;
2198: int rtemax;
2199: int subnetted = 0;
1.1.1.3 ! misho 2200: struct list *list = NULL;
! 2201: struct listnode *listnode = NULL;
1.1 misho 2202:
2203: /* Logging output event. */
2204: if (IS_RIP_DEBUG_EVENT)
2205: {
2206: if (to)
2207: zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
2208: else
2209: zlog_debug ("update routes on interface %s ifindex %d",
2210: ifc->ifp->name, ifc->ifp->ifindex);
2211: }
2212:
2213: /* Set output stream. */
2214: s = rip->obuf;
2215:
2216: /* Reset stream and RTE counter. */
2217: stream_reset (s);
1.1.1.3 ! misho 2218: rtemax = RIP_MAX_RTE;
1.1 misho 2219:
2220: /* Get RIP interface. */
2221: ri = ifc->ifp->info;
2222:
2223: /* If output interface is in simple password authentication mode, we
2224: need space for authentication data. */
2225: if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
2226: rtemax -= 1;
2227:
2228: /* If output interface is in MD5 authentication mode, we need space
2229: for authentication header and data. */
2230: if (ri->auth_type == RIP_AUTH_MD5)
2231: rtemax -= 2;
2232:
2233: /* If output interface is in simple password authentication mode
2234: and string or keychain is specified we need space for auth. data */
2235: if (ri->auth_type != RIP_NO_AUTH)
2236: {
2237: if (ri->key_chain)
2238: {
2239: struct keychain *keychain;
2240:
2241: keychain = keychain_lookup (ri->key_chain);
2242: if (keychain)
2243: key = key_lookup_for_send (keychain);
2244: }
2245: /* to be passed to auth functions later */
2246: rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
2247: }
2248:
2249: if (version == RIPv1)
2250: {
2251: memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
2252: apply_classful_mask_ipv4 (&ifaddrclass);
2253: subnetted = 0;
2254: if (ifc->address->prefixlen > ifaddrclass.prefixlen)
2255: subnetted = 1;
2256: }
2257:
2258: for (rp = route_top (rip->table); rp; rp = route_next (rp))
1.1.1.3 ! misho 2259: if ((list = rp->info) != NULL && listcount (list) != 0)
1.1 misho 2260: {
1.1.1.3 ! misho 2261: rinfo = listgetdata (listhead (list));
1.1 misho 2262: /* For RIPv1, if we are subnetted, output subnets in our network */
2263: /* that have the same mask as the output "interface". For other */
2264: /* networks, only the classfull version is output. */
2265:
2266: if (version == RIPv1)
2267: {
2268: p = (struct prefix_ipv4 *) &rp->p;
2269:
2270: if (IS_RIP_DEBUG_PACKET)
2271: zlog_debug("RIPv1 mask check, %s/%d considered for output",
2272: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2273:
2274: if (subnetted &&
2275: prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
2276: {
2277: if ((ifc->address->prefixlen != rp->p.prefixlen) &&
2278: (rp->p.prefixlen != 32))
2279: continue;
2280: }
2281: else
2282: {
2283: memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
2284: apply_classful_mask_ipv4(&classfull);
2285: if (rp->p.u.prefix4.s_addr != 0 &&
2286: classfull.prefixlen != rp->p.prefixlen)
2287: continue;
2288: }
2289: if (IS_RIP_DEBUG_PACKET)
2290: zlog_debug("RIPv1 mask check, %s/%d made it through",
2291: inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
2292: }
2293: else
2294: p = (struct prefix_ipv4 *) &rp->p;
2295:
2296: /* Apply output filters. */
2297: ret = rip_outgoing_filter (p, ri);
2298: if (ret < 0)
2299: continue;
2300:
2301: /* Changed route only output. */
2302: if (route_type == rip_changed_route &&
2303: (! (rinfo->flags & RIP_RTF_CHANGED)))
2304: continue;
2305:
2306: /* Split horizon. */
2307: /* if (split_horizon == rip_split_horizon) */
2308: if (ri->split_horizon == RIP_SPLIT_HORIZON)
2309: {
2310: /*
2311: * We perform split horizon for RIP and connected route.
2312: * For rip routes, we want to suppress the route if we would
2313: * end up sending the route back on the interface that we
2314: * learned it from, with a higher metric. For connected routes,
2315: * we suppress the route if the prefix is a subset of the
2316: * source address that we are going to use for the packet
2317: * (in order to handle the case when multiple subnets are
2318: * configured on the same interface).
2319: */
1.1.1.3 ! misho 2320: int suppress = 0;
! 2321: struct rip_info *tmp_rinfo = NULL;
! 2322:
! 2323: for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
! 2324: if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
! 2325: tmp_rinfo->ifindex == ifc->ifp->ifindex)
! 2326: {
! 2327: suppress = 1;
! 2328: break;
! 2329: }
! 2330:
! 2331: if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT &&
1.1 misho 2332: prefix_match((struct prefix *)p, ifc->address))
1.1.1.3 ! misho 2333: suppress = 1;
! 2334:
! 2335: if (suppress)
1.1 misho 2336: continue;
2337: }
2338:
2339: /* Preparation for route-map. */
2340: rinfo->metric_set = 0;
2341: rinfo->nexthop_out.s_addr = 0;
2342: rinfo->metric_out = rinfo->metric;
2343: rinfo->tag_out = rinfo->tag;
2344: rinfo->ifindex_out = ifc->ifp->ifindex;
2345:
2346: /* In order to avoid some local loops,
2347: * if the RIP route has a nexthop via this interface, keep the nexthop,
2348: * otherwise set it to 0. The nexthop should not be propagated
2349: * beyond the local broadcast/multicast area in order
2350: * to avoid an IGP multi-level recursive look-up.
2351: * see (4.4)
2352: */
2353: if (rinfo->ifindex == ifc->ifp->ifindex)
2354: rinfo->nexthop_out = rinfo->nexthop;
2355:
2356: /* Interface route-map */
2357: if (ri->routemap[RIP_FILTER_OUT])
2358: {
2359: ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
2360: (struct prefix *) p, RMAP_RIP,
2361: rinfo);
2362:
2363: if (ret == RMAP_DENYMATCH)
2364: {
2365: if (IS_RIP_DEBUG_PACKET)
2366: zlog_debug ("RIP %s/%d is filtered by route-map out",
2367: inet_ntoa (p->prefix), p->prefixlen);
2368: continue;
2369: }
2370: }
2371:
2372: /* Apply redistribute route map - continue, if deny */
2373: if (rip->route_map[rinfo->type].name
2374: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2375: {
2376: ret = route_map_apply (rip->route_map[rinfo->type].map,
2377: (struct prefix *)p, RMAP_RIP, rinfo);
2378:
2379: if (ret == RMAP_DENYMATCH)
2380: {
2381: if (IS_RIP_DEBUG_PACKET)
2382: zlog_debug ("%s/%d is filtered by route-map",
2383: inet_ntoa (p->prefix), p->prefixlen);
2384: continue;
2385: }
2386: }
2387:
2388: /* When route-map does not set metric. */
2389: if (! rinfo->metric_set)
2390: {
2391: /* If redistribute metric is set. */
2392: if (rip->route_map[rinfo->type].metric_config
2393: && rinfo->metric != RIP_METRIC_INFINITY)
2394: {
2395: rinfo->metric_out = rip->route_map[rinfo->type].metric;
2396: }
2397: else
2398: {
2399: /* If the route is not connected or localy generated
2400: one, use default-metric value*/
2401: if (rinfo->type != ZEBRA_ROUTE_RIP
2402: && rinfo->type != ZEBRA_ROUTE_CONNECT
2403: && rinfo->metric != RIP_METRIC_INFINITY)
2404: rinfo->metric_out = rip->default_metric;
2405: }
2406: }
2407:
2408: /* Apply offset-list */
2409: if (rinfo->metric != RIP_METRIC_INFINITY)
2410: rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
2411:
2412: if (rinfo->metric_out > RIP_METRIC_INFINITY)
2413: rinfo->metric_out = RIP_METRIC_INFINITY;
2414:
2415: /* Perform split-horizon with poisoned reverse
2416: * for RIP and connected routes.
2417: **/
2418: if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
2419: /*
2420: * We perform split horizon for RIP and connected route.
2421: * For rip routes, we want to suppress the route if we would
2422: * end up sending the route back on the interface that we
2423: * learned it from, with a higher metric. For connected routes,
2424: * we suppress the route if the prefix is a subset of the
2425: * source address that we are going to use for the packet
2426: * (in order to handle the case when multiple subnets are
2427: * configured on the same interface).
2428: */
1.1.1.3 ! misho 2429: struct rip_info *tmp_rinfo = NULL;
! 2430:
! 2431: for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
! 2432: if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
! 2433: tmp_rinfo->ifindex == ifc->ifp->ifindex)
! 2434: rinfo->metric_out = RIP_METRIC_INFINITY;
! 2435: if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT &&
1.1 misho 2436: prefix_match((struct prefix *)p, ifc->address))
1.1.1.3 ! misho 2437: rinfo->metric_out = RIP_METRIC_INFINITY;
1.1 misho 2438: }
2439:
2440: /* Prepare preamble, auth headers, if needs be */
2441: if (num == 0)
2442: {
2443: stream_putc (s, RIP_RESPONSE);
2444: stream_putc (s, version);
2445: stream_putw (s, 0);
2446:
2447: /* auth header for !v1 && !no_auth */
2448: if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
2449: doff = rip_auth_header_write (s, ri, key, auth_str,
2450: RIP_AUTH_SIMPLE_SIZE);
2451: }
2452:
2453: /* Write RTE to the stream. */
2454: num = rip_write_rte (num, s, p, version, rinfo);
2455: if (num == rtemax)
2456: {
2457: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2458: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2459:
2460: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
2461: to, ifc);
2462:
2463: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2464: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2465: stream_get_endp(s), "SEND");
2466: num = 0;
2467: stream_reset (s);
2468: }
2469: }
2470:
2471: /* Flush unwritten RTE. */
2472: if (num != 0)
2473: {
2474: if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
2475: rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
2476:
2477: ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
2478:
2479: if (ret >= 0 && IS_RIP_DEBUG_SEND)
2480: rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
2481: stream_get_endp (s), "SEND");
2482: num = 0;
2483: stream_reset (s);
2484: }
2485:
2486: /* Statistics updates. */
2487: ri->sent_updates++;
2488: }
2489:
2490: /* Send RIP packet to the interface. */
2491: static void
2492: rip_update_interface (struct connected *ifc, u_char version, int route_type)
2493: {
2494: struct sockaddr_in to;
2495:
2496: /* When RIP version is 2 and multicast enable interface. */
2497: if (version == RIPv2 && if_is_multicast (ifc->ifp))
2498: {
2499: if (IS_RIP_DEBUG_EVENT)
2500: zlog_debug ("multicast announce on %s ", ifc->ifp->name);
2501:
2502: rip_output_process (ifc, NULL, route_type, version);
2503: return;
2504: }
2505:
2506: /* If we can't send multicast packet, send it with unicast. */
2507: if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp))
2508: {
2509: if (ifc->address->family == AF_INET)
2510: {
2511: /* Destination address and port setting. */
2512: memset (&to, 0, sizeof (struct sockaddr_in));
2513: if (ifc->destination)
2514: /* use specified broadcast or peer destination addr */
2515: to.sin_addr = ifc->destination->u.prefix4;
2516: else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
2517: /* calculate the appropriate broadcast address */
2518: to.sin_addr.s_addr =
2519: ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
2520: ifc->address->prefixlen);
2521: else
2522: /* do not know where to send the packet */
2523: return;
2524: to.sin_port = htons (RIP_PORT_DEFAULT);
2525:
2526: if (IS_RIP_DEBUG_EVENT)
2527: zlog_debug("%s announce to %s on %s",
2528: CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
2529: inet_ntoa (to.sin_addr), ifc->ifp->name);
2530:
2531: rip_output_process (ifc, &to, route_type, version);
2532: }
2533: }
2534: }
2535:
2536: /* Update send to all interface and neighbor. */
2537: static void
2538: rip_update_process (int route_type)
2539: {
2540: struct listnode *node;
2541: struct listnode *ifnode, *ifnnode;
2542: struct connected *connected;
2543: struct interface *ifp;
2544: struct rip_interface *ri;
2545: struct route_node *rp;
2546: struct sockaddr_in to;
2547: struct prefix_ipv4 *p;
2548:
2549: /* Send RIP update to each interface. */
2550: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2551: {
2552: if (if_is_loopback (ifp))
2553: continue;
2554:
2555: if (! if_is_operative (ifp))
2556: continue;
2557:
2558: /* Fetch RIP interface information. */
2559: ri = ifp->info;
2560:
2561: /* When passive interface is specified, suppress announce to the
2562: interface. */
2563: if (ri->passive)
2564: continue;
2565:
2566: if (ri->running)
2567: {
2568: /*
2569: * If there is no version configuration in the interface,
2570: * use rip's version setting.
2571: */
2572: int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
2573: rip->version_send : ri->ri_send);
2574:
2575: if (IS_RIP_DEBUG_EVENT)
2576: zlog_debug("SEND UPDATE to %s ifindex %d",
1.1.1.3 ! misho 2577: ifp->name, ifp->ifindex);
1.1 misho 2578:
2579: /* send update on each connected network */
2580: for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
2581: {
2582: if (connected->address->family == AF_INET)
2583: {
2584: if (vsend & RIPv1)
2585: rip_update_interface (connected, RIPv1, route_type);
2586: if ((vsend & RIPv2) && if_is_multicast(ifp))
2587: rip_update_interface (connected, RIPv2, route_type);
2588: }
2589: }
2590: }
2591: }
2592:
2593: /* RIP send updates to each neighbor. */
2594: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
2595: if (rp->info != NULL)
2596: {
2597: p = (struct prefix_ipv4 *) &rp->p;
2598:
2599: ifp = if_lookup_address (p->prefix);
2600: if (! ifp)
2601: {
2602: zlog_warn ("Neighbor %s doesnt have connected interface!",
2603: inet_ntoa (p->prefix));
2604: continue;
2605: }
2606:
2607: if ( (connected = connected_lookup_address (ifp, p->prefix)) == NULL)
2608: {
2609: zlog_warn ("Neighbor %s doesnt have connected network",
2610: inet_ntoa (p->prefix));
2611: continue;
2612: }
2613:
2614: /* Set destination address and port */
2615: memset (&to, 0, sizeof (struct sockaddr_in));
2616: to.sin_addr = p->prefix;
2617: to.sin_port = htons (RIP_PORT_DEFAULT);
2618:
2619: /* RIP version is rip's configuration. */
2620: rip_output_process (connected, &to, route_type, rip->version_send);
2621: }
2622: }
2623:
2624: /* RIP's periodical timer. */
2625: static int
2626: rip_update (struct thread *t)
2627: {
2628: /* Clear timer pointer. */
2629: rip->t_update = NULL;
2630:
2631: if (IS_RIP_DEBUG_EVENT)
2632: zlog_debug ("update timer fire!");
2633:
2634: /* Process update output. */
2635: rip_update_process (rip_all_route);
2636:
2637: /* Triggered updates may be suppressed if a regular update is due by
2638: the time the triggered update would be sent. */
2639: if (rip->t_triggered_interval)
2640: {
2641: thread_cancel (rip->t_triggered_interval);
2642: rip->t_triggered_interval = NULL;
2643: }
2644: rip->trigger = 0;
2645:
2646: /* Register myself. */
2647: rip_event (RIP_UPDATE_EVENT, 0);
2648:
2649: return 0;
2650: }
2651:
2652: /* Walk down the RIP routing table then clear changed flag. */
2653: static void
2654: rip_clear_changed_flag (void)
2655: {
2656: struct route_node *rp;
1.1.1.3 ! misho 2657: struct rip_info *rinfo = NULL;
! 2658: struct list *list = NULL;
! 2659: struct listnode *listnode = NULL;
1.1 misho 2660:
2661: for (rp = route_top (rip->table); rp; rp = route_next (rp))
1.1.1.3 ! misho 2662: if ((list = rp->info) != NULL)
! 2663: for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
! 2664: {
! 2665: UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 2666: /* This flag can be set only on the first entry. */
! 2667: break;
! 2668: }
1.1 misho 2669: }
2670:
2671: /* Triggered update interval timer. */
2672: static int
2673: rip_triggered_interval (struct thread *t)
2674: {
2675: int rip_triggered_update (struct thread *);
2676:
2677: rip->t_triggered_interval = NULL;
2678:
2679: if (rip->trigger)
2680: {
2681: rip->trigger = 0;
2682: rip_triggered_update (t);
2683: }
2684: return 0;
2685: }
2686:
2687: /* Execute triggered update. */
2688: static int
2689: rip_triggered_update (struct thread *t)
2690: {
2691: int interval;
2692:
2693: /* Clear thred pointer. */
2694: rip->t_triggered_update = NULL;
2695:
2696: /* Cancel interval timer. */
2697: if (rip->t_triggered_interval)
2698: {
2699: thread_cancel (rip->t_triggered_interval);
2700: rip->t_triggered_interval = NULL;
2701: }
2702: rip->trigger = 0;
2703:
2704: /* Logging triggered update. */
2705: if (IS_RIP_DEBUG_EVENT)
2706: zlog_debug ("triggered update!");
2707:
2708: /* Split Horizon processing is done when generating triggered
2709: updates as well as normal updates (see section 2.6). */
2710: rip_update_process (rip_changed_route);
2711:
2712: /* Once all of the triggered updates have been generated, the route
2713: change flags should be cleared. */
2714: rip_clear_changed_flag ();
2715:
2716: /* After a triggered update is sent, a timer should be set for a
2717: random interval between 1 and 5 seconds. If other changes that
2718: would trigger updates occur before the timer expires, a single
2719: update is triggered when the timer expires. */
2720: interval = (random () % 5) + 1;
2721:
2722: rip->t_triggered_interval =
2723: thread_add_timer (master, rip_triggered_interval, NULL, interval);
2724:
2725: return 0;
2726: }
2727:
2728: /* Withdraw redistributed route. */
2729: void
2730: rip_redistribute_withdraw (int type)
2731: {
2732: struct route_node *rp;
1.1.1.3 ! misho 2733: struct rip_info *rinfo = NULL;
! 2734: struct list *list = NULL;
1.1 misho 2735:
2736: if (!rip)
2737: return;
2738:
2739: for (rp = route_top (rip->table); rp; rp = route_next (rp))
1.1.1.3 ! misho 2740: if ((list = rp->info) != NULL)
1.1 misho 2741: {
1.1.1.3 ! misho 2742: rinfo = listgetdata (listhead (list));
1.1 misho 2743: if (rinfo->type == type
2744: && rinfo->sub_type != RIP_ROUTE_INTERFACE)
2745: {
2746: /* Perform poisoned reverse. */
2747: rinfo->metric = RIP_METRIC_INFINITY;
2748: RIP_TIMER_ON (rinfo->t_garbage_collect,
2749: rip_garbage_collect, rip->garbage_time);
2750: RIP_TIMER_OFF (rinfo->t_timeout);
2751: rinfo->flags |= RIP_RTF_CHANGED;
2752:
2753: if (IS_RIP_DEBUG_EVENT) {
2754: struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
2755:
2756: zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
2757: inet_ntoa(p->prefix), p->prefixlen,
2758: ifindex2ifname(rinfo->ifindex));
2759: }
2760:
2761: rip_event (RIP_TRIGGERED_UPDATE, 0);
2762: }
2763: }
2764: }
2765:
2766: /* Create new RIP instance and set it to global variable. */
2767: static int
2768: rip_create (void)
2769: {
2770: rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
2771:
2772: /* Set initial value. */
2773: rip->version_send = RI_RIP_VERSION_2;
2774: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2775: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
2776: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
2777: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
2778: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
2779:
2780: /* Initialize RIP routig table. */
2781: rip->table = route_table_init ();
2782: rip->route = route_table_init ();
2783: rip->neighbor = route_table_init ();
2784:
2785: /* Make output stream. */
2786: rip->obuf = stream_new (1500);
2787:
2788: /* Make socket. */
2789: rip->sock = rip_create_socket (NULL);
2790: if (rip->sock < 0)
2791: return rip->sock;
2792:
2793: /* Create read and timer thread. */
2794: rip_event (RIP_READ, rip->sock);
2795: rip_event (RIP_UPDATE_EVENT, 1);
2796:
2797: return 0;
2798: }
2799:
2800: /* Sned RIP request to the destination. */
2801: int
2802: rip_request_send (struct sockaddr_in *to, struct interface *ifp,
2803: u_char version, struct connected *connected)
2804: {
2805: struct rte *rte;
2806: struct rip_packet rip_packet;
2807: struct listnode *node, *nnode;
2808:
2809: memset (&rip_packet, 0, sizeof (rip_packet));
2810:
2811: rip_packet.command = RIP_REQUEST;
2812: rip_packet.version = version;
2813: rte = rip_packet.rte;
2814: rte->metric = htonl (RIP_METRIC_INFINITY);
2815:
2816: if (connected)
2817: {
2818: /*
2819: * connected is only sent for ripv1 case, or when
2820: * interface does not support multicast. Caller loops
2821: * over each connected address for this case.
2822: */
2823: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2824: to, connected) != sizeof (rip_packet))
2825: return -1;
2826: else
2827: return sizeof (rip_packet);
2828: }
2829:
2830: /* send request on each connected network */
2831: for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
2832: {
2833: struct prefix_ipv4 *p;
2834:
2835: p = (struct prefix_ipv4 *) connected->address;
2836:
2837: if (p->family != AF_INET)
2838: continue;
2839:
2840: if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet),
2841: to, connected) != sizeof (rip_packet))
2842: return -1;
2843: }
2844: return sizeof (rip_packet);
2845: }
1.1.1.3 ! misho 2846:
1.1 misho 2847: static int
2848: rip_update_jitter (unsigned long time)
2849: {
2850: #define JITTER_BOUND 4
2851: /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
2852: Given that, we cannot let time be less than JITTER_BOUND seconds.
2853: The RIPv2 RFC says jitter should be small compared to
2854: update_time. We consider 1/JITTER_BOUND to be small.
2855: */
2856:
2857: int jitter_input = time;
2858: int jitter;
2859:
2860: if (jitter_input < JITTER_BOUND)
2861: jitter_input = JITTER_BOUND;
2862:
1.1.1.3 ! misho 2863: jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input));
1.1 misho 2864:
2865: return jitter/JITTER_BOUND;
2866: }
2867:
2868: void
2869: rip_event (enum rip_event event, int sock)
2870: {
2871: int jitter = 0;
2872:
2873: switch (event)
2874: {
2875: case RIP_READ:
2876: rip->t_read = thread_add_read (master, rip_read, NULL, sock);
2877: break;
2878: case RIP_UPDATE_EVENT:
2879: if (rip->t_update)
2880: {
2881: thread_cancel (rip->t_update);
2882: rip->t_update = NULL;
2883: }
2884: jitter = rip_update_jitter (rip->update_time);
2885: rip->t_update =
2886: thread_add_timer (master, rip_update, NULL,
2887: sock ? 2 : rip->update_time + jitter);
2888: break;
2889: case RIP_TRIGGERED_UPDATE:
2890: if (rip->t_triggered_interval)
2891: rip->trigger = 1;
2892: else if (! rip->t_triggered_update)
2893: rip->t_triggered_update =
2894: thread_add_event (master, rip_triggered_update, NULL, 0);
2895: break;
2896: default:
2897: break;
2898: }
2899: }
1.1.1.3 ! misho 2900:
1.1 misho 2901: DEFUN (router_rip,
2902: router_rip_cmd,
2903: "router rip",
2904: "Enable a routing process\n"
2905: "Routing Information Protocol (RIP)\n")
2906: {
2907: int ret;
2908:
2909: /* If rip is not enabled before. */
2910: if (! rip)
2911: {
2912: ret = rip_create ();
2913: if (ret < 0)
2914: {
2915: zlog_info ("Can't create RIP");
2916: return CMD_WARNING;
2917: }
2918: }
2919: vty->node = RIP_NODE;
2920: vty->index = rip;
2921:
2922: return CMD_SUCCESS;
2923: }
2924:
2925: DEFUN (no_router_rip,
2926: no_router_rip_cmd,
2927: "no router rip",
2928: NO_STR
2929: "Enable a routing process\n"
2930: "Routing Information Protocol (RIP)\n")
2931: {
2932: if (rip)
2933: rip_clean ();
2934: return CMD_SUCCESS;
2935: }
2936:
2937: DEFUN (rip_version,
2938: rip_version_cmd,
2939: "version <1-2>",
2940: "Set routing protocol version\n"
2941: "version\n")
2942: {
2943: int version;
2944:
2945: version = atoi (argv[0]);
2946: if (version != RIPv1 && version != RIPv2)
2947: {
2948: vty_out (vty, "invalid rip version %d%s", version,
2949: VTY_NEWLINE);
2950: return CMD_WARNING;
2951: }
2952: rip->version_send = version;
2953: rip->version_recv = version;
2954:
2955: return CMD_SUCCESS;
2956: }
2957:
2958: DEFUN (no_rip_version,
2959: no_rip_version_cmd,
2960: "no version",
2961: NO_STR
2962: "Set routing protocol version\n")
2963: {
2964: /* Set RIP version to the default. */
2965: rip->version_send = RI_RIP_VERSION_2;
2966: rip->version_recv = RI_RIP_VERSION_1_AND_2;
2967:
2968: return CMD_SUCCESS;
2969: }
2970:
2971: ALIAS (no_rip_version,
2972: no_rip_version_val_cmd,
2973: "no version <1-2>",
2974: NO_STR
2975: "Set routing protocol version\n"
2976: "version\n")
2977:
2978: DEFUN (rip_route,
2979: rip_route_cmd,
2980: "route A.B.C.D/M",
2981: "RIP static route configuration\n"
2982: "IP prefix <network>/<length>\n")
2983: {
2984: int ret;
2985: struct prefix_ipv4 p;
2986: struct route_node *node;
2987:
2988: ret = str2prefix_ipv4 (argv[0], &p);
2989: if (ret < 0)
2990: {
2991: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2992: return CMD_WARNING;
2993: }
2994: apply_mask_ipv4 (&p);
2995:
2996: /* For router rip configuration. */
2997: node = route_node_get (rip->route, (struct prefix *) &p);
2998:
2999: if (node->info)
3000: {
3001: vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
3002: route_unlock_node (node);
3003: return CMD_WARNING;
3004: }
3005:
3006: node->info = (char *)"static";
3007:
3008: rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
3009:
3010: return CMD_SUCCESS;
3011: }
3012:
3013: DEFUN (no_rip_route,
3014: no_rip_route_cmd,
3015: "no route A.B.C.D/M",
3016: NO_STR
3017: "RIP static route configuration\n"
3018: "IP prefix <network>/<length>\n")
3019: {
3020: int ret;
3021: struct prefix_ipv4 p;
3022: struct route_node *node;
3023:
3024: ret = str2prefix_ipv4 (argv[0], &p);
3025: if (ret < 0)
3026: {
3027: vty_out (vty, "Malformed address%s", VTY_NEWLINE);
3028: return CMD_WARNING;
3029: }
3030: apply_mask_ipv4 (&p);
3031:
3032: /* For router rip configuration. */
3033: node = route_node_lookup (rip->route, (struct prefix *) &p);
3034: if (! node)
3035: {
3036: vty_out (vty, "Can't find route %s.%s", argv[0],
3037: VTY_NEWLINE);
3038: return CMD_WARNING;
3039: }
3040:
3041: rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
3042: route_unlock_node (node);
3043:
3044: node->info = NULL;
3045: route_unlock_node (node);
3046:
3047: return CMD_SUCCESS;
3048: }
3049:
3050: #if 0
3051: static void
3052: rip_update_default_metric (void)
3053: {
3054: struct route_node *np;
1.1.1.3 ! misho 3055: struct rip_info *rinfo = NULL;
! 3056: struct list *list = NULL;
! 3057: struct listnode *listnode = NULL;
1.1 misho 3058:
3059: for (np = route_top (rip->table); np; np = route_next (np))
1.1.1.3 ! misho 3060: if ((list = np->info) != NULL)
! 3061: for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
! 3062: if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT)
! 3063: rinfo->metric = rip->default_metric;
1.1 misho 3064: }
3065: #endif
3066:
3067: DEFUN (rip_default_metric,
3068: rip_default_metric_cmd,
3069: "default-metric <1-16>",
3070: "Set a metric of redistribute routes\n"
3071: "Default metric\n")
3072: {
3073: if (rip)
3074: {
3075: rip->default_metric = atoi (argv[0]);
3076: /* rip_update_default_metric (); */
3077: }
3078: return CMD_SUCCESS;
3079: }
3080:
3081: DEFUN (no_rip_default_metric,
3082: no_rip_default_metric_cmd,
3083: "no default-metric",
3084: NO_STR
3085: "Set a metric of redistribute routes\n"
3086: "Default metric\n")
3087: {
3088: if (rip)
3089: {
3090: rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
3091: /* rip_update_default_metric (); */
3092: }
3093: return CMD_SUCCESS;
3094: }
3095:
3096: ALIAS (no_rip_default_metric,
3097: no_rip_default_metric_val_cmd,
3098: "no default-metric <1-16>",
3099: NO_STR
3100: "Set a metric of redistribute routes\n"
3101: "Default metric\n")
3102:
3103: DEFUN (rip_timers,
3104: rip_timers_cmd,
3105: "timers basic <5-2147483647> <5-2147483647> <5-2147483647>",
3106: "Adjust routing timers\n"
3107: "Basic routing protocol update timers\n"
3108: "Routing table update timer value in second. Default is 30.\n"
3109: "Routing information timeout timer. Default is 180.\n"
3110: "Garbage collection timer. Default is 120.\n")
3111: {
3112: unsigned long update;
3113: unsigned long timeout;
3114: unsigned long garbage;
3115: char *endptr = NULL;
3116: unsigned long RIP_TIMER_MAX = 2147483647;
3117: unsigned long RIP_TIMER_MIN = 5;
3118:
3119: update = strtoul (argv[0], &endptr, 10);
3120: if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')
3121: {
3122: vty_out (vty, "update timer value error%s", VTY_NEWLINE);
3123: return CMD_WARNING;
3124: }
3125:
3126: timeout = strtoul (argv[1], &endptr, 10);
3127: if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0')
3128: {
3129: vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
3130: return CMD_WARNING;
3131: }
3132:
3133: garbage = strtoul (argv[2], &endptr, 10);
3134: if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0')
3135: {
3136: vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
3137: return CMD_WARNING;
3138: }
3139:
3140: /* Set each timer value. */
3141: rip->update_time = update;
3142: rip->timeout_time = timeout;
3143: rip->garbage_time = garbage;
3144:
3145: /* Reset update timer thread. */
3146: rip_event (RIP_UPDATE_EVENT, 0);
3147:
3148: return CMD_SUCCESS;
3149: }
3150:
3151: DEFUN (no_rip_timers,
3152: no_rip_timers_cmd,
3153: "no timers basic",
3154: NO_STR
3155: "Adjust routing timers\n"
3156: "Basic routing protocol update timers\n")
3157: {
3158: /* Set each timer value to the default. */
3159: rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
3160: rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
3161: rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
3162:
3163: /* Reset update timer thread. */
3164: rip_event (RIP_UPDATE_EVENT, 0);
3165:
3166: return CMD_SUCCESS;
3167: }
3168:
3169: ALIAS (no_rip_timers,
3170: no_rip_timers_val_cmd,
3171: "no timers basic <0-65535> <0-65535> <0-65535>",
3172: NO_STR
3173: "Adjust routing timers\n"
3174: "Basic routing protocol update timers\n"
3175: "Routing table update timer value in second. Default is 30.\n"
3176: "Routing information timeout timer. Default is 180.\n"
3177: "Garbage collection timer. Default is 120.\n")
3178:
1.1.1.3 ! misho 3179:
1.1 misho 3180: struct route_table *rip_distance_table;
3181:
3182: struct rip_distance
3183: {
3184: /* Distance value for the IP source prefix. */
3185: u_char distance;
3186:
3187: /* Name of the access-list to be matched. */
3188: char *access_list;
3189: };
3190:
3191: static struct rip_distance *
3192: rip_distance_new (void)
3193: {
3194: return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
3195: }
3196:
3197: static void
3198: rip_distance_free (struct rip_distance *rdistance)
3199: {
3200: XFREE (MTYPE_RIP_DISTANCE, rdistance);
3201: }
3202:
3203: static int
3204: rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
3205: const char *access_list_str)
3206: {
3207: int ret;
3208: struct prefix_ipv4 p;
3209: u_char distance;
3210: struct route_node *rn;
3211: struct rip_distance *rdistance;
3212:
3213: ret = str2prefix_ipv4 (ip_str, &p);
3214: if (ret == 0)
3215: {
3216: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3217: return CMD_WARNING;
3218: }
3219:
3220: distance = atoi (distance_str);
3221:
3222: /* Get RIP distance node. */
3223: rn = route_node_get (rip_distance_table, (struct prefix *) &p);
3224: if (rn->info)
3225: {
3226: rdistance = rn->info;
3227: route_unlock_node (rn);
3228: }
3229: else
3230: {
3231: rdistance = rip_distance_new ();
3232: rn->info = rdistance;
3233: }
3234:
3235: /* Set distance value. */
3236: rdistance->distance = distance;
3237:
3238: /* Reset access-list configuration. */
3239: if (rdistance->access_list)
3240: {
3241: free (rdistance->access_list);
3242: rdistance->access_list = NULL;
3243: }
3244: if (access_list_str)
3245: rdistance->access_list = strdup (access_list_str);
3246:
3247: return CMD_SUCCESS;
3248: }
3249:
3250: static int
3251: rip_distance_unset (struct vty *vty, const char *distance_str,
3252: const char *ip_str, const char *access_list_str)
3253: {
3254: int ret;
3255: struct prefix_ipv4 p;
3256: struct route_node *rn;
3257: struct rip_distance *rdistance;
3258:
3259: ret = str2prefix_ipv4 (ip_str, &p);
3260: if (ret == 0)
3261: {
3262: vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
3263: return CMD_WARNING;
3264: }
3265:
3266: rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
3267: if (! rn)
3268: {
3269: vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
3270: return CMD_WARNING;
3271: }
3272:
3273: rdistance = rn->info;
3274:
3275: if (rdistance->access_list)
3276: free (rdistance->access_list);
3277: rip_distance_free (rdistance);
3278:
3279: rn->info = NULL;
3280: route_unlock_node (rn);
3281: route_unlock_node (rn);
3282:
3283: return CMD_SUCCESS;
3284: }
3285:
3286: static void
3287: rip_distance_reset (void)
3288: {
3289: struct route_node *rn;
3290: struct rip_distance *rdistance;
3291:
3292: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3293: if ((rdistance = rn->info) != NULL)
3294: {
3295: if (rdistance->access_list)
3296: free (rdistance->access_list);
3297: rip_distance_free (rdistance);
3298: rn->info = NULL;
3299: route_unlock_node (rn);
3300: }
3301: }
3302:
3303: /* Apply RIP information to distance method. */
3304: u_char
3305: rip_distance_apply (struct rip_info *rinfo)
3306: {
3307: struct route_node *rn;
3308: struct prefix_ipv4 p;
3309: struct rip_distance *rdistance;
3310: struct access_list *alist;
3311:
3312: if (! rip)
3313: return 0;
3314:
3315: memset (&p, 0, sizeof (struct prefix_ipv4));
3316: p.family = AF_INET;
3317: p.prefix = rinfo->from;
3318: p.prefixlen = IPV4_MAX_BITLEN;
3319:
3320: /* Check source address. */
3321: rn = route_node_match (rip_distance_table, (struct prefix *) &p);
3322: if (rn)
3323: {
3324: rdistance = rn->info;
3325: route_unlock_node (rn);
3326:
3327: if (rdistance->access_list)
3328: {
3329: alist = access_list_lookup (AFI_IP, rdistance->access_list);
3330: if (alist == NULL)
3331: return 0;
3332: if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
3333: return 0;
3334:
3335: return rdistance->distance;
3336: }
3337: else
3338: return rdistance->distance;
3339: }
3340:
3341: if (rip->distance)
3342: return rip->distance;
3343:
3344: return 0;
3345: }
3346:
3347: static void
3348: rip_distance_show (struct vty *vty)
3349: {
3350: struct route_node *rn;
3351: struct rip_distance *rdistance;
3352: int header = 1;
3353: char buf[BUFSIZ];
3354:
3355: vty_out (vty, " Distance: (default is %d)%s",
3356: rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT,
3357: VTY_NEWLINE);
3358:
3359: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3360: if ((rdistance = rn->info) != NULL)
3361: {
3362: if (header)
3363: {
3364: vty_out (vty, " Address Distance List%s",
3365: VTY_NEWLINE);
3366: header = 0;
3367: }
3368: sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
3369: vty_out (vty, " %-20s %4d %s%s",
3370: buf, rdistance->distance,
3371: rdistance->access_list ? rdistance->access_list : "",
3372: VTY_NEWLINE);
3373: }
3374: }
3375:
3376: DEFUN (rip_distance,
3377: rip_distance_cmd,
3378: "distance <1-255>",
3379: "Administrative distance\n"
3380: "Distance value\n")
3381: {
3382: rip->distance = atoi (argv[0]);
3383: return CMD_SUCCESS;
3384: }
3385:
3386: DEFUN (no_rip_distance,
3387: no_rip_distance_cmd,
3388: "no distance <1-255>",
3389: NO_STR
3390: "Administrative distance\n"
3391: "Distance value\n")
3392: {
3393: rip->distance = 0;
3394: return CMD_SUCCESS;
3395: }
3396:
3397: DEFUN (rip_distance_source,
3398: rip_distance_source_cmd,
3399: "distance <1-255> A.B.C.D/M",
3400: "Administrative distance\n"
3401: "Distance value\n"
3402: "IP source prefix\n")
3403: {
3404: rip_distance_set (vty, argv[0], argv[1], NULL);
3405: return CMD_SUCCESS;
3406: }
3407:
3408: DEFUN (no_rip_distance_source,
3409: no_rip_distance_source_cmd,
3410: "no distance <1-255> A.B.C.D/M",
3411: NO_STR
3412: "Administrative distance\n"
3413: "Distance value\n"
3414: "IP source prefix\n")
3415: {
3416: rip_distance_unset (vty, argv[0], argv[1], NULL);
3417: return CMD_SUCCESS;
3418: }
3419:
3420: DEFUN (rip_distance_source_access_list,
3421: rip_distance_source_access_list_cmd,
3422: "distance <1-255> A.B.C.D/M WORD",
3423: "Administrative distance\n"
3424: "Distance value\n"
3425: "IP source prefix\n"
3426: "Access list name\n")
3427: {
3428: rip_distance_set (vty, argv[0], argv[1], argv[2]);
3429: return CMD_SUCCESS;
3430: }
3431:
3432: DEFUN (no_rip_distance_source_access_list,
3433: no_rip_distance_source_access_list_cmd,
3434: "no distance <1-255> A.B.C.D/M WORD",
3435: NO_STR
3436: "Administrative distance\n"
3437: "Distance value\n"
3438: "IP source prefix\n"
3439: "Access list name\n")
3440: {
3441: rip_distance_unset (vty, argv[0], argv[1], argv[2]);
3442: return CMD_SUCCESS;
3443: }
1.1.1.3 ! misho 3444:
! 3445: /* Update ECMP routes to zebra when ECMP is disabled. */
! 3446: static void
! 3447: rip_ecmp_disable (void)
! 3448: {
! 3449: struct route_node *rp;
! 3450: struct rip_info *rinfo, *tmp_rinfo;
! 3451: struct list *list;
! 3452: struct listnode *node, *nextnode;
! 3453:
! 3454: if (!rip)
! 3455: return;
! 3456:
! 3457: for (rp = route_top (rip->table); rp; rp = route_next (rp))
! 3458: if ((list = rp->info) != NULL && listcount (list) > 1)
! 3459: {
! 3460: rinfo = listgetdata (listhead (list));
! 3461: if (!rip_route_rte (rinfo))
! 3462: continue;
! 3463:
! 3464: /* Drop all other entries, except the first one. */
! 3465: for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
! 3466: if (tmp_rinfo != rinfo)
! 3467: {
! 3468: RIP_TIMER_OFF (tmp_rinfo->t_timeout);
! 3469: RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
! 3470: list_delete_node (list, node);
! 3471: rip_info_free (tmp_rinfo);
! 3472: }
! 3473:
! 3474: /* Update zebra. */
! 3475: rip_zebra_ipv4_add (rp);
! 3476:
! 3477: /* Set the route change flag. */
! 3478: SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
! 3479:
! 3480: /* Signal the output process to trigger an update. */
! 3481: rip_event (RIP_TRIGGERED_UPDATE, 0);
! 3482: }
! 3483: }
! 3484:
! 3485: DEFUN (rip_allow_ecmp,
! 3486: rip_allow_ecmp_cmd,
! 3487: "allow-ecmp",
! 3488: "Allow Equal Cost MultiPath\n")
! 3489: {
! 3490: if (rip->ecmp)
! 3491: {
! 3492: vty_out (vty, "ECMP is already enabled.%s", VTY_NEWLINE);
! 3493: return CMD_WARNING;
! 3494: }
! 3495:
! 3496: rip->ecmp = 1;
! 3497: zlog_info ("ECMP is enabled.");
! 3498: return CMD_SUCCESS;
! 3499: }
! 3500:
! 3501: DEFUN (no_rip_allow_ecmp,
! 3502: no_rip_allow_ecmp_cmd,
! 3503: "no allow-ecmp",
! 3504: NO_STR
! 3505: "Allow Equal Cost MultiPath\n")
! 3506: {
! 3507: if (!rip->ecmp)
! 3508: {
! 3509: vty_out (vty, "ECMP is already disabled.%s", VTY_NEWLINE);
! 3510: return CMD_WARNING;
! 3511: }
! 3512:
! 3513: rip->ecmp = 0;
! 3514: zlog_info ("ECMP is disabled.");
! 3515: rip_ecmp_disable ();
! 3516: return CMD_SUCCESS;
! 3517: }
! 3518:
1.1 misho 3519: /* Print out routes update time. */
3520: static void
3521: rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
3522: {
3523: time_t clock;
3524: struct tm *tm;
3525: #define TIME_BUF 25
3526: char timebuf [TIME_BUF];
3527: struct thread *thread;
3528:
3529: if ((thread = rinfo->t_timeout) != NULL)
3530: {
3531: clock = thread_timer_remain_second (thread);
3532: tm = gmtime (&clock);
3533: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3534: vty_out (vty, "%5s", timebuf);
3535: }
3536: else if ((thread = rinfo->t_garbage_collect) != NULL)
3537: {
3538: clock = thread_timer_remain_second (thread);
3539: tm = gmtime (&clock);
3540: strftime (timebuf, TIME_BUF, "%M:%S", tm);
3541: vty_out (vty, "%5s", timebuf);
3542: }
3543: }
3544:
3545: static const char *
3546: rip_route_type_print (int sub_type)
3547: {
3548: switch (sub_type)
3549: {
3550: case RIP_ROUTE_RTE:
3551: return "n";
3552: case RIP_ROUTE_STATIC:
3553: return "s";
3554: case RIP_ROUTE_DEFAULT:
3555: return "d";
3556: case RIP_ROUTE_REDISTRIBUTE:
3557: return "r";
3558: case RIP_ROUTE_INTERFACE:
3559: return "i";
3560: default:
3561: return "?";
3562: }
3563: }
3564:
3565: DEFUN (show_ip_rip,
3566: show_ip_rip_cmd,
3567: "show ip rip",
3568: SHOW_STR
3569: IP_STR
3570: "Show RIP routes\n")
3571: {
3572: struct route_node *np;
1.1.1.3 ! misho 3573: struct rip_info *rinfo = NULL;
! 3574: struct list *list = NULL;
! 3575: struct listnode *listnode = NULL;
1.1 misho 3576:
3577: if (! rip)
3578: return CMD_SUCCESS;
3579:
3580: vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
3581: "Sub-codes:%s"
3582: " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
3583: " (i) - interface%s%s"
3584: " Network Next Hop Metric From Tag Time%s",
3585: VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
3586:
3587: for (np = route_top (rip->table); np; np = route_next (np))
1.1.1.3 ! misho 3588: if ((list = np->info) != NULL)
! 3589: for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
1.1 misho 3590: {
3591: int len;
3592:
3593: len = vty_out (vty, "%c(%s) %s/%d",
3594: /* np->lock, For debugging. */
3595: zebra_route_char(rinfo->type),
3596: rip_route_type_print (rinfo->sub_type),
3597: inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
3598:
3599: len = 24 - len;
3600:
3601: if (len > 0)
3602: vty_out (vty, "%*s", len, " ");
3603:
3604: if (rinfo->nexthop.s_addr)
3605: vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
3606: rinfo->metric);
3607: else
3608: vty_out (vty, "0.0.0.0 %2d ", rinfo->metric);
3609:
3610: /* Route which exist in kernel routing table. */
3611: if ((rinfo->type == ZEBRA_ROUTE_RIP) &&
3612: (rinfo->sub_type == RIP_ROUTE_RTE))
3613: {
3614: vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
3615: vty_out (vty, "%3d ", rinfo->tag);
3616: rip_vty_out_uptime (vty, rinfo);
3617: }
3618: else if (rinfo->metric == RIP_METRIC_INFINITY)
3619: {
3620: vty_out (vty, "self ");
3621: vty_out (vty, "%3d ", rinfo->tag);
3622: rip_vty_out_uptime (vty, rinfo);
3623: }
3624: else
3625: {
3626: if (rinfo->external_metric)
3627: {
3628: len = vty_out (vty, "self (%s:%d)",
3629: zebra_route_string(rinfo->type),
3630: rinfo->external_metric);
3631: len = 16 - len;
3632: if (len > 0)
3633: vty_out (vty, "%*s", len, " ");
3634: }
3635: else
3636: vty_out (vty, "self ");
3637: vty_out (vty, "%3d", rinfo->tag);
3638: }
3639:
3640: vty_out (vty, "%s", VTY_NEWLINE);
3641: }
3642: return CMD_SUCCESS;
3643: }
3644:
3645: /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
3646: DEFUN (show_ip_rip_status,
3647: show_ip_rip_status_cmd,
3648: "show ip rip status",
3649: SHOW_STR
3650: IP_STR
3651: "Show RIP routes\n"
3652: "IP routing protocol process parameters and statistics\n")
3653: {
3654: struct listnode *node;
3655: struct interface *ifp;
3656: struct rip_interface *ri;
3657: extern const struct message ri_version_msg[];
3658: const char *send_version;
3659: const char *receive_version;
3660:
3661: if (! rip)
3662: return CMD_SUCCESS;
3663:
3664: vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE);
3665: vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
3666: rip->update_time);
3667: vty_out (vty, " next due in %lu seconds%s",
3668: thread_timer_remain_second(rip->t_update),
3669: VTY_NEWLINE);
3670: vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time);
3671: vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time,
3672: VTY_NEWLINE);
3673:
3674: /* Filtering status show. */
3675: config_show_distribute (vty);
3676:
3677: /* Default metric information. */
3678: vty_out (vty, " Default redistribution metric is %d%s",
3679: rip->default_metric, VTY_NEWLINE);
3680:
3681: /* Redistribute information. */
3682: vty_out (vty, " Redistributing:");
3683: config_write_rip_redistribute (vty, 0);
3684: vty_out (vty, "%s", VTY_NEWLINE);
3685:
3686: vty_out (vty, " Default version control: send version %s,",
3687: lookup(ri_version_msg,rip->version_send));
3688: if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
3689: vty_out (vty, " receive any version %s", VTY_NEWLINE);
3690: else
3691: vty_out (vty, " receive version %s %s",
3692: lookup(ri_version_msg,rip->version_recv), VTY_NEWLINE);
3693:
3694: vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE);
3695:
3696: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3697: {
3698: ri = ifp->info;
3699:
3700: if (!ri->running)
3701: continue;
3702:
3703: if (ri->enable_network || ri->enable_interface)
3704: {
3705: if (ri->ri_send == RI_RIP_UNSPEC)
3706: send_version = lookup (ri_version_msg, rip->version_send);
3707: else
3708: send_version = lookup (ri_version_msg, ri->ri_send);
3709:
3710: if (ri->ri_receive == RI_RIP_UNSPEC)
3711: receive_version = lookup (ri_version_msg, rip->version_recv);
3712: else
3713: receive_version = lookup (ri_version_msg, ri->ri_receive);
3714:
3715: vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name,
3716: send_version,
3717: receive_version,
3718: ri->key_chain ? ri->key_chain : "",
3719: VTY_NEWLINE);
3720: }
3721: }
3722:
3723: vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
3724: config_write_rip_network (vty, 0);
3725:
3726: {
3727: int found_passive = 0;
3728: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3729: {
3730: ri = ifp->info;
3731:
3732: if ((ri->enable_network || ri->enable_interface) && ri->passive)
3733: {
3734: if (!found_passive)
3735: {
3736: vty_out (vty, " Passive Interface(s):%s", VTY_NEWLINE);
3737: found_passive = 1;
3738: }
3739: vty_out (vty, " %s%s", ifp->name, VTY_NEWLINE);
3740: }
3741: }
3742: }
3743:
3744: vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
3745: vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
3746: rip_peer_display (vty);
3747:
3748: rip_distance_show (vty);
3749:
3750: return CMD_SUCCESS;
3751: }
3752:
3753: /* RIP configuration write function. */
3754: static int
3755: config_write_rip (struct vty *vty)
3756: {
3757: int write = 0;
3758: struct route_node *rn;
3759: struct rip_distance *rdistance;
3760:
3761: if (rip)
3762: {
3763: /* Router RIP statement. */
3764: vty_out (vty, "router rip%s", VTY_NEWLINE);
3765: write++;
3766:
3767: /* RIP version statement. Default is RIP version 2. */
3768: if (rip->version_send != RI_RIP_VERSION_2
3769: || rip->version_recv != RI_RIP_VERSION_1_AND_2)
3770: vty_out (vty, " version %d%s", rip->version_send,
3771: VTY_NEWLINE);
3772:
3773: /* RIP timer configuration. */
3774: if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
3775: || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
3776: || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
3777: vty_out (vty, " timers basic %lu %lu %lu%s",
3778: rip->update_time,
3779: rip->timeout_time,
3780: rip->garbage_time,
3781: VTY_NEWLINE);
3782:
3783: /* Default information configuration. */
3784: if (rip->default_information)
3785: {
3786: if (rip->default_information_route_map)
3787: vty_out (vty, " default-information originate route-map %s%s",
3788: rip->default_information_route_map, VTY_NEWLINE);
3789: else
3790: vty_out (vty, " default-information originate%s",
3791: VTY_NEWLINE);
3792: }
3793:
3794: /* Redistribute configuration. */
3795: config_write_rip_redistribute (vty, 1);
3796:
3797: /* RIP offset-list configuration. */
3798: config_write_rip_offset_list (vty);
3799:
3800: /* RIP enabled network and interface configuration. */
3801: config_write_rip_network (vty, 1);
3802:
3803: /* RIP default metric configuration */
3804: if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
3805: vty_out (vty, " default-metric %d%s",
3806: rip->default_metric, VTY_NEWLINE);
3807:
3808: /* Distribute configuration. */
3809: write += config_write_distribute (vty);
3810:
3811: /* Interface routemap configuration */
3812: write += config_write_if_rmap (vty);
3813:
3814: /* Distance configuration. */
3815: if (rip->distance)
3816: vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
3817:
3818: /* RIP source IP prefix distance configuration. */
3819: for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
3820: if ((rdistance = rn->info) != NULL)
3821: vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
3822: inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
3823: rdistance->access_list ? rdistance->access_list : "",
3824: VTY_NEWLINE);
3825:
1.1.1.3 ! misho 3826: /* ECMP configuration. */
! 3827: if (rip->ecmp)
! 3828: vty_out (vty, " allow-ecmp%s", VTY_NEWLINE);
! 3829:
1.1 misho 3830: /* RIP static route configuration. */
3831: for (rn = route_top (rip->route); rn; rn = route_next (rn))
3832: if (rn->info)
3833: vty_out (vty, " route %s/%d%s",
3834: inet_ntoa (rn->p.u.prefix4),
3835: rn->p.prefixlen,
3836: VTY_NEWLINE);
3837:
3838: }
3839: return write;
3840: }
3841:
3842: /* RIP node structure. */
3843: static struct cmd_node rip_node =
3844: {
3845: RIP_NODE,
3846: "%s(config-router)# ",
3847: 1
3848: };
1.1.1.3 ! misho 3849:
1.1 misho 3850: /* Distribute-list update functions. */
3851: static void
3852: rip_distribute_update (struct distribute *dist)
3853: {
3854: struct interface *ifp;
3855: struct rip_interface *ri;
3856: struct access_list *alist;
3857: struct prefix_list *plist;
3858:
3859: if (! dist->ifname)
3860: return;
3861:
3862: ifp = if_lookup_by_name (dist->ifname);
3863: if (ifp == NULL)
3864: return;
3865:
3866: ri = ifp->info;
3867:
3868: if (dist->list[DISTRIBUTE_IN])
3869: {
3870: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);
3871: if (alist)
3872: ri->list[RIP_FILTER_IN] = alist;
3873: else
3874: ri->list[RIP_FILTER_IN] = NULL;
3875: }
3876: else
3877: ri->list[RIP_FILTER_IN] = NULL;
3878:
3879: if (dist->list[DISTRIBUTE_OUT])
3880: {
3881: alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);
3882: if (alist)
3883: ri->list[RIP_FILTER_OUT] = alist;
3884: else
3885: ri->list[RIP_FILTER_OUT] = NULL;
3886: }
3887: else
3888: ri->list[RIP_FILTER_OUT] = NULL;
3889:
3890: if (dist->prefix[DISTRIBUTE_IN])
3891: {
3892: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);
3893: if (plist)
3894: ri->prefix[RIP_FILTER_IN] = plist;
3895: else
3896: ri->prefix[RIP_FILTER_IN] = NULL;
3897: }
3898: else
3899: ri->prefix[RIP_FILTER_IN] = NULL;
3900:
3901: if (dist->prefix[DISTRIBUTE_OUT])
3902: {
3903: plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);
3904: if (plist)
3905: ri->prefix[RIP_FILTER_OUT] = plist;
3906: else
3907: ri->prefix[RIP_FILTER_OUT] = NULL;
3908: }
3909: else
3910: ri->prefix[RIP_FILTER_OUT] = NULL;
3911: }
3912:
3913: void
3914: rip_distribute_update_interface (struct interface *ifp)
3915: {
3916: struct distribute *dist;
3917:
3918: dist = distribute_lookup (ifp->name);
3919: if (dist)
3920: rip_distribute_update (dist);
3921: }
3922:
3923: /* Update all interface's distribute list. */
3924: /* ARGSUSED */
3925: static void
3926: rip_distribute_update_all (struct prefix_list *notused)
3927: {
3928: struct interface *ifp;
3929: struct listnode *node, *nnode;
3930:
3931: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
3932: rip_distribute_update_interface (ifp);
3933: }
3934: /* ARGSUSED */
3935: static void
3936: rip_distribute_update_all_wrapper(struct access_list *notused)
3937: {
3938: rip_distribute_update_all(NULL);
3939: }
1.1.1.3 ! misho 3940:
1.1 misho 3941: /* Delete all added rip route. */
3942: void
3943: rip_clean (void)
3944: {
3945: int i;
3946: struct route_node *rp;
1.1.1.3 ! misho 3947: struct rip_info *rinfo = NULL;
! 3948: struct list *list = NULL;
! 3949: struct listnode *listnode = NULL;
1.1 misho 3950:
3951: if (rip)
3952: {
3953: /* Clear RIP routes */
3954: for (rp = route_top (rip->table); rp; rp = route_next (rp))
1.1.1.3 ! misho 3955: if ((list = rp->info) != NULL)
! 3956: {
! 3957: rinfo = listgetdata (listhead (list));
! 3958: if (rip_route_rte (rinfo))
! 3959: rip_zebra_ipv4_delete (rp);
! 3960:
! 3961: for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
! 3962: {
! 3963: RIP_TIMER_OFF (rinfo->t_timeout);
! 3964: RIP_TIMER_OFF (rinfo->t_garbage_collect);
! 3965: rip_info_free (rinfo);
! 3966: }
! 3967: list_delete (list);
! 3968: rp->info = NULL;
! 3969: route_unlock_node (rp);
! 3970: }
1.1 misho 3971:
3972: /* Cancel RIP related timers. */
3973: RIP_TIMER_OFF (rip->t_update);
3974: RIP_TIMER_OFF (rip->t_triggered_update);
3975: RIP_TIMER_OFF (rip->t_triggered_interval);
3976:
3977: /* Cancel read thread. */
3978: if (rip->t_read)
3979: {
3980: thread_cancel (rip->t_read);
3981: rip->t_read = NULL;
3982: }
3983:
3984: /* Close RIP socket. */
3985: if (rip->sock >= 0)
3986: {
3987: close (rip->sock);
3988: rip->sock = -1;
3989: }
3990:
3991: /* Static RIP route configuration. */
3992: for (rp = route_top (rip->route); rp; rp = route_next (rp))
3993: if (rp->info)
3994: {
3995: rp->info = NULL;
3996: route_unlock_node (rp);
3997: }
3998:
3999: /* RIP neighbor configuration. */
4000: for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
4001: if (rp->info)
4002: {
4003: rp->info = NULL;
4004: route_unlock_node (rp);
4005: }
4006:
4007: /* Redistribute related clear. */
4008: if (rip->default_information_route_map)
4009: free (rip->default_information_route_map);
4010:
4011: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
4012: if (rip->route_map[i].name)
4013: free (rip->route_map[i].name);
4014:
4015: XFREE (MTYPE_ROUTE_TABLE, rip->table);
4016: XFREE (MTYPE_ROUTE_TABLE, rip->route);
4017: XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
4018:
4019: XFREE (MTYPE_RIP, rip);
4020: rip = NULL;
4021: }
4022:
4023: rip_clean_network ();
4024: rip_passive_nondefault_clean ();
4025: rip_offset_clean ();
4026: rip_interface_clean ();
4027: rip_distance_reset ();
4028: rip_redistribute_clean ();
4029: }
4030:
4031: /* Reset all values to the default settings. */
4032: void
4033: rip_reset (void)
4034: {
4035: /* Reset global counters. */
4036: rip_global_route_changes = 0;
4037: rip_global_queries = 0;
4038:
4039: /* Call ripd related reset functions. */
4040: rip_debug_reset ();
4041: rip_route_map_reset ();
4042:
4043: /* Call library reset functions. */
4044: vty_reset ();
4045: access_list_reset ();
4046: prefix_list_reset ();
4047:
4048: distribute_list_reset ();
4049:
4050: rip_interface_reset ();
4051: rip_distance_reset ();
4052:
4053: rip_zclient_reset ();
4054: }
4055:
4056: static void
4057: rip_if_rmap_update (struct if_rmap *if_rmap)
4058: {
4059: struct interface *ifp;
4060: struct rip_interface *ri;
4061: struct route_map *rmap;
4062:
4063: ifp = if_lookup_by_name (if_rmap->ifname);
4064: if (ifp == NULL)
4065: return;
4066:
4067: ri = ifp->info;
4068:
4069: if (if_rmap->routemap[IF_RMAP_IN])
4070: {
4071: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
4072: if (rmap)
4073: ri->routemap[IF_RMAP_IN] = rmap;
4074: else
4075: ri->routemap[IF_RMAP_IN] = NULL;
4076: }
4077: else
4078: ri->routemap[RIP_FILTER_IN] = NULL;
4079:
4080: if (if_rmap->routemap[IF_RMAP_OUT])
4081: {
4082: rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
4083: if (rmap)
4084: ri->routemap[IF_RMAP_OUT] = rmap;
4085: else
4086: ri->routemap[IF_RMAP_OUT] = NULL;
4087: }
4088: else
4089: ri->routemap[RIP_FILTER_OUT] = NULL;
4090: }
4091:
4092: void
4093: rip_if_rmap_update_interface (struct interface *ifp)
4094: {
4095: struct if_rmap *if_rmap;
4096:
4097: if_rmap = if_rmap_lookup (ifp->name);
4098: if (if_rmap)
4099: rip_if_rmap_update (if_rmap);
4100: }
4101:
4102: static void
4103: rip_routemap_update_redistribute (void)
4104: {
4105: int i;
4106:
4107: if (rip)
4108: {
4109: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
4110: {
4111: if (rip->route_map[i].name)
4112: rip->route_map[i].map =
4113: route_map_lookup_by_name (rip->route_map[i].name);
4114: }
4115: }
4116: }
4117:
4118: /* ARGSUSED */
4119: static void
4120: rip_routemap_update (const char *notused)
4121: {
4122: struct interface *ifp;
4123: struct listnode *node, *nnode;
4124:
4125: for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
4126: rip_if_rmap_update_interface (ifp);
4127:
4128: rip_routemap_update_redistribute ();
4129: }
4130:
4131: /* Allocate new rip structure and set default value. */
4132: void
4133: rip_init (void)
4134: {
4135: /* Randomize for triggered update random(). */
1.1.1.3 ! misho 4136: srandom (time (NULL));
1.1 misho 4137:
4138: /* Install top nodes. */
4139: install_node (&rip_node, config_write_rip);
4140:
4141: /* Install rip commands. */
4142: install_element (VIEW_NODE, &show_ip_rip_cmd);
4143: install_element (VIEW_NODE, &show_ip_rip_status_cmd);
4144: install_element (ENABLE_NODE, &show_ip_rip_cmd);
4145: install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
4146: install_element (CONFIG_NODE, &router_rip_cmd);
4147: install_element (CONFIG_NODE, &no_router_rip_cmd);
4148:
4149: install_default (RIP_NODE);
4150: install_element (RIP_NODE, &rip_version_cmd);
4151: install_element (RIP_NODE, &no_rip_version_cmd);
4152: install_element (RIP_NODE, &no_rip_version_val_cmd);
4153: install_element (RIP_NODE, &rip_default_metric_cmd);
4154: install_element (RIP_NODE, &no_rip_default_metric_cmd);
4155: install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
4156: install_element (RIP_NODE, &rip_timers_cmd);
4157: install_element (RIP_NODE, &no_rip_timers_cmd);
4158: install_element (RIP_NODE, &no_rip_timers_val_cmd);
4159: install_element (RIP_NODE, &rip_route_cmd);
4160: install_element (RIP_NODE, &no_rip_route_cmd);
4161: install_element (RIP_NODE, &rip_distance_cmd);
4162: install_element (RIP_NODE, &no_rip_distance_cmd);
4163: install_element (RIP_NODE, &rip_distance_source_cmd);
4164: install_element (RIP_NODE, &no_rip_distance_source_cmd);
4165: install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
4166: install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
1.1.1.3 ! misho 4167: install_element (RIP_NODE, &rip_allow_ecmp_cmd);
! 4168: install_element (RIP_NODE, &no_rip_allow_ecmp_cmd);
1.1 misho 4169:
4170: /* Debug related init. */
4171: rip_debug_init ();
4172:
4173: /* SNMP init. */
4174: #ifdef HAVE_SNMP
4175: rip_snmp_init ();
4176: #endif /* HAVE_SNMP */
4177:
4178: /* Access list install. */
4179: access_list_init ();
4180: access_list_add_hook (rip_distribute_update_all_wrapper);
4181: access_list_delete_hook (rip_distribute_update_all_wrapper);
4182:
4183: /* Prefix list initialize.*/
4184: prefix_list_init ();
4185: prefix_list_add_hook (rip_distribute_update_all);
4186: prefix_list_delete_hook (rip_distribute_update_all);
4187:
4188: /* Distribute list install. */
4189: distribute_list_init (RIP_NODE);
4190: distribute_list_add_hook (rip_distribute_update);
4191: distribute_list_delete_hook (rip_distribute_update);
4192:
4193: /* Route-map */
4194: rip_route_map_init ();
4195: rip_offset_init ();
4196:
4197: route_map_add_hook (rip_routemap_update);
4198: route_map_delete_hook (rip_routemap_update);
4199:
4200: if_rmap_init (RIP_NODE);
4201: if_rmap_hook_add (rip_if_rmap_update);
4202: if_rmap_hook_delete (rip_if_rmap_update);
4203:
4204: /* Distance control. */
4205: rip_distance_table = route_table_init ();
4206: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>