Annotation of embedaddon/quagga/lib/if.c, revision 1.1.1.3

1.1       misho       1: 
                      2: /* 
                      3:  * Interface functions.
                      4:  * Copyright (C) 1997, 98 Kunihiro Ishiguro
                      5:  *
                      6:  * This file is part of GNU Zebra.
                      7:  * 
                      8:  * GNU Zebra is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published
                     10:  * by the Free Software Foundation; either version 2, or (at your
                     11:  * option) any later version.
                     12:  *
                     13:  * GNU Zebra is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     16:  * General Public License for more details.
                     17:  *
                     18:  * You should have received a copy of the GNU General Public License
                     19:  * along with GNU Zebra; see the file COPYING.  If not, write to the
                     20:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
                     21:  * Boston, MA 02111-1307, USA.
                     22:  */
                     23: 
                     24: #include <zebra.h>
                     25: 
                     26: #include "linklist.h"
                     27: #include "vector.h"
                     28: #include "vty.h"
                     29: #include "command.h"
1.1.1.3 ! misho      30: #include "vrf.h"
1.1       misho      31: #include "if.h"
                     32: #include "sockunion.h"
                     33: #include "prefix.h"
                     34: #include "memory.h"
                     35: #include "table.h"
                     36: #include "buffer.h"
                     37: #include "str.h"
                     38: #include "log.h"
1.1.1.3 ! misho      39: 
        !            40: /* List of interfaces in only the default VRF */
1.1       misho      41: struct list *iflist;
                     42: 
                     43: /* One for each program.  This structure is needed to store hooks. */
                     44: struct if_master
                     45: {
                     46:   int (*if_new_hook) (struct interface *);
                     47:   int (*if_delete_hook) (struct interface *);
1.1.1.3 ! misho      48: } if_master = {0,};
        !            49: 
1.1       misho      50: /* Compare interface names, returning an integer greater than, equal to, or
                     51:  * less than 0, (following the strcmp convention), according to the
                     52:  * relationship between ifp1 and ifp2.  Interface names consist of an
                     53:  * alphabetic prefix and a numeric suffix.  The primary sort key is
                     54:  * lexicographic by name, and then numeric by number.  No number sorts
                     55:  * before all numbers.  Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
                     56:  * devpty0, de0 < del0
                     57:  */         
                     58: int
                     59: if_cmp_func (struct interface *ifp1, struct interface *ifp2)
                     60: {
                     61:   unsigned int l1, l2;
                     62:   long int x1, x2;
                     63:   char *p1, *p2;
                     64:   int res;
                     65: 
                     66:   p1 = ifp1->name;
                     67:   p2 = ifp2->name;
                     68: 
                     69:   while (*p1 && *p2) {
                     70:     /* look up to any number */
                     71:     l1 = strcspn(p1, "0123456789");
                     72:     l2 = strcspn(p2, "0123456789");
                     73: 
                     74:     /* name lengths are different -> compare names */
                     75:     if (l1 != l2)
                     76:       return (strcmp(p1, p2));
                     77: 
                     78:     /* Note that this relies on all numbers being less than all letters, so
                     79:      * that de0 < del0.
                     80:      */
                     81:     res = strncmp(p1, p2, l1);
                     82: 
                     83:     /* names are different -> compare them */
                     84:     if (res)
                     85:       return res;
                     86: 
                     87:     /* with identical name part, go to numeric part */
                     88:     p1 += l1;
                     89:     p2 += l1;
                     90: 
                     91:     if (!*p1) 
                     92:       return -1;
                     93:     if (!*p2) 
                     94:       return 1;
                     95: 
                     96:     x1 = strtol(p1, &p1, 10);
                     97:     x2 = strtol(p2, &p2, 10);
                     98: 
                     99:     /* let's compare numbers now */
                    100:     if (x1 < x2)
                    101:       return -1;
                    102:     if (x1 > x2)
                    103:       return 1;
                    104: 
                    105:     /* numbers were equal, lets do it again..
                    106:     (it happens with name like "eth123.456:789") */
                    107:   }
                    108:   if (*p1)
                    109:     return 1;
                    110:   if (*p2)
                    111:     return -1;
                    112:   return 0;
                    113: }
                    114: 
                    115: /* Create new interface structure. */
                    116: struct interface *
1.1.1.3 ! misho     117: if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
1.1       misho     118: {
                    119:   struct interface *ifp;
1.1.1.3 ! misho     120:   struct list *intf_list = vrf_iflist_get (vrf_id);
1.1       misho     121: 
                    122:   ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
                    123:   ifp->ifindex = IFINDEX_INTERNAL;
                    124:   
                    125:   assert (name);
                    126:   assert (namelen <= INTERFACE_NAMSIZ);        /* Need space for '\0' at end. */
                    127:   strncpy (ifp->name, name, namelen);
                    128:   ifp->name[namelen] = '\0';
1.1.1.3 ! misho     129:   ifp->vrf_id = vrf_id;
        !           130:   if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
        !           131:     listnode_add_sort (intf_list, ifp);
1.1       misho     132:   else
                    133:     zlog_err("if_create(%s): corruption detected -- interface with this "
1.1.1.3 ! misho     134:              "name exists already in VRF %u!", ifp->name, vrf_id);
1.1       misho     135:   ifp->connected = list_new ();
                    136:   ifp->connected->del = (void (*) (void *)) connected_free;
                    137: 
                    138:   if (if_master.if_new_hook)
                    139:     (*if_master.if_new_hook) (ifp);
                    140: 
                    141:   return ifp;
                    142: }
                    143: 
