LCOV - code coverage report
Current view: top level - lib - if.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 118 281 42.0 %
Date: 2015-11-19 Functions: 19 39 48.7 %

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

Generated by: LCOV version 1.10