Annotation of embedaddon/quagga/zebra/interface.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Interface function.
        !             3:  * Copyright (C) 1997, 1999 Kunihiro Ishiguro
        !             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 "vty.h"
        !            27: #include "sockunion.h"
        !            28: #include "prefix.h"
        !            29: #include "command.h"
        !            30: #include "memory.h"
        !            31: #include "ioctl.h"
        !            32: #include "connected.h"
        !            33: #include "log.h"
        !            34: #include "zclient.h"
        !            35: 
        !            36: #include "zebra/interface.h"
        !            37: #include "zebra/rtadv.h"
        !            38: #include "zebra/rib.h"
        !            39: #include "zebra/zserv.h"
        !            40: #include "zebra/redistribute.h"
        !            41: #include "zebra/debug.h"
        !            42: #include "zebra/irdp.h"
        !            43: 
        !            44: #ifdef RTADV
        !            45: /* Order is intentional.  Matches RFC4191.  This array is also used for
        !            46:    command matching, so only modify with care. */
        !            47: const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
        !            48: #endif /* RTADV */
        !            49: 
        !            50: /* Called when new interface is added. */
        !            51: static int
        !            52: if_zebra_new_hook (struct interface *ifp)
        !            53: {
        !            54:   struct zebra_if *zebra_if;
        !            55: 
        !            56:   zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if));
        !            57: 
        !            58:   zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
        !            59:   zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC;
        !            60: 
        !            61: #ifdef RTADV
        !            62:   {
        !            63:     /* Set default router advertise values. */
        !            64:     struct rtadvconf *rtadv;
        !            65: 
        !            66:     rtadv = &zebra_if->rtadv;
        !            67: 
        !            68:     rtadv->AdvSendAdvertisements = 0;
        !            69:     rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
        !            70:     rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
        !            71:     rtadv->AdvIntervalTimer = 0;
        !            72:     rtadv->AdvManagedFlag = 0;
        !            73:     rtadv->AdvOtherConfigFlag = 0;
        !            74:     rtadv->AdvHomeAgentFlag = 0;
        !            75:     rtadv->AdvLinkMTU = 0;
        !            76:     rtadv->AdvReachableTime = 0;
        !            77:     rtadv->AdvRetransTimer = 0;
        !            78:     rtadv->AdvCurHopLimit = 0;
        !            79:     rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
        !            80:     rtadv->HomeAgentPreference = 0;
        !            81:     rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
        !            82:     rtadv->AdvIntervalOption = 0;
        !            83:     rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
        !            84: 
        !            85:     rtadv->AdvPrefixList = list_new ();
        !            86:   }    
        !            87: #endif /* RTADV */
        !            88: 
        !            89:   /* Initialize installed address chains tree. */
        !            90:   zebra_if->ipv4_subnets = route_table_init ();
        !            91: 
        !            92:   ifp->info = zebra_if;
        !            93:   return 0;
        !            94: }
        !            95: 
        !            96: /* Called when interface is deleted. */
        !            97: static int
        !            98: if_zebra_delete_hook (struct interface *ifp)
        !            99: {
        !           100:   struct zebra_if *zebra_if;
        !           101:   
        !           102:   if (ifp->info)
        !           103:     {
        !           104:       zebra_if = ifp->info;
        !           105: 
        !           106:       /* Free installed address chains tree. */
        !           107:       if (zebra_if->ipv4_subnets)
        !           108:        route_table_finish (zebra_if->ipv4_subnets);
        !           109: 
        !           110:       XFREE (MTYPE_TMP, zebra_if);
        !           111:     }
        !           112: 
        !           113:   return 0;
        !           114: }
        !           115: 
        !           116: /* Tie an interface address to its derived subnet list of addresses. */
        !           117: int
        !           118: if_subnet_add (struct interface *ifp, struct connected *ifc)
        !           119: {
        !           120:   struct route_node *rn;
        !           121:   struct zebra_if *zebra_if;
        !           122:   struct prefix cp;
        !           123:   struct list *addr_list;
        !           124: 
        !           125:   assert (ifp && ifp->info && ifc);
        !           126:   zebra_if = ifp->info;
        !           127: 
        !           128:   /* Get address derived subnet node and associated address list, while marking
        !           129:      address secondary attribute appropriately. */
        !           130:   cp = *ifc->address;
        !           131:   apply_mask (&cp);
        !           132:   rn = route_node_get (zebra_if->ipv4_subnets, &cp);
        !           133: 
        !           134:   if ((addr_list = rn->info))
        !           135:     SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
        !           136:   else
        !           137:     {
        !           138:       UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
        !           139:       rn->info = addr_list = list_new ();
        !           140:       route_lock_node (rn);
        !           141:     }
        !           142: 
        !           143:   /* Tie address at the tail of address list. */
        !           144:   listnode_add (addr_list, ifc);
        !           145:   
        !           146:   /* Return list element count. */
        !           147:   return (addr_list->count);
        !           148: }
        !           149: 
        !           150: /* Untie an interface address from its derived subnet list of addresses. */
        !           151: int
        !           152: if_subnet_delete (struct interface *ifp, struct connected *ifc)
        !           153: {
        !           154:   struct route_node *rn;
        !           155:   struct zebra_if *zebra_if;
        !           156:   struct list *addr_list;
        !           157: 
        !           158:   assert (ifp && ifp->info && ifc);
        !           159:   zebra_if = ifp->info;
        !           160: 
        !           161:   /* Get address derived subnet node. */
        !           162:   rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
        !           163:   if (! (rn && rn->info))
        !           164:     return -1;
        !           165:   route_unlock_node (rn);
        !           166:   
        !           167:   /* Untie address from subnet's address list. */
        !           168:   addr_list = rn->info;
        !           169:   listnode_delete (addr_list, ifc);
        !           170:   route_unlock_node (rn);
        !           171: 
        !           172:   /* Return list element count, if not empty. */
        !           173:   if (addr_list->count)
        !           174:     {
        !           175:       /* If deleted address is primary, mark subsequent one as such and distribute. */
        !           176:       if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
        !           177:        {
        !           178:          ifc = listgetdata (listhead (addr_list));
        !           179:          zebra_interface_address_delete_update (ifp, ifc);
        !           180:          UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
        !           181:          zebra_interface_address_add_update (ifp, ifc);
        !           182:        }
        !           183:       
        !           184:       return addr_list->count;
        !           185:     }
        !           186:   
        !           187:   /* Otherwise, free list and route node. */
        !           188:   list_free (addr_list);
        !           189:   rn->info = NULL;
        !           190:   route_unlock_node (rn);
        !           191: 
        !           192:   return 0;
        !           193: }
        !           194: 
        !           195: /* if_flags_mangle: A place for hacks that require mangling
        !           196:  * or tweaking the interface flags.
        !           197:  *
        !           198:  * ******************** Solaris flags hacks **************************
        !           199:  *
        !           200:  * Solaris IFF_UP flag reflects only the primary interface as the
        !           201:  * routing socket only sends IFINFO for the primary interface.  Hence  
        !           202:  * ~IFF_UP does not per se imply all the logical interfaces are also   
        !           203:  * down - which we only know of as addresses. Instead we must determine
        !           204:  * whether the interface really is up or not according to how many   
        !           205:  * addresses are still attached. (Solaris always sends RTM_DELADDR if
        !           206:  * an interface, logical or not, goes ~IFF_UP).
        !           207:  *
        !           208:  * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
        !           209:  * are addresses left in struct connected, not just the actual underlying
        !           210:  * IFF_UP flag.
        !           211:  *
        !           212:  * We must hence remember the real state of IFF_UP, which we do in
        !           213:  * struct zebra_if.primary_state.
        !           214:  *
        !           215:  * Setting IFF_UP within zebra to administratively shutdown the
        !           216:  * interface will affect only the primary interface/address on Solaris.
        !           217:  ************************End Solaris flags hacks ***********************
        !           218:  */
        !           219: static inline void
        !           220: if_flags_mangle (struct interface *ifp, uint64_t *newflags)
        !           221: {
        !           222: #ifdef SUNOS_5
        !           223:   struct zebra_if *zif = ifp->info;
        !           224:   
        !           225:   zif->primary_state = *newflags & (IFF_UP & 0xff);
        !           226:   
        !           227:   if (CHECK_FLAG (zif->primary_state, IFF_UP)
        !           228:       || listcount(ifp->connected) > 0)
        !           229:     SET_FLAG (*newflags, IFF_UP);
        !           230:   else
        !           231:     UNSET_FLAG (*newflags, IFF_UP);
        !           232: #endif /* SUNOS_5 */
        !           233: }
        !           234: 
        !           235: /* Update the flags field of the ifp with the new flag set provided.
        !           236:  * Take whatever actions are required for any changes in flags we care
        !           237:  * about.
        !           238:  *
        !           239:  * newflags should be the raw value, as obtained from the OS.
        !           240:  */
        !           241: void
        !           242: if_flags_update (struct interface *ifp, uint64_t newflags)
        !           243: {
        !           244:   if_flags_mangle (ifp, &newflags);
        !           245:     
        !           246:   if (if_is_operative (ifp))
        !           247:     {
        !           248:       /* operative -> inoperative? */
        !           249:       ifp->flags = newflags;
        !           250:       if (!if_is_operative (ifp))
        !           251:         if_down (ifp);
        !           252:     }
        !           253:   else
        !           254:     {
        !           255:       /* inoperative -> operative? */
        !           256:       ifp->flags = newflags;
        !           257:       if (if_is_operative (ifp))
        !           258:         if_up (ifp);
        !           259:     }
        !           260: }
        !           261: 
        !           262: /* Wake up configured address if it is not in current kernel
        !           263:    address. */
        !           264: static void
        !           265: if_addr_wakeup (struct interface *ifp)
        !           266: {
        !           267:   struct listnode *node, *nnode;
        !           268:   struct connected *ifc;
        !           269:   struct prefix *p;
        !           270:   int ret;
        !           271: 
        !           272:   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
        !           273:     {
        !           274:       p = ifc->address;
        !           275:        
        !           276:       if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
        !           277:          && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
        !           278:        {
        !           279:          /* Address check. */
        !           280:          if (p->family == AF_INET)
        !           281:            {
        !           282:              if (! if_is_up (ifp))
        !           283:                {
        !           284:                  /* XXX: WTF is it trying to set flags here?
        !           285:                   * caller has just gotten a new interface, has been
        !           286:                    * handed the flags already. This code has no business
        !           287:                    * trying to override administrative status of the interface.
        !           288:                    * The only call path to here which doesn't originate from
        !           289:                    * kernel event is irdp - what on earth is it trying to do?
        !           290:                    *
        !           291:                    * further RUNNING is not a settable flag on any system
        !           292:                    * I (paulj) am aware of.
        !           293:                    */
        !           294:                  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
        !           295:                  if_refresh (ifp);
        !           296:                }
        !           297: 
        !           298:              ret = if_set_prefix (ifp, ifc);
        !           299:              if (ret < 0)
        !           300:                {
        !           301:                  zlog_warn ("Can't set interface's address: %s", 
        !           302:                             safe_strerror(errno));
        !           303:                  continue;
        !           304:                }
        !           305: 
        !           306:              /* Add to subnet chain list. */
        !           307:              if_subnet_add (ifp, ifc);
        !           308: 
        !           309:              SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !           310: 
        !           311:              zebra_interface_address_add_update (ifp, ifc);
        !           312: 
        !           313:              if (if_is_operative(ifp))
        !           314:                connected_up_ipv4 (ifp, ifc);
        !           315:            }
        !           316: #ifdef HAVE_IPV6
        !           317:          if (p->family == AF_INET6)
        !           318:            {
        !           319:              if (! if_is_up (ifp))
        !           320:                {
        !           321:                  /* XXX: See long comment above */
        !           322:                  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
        !           323:                  if_refresh (ifp);
        !           324:                }
        !           325: 
        !           326:              ret = if_prefix_add_ipv6 (ifp, ifc);
        !           327:              if (ret < 0)
        !           328:                {
        !           329:                  zlog_warn ("Can't set interface's address: %s", 
        !           330:                             safe_strerror(errno));
        !           331:                  continue;
        !           332:                }
        !           333:              SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !           334: 
        !           335:              zebra_interface_address_add_update (ifp, ifc);
        !           336: 
        !           337:              if (if_is_operative(ifp))
        !           338:                connected_up_ipv6 (ifp, ifc);
        !           339:            }
        !           340: #endif /* HAVE_IPV6 */
        !           341:        }
        !           342:     }
        !           343: }
        !           344: 
        !           345: /* Handle interface addition */
        !           346: void
        !           347: if_add_update (struct interface *ifp)
        !           348: {
        !           349:   struct zebra_if *if_data;
        !           350: 
        !           351:   if_data = ifp->info;
        !           352:   if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
        !           353:     if_set_flags (ifp, IFF_MULTICAST);
        !           354:   else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
        !           355:     if_unset_flags (ifp, IFF_MULTICAST);
        !           356: 
        !           357:   zebra_interface_add_update (ifp);
        !           358: 
        !           359:   if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !           360:     {
        !           361:       SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
        !           362: 
        !           363:       if_addr_wakeup (ifp);
        !           364: 
        !           365:       if (IS_ZEBRA_DEBUG_KERNEL)
        !           366:        zlog_debug ("interface %s index %d becomes active.", 
        !           367:                    ifp->name, ifp->ifindex);
        !           368:     }
        !           369:   else
        !           370:     {
        !           371:       if (IS_ZEBRA_DEBUG_KERNEL)
        !           372:        zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex);
        !           373:     }
        !           374: }
        !           375: 
        !           376: /* Handle an interface delete event */
        !           377: void 
        !           378: if_delete_update (struct interface *ifp)
        !           379: {
        !           380:   struct connected *ifc;
        !           381:   struct prefix *p;
        !           382:   struct route_node *rn;
        !           383:   struct zebra_if *zebra_if;
        !           384: 
        !           385:   zebra_if = ifp->info;
        !           386: 
        !           387:   if (if_is_up(ifp))
        !           388:     {
        !           389:       zlog_err ("interface %s index %d is still up while being deleted.",
        !           390:            ifp->name, ifp->ifindex);
        !           391:       return;
        !           392:     }
        !           393: 
        !           394:   /* Mark interface as inactive */
        !           395:   UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
        !           396:   
        !           397:   if (IS_ZEBRA_DEBUG_KERNEL)
        !           398:     zlog_debug ("interface %s index %d is now inactive.",
        !           399:               ifp->name, ifp->ifindex);
        !           400: 
        !           401:   /* Delete connected routes from the kernel. */
        !           402:   if (ifp->connected)
        !           403:     {
        !           404:       struct listnode *node;
        !           405:       struct listnode *last = NULL;
        !           406: 
        !           407:       while ((node = (last ? last->next : listhead (ifp->connected))))
        !           408:        {
        !           409:          ifc = listgetdata (node);
        !           410:          p = ifc->address;
        !           411:          
        !           412:          if (p->family == AF_INET
        !           413:              && (rn = route_node_lookup (zebra_if->ipv4_subnets, p)))
        !           414:            {
        !           415:              struct listnode *anode;
        !           416:              struct listnode *next;
        !           417:              struct listnode *first;
        !           418:              struct list *addr_list;
        !           419:              
        !           420:              route_unlock_node (rn);
        !           421:              addr_list = (struct list *) rn->info;
        !           422:              
        !           423:              /* Remove addresses, secondaries first. */
        !           424:              first = listhead (addr_list);
        !           425:              for (anode = first->next; anode || first; anode = next)
        !           426:                {
        !           427:                  if (!anode)
        !           428:                    {
        !           429:                      anode = first;
        !           430:                      first = NULL;
        !           431:                    }
        !           432:                  next = anode->next;
        !           433: 
        !           434:                  ifc = listgetdata (anode);
        !           435:                  p = ifc->address;
        !           436: 
        !           437:                  connected_down_ipv4 (ifp, ifc);
        !           438: 
        !           439:                  zebra_interface_address_delete_update (ifp, ifc);
        !           440: 
        !           441:                  UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !           442: 
        !           443:                  /* Remove from subnet chain. */
        !           444:                  list_delete_node (addr_list, anode);
        !           445:                  route_unlock_node (rn);
        !           446:                  
        !           447:                  /* Remove from interface address list (unconditionally). */
        !           448:                  if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !           449:                    {
        !           450:                      listnode_delete (ifp->connected, ifc);
        !           451:                      connected_free (ifc);
        !           452:                     }
        !           453:                   else
        !           454:                     last = node;
        !           455:                }
        !           456: 
        !           457:              /* Free chain list and respective route node. */
        !           458:              list_delete (addr_list);
        !           459:              rn->info = NULL;
        !           460:              route_unlock_node (rn);
        !           461:            }
        !           462: #ifdef HAVE_IPV6
        !           463:          else if (p->family == AF_INET6)
        !           464:            {
        !           465:              connected_down_ipv6 (ifp, ifc);
        !           466: 
        !           467:              zebra_interface_address_delete_update (ifp, ifc);
        !           468: 
        !           469:              UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !           470: 
        !           471:              if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !           472:                last = node;
        !           473:              else
        !           474:                {
        !           475:                  listnode_delete (ifp->connected, ifc);
        !           476:                  connected_free (ifc);
        !           477:                }
        !           478:            }
        !           479: #endif /* HAVE_IPV6 */
        !           480:          else
        !           481:            {
        !           482:              last = node;
        !           483:            }
        !           484:        }
        !           485:     }
        !           486:   zebra_interface_delete_update (ifp);
        !           487: 
        !           488:   /* Update ifindex after distributing the delete message.  This is in
        !           489:      case any client needs to have the old value of ifindex available
        !           490:      while processing the deletion.  Each client daemon is responsible
        !           491:      for setting ifindex to IFINDEX_INTERNAL after processing the
        !           492:      interface deletion message. */
        !           493:   ifp->ifindex = IFINDEX_INTERNAL;
        !           494: }
        !           495: 
        !           496: /* Interface is up. */
        !           497: void
        !           498: if_up (struct interface *ifp)
        !           499: {
        !           500:   struct listnode *node;
        !           501:   struct listnode *next;
        !           502:   struct connected *ifc;
        !           503:   struct prefix *p;
        !           504: 
        !           505:   /* Notify the protocol daemons. */
        !           506:   zebra_interface_up_update (ifp);
        !           507: 
        !           508:   /* Install connected routes to the kernel. */
        !           509:   if (ifp->connected)
        !           510:     {
        !           511:       for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
        !           512:        {
        !           513:          p = ifc->address;
        !           514: 
        !           515:          if (p->family == AF_INET)
        !           516:            connected_up_ipv4 (ifp, ifc);
        !           517: #ifdef HAVE_IPV6
        !           518:          else if (p->family == AF_INET6)
        !           519:            connected_up_ipv6 (ifp, ifc);
        !           520: #endif /* HAVE_IPV6 */
        !           521:        }
        !           522:     }
        !           523: 
        !           524:   /* Examine all static routes. */
        !           525:   rib_update ();
        !           526: }
        !           527: 
        !           528: /* Interface goes down.  We have to manage different behavior of based
        !           529:    OS. */
        !           530: void
        !           531: if_down (struct interface *ifp)
        !           532: {
        !           533:   struct listnode *node;
        !           534:   struct listnode *next;
        !           535:   struct connected *ifc;
        !           536:   struct prefix *p;
        !           537: 
        !           538:   /* Notify to the protocol daemons. */
        !           539:   zebra_interface_down_update (ifp);
        !           540: 
        !           541:   /* Delete connected routes from the kernel. */
        !           542:   if (ifp->connected)
        !           543:     {
        !           544:       for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
        !           545:        {
        !           546:          p = ifc->address;
        !           547: 
        !           548:          if (p->family == AF_INET)
        !           549:            connected_down_ipv4 (ifp, ifc);
        !           550: #ifdef HAVE_IPV6
        !           551:          else if (p->family == AF_INET6)
        !           552:            connected_down_ipv6 (ifp, ifc);
        !           553: #endif /* HAVE_IPV6 */
        !           554:        }
        !           555:     }
        !           556: 
        !           557:   /* Examine all static routes which direct to the interface. */
        !           558:   rib_update ();
        !           559: }
        !           560: 
        !           561: void
        !           562: if_refresh (struct interface *ifp)
        !           563: {
        !           564:   if_get_flags (ifp);
        !           565: }
        !           566: 
        !           567: /* Output prefix string to vty. */
        !           568: static int
        !           569: prefix_vty_out (struct vty *vty, struct prefix *p)
        !           570: {
        !           571:   char str[INET6_ADDRSTRLEN];
        !           572: 
        !           573:   inet_ntop (p->family, &p->u.prefix, str, sizeof (str));
        !           574:   vty_out (vty, "%s", str);
        !           575:   return strlen (str);
        !           576: }
        !           577: 
        !           578: /* Dump if address information to vty. */
        !           579: static void
        !           580: connected_dump_vty (struct vty *vty, struct connected *connected)
        !           581: {
        !           582:   struct prefix *p;
        !           583: 
        !           584:   /* Print interface address. */
        !           585:   p = connected->address;
        !           586:   vty_out (vty, "  %s ", prefix_family_str (p));
        !           587:   prefix_vty_out (vty, p);
        !           588:   vty_out (vty, "/%d", p->prefixlen);
        !           589: 
        !           590:   /* If there is destination address, print it. */
        !           591:   if (connected->destination)
        !           592:     {
        !           593:       vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
        !           594:       prefix_vty_out (vty, connected->destination);
        !           595:     }
        !           596: 
        !           597:   if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
        !           598:     vty_out (vty, " secondary");
        !           599: 
        !           600:   if (connected->label)
        !           601:     vty_out (vty, " %s", connected->label);
        !           602: 
        !           603:   vty_out (vty, "%s", VTY_NEWLINE);
        !           604: }
        !           605: 
        !           606: #ifdef RTADV
        !           607: /* Dump interface ND information to vty. */
        !           608: static void
        !           609: nd_dump_vty (struct vty *vty, struct interface *ifp)
        !           610: {
        !           611:   struct zebra_if *zif;
        !           612:   struct rtadvconf *rtadv;
        !           613:   int interval;
        !           614: 
        !           615:   zif = (struct zebra_if *) ifp->info;
        !           616:   rtadv = &zif->rtadv;
        !           617: 
        !           618:   if (rtadv->AdvSendAdvertisements)
        !           619:     {
        !           620:       vty_out (vty, "  ND advertised reachable time is %d milliseconds%s",
        !           621:               rtadv->AdvReachableTime, VTY_NEWLINE);
        !           622:       vty_out (vty, "  ND advertised retransmit interval is %d milliseconds%s",
        !           623:               rtadv->AdvRetransTimer, VTY_NEWLINE);
        !           624:       interval = rtadv->MaxRtrAdvInterval;
        !           625:       if (interval % 1000)
        !           626:         vty_out (vty, "  ND router advertisements are sent every "
        !           627:                        "%d milliseconds%s", interval,
        !           628:                 VTY_NEWLINE);
        !           629:       else
        !           630:         vty_out (vty, "  ND router advertisements are sent every "
        !           631:                        "%d seconds%s", interval / 1000,
        !           632:                 VTY_NEWLINE);
        !           633:       vty_out (vty, "  ND router advertisements live for %d seconds%s",
        !           634:               rtadv->AdvDefaultLifetime, VTY_NEWLINE);
        !           635:       vty_out (vty, "  ND router advertisement default router preference is "
        !           636:                        "%s%s", rtadv_pref_strs[rtadv->DefaultPreference],
        !           637:                 VTY_NEWLINE);
        !           638:       if (rtadv->AdvManagedFlag)
        !           639:        vty_out (vty, "  Hosts use DHCP to obtain routable addresses.%s",
        !           640:                 VTY_NEWLINE);
        !           641:       else
        !           642:        vty_out (vty, "  Hosts use stateless autoconfig for addresses.%s",
        !           643:                 VTY_NEWLINE);
        !           644:       if (rtadv->AdvHomeAgentFlag)
        !           645:        vty_out (vty, "  ND router advertisements with "
        !           646:                                "Home Agent flag bit set.%s",
        !           647:                 VTY_NEWLINE);
        !           648:       if (rtadv->AdvIntervalOption)
        !           649:        vty_out (vty, "  ND router advertisements with Adv. Interval option.%s",
        !           650:                 VTY_NEWLINE);
        !           651:     }
        !           652: }
        !           653: #endif /* RTADV */
        !           654: 
        !           655: /* Interface's information print out to vty interface. */
        !           656: static void
        !           657: if_dump_vty (struct vty *vty, struct interface *ifp)
        !           658: {
        !           659: #ifdef HAVE_STRUCT_SOCKADDR_DL
        !           660:   struct sockaddr_dl *sdl;
        !           661: #endif /* HAVE_STRUCT_SOCKADDR_DL */
        !           662:   struct connected *connected;
        !           663:   struct listnode *node;
        !           664:   struct route_node *rn;
        !           665:   struct zebra_if *zebra_if;
        !           666: 
        !           667:   zebra_if = ifp->info;
        !           668: 
        !           669:   vty_out (vty, "Interface %s is ", ifp->name);
        !           670:   if (if_is_up(ifp)) {
        !           671:     vty_out (vty, "up, line protocol ");
        !           672:     
        !           673:     if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
        !           674:       if (if_is_running(ifp))
        !           675:        vty_out (vty, "is up%s", VTY_NEWLINE);
        !           676:       else
        !           677:        vty_out (vty, "is down%s", VTY_NEWLINE);
        !           678:     } else {
        !           679:       vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
        !           680:     }
        !           681:   } else {
        !           682:     vty_out (vty, "down%s", VTY_NEWLINE);
        !           683:   }
        !           684: 
        !           685:   if (ifp->desc)
        !           686:     vty_out (vty, "  Description: %s%s", ifp->desc,
        !           687:             VTY_NEWLINE);
        !           688:   if (ifp->ifindex == IFINDEX_INTERNAL)
        !           689:     {
        !           690:       vty_out(vty, "  pseudo interface%s", VTY_NEWLINE);
        !           691:       return;
        !           692:     }
        !           693:   else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !           694:     {
        !           695:       vty_out(vty, "  index %d inactive interface%s", 
        !           696:              ifp->ifindex, 
        !           697:              VTY_NEWLINE);
        !           698:       return;
        !           699:     }
        !           700: 
        !           701:   vty_out (vty, "  index %d metric %d mtu %d ",
        !           702:           ifp->ifindex, ifp->metric, ifp->mtu);
        !           703: #ifdef HAVE_IPV6
        !           704:   if (ifp->mtu6 != ifp->mtu)
        !           705:     vty_out (vty, "mtu6 %d ", ifp->mtu6);
        !           706: #endif 
        !           707:   vty_out (vty, "%s  flags: %s%s", VTY_NEWLINE,
        !           708:            if_flag_dump (ifp->flags), VTY_NEWLINE);
        !           709:   
        !           710:   /* Hardware address. */
        !           711: #ifdef HAVE_STRUCT_SOCKADDR_DL
        !           712:   sdl = &ifp->sdl;
        !           713:   if (sdl != NULL && sdl->sdl_alen != 0)
        !           714:     {
        !           715:       int i;
        !           716:       u_char *ptr;
        !           717: 
        !           718:       vty_out (vty, "  HWaddr: ");
        !           719:       for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++)
        !           720:         vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr);
        !           721:       vty_out (vty, "%s", VTY_NEWLINE);
        !           722:     }
        !           723: #else
        !           724:   if (ifp->hw_addr_len != 0)
        !           725:     {
        !           726:       int i;
        !           727: 
        !           728:       vty_out (vty, "  HWaddr: ");
        !           729:       for (i = 0; i < ifp->hw_addr_len; i++)
        !           730:        vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]);
        !           731:       vty_out (vty, "%s", VTY_NEWLINE);
        !           732:     }
        !           733: #endif /* HAVE_STRUCT_SOCKADDR_DL */
        !           734:   
        !           735:   /* Bandwidth in kbps */
        !           736:   if (ifp->bandwidth != 0)
        !           737:     {
        !           738:       vty_out(vty, "  bandwidth %u kbps", ifp->bandwidth);
        !           739:       vty_out(vty, "%s", VTY_NEWLINE);
        !           740:     }
        !           741: 
        !           742:   for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn))
        !           743:     {
        !           744:       if (! rn->info)
        !           745:        continue;
        !           746:       
        !           747:       for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected))
        !           748:         connected_dump_vty (vty, connected);
        !           749:     }
        !           750: 
        !           751:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
        !           752:     {
        !           753:       if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
        !           754:          (connected->address->family == AF_INET6))
        !           755:        connected_dump_vty (vty, connected);
        !           756:     }
        !           757: 
        !           758: #ifdef RTADV
        !           759:   nd_dump_vty (vty, ifp);
        !           760: #endif /* RTADV */
        !           761: 
        !           762: #ifdef HAVE_PROC_NET_DEV
        !           763:   /* Statistics print out using proc file system. */
        !           764:   vty_out (vty, "    %lu input packets (%lu multicast), %lu bytes, "
        !           765:           "%lu dropped%s",
        !           766:           ifp->stats.rx_packets, ifp->stats.rx_multicast,
        !           767:           ifp->stats.rx_bytes, ifp->stats.rx_dropped, VTY_NEWLINE);
        !           768: 
        !           769:   vty_out (vty, "    %lu input errors, %lu length, %lu overrun,"
        !           770:           " %lu CRC, %lu frame%s",
        !           771:           ifp->stats.rx_errors, ifp->stats.rx_length_errors,
        !           772:           ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
        !           773:           ifp->stats.rx_frame_errors, VTY_NEWLINE);
        !           774: 
        !           775:   vty_out (vty, "    %lu fifo, %lu missed%s", ifp->stats.rx_fifo_errors,
        !           776:           ifp->stats.rx_missed_errors, VTY_NEWLINE);
        !           777: 
        !           778:   vty_out (vty, "    %lu output packets, %lu bytes, %lu dropped%s",
        !           779:           ifp->stats.tx_packets, ifp->stats.tx_bytes,
        !           780:           ifp->stats.tx_dropped, VTY_NEWLINE);
        !           781: 
        !           782:   vty_out (vty, "    %lu output errors, %lu aborted, %lu carrier,"
        !           783:           " %lu fifo, %lu heartbeat%s",
        !           784:           ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
        !           785:           ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
        !           786:           ifp->stats.tx_heartbeat_errors, VTY_NEWLINE);
        !           787: 
        !           788:   vty_out (vty, "    %lu window, %lu collisions%s",
        !           789:           ifp->stats.tx_window_errors, ifp->stats.collisions, VTY_NEWLINE);
        !           790: #endif /* HAVE_PROC_NET_DEV */
        !           791: 
        !           792: #ifdef HAVE_NET_RT_IFLIST
        !           793: #if defined (__bsdi__) || defined (__NetBSD__)
        !           794:   /* Statistics print out using sysctl (). */
        !           795:   vty_out (vty, "    input packets %qu, bytes %qu, dropped %qu,"
        !           796:           " multicast packets %qu%s",
        !           797:           ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
        !           798:           ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
        !           799:           VTY_NEWLINE);
        !           800: 
        !           801:   vty_out (vty, "    input errors %qu%s",
        !           802:           ifp->stats.ifi_ierrors, VTY_NEWLINE);
        !           803: 
        !           804:   vty_out (vty, "    output packets %qu, bytes %qu, multicast packets %qu%s",
        !           805:           ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
        !           806:           ifp->stats.ifi_omcasts, VTY_NEWLINE);
        !           807: 
        !           808:   vty_out (vty, "    output errors %qu%s",
        !           809:           ifp->stats.ifi_oerrors, VTY_NEWLINE);
        !           810: 
        !           811:   vty_out (vty, "    collisions %qu%s",
        !           812:           ifp->stats.ifi_collisions, VTY_NEWLINE);
        !           813: #else
        !           814:   /* Statistics print out using sysctl (). */
        !           815:   vty_out (vty, "    input packets %lu, bytes %lu, dropped %lu,"
        !           816:           " multicast packets %lu%s",
        !           817:           ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
        !           818:           ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts,
        !           819:           VTY_NEWLINE);
        !           820: 
        !           821:   vty_out (vty, "    input errors %lu%s",
        !           822:           ifp->stats.ifi_ierrors, VTY_NEWLINE);
        !           823: 
        !           824:   vty_out (vty, "    output packets %lu, bytes %lu, multicast packets %lu%s",
        !           825:           ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
        !           826:           ifp->stats.ifi_omcasts, VTY_NEWLINE);
        !           827: 
        !           828:   vty_out (vty, "    output errors %lu%s",
        !           829:           ifp->stats.ifi_oerrors, VTY_NEWLINE);
        !           830: 
        !           831:   vty_out (vty, "    collisions %lu%s",
        !           832:           ifp->stats.ifi_collisions, VTY_NEWLINE);
        !           833: #endif /* __bsdi__ || __NetBSD__ */
        !           834: #endif /* HAVE_NET_RT_IFLIST */
        !           835: }
        !           836: 
        !           837: /* Wrapper hook point for zebra daemon so that ifindex can be set 
        !           838:  * DEFUN macro not used as extract.pl HAS to ignore this
        !           839:  * See also interface_cmd in lib/if.c
        !           840:  */ 
        !           841: DEFUN_NOSH (zebra_interface,
        !           842:            zebra_interface_cmd,
        !           843:            "interface IFNAME",
        !           844:            "Select an interface to configure\n"
        !           845:            "Interface's name\n")
        !           846: {
        !           847:   int ret;
        !           848:   struct interface * ifp;
        !           849:   
        !           850:   /* Call lib interface() */
        !           851:   if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
        !           852:     return ret;
        !           853: 
        !           854:   ifp = vty->index;  
        !           855: 
        !           856:   if (ifp->ifindex == IFINDEX_INTERNAL)
        !           857:     /* Is this really necessary?  Shouldn't status be initialized to 0
        !           858:        in that case? */
        !           859:     UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
        !           860: 
        !           861:   return ret;
        !           862: }
        !           863: 
        !           864: struct cmd_node interface_node =
        !           865: {
        !           866:   INTERFACE_NODE,
        !           867:   "%s(config-if)# ",
        !           868:   1
        !           869: };
        !           870: 
        !           871: /* Show all or specified interface to vty. */
        !           872: DEFUN (show_interface, show_interface_cmd,
        !           873:        "show interface [IFNAME]",  
        !           874:        SHOW_STR
        !           875:        "Interface status and configuration\n"
        !           876:        "Inteface name\n")
        !           877: {
        !           878:   struct listnode *node;
        !           879:   struct interface *ifp;
        !           880:   
        !           881: #ifdef HAVE_PROC_NET_DEV
        !           882:   /* If system has interface statistics via proc file system, update
        !           883:      statistics. */
        !           884:   ifstat_update_proc ();
        !           885: #endif /* HAVE_PROC_NET_DEV */
        !           886: #ifdef HAVE_NET_RT_IFLIST
        !           887:   ifstat_update_sysctl ();
        !           888: #endif /* HAVE_NET_RT_IFLIST */
        !           889: 
        !           890:   /* Specified interface print. */
        !           891:   if (argc != 0)
        !           892:     {
        !           893:       ifp = if_lookup_by_name (argv[0]);
        !           894:       if (ifp == NULL) 
        !           895:        {
        !           896:          vty_out (vty, "%% Can't find interface %s%s", argv[0],
        !           897:                   VTY_NEWLINE);
        !           898:          return CMD_WARNING;
        !           899:        }
        !           900:       if_dump_vty (vty, ifp);
        !           901:       return CMD_SUCCESS;
        !           902:     }
        !           903: 
        !           904:   /* All interface print. */
        !           905:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !           906:     if_dump_vty (vty, ifp);
        !           907: 
        !           908:   return CMD_SUCCESS;
        !           909: }
        !           910: 
        !           911: DEFUN (show_interface_desc,
        !           912:        show_interface_desc_cmd,
        !           913:        "show interface description",
        !           914:        SHOW_STR
        !           915:        "Interface status and configuration\n"
        !           916:        "Interface description\n")
        !           917: {
        !           918:   struct listnode *node;
        !           919:   struct interface *ifp;
        !           920: 
        !           921:   vty_out (vty, "Interface       Status  Protocol  Description%s", VTY_NEWLINE);
        !           922:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !           923:     {
        !           924:       int len;
        !           925: 
        !           926:       len = vty_out (vty, "%s", ifp->name);
        !           927:       vty_out (vty, "%*s", (16 - len), " ");
        !           928:       
        !           929:       if (if_is_up(ifp))
        !           930:        {
        !           931:          vty_out (vty, "up      ");
        !           932:          if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
        !           933:            {
        !           934:              if (if_is_running(ifp))
        !           935:                vty_out (vty, "up        ");
        !           936:              else
        !           937:                vty_out (vty, "down      ");
        !           938:            }
        !           939:          else
        !           940:            {
        !           941:              vty_out (vty, "unknown   ");
        !           942:            }
        !           943:        }
        !           944:       else
        !           945:        {
        !           946:          vty_out (vty, "down    down      ");
        !           947:        }
        !           948: 
        !           949:       if (ifp->desc)
        !           950:        vty_out (vty, "%s", ifp->desc);
        !           951:       vty_out (vty, "%s", VTY_NEWLINE);
        !           952:     }
        !           953:   return CMD_SUCCESS;
        !           954: }
        !           955: 
        !           956: DEFUN (multicast,
        !           957:        multicast_cmd,
        !           958:        "multicast",
        !           959:        "Set multicast flag to interface\n")
        !           960: {
        !           961:   int ret;
        !           962:   struct interface *ifp;
        !           963:   struct zebra_if *if_data;
        !           964: 
        !           965:   ifp = (struct interface *) vty->index;
        !           966:   if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !           967:     {
        !           968:       ret = if_set_flags (ifp, IFF_MULTICAST);
        !           969:       if (ret < 0)
        !           970:        {
        !           971:          vty_out (vty, "Can't set multicast flag%s", VTY_NEWLINE);
        !           972:          return CMD_WARNING;
        !           973:        }
        !           974:       if_refresh (ifp);
        !           975:     }
        !           976:   if_data = ifp->info;
        !           977:   if_data->multicast = IF_ZEBRA_MULTICAST_ON;
        !           978: 
        !           979:   return CMD_SUCCESS;
        !           980: }
        !           981: 
        !           982: DEFUN (no_multicast,
        !           983:        no_multicast_cmd,
        !           984:        "no multicast",
        !           985:        NO_STR
        !           986:        "Unset multicast flag to interface\n")
        !           987: {
        !           988:   int ret;
        !           989:   struct interface *ifp;
        !           990:   struct zebra_if *if_data;
        !           991: 
        !           992:   ifp = (struct interface *) vty->index;
        !           993:   if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !           994:     {
        !           995:       ret = if_unset_flags (ifp, IFF_MULTICAST);
        !           996:       if (ret < 0)
        !           997:        {
        !           998:          vty_out (vty, "Can't unset multicast flag%s", VTY_NEWLINE);
        !           999:          return CMD_WARNING;
        !          1000:        }
        !          1001:       if_refresh (ifp);
        !          1002:     }
        !          1003:   if_data = ifp->info;
        !          1004:   if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
        !          1005: 
        !          1006:   return CMD_SUCCESS;
        !          1007: }
        !          1008: 
        !          1009: DEFUN (linkdetect,
        !          1010:        linkdetect_cmd,
        !          1011:        "link-detect",
        !          1012:        "Enable link detection on interface\n")
        !          1013: {
        !          1014:   struct interface *ifp;
        !          1015:   int if_was_operative;
        !          1016:   
        !          1017:   ifp = (struct interface *) vty->index;
        !          1018:   if_was_operative = if_is_operative(ifp);
        !          1019:   SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
        !          1020: 
        !          1021:   /* When linkdetection is enabled, if might come down */
        !          1022:   if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
        !          1023: 
        !          1024:   /* FIXME: Will defer status change forwarding if interface
        !          1025:      does not come down! */
        !          1026: 
        !          1027:   return CMD_SUCCESS;
        !          1028: }
        !          1029: 
        !          1030: 
        !          1031: DEFUN (no_linkdetect,
        !          1032:        no_linkdetect_cmd,
        !          1033:        "no link-detect",
        !          1034:        NO_STR
        !          1035:        "Disable link detection on interface\n")
        !          1036: {
        !          1037:   struct interface *ifp;
        !          1038:   int if_was_operative;
        !          1039: 
        !          1040:   ifp = (struct interface *) vty->index;
        !          1041:   if_was_operative = if_is_operative(ifp);
        !          1042:   UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
        !          1043:   
        !          1044:   /* Interface may come up after disabling link detection */
        !          1045:   if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
        !          1046: 
        !          1047:   /* FIXME: see linkdetect_cmd */
        !          1048: 
        !          1049:   return CMD_SUCCESS;
        !          1050: }
        !          1051: 
        !          1052: DEFUN (shutdown_if,
        !          1053:        shutdown_if_cmd,
        !          1054:        "shutdown",
        !          1055:        "Shutdown the selected interface\n")
        !          1056: {
        !          1057:   int ret;
        !          1058:   struct interface *ifp;
        !          1059:   struct zebra_if *if_data;
        !          1060: 
        !          1061:   ifp = (struct interface *) vty->index;
        !          1062:   ret = if_unset_flags (ifp, IFF_UP);
        !          1063:   if (ret < 0)
        !          1064:     {
        !          1065:       vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE);
        !          1066:       return CMD_WARNING;
        !          1067:     }
        !          1068:   if_refresh (ifp);
        !          1069:   if_data = ifp->info;
        !          1070:   if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
        !          1071: 
        !          1072:   return CMD_SUCCESS;
        !          1073: }
        !          1074: 
        !          1075: DEFUN (no_shutdown_if,
        !          1076:        no_shutdown_if_cmd,
        !          1077:        "no shutdown",
        !          1078:        NO_STR
        !          1079:        "Shutdown the selected interface\n")
        !          1080: {
        !          1081:   int ret;
        !          1082:   struct interface *ifp;
        !          1083:   struct zebra_if *if_data;
        !          1084: 
        !          1085:   ifp = (struct interface *) vty->index;
        !          1086:   ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING);
        !          1087:   if (ret < 0)
        !          1088:     {
        !          1089:       vty_out (vty, "Can't up interface%s", VTY_NEWLINE);
        !          1090:       return CMD_WARNING;
        !          1091:     }
        !          1092:   if_refresh (ifp);
        !          1093:   if_data = ifp->info;
        !          1094:   if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
        !          1095: 
        !          1096:   return CMD_SUCCESS;
        !          1097: }
        !          1098: 
        !          1099: DEFUN (bandwidth_if,
        !          1100:        bandwidth_if_cmd,
        !          1101:        "bandwidth <1-10000000>",
        !          1102:        "Set bandwidth informational parameter\n"
        !          1103:        "Bandwidth in kilobits\n")
        !          1104: {
        !          1105:   struct interface *ifp;   
        !          1106:   unsigned int bandwidth;
        !          1107:   
        !          1108:   ifp = (struct interface *) vty->index;
        !          1109:   bandwidth = strtol(argv[0], NULL, 10);
        !          1110: 
        !          1111:   /* bandwidth range is <1-10000000> */
        !          1112:   if (bandwidth < 1 || bandwidth > 10000000)
        !          1113:     {
        !          1114:       vty_out (vty, "Bandwidth is invalid%s", VTY_NEWLINE);
        !          1115:       return CMD_WARNING;
        !          1116:     }
        !          1117:   
        !          1118:   ifp->bandwidth = bandwidth;
        !          1119: 
        !          1120:   /* force protocols to recalculate routes due to cost change */
        !          1121:   if (if_is_operative (ifp))
        !          1122:     zebra_interface_up_update (ifp);
        !          1123:   
        !          1124:   return CMD_SUCCESS;
        !          1125: }
        !          1126: 
        !          1127: DEFUN (no_bandwidth_if,
        !          1128:        no_bandwidth_if_cmd,
        !          1129:        "no bandwidth",
        !          1130:        NO_STR
        !          1131:        "Set bandwidth informational parameter\n")
        !          1132: {
        !          1133:   struct interface *ifp;   
        !          1134:   
        !          1135:   ifp = (struct interface *) vty->index;
        !          1136: 
        !          1137:   ifp->bandwidth = 0;
        !          1138:   
        !          1139:   /* force protocols to recalculate routes due to cost change */
        !          1140:   if (if_is_operative (ifp))
        !          1141:     zebra_interface_up_update (ifp);
        !          1142: 
        !          1143:   return CMD_SUCCESS;
        !          1144: }
        !          1145: 
        !          1146: ALIAS (no_bandwidth_if,
        !          1147:        no_bandwidth_if_val_cmd,
        !          1148:        "no bandwidth <1-10000000>",
        !          1149:        NO_STR
        !          1150:        "Set bandwidth informational parameter\n"
        !          1151:        "Bandwidth in kilobits\n")
        !          1152: 
        !          1153: static int
        !          1154: ip_address_install (struct vty *vty, struct interface *ifp,
        !          1155:                    const char *addr_str, const char *peer_str,
        !          1156:                    const char *label)
        !          1157: {
        !          1158:   struct prefix_ipv4 cp;
        !          1159:   struct connected *ifc;
        !          1160:   struct prefix_ipv4 *p;
        !          1161:   int ret;
        !          1162: 
        !          1163:   ret = str2prefix_ipv4 (addr_str, &cp);
        !          1164:   if (ret <= 0)
        !          1165:     {
        !          1166:       vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
        !          1167:       return CMD_WARNING;
        !          1168:     }
        !          1169: 
        !          1170:   ifc = connected_check (ifp, (struct prefix *) &cp);
        !          1171:   if (! ifc)
        !          1172:     {
        !          1173:       ifc = connected_new ();
        !          1174:       ifc->ifp = ifp;
        !          1175: 
        !          1176:       /* Address. */
        !          1177:       p = prefix_ipv4_new ();
        !          1178:       *p = cp;
        !          1179:       ifc->address = (struct prefix *) p;
        !          1180: 
        !          1181:       /* Broadcast. */
        !          1182:       if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
        !          1183:        {
        !          1184:          p = prefix_ipv4_new ();
        !          1185:          *p = cp;
        !          1186:          p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
        !          1187:          ifc->destination = (struct prefix *) p;
        !          1188:        }
        !          1189: 
        !          1190:       /* Label. */
        !          1191:       if (label)
        !          1192:        ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
        !          1193: 
        !          1194:       /* Add to linked list. */
        !          1195:       listnode_add (ifp->connected, ifc);
        !          1196:     }
        !          1197: 
        !          1198:   /* This address is configured from zebra. */
        !          1199:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !          1200:     SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
        !          1201: 
        !          1202:   /* In case of this route need to install kernel. */
        !          1203:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
        !          1204:       && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !          1205:     {
        !          1206:       /* Some system need to up the interface to set IP address. */
        !          1207:       if (! if_is_up (ifp))
        !          1208:        {
        !          1209:          if_set_flags (ifp, IFF_UP | IFF_RUNNING);
        !          1210:          if_refresh (ifp);
        !          1211:        }
        !          1212: 
        !          1213:       ret = if_set_prefix (ifp, ifc);
        !          1214:       if (ret < 0)
        !          1215:        {
        !          1216:          vty_out (vty, "%% Can't set interface IP address: %s.%s", 
        !          1217:                   safe_strerror(errno), VTY_NEWLINE);
        !          1218:          return CMD_WARNING;
        !          1219:        }
        !          1220: 
        !          1221:       /* Add to subnet chain list (while marking secondary attribute). */
        !          1222:       if_subnet_add (ifp, ifc);
        !          1223: 
        !          1224:       /* IP address propery set. */
        !          1225:       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !          1226: 
        !          1227:       /* Update interface address information to protocol daemon. */
        !          1228:       zebra_interface_address_add_update (ifp, ifc);
        !          1229: 
        !          1230:       /* If interface is up register connected route. */
        !          1231:       if (if_is_operative(ifp))
        !          1232:        connected_up_ipv4 (ifp, ifc);
        !          1233:     }
        !          1234: 
        !          1235:   return CMD_SUCCESS;
        !          1236: }
        !          1237: 
        !          1238: static int
        !          1239: ip_address_uninstall (struct vty *vty, struct interface *ifp,
        !          1240:                      const char *addr_str, const char *peer_str,
        !          1241:                      const char *label)
        !          1242: {
        !          1243:   struct prefix_ipv4 cp;
        !          1244:   struct connected *ifc;
        !          1245:   int ret;
        !          1246: 
        !          1247:   /* Convert to prefix structure. */
        !          1248:   ret = str2prefix_ipv4 (addr_str, &cp);
        !          1249:   if (ret <= 0)
        !          1250:     {
        !          1251:       vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
        !          1252:       return CMD_WARNING;
        !          1253:     }
        !          1254: 
        !          1255:   /* Check current interface address. */
        !          1256:   ifc = connected_check (ifp, (struct prefix *) &cp);
        !          1257:   if (! ifc)
        !          1258:     {
        !          1259:       vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
        !          1260:       return CMD_WARNING;
        !          1261:     }
        !          1262: 
        !          1263:   /* This is not configured address. */
        !          1264:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !          1265:     return CMD_WARNING;
        !          1266: 
        !          1267:   UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
        !          1268:   
        !          1269:   /* This is not real address or interface is not active. */
        !          1270:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
        !          1271:       || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !          1272:     {
        !          1273:       listnode_delete (ifp->connected, ifc);
        !          1274:       connected_free (ifc);
        !          1275:       return CMD_WARNING;
        !          1276:     }
        !          1277: 
        !          1278:   /* This is real route. */
        !          1279:   ret = if_unset_prefix (ifp, ifc);
        !          1280:   if (ret < 0)
        !          1281:     {
        !          1282:       vty_out (vty, "%% Can't unset interface IP address: %s.%s", 
        !          1283:               safe_strerror(errno), VTY_NEWLINE);
        !          1284:       return CMD_WARNING;
        !          1285:     }
        !          1286: 
        !          1287: #if 0
        !          1288:   /* Redistribute this information. */
        !          1289:   zebra_interface_address_delete_update (ifp, ifc);
        !          1290: 
        !          1291:   /* Remove connected route. */
        !          1292:   connected_down_ipv4 (ifp, ifc);
        !          1293: 
        !          1294:   /* Free address information. */
        !          1295:   listnode_delete (ifp->connected, ifc);
        !          1296:   connected_free (ifc);
        !          1297: #endif
        !          1298: 
        !          1299:   return CMD_SUCCESS;
        !          1300: }
        !          1301: 
        !          1302: DEFUN (ip_address,
        !          1303:        ip_address_cmd,
        !          1304:        "ip address A.B.C.D/M",
        !          1305:        "Interface Internet Protocol config commands\n"
        !          1306:        "Set the IP address of an interface\n"
        !          1307:        "IP address (e.g. 10.0.0.1/8)\n")
        !          1308: {
        !          1309:   return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
        !          1310: }
        !          1311: 
        !          1312: DEFUN (no_ip_address,
        !          1313:        no_ip_address_cmd,
        !          1314:        "no ip address A.B.C.D/M",
        !          1315:        NO_STR
        !          1316:        "Interface Internet Protocol config commands\n"
        !          1317:        "Set the IP address of an interface\n"
        !          1318:        "IP Address (e.g. 10.0.0.1/8)")
        !          1319: {
        !          1320:   return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
        !          1321: }
        !          1322: 
        !          1323: #ifdef HAVE_NETLINK
        !          1324: DEFUN (ip_address_label,
        !          1325:        ip_address_label_cmd,
        !          1326:        "ip address A.B.C.D/M label LINE",
        !          1327:        "Interface Internet Protocol config commands\n"
        !          1328:        "Set the IP address of an interface\n"
        !          1329:        "IP address (e.g. 10.0.0.1/8)\n"
        !          1330:        "Label of this address\n"
        !          1331:        "Label\n")
        !          1332: {
        !          1333:   return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
        !          1334: }
        !          1335: 
        !          1336: DEFUN (no_ip_address_label,
        !          1337:        no_ip_address_label_cmd,
        !          1338:        "no ip address A.B.C.D/M label LINE",
        !          1339:        NO_STR
        !          1340:        "Interface Internet Protocol config commands\n"
        !          1341:        "Set the IP address of an interface\n"
        !          1342:        "IP address (e.g. 10.0.0.1/8)\n"
        !          1343:        "Label of this address\n"
        !          1344:        "Label\n")
        !          1345: {
        !          1346:   return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
        !          1347: }
        !          1348: #endif /* HAVE_NETLINK */
        !          1349: 
        !          1350: #ifdef HAVE_IPV6
        !          1351: static int
        !          1352: ipv6_address_install (struct vty *vty, struct interface *ifp,
        !          1353:                      const char *addr_str, const char *peer_str,
        !          1354:                      const char *label, int secondary)
        !          1355: {
        !          1356:   struct prefix_ipv6 cp;
        !          1357:   struct connected *ifc;
        !          1358:   struct prefix_ipv6 *p;
        !          1359:   int ret;
        !          1360: 
        !          1361:   ret = str2prefix_ipv6 (addr_str, &cp);
        !          1362:   if (ret <= 0)
        !          1363:     {
        !          1364:       vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
        !          1365:       return CMD_WARNING;
        !          1366:     }
        !          1367: 
        !          1368:   ifc = connected_check (ifp, (struct prefix *) &cp);
        !          1369:   if (! ifc)
        !          1370:     {
        !          1371:       ifc = connected_new ();
        !          1372:       ifc->ifp = ifp;
        !          1373: 
        !          1374:       /* Address. */
        !          1375:       p = prefix_ipv6_new ();
        !          1376:       *p = cp;
        !          1377:       ifc->address = (struct prefix *) p;
        !          1378: 
        !          1379:       /* Secondary. */
        !          1380:       if (secondary)
        !          1381:        SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY);
        !          1382: 
        !          1383:       /* Label. */
        !          1384:       if (label)
        !          1385:        ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
        !          1386: 
        !          1387:       /* Add to linked list. */
        !          1388:       listnode_add (ifp->connected, ifc);
        !          1389:     }
        !          1390: 
        !          1391:   /* This address is configured from zebra. */
        !          1392:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !          1393:     SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED);
        !          1394: 
        !          1395:   /* In case of this route need to install kernel. */
        !          1396:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
        !          1397:       && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !          1398:     {
        !          1399:       /* Some system need to up the interface to set IP address. */
        !          1400:       if (! if_is_up (ifp))
        !          1401:        {
        !          1402:          if_set_flags (ifp, IFF_UP | IFF_RUNNING);
        !          1403:          if_refresh (ifp);
        !          1404:        }
        !          1405: 
        !          1406:       ret = if_prefix_add_ipv6 (ifp, ifc);
        !          1407: 
        !          1408:       if (ret < 0)
        !          1409:        {
        !          1410:          vty_out (vty, "%% Can't set interface IP address: %s.%s", 
        !          1411:                   safe_strerror(errno), VTY_NEWLINE);
        !          1412:          return CMD_WARNING;
        !          1413:        }
        !          1414: 
        !          1415:       /* IP address propery set. */
        !          1416:       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
        !          1417: 
        !          1418:       /* Update interface address information to protocol daemon. */
        !          1419:       zebra_interface_address_add_update (ifp, ifc);
        !          1420: 
        !          1421:       /* If interface is up register connected route. */
        !          1422:       if (if_is_operative(ifp))
        !          1423:        connected_up_ipv6 (ifp, ifc);
        !          1424:     }
        !          1425: 
        !          1426:   return CMD_SUCCESS;
        !          1427: }
        !          1428: 
        !          1429: static int
        !          1430: ipv6_address_uninstall (struct vty *vty, struct interface *ifp,
        !          1431:                        const char *addr_str, const char *peer_str,
        !          1432:                        const char *label, int secondry)
        !          1433: {
        !          1434:   struct prefix_ipv6 cp;
        !          1435:   struct connected *ifc;
        !          1436:   int ret;
        !          1437: 
        !          1438:   /* Convert to prefix structure. */
        !          1439:   ret = str2prefix_ipv6 (addr_str, &cp);
        !          1440:   if (ret <= 0)
        !          1441:     {
        !          1442:       vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
        !          1443:       return CMD_WARNING;
        !          1444:     }
        !          1445: 
        !          1446:   /* Check current interface address. */
        !          1447:   ifc = connected_check (ifp, (struct prefix *) &cp);
        !          1448:   if (! ifc)
        !          1449:     {
        !          1450:       vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
        !          1451:       return CMD_WARNING;
        !          1452:     }
        !          1453: 
        !          1454:   /* This is not configured address. */
        !          1455:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !          1456:     return CMD_WARNING;
        !          1457: 
        !          1458:   /* This is not real address or interface is not active. */
        !          1459:   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)
        !          1460:       || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        !          1461:     {
        !          1462:       listnode_delete (ifp->connected, ifc);
        !          1463:       connected_free (ifc);
        !          1464:       return CMD_WARNING;
        !          1465:     }
        !          1466: 
        !          1467:   /* This is real route. */
        !          1468:   ret = if_prefix_delete_ipv6 (ifp, ifc);
        !          1469:   if (ret < 0)
        !          1470:     {
        !          1471:       vty_out (vty, "%% Can't unset interface IP address: %s.%s", 
        !          1472:               safe_strerror(errno), VTY_NEWLINE);
        !          1473:       return CMD_WARNING;
        !          1474:     }
        !          1475: 
        !          1476:   /* Redistribute this information. */
        !          1477:   zebra_interface_address_delete_update (ifp, ifc);
        !          1478: 
        !          1479:   /* Remove connected route. */
        !          1480:   connected_down_ipv6 (ifp, ifc);
        !          1481: 
        !          1482:   /* Free address information. */
        !          1483:   listnode_delete (ifp->connected, ifc);
        !          1484:   connected_free (ifc);
        !          1485: 
        !          1486:   return CMD_SUCCESS;
        !          1487: }
        !          1488: 
        !          1489: DEFUN (ipv6_address,
        !          1490:        ipv6_address_cmd,
        !          1491:        "ipv6 address X:X::X:X/M",
        !          1492:        "Interface IPv6 config commands\n"
        !          1493:        "Set the IP address of an interface\n"
        !          1494:        "IPv6 address (e.g. 3ffe:506::1/48)\n")
        !          1495: {
        !          1496:   return ipv6_address_install (vty, vty->index, argv[0], NULL, NULL, 0);
        !          1497: }
        !          1498: 
        !          1499: DEFUN (no_ipv6_address,
        !          1500:        no_ipv6_address_cmd,
        !          1501:        "no ipv6 address X:X::X:X/M",
        !          1502:        NO_STR
        !          1503:        "Interface IPv6 config commands\n"
        !          1504:        "Set the IP address of an interface\n"
        !          1505:        "IPv6 address (e.g. 3ffe:506::1/48)\n")
        !          1506: {
        !          1507:   return ipv6_address_uninstall (vty, vty->index, argv[0], NULL, NULL, 0);
        !          1508: }
        !          1509: #endif /* HAVE_IPV6 */
        !          1510: 
        !          1511: static int
        !          1512: if_config_write (struct vty *vty)
        !          1513: {
        !          1514:   struct listnode *node;
        !          1515:   struct interface *ifp;
        !          1516: 
        !          1517:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !          1518:     {
        !          1519:       struct zebra_if *if_data;
        !          1520:       struct listnode *addrnode;
        !          1521:       struct connected *ifc;
        !          1522:       struct prefix *p;
        !          1523: 
        !          1524:       if_data = ifp->info;
        !          1525:       
        !          1526:       vty_out (vty, "interface %s%s", ifp->name,
        !          1527:               VTY_NEWLINE);
        !          1528: 
        !          1529:       if (ifp->desc)
        !          1530:        vty_out (vty, " description %s%s", ifp->desc,
        !          1531:                 VTY_NEWLINE);
        !          1532: 
        !          1533:       /* Assign bandwidth here to avoid unnecessary interface flap
        !          1534:         while processing config script */
        !          1535:       if (ifp->bandwidth != 0)
        !          1536:        vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE); 
        !          1537: 
        !          1538:       if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
        !          1539:        vty_out(vty, " link-detect%s", VTY_NEWLINE);
        !          1540: 
        !          1541:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc))
        !          1542:          {
        !          1543:            if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
        !          1544:              {
        !          1545:                char buf[INET6_ADDRSTRLEN];
        !          1546:                p = ifc->address;
        !          1547:                vty_out (vty, " ip%s address %s/%d",
        !          1548:                         p->family == AF_INET ? "" : "v6",
        !          1549:                         inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)),
        !          1550:                         p->prefixlen);
        !          1551: 
        !          1552:                if (ifc->label)
        !          1553:                  vty_out (vty, " label %s", ifc->label);
        !          1554: 
        !          1555:                vty_out (vty, "%s", VTY_NEWLINE);
        !          1556:              }
        !          1557:          }
        !          1558: 
        !          1559:       if (if_data)
        !          1560:        {
        !          1561:          if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
        !          1562:            vty_out (vty, " shutdown%s", VTY_NEWLINE);
        !          1563: 
        !          1564:          if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC)
        !          1565:            vty_out (vty, " %smulticast%s",
        !          1566:                     if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ",
        !          1567:                     VTY_NEWLINE);
        !          1568:        }
        !          1569: 
        !          1570: #ifdef RTADV
        !          1571:       rtadv_config_write (vty, ifp);
        !          1572: #endif /* RTADV */
        !          1573: 
        !          1574: #ifdef HAVE_IRDP
        !          1575:       irdp_config_write (vty, ifp);
        !          1576: #endif /* IRDP */
        !          1577: 
        !          1578:       vty_out (vty, "!%s", VTY_NEWLINE);
        !          1579:     }
        !          1580:   return 0;
        !          1581: }
        !          1582: 
        !          1583: /* Allocate and initialize interface vector. */
        !          1584: void
        !          1585: zebra_if_init (void)
        !          1586: {
        !          1587:   /* Initialize interface and new hook. */
        !          1588:   if_init ();
        !          1589:   if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
        !          1590:   if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
        !          1591:   
        !          1592:   /* Install configuration write function. */
        !          1593:   install_node (&interface_node, if_config_write);
        !          1594: 
        !          1595:   install_element (VIEW_NODE, &show_interface_cmd);
        !          1596:   install_element (ENABLE_NODE, &show_interface_cmd);
        !          1597:   install_element (ENABLE_NODE, &show_interface_desc_cmd);
        !          1598:   install_element (CONFIG_NODE, &zebra_interface_cmd);
        !          1599:   install_element (CONFIG_NODE, &no_interface_cmd);
        !          1600:   install_default (INTERFACE_NODE);
        !          1601:   install_element (INTERFACE_NODE, &interface_desc_cmd);
        !          1602:   install_element (INTERFACE_NODE, &no_interface_desc_cmd);
        !          1603:   install_element (INTERFACE_NODE, &multicast_cmd);
        !          1604:   install_element (INTERFACE_NODE, &no_multicast_cmd);
        !          1605:   install_element (INTERFACE_NODE, &linkdetect_cmd);
        !          1606:   install_element (INTERFACE_NODE, &no_linkdetect_cmd);
        !          1607:   install_element (INTERFACE_NODE, &shutdown_if_cmd);
        !          1608:   install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
        !          1609:   install_element (INTERFACE_NODE, &bandwidth_if_cmd);
        !          1610:   install_element (INTERFACE_NODE, &no_bandwidth_if_cmd);
        !          1611:   install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
        !          1612:   install_element (INTERFACE_NODE, &ip_address_cmd);
        !          1613:   install_element (INTERFACE_NODE, &no_ip_address_cmd);
        !          1614: #ifdef HAVE_IPV6
        !          1615:   install_element (INTERFACE_NODE, &ipv6_address_cmd);
        !          1616:   install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
        !          1617: #endif /* HAVE_IPV6 */
        !          1618: #ifdef HAVE_NETLINK
        !          1619:   install_element (INTERFACE_NODE, &ip_address_label_cmd);
        !          1620:   install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
        !          1621: #endif /* HAVE_NETLINK */
        !          1622: }

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