1.1.1.3 ! misho     144: struct interface *
        !           145: if_create (const char *name, int namelen)
        !           146: {
        !           147:   return if_create_vrf (name, namelen, VRF_DEFAULT);
        !           148: }
        !           149: 
1.1       misho     150: /* Delete interface structure. */
                    151: void
                    152: if_delete_retain (struct interface *ifp)
                    153: {
                    154:   if (if_master.if_delete_hook)
                    155:     (*if_master.if_delete_hook) (ifp);
                    156: 
                    157:   /* Free connected address list */
1.1.1.2   misho     158:   list_delete_all_node (ifp->connected);
1.1       misho     159: }
                    160: 
                    161: /* Delete and free interface structure. */
                    162: void
                    163: if_delete (struct interface *ifp)
                    164: {
1.1.1.3 ! misho     165:   listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
1.1       misho     166: 
                    167:   if_delete_retain(ifp);
                    168: 
1.1.1.2   misho     169:   list_free (ifp->connected);
                    170: 
1.1       misho     171:   XFREE (MTYPE_IF, ifp);
                    172: }
                    173: 
                    174: /* Add hook to interface master. */
                    175: void
                    176: if_add_hook (int type, int (*func)(struct interface *ifp))
                    177: {
                    178:   switch (type) {
                    179:   case IF_NEW_HOOK:
                    180:     if_master.if_new_hook = func;
                    181:     break;
                    182:   case IF_DELETE_HOOK:
                    183:     if_master.if_delete_hook = func;
                    184:     break;
                    185:   default:
                    186:     break;
                    187:   }
                    188: }
                    189: 
                    190: /* Interface existance check by index. */
                    191: struct interface *
1.1.1.3 ! misho     192: if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
1.1       misho     193: {
                    194:   struct listnode *node;
                    195:   struct interface *ifp;
                    196: 
1.1.1.3 ! misho     197:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     198:     {
1.1.1.3 ! misho     199:       if (ifp->ifindex == ifindex)
1.1       misho     200:        return ifp;
                    201:     }
                    202:   return NULL;
                    203: }
                    204: 
1.1.1.3 ! misho     205: struct interface *
        !           206: if_lookup_by_index (ifindex_t ifindex)
        !           207: {
        !           208:   return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT);
        !           209: }
        !           210: 
1.1       misho     211: const char *
1.1.1.3 ! misho     212: ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
1.1       misho     213: {
                    214:   struct interface *ifp;
                    215: 
1.1.1.3 ! misho     216:   return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ?
1.1       misho     217:         ifp->name : "unknown";
                    218: }
                    219: 
1.1.1.3 ! misho     220: const char *
        !           221: ifindex2ifname (ifindex_t ifindex)
        !           222: {
        !           223:   return ifindex2ifname_vrf (ifindex, VRF_DEFAULT);
        !           224: }
        !           225: 
        !           226: ifindex_t
        !           227: ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
1.1       misho     228: {
                    229:   struct interface *ifp;
                    230: 
1.1.1.3 ! misho     231:   return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
1.1       misho     232:                                                    : IFINDEX_INTERNAL;
                    233: }
                    234: 
1.1.1.3 ! misho     235: ifindex_t
        !           236: ifname2ifindex (const char *name)
        !           237: {
        !           238:   return ifname2ifindex_vrf (name, VRF_DEFAULT);
        !           239: }
        !           240: 
1.1       misho     241: /* Interface existance check by interface name. */
                    242: struct interface *
1.1.1.3 ! misho     243: if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
1.1       misho     244: {
                    245:   struct listnode *node;
                    246:   struct interface *ifp;
                    247:   
                    248:   if (name)
1.1.1.3 ! misho     249:     for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     250:       {
                    251:         if (strcmp(name, ifp->name) == 0)
                    252:           return ifp;
                    253:       }
                    254:   return NULL;
                    255: }
                    256: 
                    257: struct interface *
1.1.1.3 ! misho     258: if_lookup_by_name (const char *name)
        !           259: {
        !           260:   return if_lookup_by_name_vrf (name, VRF_DEFAULT);
        !           261: }
        !           262: 
        !           263: struct interface *
        !           264: if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
1.1       misho     265: {
                    266:   struct listnode *node;
                    267:   struct interface *ifp;
                    268: 
                    269:   if (namelen > INTERFACE_NAMSIZ)
                    270:     return NULL;
                    271: 
1.1.1.3 ! misho     272:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     273:     {
                    274:       if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
                    275:        return ifp;
                    276:     }
                    277:   return NULL;
                    278: }
                    279: 
1.1.1.3 ! misho     280: struct interface *
        !           281: if_lookup_by_name_len(const char *name, size_t namelen)
        !           282: {
        !           283:   return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
        !           284: }
        !           285: 
1.1       misho     286: /* Lookup interface by IPv4 address. */
                    287: struct interface *
1.1.1.3 ! misho     288: if_lookup_exact_address_vrf (struct in_addr src, vrf_id_t vrf_id)
1.1       misho     289: {
                    290:   struct listnode *node;
                    291:   struct listnode *cnode;
                    292:   struct interface *ifp;
                    293:   struct prefix *p;
                    294:   struct connected *c;
                    295: 
1.1.1.3 ! misho     296:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     297:     {
                    298:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    299:        {
                    300:          p = c->address;
                    301: 
                    302:          if (p && p->family == AF_INET)
                    303:            {
                    304:              if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
                    305:                return ifp;
                    306:            }         
                    307:        }
                    308:     }
                    309:   return NULL;
                    310: }
                    311: 
