Annotation of embedaddon/quagga/ripd/ripd.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>