File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / if.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 10 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

    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_all_node (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:   list_free (ifp->connected);
  161: 
  162:   XFREE (MTYPE_IF, ifp);
  163: }
  164: 
  165: /* Add hook to interface master. */
  166: void
  167: if_add_hook (int type, int (*func)(struct interface *ifp))
  168: {
  169:   switch (type) {
  170:   case IF_NEW_HOOK:
  171:     if_master.if_new_hook = func;
  172:     break;
  173:   case IF_DELETE_HOOK:
  174:     if_master.if_delete_hook = func;
  175:     break;
  176:   default:
  177:     break;
  178:   }
  179: }
  180: 
  181: /* Interface existance check by index. */
  182: struct interface *
  183: if_lookup_by_index (unsigned int index)
  184: {
  185:   struct listnode *node;
  186:   struct interface *ifp;
  187: 
  188:   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
  189:     {
  190:       if (ifp->ifindex == index)
  191: 	return ifp;
  192:     }
  193:   return NULL;
  194: }
  195: 
  196: const char *
  197: ifindex2ifname (unsigned int index)
  198: {
  199:   struct interface *ifp;
  200: 
  201:   return ((ifp = if_lookup_by_index(index)) != NULL) ?
  202:   	 ifp->name : "unknown";
  203: }
  204: 
  205: unsigned int
  206: ifname2ifindex (const char *name)
  207: {
  208:   struct interface *ifp;
  209: 
  210:   return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex
  211:                                                    : IFINDEX_INTERNAL;
  212: }
  213: 
  214: /* Interface existance check by interface name. */
  215: struct interface *
  216: if_lookup_by_name (const char *name)
  217: {
  218:   struct listnode *node;
  219:   struct interface *ifp;
  220:   
  221:   if (name)
  222:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  223:       {
  224:         if (strcmp(name, ifp->name) == 0)
  225:           return ifp;
  226:       }
  227:   return NULL;
  228: }
  229: 
  230: struct interface *
  231: if_lookup_by_name_len(const char *name, size_t namelen)
  232: {
  233:   struct listnode *node;
  234:   struct interface *ifp;
  235: 
  236:   if (namelen > INTERFACE_NAMSIZ)
  237:     return NULL;
  238: 
  239:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  240:     {
  241:       if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
  242: 	return ifp;
  243:     }
  244:   return NULL;
  245: }
  246: 
  247: /* Lookup interface by IPv4 address. */
  248: struct interface *
  249: if_lookup_exact_address (struct in_addr src)
  250: {
  251:   struct listnode *node;
  252:   struct listnode *cnode;
  253:   struct interface *ifp;
  254:   struct prefix *p;
  255:   struct connected *c;
  256: 
  257:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  258:     {
  259:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
  260: 	{
  261: 	  p = c->address;
  262: 
  263: 	  if (p && p->family == AF_INET)
  264: 	    {
  265: 	      if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
  266: 		return ifp;
  267: 	    }	      
  268: 	}
  269:     }
  270:   return NULL;
  271: }
  272: 
  273: /* Lookup interface by IPv4 address. */
  274: struct interface *
  275: if_lookup_address (struct in_addr src)
  276: {
  277:   struct listnode *node;
  278:   struct prefix addr;
  279:   int bestlen = 0;
  280:   struct listnode *cnode;
  281:   struct interface *ifp;
  282:   struct connected *c;
  283:   struct interface *match;
  284: 
  285:   addr.family = AF_INET;
  286:   addr.u.prefix4 = src;
  287:   addr.prefixlen = IPV4_MAX_BITLEN;
  288: 
  289:   match = NULL;
  290: 
  291:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  292:     {
  293:       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
  294: 	{
  295: 	  if (c->address && (c->address->family == AF_INET) &&
  296: 	      prefix_match(CONNECTED_PREFIX(c), &addr) &&
  297: 	      (c->address->prefixlen > bestlen))
  298: 	    {
  299: 	      bestlen = c->address->prefixlen;
  300: 	      match = ifp;
  301: 	    }
  302: 	}
  303:     }
  304:   return match;
  305: }
  306: 
  307: /* Get interface by name if given name interface doesn't exist create
  308:    one. */
  309: struct interface *
  310: if_get_by_name (const char *name)
  311: {
  312:   struct interface *ifp;
  313: 
  314:   return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp :
  315: 	 if_create(name, strlen(name));
  316: }
  317: 
  318: struct interface *
  319: if_get_by_name_len(const char *name, size_t namelen)
  320: {
  321:   struct interface *ifp;
  322: 
  323:   return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp :
  324: 	 if_create(name, namelen);
  325: }
  326: 
  327: /* Does interface up ? */
  328: int
  329: if_is_up (struct interface *ifp)
  330: {
  331:   return ifp->flags & IFF_UP;
  332: }
  333: 
  334: /* Is interface running? */
  335: int
  336: if_is_running (struct interface *ifp)
  337: {
  338:   return ifp->flags & IFF_RUNNING;
  339: }
  340: 
  341: /* Is the interface operative, eg. either UP & RUNNING
  342:    or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
  343: int
  344: if_is_operative (struct interface *ifp)
  345: {
  346:   return ((ifp->flags & IFF_UP) &&
  347: 	  (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
  348: }
  349: 
  350: /* Is this loopback interface ? */
  351: int
  352: if_is_loopback (struct interface *ifp)
  353: {
  354:   /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
  355:    * but Y on platform N?
  356:    */
  357:   return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
  358: }
  359: 
  360: /* Does this interface support broadcast ? */
  361: int
  362: if_is_broadcast (struct interface *ifp)
  363: {
  364:   return ifp->flags & IFF_BROADCAST;
  365: }
  366: 
  367: /* Does this interface support broadcast ? */
  368: int
  369: if_is_pointopoint (struct interface *ifp)
  370: {
  371:   return ifp->flags & IFF_POINTOPOINT;
  372: }
  373: 
  374: /* Does this interface support multicast ? */
  375: int
  376: if_is_multicast (struct interface *ifp)
  377: {
  378:   return ifp->flags & IFF_MULTICAST;
  379: }
  380: 
  381: /* Printout flag information into log */
  382: const char *
  383: if_flag_dump (unsigned long flag)
  384: {
  385:   int separator = 0;
  386:   static char logbuf[BUFSIZ];
  387: 
  388: #define IFF_OUT_LOG(X,STR) \
  389:   if (flag & (X)) \
  390:     { \
  391:       if (separator) \
  392: 	strlcat (logbuf, ",", BUFSIZ); \
  393:       else \
  394: 	separator = 1; \
  395:       strlcat (logbuf, STR, BUFSIZ); \
  396:     }
  397: 
  398:   strlcpy (logbuf, "<", BUFSIZ);
  399:   IFF_OUT_LOG (IFF_UP, "UP");
  400:   IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
  401:   IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
  402:   IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
  403:   IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
  404:   IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
  405:   IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
  406:   IFF_OUT_LOG (IFF_NOARP, "NOARP");
  407:   IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
  408:   IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
  409:   IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
  410:   IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
  411:   IFF_OUT_LOG (IFF_LINK0, "LINK0");
  412:   IFF_OUT_LOG (IFF_LINK1, "LINK1");
  413:   IFF_OUT_LOG (IFF_LINK2, "LINK2");
  414:   IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
  415:   IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
  416:   IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
  417:   IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
  418:   IFF_OUT_LOG (IFF_IPV4, "IPv4");
  419:   IFF_OUT_LOG (IFF_IPV6, "IPv6");
  420: 
  421:   strlcat (logbuf, ">", BUFSIZ);
  422: 
  423:   return logbuf;
  424: #undef IFF_OUT_LOG
  425: }
  426: 
  427: /* For debugging */
  428: static void
  429: if_dump (const struct interface *ifp)
  430: {
  431:   struct listnode *node;
  432:   struct connected *c;
  433: 
  434:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
  435:     zlog_info ("Interface %s index %d metric %d mtu %d "
  436: #ifdef HAVE_IPV6
  437:                "mtu6 %d "
  438: #endif /* HAVE_IPV6 */
  439:                "%s",
  440:                ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, 
  441: #ifdef HAVE_IPV6
  442:                ifp->mtu6,
  443: #endif /* HAVE_IPV6 */
  444:                if_flag_dump (ifp->flags));
  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>