1.1.1.3 ! misho     312: struct interface *
        !           313: if_lookup_exact_address (struct in_addr src)
        !           314: {
        !           315:   return if_lookup_exact_address_vrf (src, VRF_DEFAULT);
        !           316: }
        !           317: 
1.1       misho     318: /* Lookup interface by IPv4 address. */
                    319: struct interface *
1.1.1.3 ! misho     320: if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id)
1.1       misho     321: {
                    322:   struct listnode *node;
                    323:   struct prefix addr;
                    324:   int bestlen = 0;
                    325:   struct listnode *cnode;
                    326:   struct interface *ifp;
                    327:   struct connected *c;
                    328:   struct interface *match;
                    329: 
                    330:   addr.family = AF_INET;
                    331:   addr.u.prefix4 = src;
                    332:   addr.prefixlen = IPV4_MAX_BITLEN;
                    333: 
                    334:   match = NULL;
                    335: 
1.1.1.3 ! misho     336:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     337:     {
                    338:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    339:        {
                    340:          if (c->address && (c->address->family == AF_INET) &&
                    341:              prefix_match(CONNECTED_PREFIX(c), &addr) &&
                    342:              (c->address->prefixlen > bestlen))
                    343:            {
                    344:              bestlen = c->address->prefixlen;
                    345:              match = ifp;
                    346:            }
                    347:        }
                    348:     }
                    349:   return match;
                    350: }
                    351: 
1.1.1.3 ! misho     352: struct interface *
        !           353: if_lookup_address (struct in_addr src)
        !           354: {
        !           355:   return if_lookup_address_vrf (src, VRF_DEFAULT);
        !           356: }
        !           357: 
        !           358: /* Lookup interface by prefix */
        !           359: struct interface *
        !           360: if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
        !           361: {
        !           362:   struct listnode *node;
        !           363:   struct listnode *cnode;
        !           364:   struct interface *ifp;
        !           365:   struct connected *c;
        !           366: 
        !           367:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
        !           368:     {
        !           369:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
        !           370:         {
        !           371:           if (prefix_cmp(c->address, prefix) == 0)
        !           372:             {
        !           373:               return ifp;
        !           374:             }
        !           375:         }
        !           376:     }
        !           377:   return NULL;
        !           378: }
        !           379: 
        !           380: struct interface *
        !           381: if_lookup_prefix (struct prefix *prefix)
        !           382: {
        !           383:   return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
        !           384: }
        !           385: 
1.1       misho     386: /* Get interface by name if given name interface doesn't exist create
                    387:    one. */
                    388: struct interface *
1.1.1.3 ! misho     389: if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
1.1       misho     390: {
                    391:   struct interface *ifp;
                    392: 
1.1.1.3 ! misho     393:   return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
        !           394:          if_create_vrf (name, strlen(name), vrf_id);
        !           395: }
        !           396: 
        !           397: struct interface *
        !           398: if_get_by_name (const char *name)
        !           399: {
        !           400:   return if_get_by_name_vrf (name, VRF_DEFAULT);
1.1       misho     401: }
                    402: 
                    403: struct interface *
