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

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"
                     30: #include "if.h"
                     31: #include "sockunion.h"
                     32: #include "prefix.h"
                     33: #include "memory.h"
                     34: #include "table.h"
                     35: #include "buffer.h"
                     36: #include "str.h"
                     37: #include "log.h"
                     38: 
                     39: /* Master list of interfaces. */
                     40: struct list *iflist;
                     41: 
                     42: /* One for each program.  This structure is needed to store hooks. */
                     43: struct if_master
                     44: {
                     45:   int (*if_new_hook) (struct interface *);
                     46:   int (*if_delete_hook) (struct interface *);
                     47: } if_master;
                     48: 
                     49: /* Compare interface names, returning an integer greater than, equal to, or
                     50:  * less than 0, (following the strcmp convention), according to the
                     51:  * relationship between ifp1 and ifp2.  Interface names consist of an
                     52:  * alphabetic prefix and a numeric suffix.  The primary sort key is
                     53:  * lexicographic by name, and then numeric by number.  No number sorts
                     54:  * before all numbers.  Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
                     55:  * devpty0, de0 < del0
                     56:  */         
                     57: int
                     58: if_cmp_func (struct interface *ifp1, struct interface *ifp2)
                     59: {
                     60:   unsigned int l1, l2;
                     61:   long int x1, x2;
                     62:   char *p1, *p2;
                     63:   int res;
                     64: 
                     65:   p1 = ifp1->name;
                     66:   p2 = ifp2->name;
                     67: 
                     68:   while (*p1 && *p2) {
                     69:     /* look up to any number */
                     70:     l1 = strcspn(p1, "0123456789");
                     71:     l2 = strcspn(p2, "0123456789");
                     72: 
                     73:     /* name lengths are different -> compare names */
                     74:     if (l1 != l2)
                     75:       return (strcmp(p1, p2));
                     76: 
                     77:     /* Note that this relies on all numbers being less than all letters, so
                     78:      * that de0 < del0.
                     79:      */
                     80:     res = strncmp(p1, p2, l1);
                     81: 
                     82:     /* names are different -> compare them */
                     83:     if (res)
                     84:       return res;
                     85: 
                     86:     /* with identical name part, go to numeric part */
                     87:     p1 += l1;
                     88:     p2 += l1;
                     89: 
                     90:     if (!*p1) 
                     91:       return -1;
                     92:     if (!*p2) 
                     93:       return 1;
                     94: 
                     95:     x1 = strtol(p1, &p1, 10);
                     96:     x2 = strtol(p2, &p2, 10);
                     97: 
                     98:     /* let's compare numbers now */
                     99:     if (x1 < x2)
                    100:       return -1;
                    101:     if (x1 > x2)
                    102:       return 1;
                    103: 
                    104:     /* numbers were equal, lets do it again..
                    105:     (it happens with name like "eth123.456:789") */
                    106:   }
                    107:   if (*p1)
                    108:     return 1;
                    109:   if (*p2)
                    110:     return -1;
                    111:   return 0;
                    112: }
                    113: 
                    114: /* Create new interface structure. */
                    115: struct interface *
                    116: if_create (const char *name, int namelen)
                    117: {
                    118:   struct interface *ifp;
                    119: 
                    120:   ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
                    121:   ifp->ifindex = IFINDEX_INTERNAL;
                    122:   
                    123:   assert (name);
                    124:   assert (namelen <= INTERFACE_NAMSIZ);        /* Need space for '\0' at end. */
                    125:   strncpy (ifp->name, name, namelen);
                    126:   ifp->name[namelen] = '\0';
                    127:   if (if_lookup_by_name(ifp->name) == NULL)
                    128:     listnode_add_sort (iflist, ifp);
                    129:   else
                    130:     zlog_err("if_create(%s): corruption detected -- interface with this "
                    131:             "name exists already!", ifp->name);
                    132:   ifp->connected = list_new ();
                    133:   ifp->connected->del = (void (*) (void *)) connected_free;
                    134: 
                    135:   if (if_master.if_new_hook)
                    136:     (*if_master.if_new_hook) (ifp);
                    137: 
                    138:   return ifp;
                    139: }
                    140: 
                    141: /* Delete interface structure. */
                    142: void
                    143: if_delete_retain (struct interface *ifp)
                    144: {
                    145:   if (if_master.if_delete_hook)
                    146:     (*if_master.if_delete_hook) (ifp);
                    147: 
                    148:   /* Free connected address list */
                    149:   list_delete (ifp->connected);
                    150: }
                    151: 
                    152: /* Delete and free interface structure. */
                    153: void
                    154: if_delete (struct interface *ifp)
                    155: {
                    156:   listnode_delete (iflist, ifp);
                    157: 
                    158:   if_delete_retain(ifp);
                    159: 
                    160:   XFREE (MTYPE_IF, ifp);
                    161: }
                    162: 
                    163: /* Add hook to interface master. */
                    164: void
                    165: if_add_hook (int type, int (*func)(struct interface *ifp))
                    166: {
                    167:   switch (type) {
                    168:   case IF_NEW_HOOK:
                    169:     if_master.if_new_hook = func;
                    170:     break;
                    171:   case IF_DELETE_HOOK:
                    172:     if_master.if_delete_hook = func;
                    173:     break;
                    174:   default:
                    175:     break;
                    176:   }
                    177: }
                    178: 
                    179: /* Interface existance check by index. */
                    180: struct interface *
                    181: if_lookup_by_index (unsigned int index)
                    182: {
                    183:   struct listnode *node;
                    184:   struct interface *ifp;
                    185: 
                    186:   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
                    187:     {
                    188:       if (ifp->ifindex == index)
                    189:        return ifp;
                    190:     }
                    191:   return NULL;
                    192: }
                    193: 
                    194: const char *
                    195: ifindex2ifname (unsigned int index)
                    196: {
                    197:   struct interface *ifp;
                    198: 
                    199:   return ((ifp = if_lookup_by_index(index)) != NULL) ?
                    200:         ifp->name : "unknown";
                    201: }
                    202: 
                    203: unsigned int
                    204: ifname2ifindex (const char *name)
                    205: {
                    206:   struct interface *ifp;
                    207: 
                    208:   return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex
                    209:                                                    : IFINDEX_INTERNAL;
                    210: }
                    211: 
                    212: /* Interface existance check by interface name. */
                    213: struct interface *
                    214: if_lookup_by_name (const char *name)
                    215: {
                    216:   struct listnode *node;
                    217:   struct interface *ifp;
                    218:   
                    219:   if (name)
                    220:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    221:       {
                    222:         if (strcmp(name, ifp->name) == 0)
                    223:           return ifp;
                    224:       }
                    225:   return NULL;
                    226: }
                    227: 
                    228: struct interface *
                    229: if_lookup_by_name_len(const char *name, size_t namelen)
                    230: {
                    231:   struct listnode *node;
                    232:   struct interface *ifp;
                    233: 
                    234:   if (namelen > INTERFACE_NAMSIZ)
                    235:     return NULL;
                    236: 
                    237:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    238:     {
                    239:       if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
                    240:        return ifp;
                    241:     }
                    242:   return NULL;
                    243: }
                    244: 
                    245: /* Lookup interface by IPv4 address. */
                    246: struct interface *
                    247: if_lookup_exact_address (struct in_addr src)
                    248: {
                    249:   struct listnode *node;
                    250:   struct listnode *cnode;
                    251:   struct interface *ifp;
                    252:   struct prefix *p;
                    253:   struct connected *c;
                    254: 
                    255:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    256:     {
                    257:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    258:        {
                    259:          p = c->address;
                    260: 
                    261:          if (p && p->family == AF_INET)
                    262:            {
                    263:              if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
                    264:                return ifp;
                    265:            }         
                    266:        }
                    267:     }
                    268:   return NULL;
                    269: }
                    270: 
                    271: /* Lookup interface by IPv4 address. */
                    272: struct interface *
                    273: if_lookup_address (struct in_addr src)
                    274: {
                    275:   struct listnode *node;
                    276:   struct prefix addr;
                    277:   int bestlen = 0;
                    278:   struct listnode *cnode;
                    279:   struct interface *ifp;
                    280:   struct connected *c;
                    281:   struct interface *match;
                    282: 
                    283:   addr.family = AF_INET;
                    284:   addr.u.prefix4 = src;
                    285:   addr.prefixlen = IPV4_MAX_BITLEN;
                    286: 
                    287:   match = NULL;
                    288: 
                    289:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    290:     {
                    291:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    292:        {
                    293:          if (c->address && (c->address->family == AF_INET) &&
                    294:              prefix_match(CONNECTED_PREFIX(c), &addr) &&
                    295:              (c->address->prefixlen > bestlen))
                    296:            {
                    297:              bestlen = c->address->prefixlen;
                    298:              match = ifp;
                    299:            }
                    300:        }
                    301:     }
                    302:   return match;
                    303: }
                    304: 
                    305: /* Get interface by name if given name interface doesn't exist create
                    306:    one. */
                    307: struct interface *
                    308: if_get_by_name (const char *name)
                    309: {
                    310:   struct interface *ifp;
                    311: 
                    312:   return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp :
                    313:         if_create(name, strlen(name));
                    314: }
                    315: 
                    316: struct interface *
                    317: if_get_by_name_len(const char *name, size_t namelen)
                    318: {
                    319:   struct interface *ifp;
                    320: 
                    321:   return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp :
                    322:         if_create(name, namelen);
                    323: }
                    324: 
                    325: /* Does interface up ? */
                    326: int
                    327: if_is_up (struct interface *ifp)
                    328: {
                    329:   return ifp->flags & IFF_UP;
                    330: }
                    331: 
                    332: /* Is interface running? */
                    333: int
                    334: if_is_running (struct interface *ifp)
                    335: {
                    336:   return ifp->flags & IFF_RUNNING;
                    337: }
                    338: 
                    339: /* Is the interface operative, eg. either UP & RUNNING
                    340:    or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
                    341: int
                    342: if_is_operative (struct interface *ifp)
                    343: {
                    344:   return ((ifp->flags & IFF_UP) &&
                    345:          (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
                    346: }
                    347: 
                    348: /* Is this loopback interface ? */
                    349: int
                    350: if_is_loopback (struct interface *ifp)
                    351: {
                    352:   /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
                    353:    * but Y on platform N?
                    354:    */
                    355:   return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
                    356: }
                    357: 
                    358: /* Does this interface support broadcast ? */
                    359: int
                    360: if_is_broadcast (struct interface *ifp)
                    361: {
                    362:   return ifp->flags & IFF_BROADCAST;
                    363: }
                    364: 
                    365: /* Does this interface support broadcast ? */
                    366: int
                    367: if_is_pointopoint (struct interface *ifp)
                    368: {
                    369:   return ifp->flags & IFF_POINTOPOINT;
                    370: }
                    371: 
                    372: /* Does this interface support multicast ? */
                    373: int
                    374: if_is_multicast (struct interface *ifp)
                    375: {
                    376:   return ifp->flags & IFF_MULTICAST;
                    377: }
                    378: 
                    379: /* Printout flag information into log */
                    380: const char *
                    381: if_flag_dump (unsigned long flag)
                    382: {
                    383:   int separator = 0;
                    384:   static char logbuf[BUFSIZ];
                    385: 
                    386: #define IFF_OUT_LOG(X,STR) \
                    387:   if (flag & (X)) \
                    388:     { \
                    389:       if (separator) \
                    390:        strlcat (logbuf, ",", BUFSIZ); \
                    391:       else \
                    392:        separator = 1; \
                    393:       strlcat (logbuf, STR, BUFSIZ); \
                    394:     }
                    395: 
                    396:   strlcpy (logbuf, "<", BUFSIZ);
                    397:   IFF_OUT_LOG (IFF_UP, "UP");
                    398:   IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
                    399:   IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
                    400:   IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
                    401:   IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
                    402:   IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
                    403:   IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
                    404:   IFF_OUT_LOG (IFF_NOARP, "NOARP");
                    405:   IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
                    406:   IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
                    407:   IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
                    408:   IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
                    409:   IFF_OUT_LOG (IFF_LINK0, "LINK0");
                    410:   IFF_OUT_LOG (IFF_LINK1, "LINK1");
                    411:   IFF_OUT_LOG (IFF_LINK2, "LINK2");
                    412:   IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
                    413:   IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
                    414:   IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
                    415:   IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
                    416:   IFF_OUT_LOG (IFF_IPV4, "IPv4");
                    417:   IFF_OUT_LOG (IFF_IPV6, "IPv6");
                    418: 
                    419:   strlcat (logbuf, ">", BUFSIZ);
                    420: 
                    421:   return logbuf;
                    422: #undef IFF_OUT_LOG
                    423: }
                    424: 
                    425: /* For debugging */
                    426: static void
                    427: if_dump (const struct interface *ifp)
                    428: {
                    429:   struct listnode *node;
                    430:   struct connected *c;
                    431: 
                    432:   zlog_info ("Interface %s index %d metric %d mtu %d "
                    433: #ifdef HAVE_IPV6
                    434:              "mtu6 %d "
                    435: #endif /* HAVE_IPV6 */
                    436:              "%s",
                    437:             ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, 
                    438: #ifdef HAVE_IPV6
                    439:             ifp->mtu6,
                    440: #endif /* HAVE_IPV6 */
                    441:             if_flag_dump (ifp->flags));
                    442:   
                    443:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
                    444:     ;
                    445: }
                    446: 
                    447: /* Interface printing for all interface. */
                    448: void
                    449: if_dump_all (void)
                    450: {
                    451:   struct listnode *node;
                    452:   void *p;
                    453: 
                    454:   for (ALL_LIST_ELEMENTS_RO (iflist, node, p))
                    455:     if_dump (p);
                    456: }
                    457: 
                    458: DEFUN (interface_desc, 
                    459:        interface_desc_cmd,
                    460:        "description .LINE",
                    461:        "Interface specific description\n"
                    462:        "Characters describing this interface\n")
                    463: {
                    464:   struct interface *ifp;
                    465: 
                    466:   if (argc == 0)
                    467:     return CMD_SUCCESS;
                    468: 
                    469:   ifp = vty->index;
                    470:   if (ifp->desc)
                    471:     XFREE (MTYPE_TMP, ifp->desc);
                    472:   ifp->desc = argv_concat(argv, argc, 0);
                    473: 
                    474:   return CMD_SUCCESS;
                    475: }
                    476: 
                    477: DEFUN (no_interface_desc, 
                    478:        no_interface_desc_cmd,
                    479:        "no description",
                    480:        NO_STR
                    481:        "Interface specific description\n")
                    482: {
                    483:   struct interface *ifp;
                    484: 
                    485:   ifp = vty->index;
                    486:   if (ifp->desc)
                    487:     XFREE (MTYPE_TMP, ifp->desc);
                    488:   ifp->desc = NULL;
                    489: 
                    490:   return CMD_SUCCESS;
                    491: }
                    492: 
                    493: #ifdef SUNOS_5
                    494: /* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
                    495:  * a seperate struct interface for each logical interface, so config
                    496:  * file may be full of 'interface fooX:Y'. Solaris however does not
                    497:  * expose logical interfaces via PF_ROUTE, so trying to track logical
                    498:  * interfaces can be fruitless, for that reason Quagga only tracks
                    499:  * the primary IP interface.
                    500:  *
                    501:  * We try accomodate SUNWzebra by:
                    502:  * - looking up the interface name, to see whether it exists, if so
                    503:  *   its useable
                    504:  *   - for protocol daemons, this could only because zebra told us of
                    505:  *     the interface
                    506:  *   - for zebra, only because it learnt from kernel
                    507:  * - if not:
                    508:  *   - search the name to see if it contains a sub-ipif / logical interface
                    509:  *     seperator, the ':' char. If it does:
                    510:  *     - text up to that char must be the primary name - get that name.
                    511:  *     if not:
                    512:  *     - no idea, just get the name in its entirety.
                    513:  */
                    514: static struct interface *
                    515: if_sunwzebra_get (const char *name, size_t nlen)
                    516: {
                    517:   struct interface *ifp;
                    518:   size_t seppos = 0;
                    519: 
                    520:   if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL)
                    521:     return ifp;
                    522:   
                    523:   /* hunt the primary interface name... */
                    524:   while (seppos < nlen && name[seppos] != ':')
                    525:     seppos++;
                    526:   
                    527:   /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
                    528:   if (seppos < nlen)
                    529:     return if_get_by_name_len (name, seppos);
                    530:   else
                    531:     return if_get_by_name_len (name, nlen);
                    532: }
                    533: #endif /* SUNOS_5 */
                    534: 
                    535: DEFUN (interface,
                    536:        interface_cmd,
                    537:        "interface IFNAME",
                    538:        "Select an interface to configure\n"
                    539:        "Interface's name\n")
                    540: {
                    541:   struct interface *ifp;
                    542:   size_t sl;
                    543: 
                    544:   if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
                    545:     {
                    546:       vty_out (vty, "%% Interface name %s is invalid: length exceeds "
                    547:                    "%d characters%s",
                    548:               argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
                    549:       return CMD_WARNING;
                    550:     }
                    551: 
                    552: #ifdef SUNOS_5
                    553:   ifp = if_sunwzebra_get (argv[0], sl);
                    554: #else
                    555:   ifp = if_get_by_name_len(argv[0], sl);
                    556: #endif /* SUNOS_5 */
                    557: 
                    558:   vty->index = ifp;
                    559:   vty->node = INTERFACE_NODE;
                    560: 
                    561:   return CMD_SUCCESS;
                    562: }
                    563: 
                    564: DEFUN_NOSH (no_interface,
                    565:            no_interface_cmd,
                    566:            "no interface IFNAME",
                    567:            NO_STR
                    568:            "Delete a pseudo interface's configuration\n"
                    569:            "Interface's name\n")
                    570: {
                    571:   // deleting interface
                    572:   struct interface *ifp;
                    573: 
                    574:   ifp = if_lookup_by_name (argv[0]);
                    575: 
                    576:   if (ifp == NULL)
                    577:     {
                    578:       vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
                    579:       return CMD_WARNING;
                    580:     }
                    581: 
                    582:   if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) 
                    583:     {
                    584:       vty_out (vty, "%% Only inactive interfaces can be deleted%s",
                    585:              VTY_NEWLINE);
                    586:       return CMD_WARNING;
                    587:     }
                    588: 
                    589:   if_delete(ifp);
                    590: 
                    591:   return CMD_SUCCESS;
                    592: }
                    593: 
                    594: /* For debug purpose. */
                    595: DEFUN (show_address,
                    596:        show_address_cmd,
                    597:        "show address",
                    598:        SHOW_STR
                    599:        "address\n")
                    600: {
                    601:   struct listnode *node;
                    602:   struct listnode *node2;
                    603:   struct interface *ifp;
                    604:   struct connected *ifc;
                    605:   struct prefix *p;
                    606: 
                    607:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    608:     {
                    609:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
                    610:        {
                    611:          p = ifc->address;
                    612: 
                    613:          if (p->family == AF_INET)
                    614:            vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
                    615:                     VTY_NEWLINE);
                    616:        }
                    617:     }
                    618:   return CMD_SUCCESS;
                    619: }
                    620: 
                    621: /* Allocate connected structure. */
                    622: struct connected *
                    623: connected_new (void)
                    624: {
                    625:   return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
                    626: }
                    627: 
                    628: /* Free connected structure. */
                    629: void
                    630: connected_free (struct connected *connected)
                    631: {
                    632:   if (connected->address)
                    633:     prefix_free (connected->address);
                    634: 
                    635:   if (connected->destination)
                    636:     prefix_free (connected->destination);
                    637: 
                    638:   if (connected->label)
                    639:     XFREE (MTYPE_CONNECTED_LABEL, connected->label);
                    640: 
                    641:   XFREE (MTYPE_CONNECTED, connected);
                    642: }
                    643: 
                    644: /* Print if_addr structure. */
                    645: static void __attribute__ ((unused))
                    646: connected_log (struct connected *connected, char *str)
                    647: {
                    648:   struct prefix *p;
                    649:   struct interface *ifp;
                    650:   char logbuf[BUFSIZ];
                    651:   char buf[BUFSIZ];
                    652:   
                    653:   ifp = connected->ifp;
                    654:   p = connected->address;
                    655: 
                    656:   snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", 
                    657:            str, ifp->name, prefix_family_str (p),
                    658:            inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
                    659:            p->prefixlen);
                    660: 
                    661:   p = connected->destination;
                    662:   if (p)
                    663:     {
                    664:       strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
                    665:               BUFSIZ - strlen(logbuf));
                    666:     }
                    667:   zlog (NULL, LOG_INFO, "%s", logbuf);
                    668: }
                    669: 
                    670: /* If two connected address has same prefix return 1. */
                    671: static int
                    672: connected_same_prefix (struct prefix *p1, struct prefix *p2)
                    673: {
                    674:   if (p1->family == p2->family)
                    675:     {
                    676:       if (p1->family == AF_INET &&
                    677:          IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
                    678:        return 1;
                    679: #ifdef HAVE_IPV6
                    680:       if (p1->family == AF_INET6 &&
                    681:          IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
                    682:        return 1;
                    683: #endif /* HAVE_IPV6 */
                    684:     }
                    685:   return 0;
                    686: }
                    687: 
                    688: struct connected *
                    689: connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
                    690: {
                    691:   struct listnode *node;
                    692:   struct listnode *next;
                    693:   struct connected *ifc;
                    694: 
                    695:   /* In case of same prefix come, replace it with new one. */
                    696:   for (node = listhead (ifp->connected); node; node = next)
                    697:     {
                    698:       ifc = listgetdata (node);
                    699:       next = node->next;
                    700: 
                    701:       if (connected_same_prefix (ifc->address, p))
                    702:        {
                    703:          listnode_delete (ifp->connected, ifc);
                    704:          return ifc;
                    705:        }
                    706:     }
                    707:   return NULL;
                    708: }
                    709: 
                    710: /* Find the IPv4 address on our side that will be used when packets
                    711:    are sent to dst. */
                    712: struct connected *
                    713: connected_lookup_address (struct interface *ifp, struct in_addr dst)
                    714: {
                    715:   struct prefix addr;
                    716:   struct listnode *cnode;
                    717:   struct connected *c;
                    718:   struct connected *match;
                    719: 
                    720:   addr.family = AF_INET;
                    721:   addr.u.prefix4 = dst;
                    722:   addr.prefixlen = IPV4_MAX_BITLEN;
                    723: 
                    724:   match = NULL;
                    725: 
                    726:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
                    727:     {
                    728:       if (c->address && (c->address->family == AF_INET) &&
                    729:          prefix_match(CONNECTED_PREFIX(c), &addr) &&
                    730:          (!match || (c->address->prefixlen > match->address->prefixlen)))
                    731:        match = c;
                    732:     }
                    733:   return match;
                    734: }
                    735: 
                    736: struct connected *
                    737: connected_add_by_prefix (struct interface *ifp, struct prefix *p, 
                    738:                          struct prefix *destination)
                    739: {
                    740:   struct connected *ifc;
                    741: 
                    742:   /* Allocate new connected address. */
                    743:   ifc = connected_new ();
                    744:   ifc->ifp = ifp;
                    745: 
                    746:   /* Fetch interface address */
                    747:   ifc->address = prefix_new();
                    748:   memcpy (ifc->address, p, sizeof(struct prefix));
                    749: 
                    750:   /* Fetch dest address */
                    751:   if (destination)
                    752:     {
                    753:       ifc->destination = prefix_new();
                    754:       memcpy (ifc->destination, destination, sizeof(struct prefix));
                    755:     }
                    756: 
                    757:   /* Add connected address to the interface. */
                    758:   listnode_add (ifp->connected, ifc);
                    759:   return ifc;
                    760: }
                    761: 
                    762: #ifndef HAVE_IF_NAMETOINDEX
                    763: unsigned int
                    764: if_nametoindex (const char *name)
                    765: {
                    766:   struct interface *ifp;
                    767: 
                    768:   return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
                    769:         ? ifp->ifindex : 0;
                    770: }
                    771: #endif
                    772: 
                    773: #ifndef HAVE_IF_INDEXTONAME
                    774: char *
                    775: if_indextoname (unsigned int ifindex, char *name)
                    776: {
                    777:   struct interface *ifp;
                    778: 
                    779:   if (!(ifp = if_lookup_by_index(ifindex)))
                    780:     return NULL;
                    781:   strncpy (name, ifp->name, IFNAMSIZ);
                    782:   return ifp->name;
                    783: }
                    784: #endif
                    785: 
                    786: #if 0 /* this route_table of struct connected's is unused
                    787:        * however, it would be good to use a route_table rather than
                    788:        * a list..
                    789:        */
                    790: /* Interface looking up by interface's address. */
                    791: /* Interface's IPv4 address reverse lookup table. */
                    792: struct route_table *ifaddr_ipv4_table;
                    793: /* struct route_table *ifaddr_ipv6_table; */
                    794: 
                    795: static void
                    796: ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
                    797: {
                    798:   struct route_node *rn;
                    799:   struct prefix_ipv4 p;
                    800: 
                    801:   p.family = AF_INET;
                    802:   p.prefixlen = IPV4_MAX_PREFIXLEN;
                    803:   p.prefix = *ifaddr;
                    804: 
                    805:   rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
                    806:   if (rn)
                    807:     {
                    808:       route_unlock_node (rn);
                    809:       zlog_info ("ifaddr_ipv4_add(): address %s is already added",
                    810:                 inet_ntoa (*ifaddr));
                    811:       return;
                    812:     }
                    813:   rn->info = ifp;
                    814: }
                    815: 
                    816: static void
                    817: ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
                    818: {
                    819:   struct route_node *rn;
                    820:   struct prefix_ipv4 p;
                    821: 
                    822:   p.family = AF_INET;
                    823:   p.prefixlen = IPV4_MAX_PREFIXLEN;
                    824:   p.prefix = *ifaddr;
                    825: 
                    826:   rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
                    827:   if (! rn)
                    828:     {
                    829:       zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
                    830:                 inet_ntoa (*ifaddr));
                    831:       return;
                    832:     }
                    833:   rn->info = NULL;
                    834:   route_unlock_node (rn);
                    835:   route_unlock_node (rn);
                    836: }
                    837: 
                    838: /* Lookup interface by interface's IP address or interface index. */
                    839: static struct interface *
                    840: ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
                    841: {
                    842:   struct prefix_ipv4 p;
                    843:   struct route_node *rn;
                    844:   struct interface *ifp;
                    845: 
                    846:   if (addr)
                    847:     {
                    848:       p.family = AF_INET;
                    849:       p.prefixlen = IPV4_MAX_PREFIXLEN;
                    850:       p.prefix = *addr;
                    851: 
                    852:       rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
                    853:       if (! rn)
                    854:        return NULL;
                    855:       
                    856:       ifp = rn->info;
                    857:       route_unlock_node (rn);
                    858:       return ifp;
                    859:     }
                    860:   else
                    861:     return if_lookup_by_index(ifindex);
                    862: }
                    863: #endif /* ifaddr_ipv4_table */
                    864: 
                    865: /* Initialize interface list. */
                    866: void
                    867: if_init (void)
                    868: {
                    869:   iflist = list_new ();
                    870: #if 0
                    871:   ifaddr_ipv4_table = route_table_init ();
                    872: #endif /* ifaddr_ipv4_table */
                    873: 
                    874:   if (iflist) {
                    875:     iflist->cmp = (int (*)(void *, void *))if_cmp_func;
                    876:     return;
                    877:   }
                    878: 
                    879:   memset (&if_master, 0, sizeof if_master);
                    880: }
                    881: 
                    882: void
                    883: if_terminate (void)
                    884: {
                    885:   for (;;)
                    886:     {
                    887:       struct interface *ifp;
                    888: 
                    889:       ifp = listnode_head (iflist);
                    890:       if (ifp == NULL)
                    891:        break;
                    892: 
                    893:       if_delete (ifp);
                    894:     }
                    895: 
                    896:   list_delete (iflist);
                    897:   iflist = NULL;
                    898: }

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