1.1.1.3 ! misho     404: if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
1.1       misho     405: {
                    406:   struct interface *ifp;
                    407: 
1.1.1.3 ! misho     408:   return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
        !           409:          ifp : if_create_vrf (name, namelen, vrf_id);
        !           410: }
        !           411: 
        !           412: struct interface *
        !           413: if_get_by_name_len (const char *name, size_t namelen)
        !           414: {
        !           415:   return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
1.1       misho     416: }
                    417: 
                    418: /* Does interface up ? */
                    419: int
                    420: if_is_up (struct interface *ifp)
                    421: {
                    422:   return ifp->flags & IFF_UP;
                    423: }
                    424: 
                    425: /* Is interface running? */
                    426: int
                    427: if_is_running (struct interface *ifp)
                    428: {
                    429:   return ifp->flags & IFF_RUNNING;
                    430: }
                    431: 
                    432: /* Is the interface operative, eg. either UP & RUNNING
                    433:    or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
                    434: int
                    435: if_is_operative (struct interface *ifp)
                    436: {
                    437:   return ((ifp->flags & IFF_UP) &&
                    438:          (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
                    439: }
                    440: 
                    441: /* Is this loopback interface ? */
                    442: int
                    443: if_is_loopback (struct interface *ifp)
                    444: {
                    445:   /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
                    446:    * but Y on platform N?
                    447:    */
                    448:   return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
                    449: }
                    450: 
                    451: /* Does this interface support broadcast ? */
                    452: int
                    453: if_is_broadcast (struct interface *ifp)
                    454: {
                    455:   return ifp->flags & IFF_BROADCAST;
                    456: }
                    457: 
                    458: /* Does this interface support broadcast ? */
                    459: int
                    460: if_is_pointopoint (struct interface *ifp)
                    461: {
                    462:   return ifp->flags & IFF_POINTOPOINT;
                    463: }
                    464: 
                    465: /* Does this interface support multicast ? */
                    466: int
                    467: if_is_multicast (struct interface *ifp)
                    468: {
                    469:   return ifp->flags & IFF_MULTICAST;
                    470: }
                    471: 
                    472: /* Printout flag information into log */
                    473: const char *
                    474: if_flag_dump (unsigned long flag)
                    475: {
                    476:   int separator = 0;
                    477:   static char logbuf[BUFSIZ];
                    478: 
                    479: #define IFF_OUT_LOG(X,STR) \
                    480:   if (flag & (X)) \
                    481:     { \
                    482:       if (separator) \
                    483:        strlcat (logbuf, ",", BUFSIZ); \
                    484:       else \
                    485:        separator = 1; \
                    486:       strlcat (logbuf, STR, BUFSIZ); \
                    487:     }
                    488: 
                    489:   strlcpy (logbuf, "<", BUFSIZ);
                    490:   IFF_OUT_LOG (IFF_UP, "UP");
                    491:   IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
                    492:   IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
                    493:   IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
                    494:   IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
                    495:   IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
                    496:   IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
                    497:   IFF_OUT_LOG (IFF_NOARP, "NOARP");
                    498:   IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
                    499:   IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
                    500:   IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
                    501:   IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
                    502:   IFF_OUT_LOG (IFF_LINK0, "LINK0");
                    503:   IFF_OUT_LOG (IFF_LINK1, "LINK1");
                    504:   IFF_OUT_LOG (IFF_LINK2, "LINK2");
                    505:   IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
                    506:   IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
                    507:   IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
                    508:   IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
                    509:   IFF_OUT_LOG (IFF_IPV4, "IPv4");
                    510:   IFF_OUT_LOG (IFF_IPV6, "IPv6");
                    511: 
                    512:   strlcat (logbuf, ">", BUFSIZ);
                    513: 
                    514:   return logbuf;
                    515: #undef IFF_OUT_LOG
                    516: }
                    517: 
                    518: /* For debugging */
                    519: static void
                    520: if_dump (const struct interface *ifp)
                    521: {
                    522:   struct listnode *node;
1.1.1.3 ! misho     523:   struct connected *c __attribute__((unused));
1.1       misho     524: 
1.1.1.2   misho     525:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
1.1.1.3 ! misho     526:     zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
1.1       misho     527: #ifdef HAVE_IPV6
1.1.1.2   misho     528:                "mtu6 %d "
1.1       misho     529: #endif /* HAVE_IPV6 */
1.1.1.2   misho     530:                "%s",
1.1.1.3 ! misho     531:                ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
1.1       misho     532: #ifdef HAVE_IPV6
1.1.1.2   misho     533:                ifp->mtu6,
1.1       misho     534: #endif /* HAVE_IPV6 */
1.1.1.2   misho     535:                if_flag_dump (ifp->flags));
1.1       misho     536: }
                    537: 
                    538: /* Interface printing for all interface. */
                    539: void
                    540: if_dump_all (void)
                    541: {
1.1.1.3 ! misho     542:   struct list *intf_list;
1.1       misho     543:   struct listnode *node;
                    544:   void *p;
1.1.1.3 ! misho     545:   vrf_iter_t iter;
1.1       misho     546: 
1.1.1.3 ! misho     547:   for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
        !           548:     if ((intf_list = vrf_iter2iflist (iter)) != NULL)
        !           549:       for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
        !           550:         if_dump (p);
1.1       misho     551: }
                    552: 
                    553: DEFUN (interface_desc, 
                    554:        interface_desc_cmd,
                    555:        "description .LINE",
                    556:        "Interface specific description\n"
                    557:        "Characters describing this interface\n")
                    558: {
                    559:   struct interface *ifp;
                    560: 
                    561:   if (argc == 0)
                    562:     return CMD_SUCCESS;
                    563: 
                    564:   ifp = vty->index;
                    565:   if (ifp->desc)
                    566:     XFREE (MTYPE_TMP, ifp->desc);
                    567:   ifp->desc = argv_concat(argv, argc, 0);
                    568: 
                    569:   return CMD_SUCCESS;
                    570: }
                    571: 
                    572: DEFUN (no_interface_desc, 
                    573:        no_interface_desc_cmd,
                    574:        "no description",
                    575:        NO_STR
                    576:        "Interface specific description\n")
                    577: {
                    578:   struct interface *ifp;
                    579: 
                    580:   ifp = vty->index;
                    581:   if (ifp->desc)
                    582:     XFREE (MTYPE_TMP, ifp->desc);
                    583:   ifp->desc = NULL;
                    584: 
                    585:   return CMD_SUCCESS;
                    586: }
1.1.1.3 ! misho     587: 
1.1       misho     588: #ifdef SUNOS_5
                    589: /* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
                    590:  * a seperate struct interface for each logical interface, so config
                    591:  * file may be full of 'interface fooX:Y'. Solaris however does not
                    592:  * expose logical interfaces via PF_ROUTE, so trying to track logical
                    593:  * interfaces can be fruitless, for that reason Quagga only tracks
                    594:  * the primary IP interface.
                    595:  *
                    596:  * We try accomodate SUNWzebra by:
                    597:  * - looking up the interface name, to see whether it exists, if so
                    598:  *   its useable
                    599:  *   - for protocol daemons, this could only because zebra told us of
                    600:  *     the interface
                    601:  *   - for zebra, only because it learnt from kernel
                    602:  * - if not:
                    603:  *   - search the name to see if it contains a sub-ipif / logical interface
                    604:  *     seperator, the ':' char. If it does:
                    605:  *     - text up to that char must be the primary name - get that name.
                    606:  *     if not:
                    607:  *     - no idea, just get the name in its entirety.
                    608:  */
                    609: static struct interface *
1.1.1.3 ! misho     610: if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
1.1       misho     611: {
                    612:   struct interface *ifp;
                    613:   size_t seppos = 0;
                    614: 
1.1.1.3 ! misho     615:   if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
1.1       misho     616:     return ifp;
                    617:   
                    618:   /* hunt the primary interface name... */
                    619:   while (seppos < nlen && name[seppos] != ':')
                    620:     seppos++;
                    621:   
                    622:   /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
                    623:   if (seppos < nlen)
1.1.1.3 ! misho     624:     return if_get_by_name_len_vrf (name, seppos, vrf_id);
1.1       misho     625:   else
1.1.1.3 ! misho     626:     return if_get_by_name_len_vrf (name, nlen, vrf_id);
1.1       misho     627: }
                    628: #endif /* SUNOS_5 */
1.1.1.3 ! misho     629: 
1.1       misho     630: DEFUN (interface,
                    631:        interface_cmd,
                    632:        "interface IFNAME",
                    633:        "Select an interface to configure\n"
                    634:        "Interface's name\n")
                    635: {
                    636:   struct interface *ifp;
                    637:   size_t sl;
1.1.1.3 ! misho     638:   vrf_id_t vrf_id = VRF_DEFAULT;
1.1       misho     639: 
                    640:   if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
                    641:     {
                    642:       vty_out (vty, "%% Interface name %s is invalid: length exceeds "
                    643:                    "%d characters%s",
                    644:               argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
                    645:       return CMD_WARNING;
                    646:     }
                    647: 
1.1.1.3 ! misho     648:   if (argc > 1)
        !           649:     VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
        !           650: 
1.1       misho     651: #ifdef SUNOS_5
1.1.1.3 ! misho     652:   ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
1.1       misho     653: #else
1.1.1.3 ! misho     654:   ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
1.1       misho     655: #endif /* SUNOS_5 */
                    656: 
                    657:   vty->index = ifp;
                    658:   vty->node = INTERFACE_NODE;
                    659: 
                    660:   return CMD_SUCCESS;
                    661: }
                    662: 
1.1.1.3 ! misho     663: ALIAS (interface,
        !           664:        interface_vrf_cmd,
        !           665:        "interface IFNAME " VRF_CMD_STR,
        !           666:        "Select an interface to configure\n"
        !           667:        "Interface's name\n"
        !           668:        VRF_CMD_HELP_STR)
        !           669: 
1.1       misho     670: DEFUN_NOSH (no_interface,
                    671:            no_interface_cmd,
                    672:            "no interface IFNAME",
                    673:            NO_STR
                    674:            "Delete a pseudo interface's configuration\n"
                    675:            "Interface's name\n")
                    676: {
                    677:   // deleting interface
                    678:   struct interface *ifp;
1.1.1.3 ! misho     679:   vrf_id_t vrf_id = VRF_DEFAULT;
1.1       misho     680: 
1.1.1.3 ! misho     681:   if (argc > 1)
        !           682:     VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
        !           683: 
        !           684:   ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
1.1       misho     685: 
                    686:   if (ifp == NULL)
                    687:     {
                    688:       vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
                    689:       return CMD_WARNING;
                    690:     }
                    691: 
                    692:   if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) 
                    693:     {
                    694:       vty_out (vty, "%% Only inactive interfaces can be deleted%s",
                    695:              VTY_NEWLINE);
                    696:       return CMD_WARNING;
                    697:     }
                    698: 
                    699:   if_delete(ifp);
                    700: 
                    701:   return CMD_SUCCESS;
                    702: }
                    703: 
1.1.1.3 ! misho     704: ALIAS (no_interface,
        !           705:        no_interface_vrf_cmd,
        !           706:        "no interface IFNAME " VRF_CMD_STR,
        !           707:        NO_STR
        !           708:        "Delete a pseudo interface's configuration\n"
        !           709:        "Interface's name\n"
        !           710:        VRF_CMD_HELP_STR)
        !           711: 
1.1       misho     712: /* For debug purpose. */
                    713: DEFUN (show_address,
                    714:        show_address_cmd,
                    715:        "show address",
                    716:        SHOW_STR
                    717:        "address\n")
                    718: {
                    719:   struct listnode *node;
                    720:   struct listnode *node2;
                    721:   struct interface *ifp;
                    722:   struct connected *ifc;
                    723:   struct prefix *p;
1.1.1.3 ! misho     724:   vrf_id_t vrf_id = VRF_DEFAULT;
1.1       misho     725: 
1.1.1.3 ! misho     726:   if (argc > 0)
        !           727:     VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
        !           728: 
        !           729:   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
1.1       misho     730:     {
                    731:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
                    732:        {
                    733:          p = ifc->address;
                    734: 
                    735:          if (p->family == AF_INET)
                    736:            vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
                    737:                     VTY_NEWLINE);
                    738:        }
                    739:     }
                    740:   return CMD_SUCCESS;
                    741: }
                    742: 
1.1.1.3 ! misho     743: ALIAS (show_address,
        !           744:        show_address_vrf_cmd,
        !           745:        "show address " VRF_CMD_STR,
        !           746:        SHOW_STR
        !           747:        "address\n"
        !           748:        VRF_CMD_HELP_STR)
        !           749: 
        !           750: DEFUN (show_address_vrf_all,
        !           751:        show_address_vrf_all_cmd,
        !           752:        "show address " VRF_ALL_CMD_STR,
        !           753:        SHOW_STR
        !           754:        "address\n"
        !           755:        VRF_ALL_CMD_HELP_STR)
        !           756: {
        !           757:   struct list *intf_list;
        !           758:   struct listnode *node;
        !           759:   struct listnode *node2;
        !           760:   struct interface *ifp;
        !           761:   struct connected *ifc;
        !           762:   struct prefix *p;
        !           763:   vrf_iter_t iter;
        !           764: 
        !           765:   for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
        !           766:     {
        !           767:       intf_list = vrf_iter2iflist (iter);
        !           768:       if (!intf_list || !listcount (intf_list))
        !           769:         continue;
        !           770: 
        !           771:       vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
        !           772:                VTY_NEWLINE, VTY_NEWLINE);
        !           773: 
        !           774:       for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
        !           775:         {
        !           776:           for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
        !           777:             {
        !           778:               p = ifc->address;
        !           779: 
        !           780:               if (p->family == AF_INET)
        !           781:                 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
        !           782:                          VTY_NEWLINE);
        !           783:             }
        !           784:         }
        !           785:     }
        !           786:   return CMD_SUCCESS;
        !           787: }
        !           788: 
1.1       misho     789: /* Allocate connected structure. */
                    790: struct connected *
                    791: connected_new (void)
                    792: {
                    793:   return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
                    794: }
                    795: 
                    796: /* Free connected structure. */
                    797: void
                    798: connected_free (struct connected *connected)
                    799: {
                    800:   if (connected->address)
                    801:     prefix_free (connected->address);
                    802: 
                    803:   if (connected->destination)
                    804:     prefix_free (connected->destination);
                    805: 
                    806:   if (connected->label)
                    807:     XFREE (MTYPE_CONNECTED_LABEL, connected->label);
                    808: 
                    809:   XFREE (MTYPE_CONNECTED, connected);
                    810: }
                    811: 
                    812: /* Print if_addr structure. */
                    813: static void __attribute__ ((unused))
                    814: connected_log (struct connected *connected, char *str)
                    815: {
                    816:   struct prefix *p;
                    817:   struct interface *ifp;
                    818:   char logbuf[BUFSIZ];
                    819:   char buf[BUFSIZ];
                    820:   
                    821:   ifp = connected->ifp;
                    822:   p = connected->address;
                    823: 
1.1.1.3 ! misho     824:   snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
        !           825:            str, ifp->name, ifp->vrf_id, prefix_family_str (p),
1.1       misho     826:            inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
                    827:            p->prefixlen);
                    828: 
                    829:   p = connected->destination;
                    830:   if (p)
                    831:     {
                    832:       strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
                    833:               BUFSIZ - strlen(logbuf));
                    834:     }
                    835:   zlog (NULL, LOG_INFO, "%s", logbuf);
                    836: }
                    837: 
                    838: /* If two connected address has same prefix return 1. */
                    839: static int
                    840: connected_same_prefix (struct prefix *p1, struct prefix *p2)
                    841: {
                    842:   if (p1->family == p2->family)
                    843:     {
                    844:       if (p1->family == AF_INET &&
                    845:          IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
                    846:        return 1;
                    847: #ifdef HAVE_IPV6
                    848:       if (p1->family == AF_INET6 &&
                    849:          IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
                    850:        return 1;
                    851: #endif /* HAVE_IPV6 */
                    852:     }
                    853:   return 0;
                    854: }
                    855: 
                    856: struct connected *
                    857: connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
                    858: {
                    859:   struct listnode *node;
                    860:   struct listnode *next;
                    861:   struct connected *ifc;
                    862: 
                    863:   /* In case of same prefix come, replace it with new one. */
                    864:   for (node = listhead (ifp->connected); node; node = next)
                    865:     {
                    866:       ifc = listgetdata (node);
                    867:       next = node->next;
                    868: 
                    869:       if (connected_same_prefix (ifc->address, p))
                    870:        {
                    871:          listnode_delete (ifp->connected, ifc);
                    872:          return ifc;
                    873:        }
                    874:     }
                    875:   return NULL;
                    876: }
                    877: 
                    878: /* Find the IPv4 address on our side that will be used when packets
                    879:    are sent to dst. */
                    880: struct connected *
                    881: connected_lookup_address (struct interface *ifp, struct in_addr dst)
                    882: {
                    883:   struct prefix addr;
                    884:   struct listnode *cnode;
                    885:   struct connected *c;
                    886:   struct connected *match;
                    887: 
                    888:   addr.family = AF_INET;
                    889:   addr.u.prefix4 = dst;
                    890:   addr.prefixlen = IPV4_MAX_BITLEN;
                    891: 
                    892:   match = NULL;
                    893: 
                    894:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    895:     {
                    896:       if (c->address && (c->address->family == AF_INET) &&
                    897:          prefix_match(CONNECTED_PREFIX(c), &addr) &&
                    898:          (!match || (c->address->prefixlen > match->address->prefixlen)))
                    899:        match = c;
                    900:     }
                    901:   return match;
                    902: }
                    903: 
                    904: struct connected *
                    905: connected_add_by_prefix (struct interface *ifp, struct prefix *p, 
                    906:                          struct prefix *destination)
                    907: {
                    908:   struct connected *ifc;
                    909: 
                    910:   /* Allocate new connected address. */
                    911:   ifc = connected_new ();
                    912:   ifc->ifp = ifp;
                    913: 
                    914:   /* Fetch interface address */
                    915:   ifc->address = prefix_new();
                    916:   memcpy (ifc->address, p, sizeof(struct prefix));
                    917: 
                    918:   /* Fetch dest address */
                    919:   if (destination)
                    920:     {
                    921:       ifc->destination = prefix_new();
                    922:       memcpy (ifc->destination, destination, sizeof(struct prefix));
                    923:     }
                    924: 
                    925:   /* Add connected address to the interface. */
                    926:   listnode_add (ifp->connected, ifc);
                    927:   return ifc;
                    928: }
                    929: 
                    930: #ifndef HAVE_IF_NAMETOINDEX
1.1.1.3 ! misho     931: ifindex_t
1.1       misho     932: if_nametoindex (const char *name)
                    933: {
                    934:   struct interface *ifp;
                    935: 
                    936:   return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
                    937:         ? ifp->ifindex : 0;
                    938: }
                    939: #endif
                    940: 
                    941: #ifndef HAVE_IF_INDEXTONAME
                    942: char *
1.1.1.3 ! misho     943: if_indextoname (ifindex_t ifindex, char *name)
1.1       misho     944: {
                    945:   struct interface *ifp;
                    946: 
                    947:   if (!(ifp = if_lookup_by_index(ifindex)))
                    948:     return NULL;
                    949:   strncpy (name, ifp->name, IFNAMSIZ);
                    950:   return ifp->name;
                    951: }
                    952: #endif
1.1.1.3 ! misho     953: 
1.1       misho     954: #if 0 /* this route_table of struct connected's is unused
                    955:        * however, it would be good to use a route_table rather than
                    956:        * a list..
                    957:        */
                    958: /* Interface looking up by interface's address. */
                    959: /* Interface's IPv4 address reverse lookup table. */
                    960: struct route_table *ifaddr_ipv4_table;
                    961: /* struct route_table *ifaddr_ipv6_table; */
                    962: 
                    963: static void
                    964: ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
                    965: {
                    966:   struct route_node *rn;
                    967:   struct prefix_ipv4 p;
                    968: 
                    969:   p.family = AF_INET;
                    970:   p.prefixlen = IPV4_MAX_PREFIXLEN;
                    971:   p.prefix = *ifaddr;
                    972: 
                    973:   rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
                    974:   if (rn)
                    975:     {
                    976:       route_unlock_node (rn);
                    977:       zlog_info ("ifaddr_ipv4_add(): address %s is already added",
                    978:                 inet_ntoa (*ifaddr));
                    979:       return;
                    980:     }
                    981:   rn->info = ifp;
                    982: }
                    983: 
                    984: static void
                    985: ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
                    986: {
                    987:   struct route_node *rn;
                    988:   struct prefix_ipv4 p;
                    989: 
                    990:   p.family = AF_INET;
                    991:   p.prefixlen = IPV4_MAX_PREFIXLEN;
                    992:   p.prefix = *ifaddr;
                    993: 
                    994:   rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
                    995:   if (! rn)
                    996:     {
                    997:       zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
                    998:                 inet_ntoa (*ifaddr));
                    999:       return;
                   1000:     }
                   1001:   rn->info = NULL;
                   1002:   route_unlock_node (rn);
                   1003:   route_unlock_node (rn);
                   1004: }
                   1005: 
                   1006: /* Lookup interface by interface's IP address or interface index. */
                   1007: static struct interface *
1.1.1.3 ! misho    1008: ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
1.1       misho    1009: {
                   1010:   struct prefix_ipv4 p;
                   1011:   struct route_node *rn;
                   1012:   struct interface *ifp;
                   1013: 
                   1014:   if (addr)
                   1015:     {
                   1016:       p.family = AF_INET;
                   1017:       p.prefixlen = IPV4_MAX_PREFIXLEN;
                   1018:       p.prefix = *addr;
                   1019: 
                   1020:       rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
                   1021:       if (! rn)
                   1022:        return NULL;
                   1023:       
                   1024:       ifp = rn->info;
                   1025:       route_unlock_node (rn);
                   1026:       return ifp;
                   1027:     }
                   1028:   else
                   1029:     return if_lookup_by_index(ifindex);
                   1030: }
                   1031: #endif /* ifaddr_ipv4_table */
                   1032: 
                   1033: /* Initialize interface list. */
                   1034: void
1.1.1.3 ! misho    1035: if_init (vrf_id_t vrf_id, struct list **intf_list)
1.1       misho    1036: {
1.1.1.3 ! misho    1037:   *intf_list = list_new ();
1.1       misho    1038: #if 0
                   1039:   ifaddr_ipv4_table = route_table_init ();
                   1040: #endif /* ifaddr_ipv4_table */
                   1041: 
1.1.1.3 ! misho    1042:   (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
1.1       misho    1043: 
1.1.1.3 ! misho    1044:   if (vrf_id == VRF_DEFAULT)
        !          1045:     iflist = *intf_list;
1.1       misho    1046: }
                   1047: 
                   1048: void
1.1.1.3 ! misho    1049: if_terminate (vrf_id_t vrf_id, struct list **intf_list)
1.1       misho    1050: {
                   1051:   for (;;)
                   1052:     {
                   1053:       struct interface *ifp;
                   1054: 
1.1.1.3 ! misho    1055:       ifp = listnode_head (*intf_list);
1.1       misho    1056:       if (ifp == NULL)
                   1057:        break;
                   1058: 
                   1059:       if_delete (ifp);
                   1060:     }
                   1061: 
1.1.1.3 ! misho    1062:   list_delete (*intf_list);
        !          1063:   *intf_list = NULL;
        !          1064: 
        !          1065:   if (vrf_id == VRF_DEFAULT)
        !          1066:     iflist = NULL;
        !          1067: }
        !          1068: 
        !          1069: const char *
        !          1070: if_link_type_str (enum zebra_link_type llt)
        !          1071: {
        !          1072:   switch (llt)
        !          1073:     {
        !          1074: #define llts(T,S) case (T): return (S)
        !          1075:       llts(ZEBRA_LLT_UNKNOWN,               "Unknown");
        !          1076:       llts(ZEBRA_LLT_ETHER,                 "Ethernet");
        !          1077:       llts(ZEBRA_LLT_EETHER,                "Experimental Ethernet");
        !          1078:       llts(ZEBRA_LLT_AX25,                  "AX.25 Level 2");
        !          1079:       llts(ZEBRA_LLT_PRONET,                "PROnet token ring");
        !          1080:       llts(ZEBRA_LLT_IEEE802,               "IEEE 802.2 Ethernet/TR/TB");
        !          1081:       llts(ZEBRA_LLT_ARCNET,                "ARCnet");
        !          1082:       llts(ZEBRA_LLT_APPLETLK,              "AppleTalk");
        !          1083:       llts(ZEBRA_LLT_DLCI,                  "Frame Relay DLCI");
        !          1084:       llts(ZEBRA_LLT_ATM,                   "ATM");
        !          1085:       llts(ZEBRA_LLT_METRICOM,              "Metricom STRIP");
        !          1086:       llts(ZEBRA_LLT_IEEE1394,              "IEEE 1394 IPv4");
        !          1087:       llts(ZEBRA_LLT_EUI64,                 "EUI-64");
        !          1088:       llts(ZEBRA_LLT_INFINIBAND,            "InfiniBand");
        !          1089:       llts(ZEBRA_LLT_SLIP,                  "SLIP");
        !          1090:       llts(ZEBRA_LLT_CSLIP,                 "Compressed SLIP");
        !          1091:       llts(ZEBRA_LLT_SLIP6,                 "SLIPv6");
        !          1092:       llts(ZEBRA_LLT_CSLIP6,                "Compressed SLIPv6");
        !          1093:       llts(ZEBRA_LLT_ROSE,                  "ROSE packet radio");
        !          1094:       llts(ZEBRA_LLT_X25,                   "CCITT X.25");
        !          1095:       llts(ZEBRA_LLT_PPP,                   "PPP");
        !          1096:       llts(ZEBRA_LLT_CHDLC,                 "Cisco HDLC");
        !          1097:       llts(ZEBRA_LLT_RAWHDLC,               "Raw HDLC");
        !          1098:       llts(ZEBRA_LLT_LAPB,                  "LAPB");
        !          1099:       llts(ZEBRA_LLT_IPIP,                  "IPIP Tunnel");
        !          1100:       llts(ZEBRA_LLT_IPIP6,                 "IPIP6 Tunnel");
        !          1101:       llts(ZEBRA_LLT_FRAD,                  "FRAD");
        !          1102:       llts(ZEBRA_LLT_SKIP,                  "SKIP vif");
        !          1103:       llts(ZEBRA_LLT_LOOPBACK,              "Loopback");
        !          1104:       llts(ZEBRA_LLT_LOCALTLK,              "Localtalk");
        !          1105:       llts(ZEBRA_LLT_FDDI,                  "FDDI");
        !          1106:       llts(ZEBRA_LLT_SIT,                   "IPv6-in-IPv4 SIT");
        !          1107:       llts(ZEBRA_LLT_IPDDP,                 "IP-in-DDP tunnel");
        !          1108:       llts(ZEBRA_LLT_IPGRE,                 "GRE over IP");
        !          1109:       llts(ZEBRA_LLT_PIMREG,                "PIMSM registration");
        !          1110:       llts(ZEBRA_LLT_HIPPI,                 "HiPPI");
        !          1111:       llts(ZEBRA_LLT_IRDA,                  "IrDA");
        !          1112:       llts(ZEBRA_LLT_FCPP,                  "Fibre-Channel PtP");
        !          1113:       llts(ZEBRA_LLT_FCAL,                  "Fibre-Channel Arbitrated Loop");
        !          1114:       llts(ZEBRA_LLT_FCPL,                  "Fibre-Channel Public Loop");
        !          1115:       llts(ZEBRA_LLT_FCFABRIC,              "Fibre-Channel Fabric");
        !          1116:       llts(ZEBRA_LLT_IEEE802_TR,            "IEEE 802.2 Token Ring");
        !          1117:       llts(ZEBRA_LLT_IEEE80211,             "IEEE 802.11");
        !          1118:       llts(ZEBRA_LLT_IEEE80211_RADIOTAP,    "IEEE 802.11 Radiotap");
        !          1119:       llts(ZEBRA_LLT_IEEE802154,            "IEEE 802.15.4");
        !          1120:       llts(ZEBRA_LLT_IEEE802154_PHY,        "IEEE 802.15.4 Phy");
        !          1121:       default:
        !          1122:         zlog_warn ("Unknown value %d", llt);
        !          1123:         return "Unknown type!";
        !          1124: #undef llts
        !          1125:     }
        !          1126:   return NULL;
1.1       misho    1127: }

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