LCOV - code coverage report
Current view: top level - zebra - zserv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 282 731 38.6 %
Date: 2015-11-19 Functions: 14 46 30.4 %

          Line data    Source code
       1             : /* Zebra daemon server routine.
       2             :  * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with GNU Zebra; see the file COPYING.  If not, write to the 
      18             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
      19             :  * Boston, MA 02111-1307, USA.  
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "prefix.h"
      25             : #include "command.h"
      26             : #include "if.h"
      27             : #include "thread.h"
      28             : #include "stream.h"
      29             : #include "memory.h"
      30             : #include "table.h"
      31             : #include "rib.h"
      32             : #include "network.h"
      33             : #include "sockunion.h"
      34             : #include "log.h"
      35             : #include "zclient.h"
      36             : #include "privs.h"
      37             : #include "network.h"
      38             : #include "buffer.h"
      39             : 
      40             : #include "zebra/zserv.h"
      41             : #include "zebra/router-id.h"
      42             : #include "zebra/redistribute.h"
      43             : #include "zebra/debug.h"
      44             : #include "zebra/ipforward.h"
      45             : 
      46             : /* Event list of zebra. */
      47             : enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
      48             : 
      49             : extern struct zebra_t zebrad;
      50             : 
      51             : static void zebra_event (enum event event, int sock, struct zserv *client);
      52             : 
      53             : extern struct zebra_privs_t zserv_privs;
      54             : 
      55             : static void zebra_client_close (struct zserv *client);
      56             : 
      57             : static int
      58           0 : zserv_delayed_close(struct thread *thread)
      59             : {
      60           0 :   struct zserv *client = THREAD_ARG(thread);
      61             : 
      62           0 :   client->t_suicide = NULL;
      63           0 :   zebra_client_close(client);
      64           0 :   return 0;
      65             : }
      66             : 
      67             : /* When client connects, it sends hello message
      68             :  * with promise to send zebra routes of specific type.
      69             :  * Zebra stores a socket fd of the client into
      70             :  * this array. And use it to clean up routes that
      71             :  * client didn't remove for some reasons after closing
      72             :  * connection.
      73             :  */
      74             : static int route_type_oaths[ZEBRA_ROUTE_MAX];
      75             : 
      76             : static int
      77           0 : zserv_flush_data(struct thread *thread)
      78             : {
      79           0 :   struct zserv *client = THREAD_ARG(thread);
      80             : 
      81           0 :   client->t_write = NULL;
      82           0 :   if (client->t_suicide)
      83             :     {
      84           0 :       zebra_client_close(client);
      85           0 :       return -1;
      86             :     }
      87           0 :   switch (buffer_flush_available(client->wb, client->sock))
      88             :     {
      89             :     case BUFFER_ERROR:
      90           0 :       zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, "
      91             :                 "closing", __func__, client->sock);
      92           0 :       zebra_client_close(client);
      93           0 :       break;
      94             :     case BUFFER_PENDING:
      95           0 :       client->t_write = thread_add_write(zebrad.master, zserv_flush_data,
      96             :                                          client, client->sock);
      97           0 :       break;
      98             :     case BUFFER_EMPTY:
      99           0 :       break;
     100             :     }
     101           0 :   return 0;
     102             : }
     103             : 
     104             : static int
     105           0 : zebra_server_send_message(struct zserv *client)
     106             : {
     107           0 :   if (client->t_suicide)
     108           0 :     return -1;
     109           0 :   switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
     110             :                        stream_get_endp(client->obuf)))
     111             :     {
     112             :     case BUFFER_ERROR:
     113           0 :       zlog_warn("%s: buffer_write failed to zserv client fd %d, closing",
     114             :                  __func__, client->sock);
     115             :       /* Schedule a delayed close since many of the functions that call this
     116             :          one do not check the return code.  They do not allow for the
     117             :          possibility that an I/O error may have caused the client to be
     118             :          deleted. */
     119           0 :       client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
     120             :                                            client, 0);
     121           0 :       return -1;
     122             :     case BUFFER_EMPTY:
     123           0 :       THREAD_OFF(client->t_write);
     124           0 :       break;
     125             :     case BUFFER_PENDING:
     126           0 :       THREAD_WRITE_ON(zebrad.master, client->t_write,
     127             :                       zserv_flush_data, client, client->sock);
     128           0 :       break;
     129             :     }
     130           0 :   return 0;
     131             : }
     132             : 
     133             : static void
     134           0 : zserv_create_header (struct stream *s, uint16_t cmd)
     135             : {
     136             :   /* length placeholder, caller can update */
     137           0 :   stream_putw (s, ZEBRA_HEADER_SIZE);
     138           0 :   stream_putc (s, ZEBRA_HEADER_MARKER);
     139           0 :   stream_putc (s, ZSERV_VERSION);
     140           0 :   stream_putw (s, cmd);
     141           0 : }
     142             : 
     143             : static void
     144           0 : zserv_encode_interface (struct stream *s, struct interface *ifp)
     145             : {
     146             :   /* Interface information. */
     147           0 :   stream_put (s, ifp->name, INTERFACE_NAMSIZ);
     148           0 :   stream_putl (s, ifp->ifindex);
     149           0 :   stream_putc (s, ifp->status);
     150           0 :   stream_putq (s, ifp->flags);
     151           0 :   stream_putl (s, ifp->metric);
     152           0 :   stream_putl (s, ifp->mtu);
     153           0 :   stream_putl (s, ifp->mtu6);
     154           0 :   stream_putl (s, ifp->bandwidth);
     155             : #ifdef HAVE_STRUCT_SOCKADDR_DL
     156             :   stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage));
     157             : #else
     158           0 :   stream_putl (s, ifp->hw_addr_len);
     159           0 :   if (ifp->hw_addr_len)
     160           0 :     stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
     161             : #endif /* HAVE_STRUCT_SOCKADDR_DL */
     162             : 
     163             :   /* Write packet size. */
     164           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     165           0 : }
     166             : 
     167             : /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
     168             : /*
     169             :  * This function is called in the following situations:
     170             :  * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
     171             :  *   from the client.
     172             :  * - at startup, when zebra figures out the available interfaces
     173             :  * - when an interface is added (where support for
     174             :  *   RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
     175             :  *   an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
     176             :  *   received)
     177             :  */
     178             : int
     179           0 : zsend_interface_add (struct zserv *client, struct interface *ifp)
     180             : {
     181             :   struct stream *s;
     182             : 
     183             :   /* Check this client need interface information. */
     184           0 :   if (! client->ifinfo)
     185           0 :     return 0;
     186             : 
     187           0 :   s = client->obuf;
     188           0 :   stream_reset (s);
     189             : 
     190           0 :   zserv_create_header (s, ZEBRA_INTERFACE_ADD);
     191           0 :   zserv_encode_interface (s, ifp);
     192             : 
     193           0 :   return zebra_server_send_message(client);
     194             : }
     195             : 
     196             : /* Interface deletion from zebra daemon. */
     197             : int
     198           0 : zsend_interface_delete (struct zserv *client, struct interface *ifp)
     199             : {
     200             :   struct stream *s;
     201             : 
     202             :   /* Check this client need interface information. */
     203           0 :   if (! client->ifinfo)
     204           0 :     return 0;
     205             : 
     206           0 :   s = client->obuf;
     207           0 :   stream_reset (s);
     208             : 
     209           0 :   zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
     210           0 :   zserv_encode_interface (s, ifp);
     211             : 
     212           0 :   return zebra_server_send_message (client);
     213             : }
     214             : 
     215             : /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
     216             :  * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. 
     217             :  *
     218             :  * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
     219             :  * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
     220             :  *   from the client, after the ZEBRA_INTERFACE_ADD has been
     221             :  *   sent from zebra to the client
     222             :  * - redistribute new address info to all clients in the following situations
     223             :  *    - at startup, when zebra figures out the available interfaces
     224             :  *    - when an interface is added (where support for
     225             :  *      RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
     226             :  *      an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
     227             :  *      received)
     228             :  *    - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
     229             :  *      and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
     230             :  *    - when an RTM_NEWADDR message is received from the kernel,
     231             :  * 
     232             :  * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE: 
     233             :  *
     234             :  *                   zsend_interface_address(DELETE)
     235             :  *                           ^                         
     236             :  *                           |                        
     237             :  *          zebra_interface_address_delete_update    
     238             :  *             ^                        ^      ^
     239             :  *             |                        |      if_delete_update
     240             :  *             |                        |
     241             :  *         ip_address_uninstall        connected_delete_ipv4
     242             :  *         [ipv6_addresss_uninstall]   [connected_delete_ipv6]
     243             :  *             ^                        ^
     244             :  *             |                        |
     245             :  *             |                  RTM_NEWADDR on routing/netlink socket
     246             :  *             |
     247             :  *         vty commands:
     248             :  *     "no ip address A.B.C.D/M [label LINE]"
     249             :  *     "no ip address A.B.C.D/M secondary"
     250             :  *     ["no ipv6 address X:X::X:X/M"]
     251             :  *
     252             :  */
     253             : int
     254           0 : zsend_interface_address (int cmd, struct zserv *client, 
     255             :                          struct interface *ifp, struct connected *ifc)
     256             : {
     257             :   int blen;
     258             :   struct stream *s;
     259             :   struct prefix *p;
     260             : 
     261             :   /* Check this client need interface information. */
     262           0 :   if (! client->ifinfo)
     263           0 :     return 0;
     264             : 
     265           0 :   s = client->obuf;
     266           0 :   stream_reset (s);
     267             :   
     268           0 :   zserv_create_header (s, cmd);
     269           0 :   stream_putl (s, ifp->ifindex);
     270             : 
     271             :   /* Interface address flag. */
     272           0 :   stream_putc (s, ifc->flags);
     273             : 
     274             :   /* Prefix information. */
     275           0 :   p = ifc->address;
     276           0 :   stream_putc (s, p->family);
     277           0 :   blen = prefix_blen (p);
     278           0 :   stream_put (s, &p->u.prefix, blen);
     279             : 
     280             :   /* 
     281             :    * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
     282             :    * but zebra_interface_address_delete_read() in the gnu version 
     283             :    * expects to find it
     284             :    */
     285           0 :   stream_putc (s, p->prefixlen);
     286             : 
     287             :   /* Destination. */
     288           0 :   p = ifc->destination;
     289           0 :   if (p)
     290           0 :     stream_put (s, &p->u.prefix, blen);
     291             :   else
     292           0 :     stream_put (s, NULL, blen);
     293             : 
     294             :   /* Write packet size. */
     295           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     296             : 
     297           0 :   return zebra_server_send_message(client);
     298             : }
     299             : 
     300             : /*
     301             :  * The cmd passed to zsend_interface_update  may be ZEBRA_INTERFACE_UP or
     302             :  * ZEBRA_INTERFACE_DOWN.
     303             :  *
     304             :  * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
     305             :  * the clients in one of 2 situations:
     306             :  *   - an if_up is detected e.g., as a result of an RTM_IFINFO message
     307             :  *   - a vty command modifying the bandwidth of an interface is received.
     308             :  * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
     309             :  */
     310             : int
     311           0 : zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
     312             : {
     313             :   struct stream *s;
     314             : 
     315             :   /* Check this client need interface information. */
     316           0 :   if (! client->ifinfo)
     317           0 :     return 0;
     318             : 
     319           0 :   s = client->obuf;
     320           0 :   stream_reset (s);
     321             : 
     322           0 :   zserv_create_header (s, cmd);
     323           0 :   zserv_encode_interface (s, ifp);
     324             : 
     325           0 :   return zebra_server_send_message(client);
     326             : }
     327             : 
     328             : /*
     329             :  * The zebra server sends the clients  a ZEBRA_IPV4_ROUTE_ADD or a
     330             :  * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
     331             :  * situations:
     332             :  * - when the client starts up, and requests default information
     333             :  *   by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
     334             :  * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
     335             :  *   ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
     336             :  * - when the zebra server redistributes routes after it updates its rib
     337             :  *
     338             :  * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
     339             :  * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
     340             :  * - a "ip route"  or "ipv6 route" vty command is issued, a prefix is
     341             :  * - deleted from zebra's rib, and this info
     342             :  *   has to be redistributed to the clients 
     343             :  * 
     344             :  * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
     345             :  * zebra server when the client wants to tell the zebra server to add a
     346             :  * route to the kernel (zapi_ipv4_add etc. ).  Since it's essentially the
     347             :  * same message being sent back and forth, this function and
     348             :  * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
     349             :  * duplication.
     350             :  */
     351             : int
     352           0 : zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
     353             :                        struct prefix *src_p, struct rib *rib)
     354             : {
     355             :   int psize;
     356             :   struct stream *s;
     357             :   struct nexthop *nexthop;
     358           0 :   unsigned long nhnummark = 0, messmark = 0;
     359           0 :   int nhnum = 0;
     360           0 :   u_char zapi_flags = 0;
     361             :   
     362           0 :   s = client->obuf;
     363           0 :   stream_reset (s);
     364             :   
     365           0 :   zserv_create_header (s, cmd);
     366             :   
     367             :   /* Put type and nexthop. */
     368           0 :   stream_putc (s, rib->type);
     369           0 :   stream_putc (s, rib->flags);
     370             :   
     371             :   /* marker for message flags field */
     372           0 :   messmark = stream_get_endp (s);
     373           0 :   stream_putc (s, 0);
     374             : 
     375             :   /* Prefix. */
     376           0 :   psize = PSIZE (p->prefixlen);
     377           0 :   stream_putc (s, p->prefixlen);
     378           0 :   stream_write (s, (u_char *) & p->u.prefix, psize);
     379             : 
     380           0 :   if (src_p)
     381             :     {
     382           0 :       SET_FLAG (zapi_flags, ZAPI_MESSAGE_SRCPFX);
     383           0 :       psize = PSIZE (src_p->prefixlen);
     384           0 :       stream_putc (s, src_p->prefixlen);
     385           0 :       stream_write (s, (u_char *) & src_p->u.prefix, psize);
     386             :     }
     387             : 
     388             :   /* 
     389             :    * XXX The message format sent by zebra below does not match the format
     390             :    * of the corresponding message expected by the zebra server
     391             :    * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly,
     392             :    * (is there a bug on the client side if more than one segment is sent?)
     393             :    * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX 
     394             :    * is hard-coded.
     395             :    */
     396             :   /* Nexthop */
     397             :   
     398           0 :   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
     399             :     {
     400           0 :       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
     401           0 :           || nexthop_has_fib_child(nexthop))
     402             :         {
     403           0 :           SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
     404           0 :           SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
     405             :           
     406           0 :           if (nhnummark == 0)
     407             :             {
     408           0 :               nhnummark = stream_get_endp (s);
     409           0 :               stream_putc (s, 1); /* placeholder */
     410             :             }
     411             :           
     412           0 :           nhnum++;
     413             : 
     414           0 :           switch(nexthop->type) 
     415             :             {
     416             :               case NEXTHOP_TYPE_IPV4:
     417             :               case NEXTHOP_TYPE_IPV4_IFINDEX:
     418           0 :                 stream_put_in_addr (s, &nexthop->gate.ipv4);
     419           0 :                 break;
     420             : #ifdef HAVE_IPV6
     421             :               case NEXTHOP_TYPE_IPV6:
     422             :               case NEXTHOP_TYPE_IPV6_IFINDEX:
     423             :               case NEXTHOP_TYPE_IPV6_IFNAME:
     424           0 :                 stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
     425           0 :                 break;
     426             : #endif
     427             :               default:
     428           0 :                 if (cmd == ZEBRA_IPV4_ROUTE_ADD 
     429           0 :                     || cmd == ZEBRA_IPV4_ROUTE_DELETE)
     430           0 :                   {
     431             :                     struct in_addr empty;
     432           0 :                     memset (&empty, 0, sizeof (struct in_addr));
     433           0 :                     stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
     434             :                   }
     435             :                 else
     436             :                   {
     437             :                     struct in6_addr empty;
     438           0 :                     memset (&empty, 0, sizeof (struct in6_addr));
     439           0 :                     stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
     440             :                   }
     441             :               }
     442             : 
     443             :           /* Interface index. */
     444           0 :           stream_putc (s, 1);
     445           0 :           stream_putl (s, nexthop->ifindex);
     446             : 
     447           0 :           break;
     448             :         }
     449             :     }
     450             : 
     451             :   /* Metric */
     452           0 :   if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD)
     453             :     {
     454           0 :       SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
     455           0 :       stream_putc (s, rib->distance);
     456           0 :       SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
     457           0 :       stream_putl (s, rib->metric);
     458             :     }
     459             :   
     460             :   /* write real message flags value */
     461           0 :   stream_putc_at (s, messmark, zapi_flags);
     462             :   
     463             :   /* Write next-hop number */
     464           0 :   if (nhnummark)
     465           0 :     stream_putc_at (s, nhnummark, nhnum);
     466             :   
     467             :   /* Write packet size. */
     468           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     469             : 
     470           0 :   return zebra_server_send_message(client);
     471             : }
     472             : 
     473             : #ifdef HAVE_IPV6
     474             : static int
     475           0 : zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
     476             : {
     477             :   struct stream *s;
     478             :   struct rib *rib;
     479             :   unsigned long nump;
     480             :   u_char num;
     481             :   struct nexthop *nexthop;
     482             : 
     483             :   /* Lookup nexthop. */
     484           0 :   rib = rib_match_ipv6 (addr);
     485             : 
     486             :   /* Get output stream. */
     487           0 :   s = client->obuf;
     488           0 :   stream_reset (s);
     489             : 
     490             :   /* Fill in result. */
     491           0 :   zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
     492           0 :   stream_put (s, &addr, 16);
     493             : 
     494           0 :   if (rib)
     495             :     {
     496           0 :       stream_putl (s, rib->metric);
     497           0 :       num = 0;
     498           0 :       nump = stream_get_endp(s);
     499           0 :       stream_putc (s, 0);
     500             :       /* Only non-recursive routes are elegible to resolve nexthop we
     501             :        * are looking up. Therefore, we will just iterate over the top
     502             :        * chain of nexthops. */
     503           0 :       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
     504           0 :         if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
     505             :           {
     506           0 :             stream_putc (s, nexthop->type);
     507           0 :             switch (nexthop->type)
     508             :               {
     509             :               case ZEBRA_NEXTHOP_IPV6:
     510           0 :                 stream_put (s, &nexthop->gate.ipv6, 16);
     511           0 :                 break;
     512             :               case ZEBRA_NEXTHOP_IPV6_IFINDEX:
     513             :               case ZEBRA_NEXTHOP_IPV6_IFNAME:
     514           0 :                 stream_put (s, &nexthop->gate.ipv6, 16);
     515           0 :                 stream_putl (s, nexthop->ifindex);
     516           0 :                 break;
     517             :               case ZEBRA_NEXTHOP_IFINDEX:
     518             :               case ZEBRA_NEXTHOP_IFNAME:
     519           0 :                 stream_putl (s, nexthop->ifindex);
     520           0 :                 break;
     521             :               default:
     522             :                 /* do nothing */
     523           0 :                 break;
     524             :               }
     525           0 :             num++;
     526             :           }
     527           0 :       stream_putc_at (s, nump, num);
     528             :     }
     529             :   else
     530             :     {
     531           0 :       stream_putl (s, 0);
     532           0 :       stream_putc (s, 0);
     533             :     }
     534             : 
     535           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     536             :   
     537           0 :   return zebra_server_send_message(client);
     538             : }
     539             : #endif /* HAVE_IPV6 */
     540             : 
     541             : static int
     542           0 : zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
     543             : {
     544             :   struct stream *s;
     545             :   struct rib *rib;
     546             :   unsigned long nump;
     547             :   u_char num;
     548             :   struct nexthop *nexthop;
     549             : 
     550             :   /* Lookup nexthop. */
     551           0 :   rib = rib_match_ipv4 (addr);
     552             : 
     553             :   /* Get output stream. */
     554           0 :   s = client->obuf;
     555           0 :   stream_reset (s);
     556             : 
     557             :   /* Fill in result. */
     558           0 :   zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
     559           0 :   stream_put_in_addr (s, &addr);
     560             : 
     561           0 :   if (rib)
     562             :     {
     563           0 :       if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
     564           0 :         zlog_debug("%s: Matching rib entry found.", __func__);
     565           0 :       stream_putl (s, rib->metric);
     566           0 :       num = 0;
     567           0 :       nump = stream_get_endp(s);
     568           0 :       stream_putc (s, 0);
     569             :       /* Only non-recursive routes are elegible to resolve the nexthop we
     570             :        * are looking up. Therefore, we will just iterate over the top
     571             :        * chain of nexthops. */
     572           0 :       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
     573           0 :         if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
     574             :           {
     575           0 :             stream_putc (s, nexthop->type);
     576           0 :             switch (nexthop->type)
     577             :               {
     578             :               case ZEBRA_NEXTHOP_IPV4:
     579           0 :                 stream_put_in_addr (s, &nexthop->gate.ipv4);
     580           0 :                 break;
     581             :               case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     582           0 :                 stream_put_in_addr (s, &nexthop->gate.ipv4);
     583           0 :                 stream_putl (s, nexthop->ifindex);
     584           0 :                 break;
     585             :               case ZEBRA_NEXTHOP_IFINDEX:
     586             :               case ZEBRA_NEXTHOP_IFNAME:
     587           0 :                 stream_putl (s, nexthop->ifindex);
     588           0 :                 break;
     589             :               default:
     590             :                 /* do nothing */
     591           0 :                 break;
     592             :               }
     593           0 :             num++;
     594             :           }
     595           0 :       stream_putc_at (s, nump, num);
     596             :     }
     597             :   else
     598             :     {
     599           0 :       if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
     600           0 :         zlog_debug("%s: No matching rib entry found.", __func__);
     601           0 :       stream_putl (s, 0);
     602           0 :       stream_putc (s, 0);
     603             :     }
     604             : 
     605           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     606             :   
     607           0 :   return zebra_server_send_message(client);
     608             : }
     609             : 
     610             : static int
     611           0 : zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
     612             : {
     613             :   struct stream *s;
     614             :   struct rib *rib;
     615             :   unsigned long nump;
     616             :   u_char num;
     617             :   struct nexthop *nexthop;
     618             : 
     619             :   /* Lookup nexthop. */
     620           0 :   rib = rib_lookup_ipv4 (p);
     621             : 
     622             :   /* Get output stream. */
     623           0 :   s = client->obuf;
     624           0 :   stream_reset (s);
     625             : 
     626             :   /* Fill in result. */
     627           0 :   zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
     628           0 :   stream_put_in_addr (s, &p->prefix);
     629             : 
     630           0 :   if (rib)
     631             :     {
     632           0 :       stream_putl (s, rib->metric);
     633           0 :       num = 0;
     634           0 :       nump = stream_get_endp(s);
     635           0 :       stream_putc (s, 0);
     636           0 :       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
     637           0 :         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
     638           0 :             || nexthop_has_fib_child(nexthop))
     639             :           {
     640           0 :             stream_putc (s, nexthop->type);
     641           0 :             switch (nexthop->type)
     642             :               {
     643             :               case ZEBRA_NEXTHOP_IPV4:
     644           0 :                 stream_put_in_addr (s, &nexthop->gate.ipv4);
     645           0 :                 break;
     646             :               case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     647           0 :                 stream_put_in_addr (s, &nexthop->gate.ipv4);
     648           0 :                 stream_putl (s, nexthop->ifindex);
     649           0 :                 break;
     650             :               case ZEBRA_NEXTHOP_IFINDEX:
     651             :               case ZEBRA_NEXTHOP_IFNAME:
     652           0 :                 stream_putl (s, nexthop->ifindex);
     653           0 :                 break;
     654             :               default:
     655             :                 /* do nothing */
     656           0 :                 break;
     657             :               }
     658           0 :             num++;
     659             :           }
     660           0 :       stream_putc_at (s, nump, num);
     661             :     }
     662             :   else
     663             :     {
     664           0 :       stream_putl (s, 0);
     665           0 :       stream_putc (s, 0);
     666             :     }
     667             : 
     668           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     669             :   
     670           0 :   return zebra_server_send_message(client);
     671             : }
     672             : 
     673             : /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
     674             : int
     675           0 : zsend_router_id_update (struct zserv *client, struct prefix *p)
     676             : {
     677             :   struct stream *s;
     678             :   int blen;
     679             : 
     680             :   /* Check this client need interface information. */
     681           0 :   if (!client->ridinfo)
     682           0 :     return 0;
     683             : 
     684           0 :   s = client->obuf;
     685           0 :   stream_reset (s);
     686             : 
     687             :   /* Message type. */
     688           0 :   zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE);
     689             : 
     690             :   /* Prefix information. */
     691           0 :   stream_putc (s, p->family);
     692           0 :   blen = prefix_blen (p);
     693           0 :   stream_put (s, &p->u.prefix, blen);
     694           0 :   stream_putc (s, p->prefixlen);
     695             : 
     696             :   /* Write packet size. */
     697           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     698             : 
     699           0 :   return zebra_server_send_message(client);
     700             : }
     701             : 
     702             : /* Register zebra server interface information.  Send current all
     703             :    interface and address information. */
     704             : static int
     705           0 : zread_interface_add (struct zserv *client, u_short length)
     706             : {
     707             :   struct listnode *ifnode, *ifnnode;
     708             :   struct listnode *cnode, *cnnode;
     709             :   struct interface *ifp;
     710             :   struct connected *c;
     711             : 
     712             :   /* Interface information is needed. */
     713           0 :   client->ifinfo = 1;
     714             : 
     715           0 :   for (ALL_LIST_ELEMENTS (iflist, ifnode, ifnnode, ifp))
     716             :     {
     717             :       /* Skip pseudo interface. */
     718           0 :       if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
     719           0 :         continue;
     720             : 
     721           0 :       if (zsend_interface_add (client, ifp) < 0)
     722           0 :         return -1;
     723             : 
     724           0 :       for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
     725             :         {
     726           0 :           if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
     727           0 :               (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, 
     728             :                                         ifp, c) < 0))
     729           0 :             return -1;
     730             :         }
     731             :     }
     732           0 :   return 0;
     733             : }
     734             : 
     735             : /* Unregister zebra server interface information. */
     736             : static int
     737           0 : zread_interface_delete (struct zserv *client, u_short length)
     738             : {
     739           0 :   client->ifinfo = 0;
     740           0 :   return 0;
     741             : }
     742             : 
     743             : /* This function support multiple nexthop. */
     744             : /* 
     745             :  * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
     746             :  * add kernel route. 
     747             :  */
     748             : static int
     749          60 : zread_ipv4_add (struct zserv *client, u_short length)
     750             : {
     751             :   int i;
     752             :   struct rib *rib;
     753             :   struct prefix_ipv4 p;
     754             :   u_char message;
     755             :   struct in_addr nexthop;
     756             :   u_char nexthop_num;
     757             :   u_char nexthop_type;
     758             :   struct stream *s;
     759             :   unsigned int ifindex;
     760             :   u_char ifname_len;
     761             :   safi_t safi;  
     762             : 
     763             : 
     764             :   /* Get input stream.  */
     765          60 :   s = client->ibuf;
     766             : 
     767             :   /* Allocate new rib. */
     768          60 :   rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
     769             :   
     770             :   /* Type, flags, message. */
     771          60 :   rib->type = stream_getc (s);
     772          60 :   rib->flags = stream_getc (s);
     773          60 :   message = stream_getc (s); 
     774          60 :   safi = stream_getw (s);
     775          60 :   rib->uptime = time (NULL);
     776             : 
     777             :   /* IPv4 prefix. */
     778          60 :   memset (&p, 0, sizeof (struct prefix_ipv4));
     779          60 :   p.family = AF_INET;
     780          60 :   p.prefixlen = stream_getc (s);
     781          60 :   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
     782             : 
     783             :   /* Nexthop parse. */
     784          60 :   if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
     785             :     {
     786          60 :       nexthop_num = stream_getc (s);
     787             : 
     788         259 :       for (i = 0; i < nexthop_num; i++)
     789             :         {
     790         199 :           nexthop_type = stream_getc (s);
     791             : 
     792         199 :           switch (nexthop_type)
     793             :             {
     794             :             case ZEBRA_NEXTHOP_IFINDEX:
     795          22 :               ifindex = stream_getl (s);
     796          22 :               nexthop_ifindex_add (rib, ifindex);
     797          22 :               break;
     798             :             case ZEBRA_NEXTHOP_IFNAME:
     799           0 :               ifname_len = stream_getc (s);
     800           0 :               stream_forward_getp (s, ifname_len);
     801           0 :               break;
     802             :             case ZEBRA_NEXTHOP_IPV4:
     803         168 :               nexthop.s_addr = stream_get_ipv4 (s);
     804         168 :               nexthop_ipv4_add (rib, &nexthop, NULL);
     805         168 :               break;
     806             :             case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     807           9 :               nexthop.s_addr = stream_get_ipv4 (s);
     808           9 :               ifindex = stream_getl (s);
     809           9 :               nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
     810           9 :               break;
     811             :             case ZEBRA_NEXTHOP_IPV6:
     812           0 :               stream_forward_getp (s, IPV6_MAX_BYTELEN);
     813           0 :               break;
     814             :             case ZEBRA_NEXTHOP_BLACKHOLE:
     815           0 :               nexthop_blackhole_add (rib);
     816           0 :               break;
     817             :             }
     818             :         }
     819             :     }
     820             : 
     821             :   /* Distance. */
     822          60 :   if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
     823           0 :     rib->distance = stream_getc (s);
     824             : 
     825             :   /* Metric. */
     826          60 :   if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
     827           0 :     rib->metric = stream_getl (s);
     828             :     
     829             :   /* Table */
     830          60 :   rib->table=zebrad.rtm_table_default;
     831          60 :   rib_add_ipv4_multipath (&p, rib, safi);
     832          60 :   return 0;
     833             : }
     834             : 
     835             : /* Zebra server IPv4 prefix delete function. */
     836             : static int
     837          33 : zread_ipv4_delete (struct zserv *client, u_short length)
     838             : {
     839             :   int i;
     840             :   struct stream *s;
     841             :   struct zapi_ipv4 api;
     842             :   struct in_addr nexthop, *nexthop_p;
     843             :   unsigned long ifindex;
     844             :   struct prefix_ipv4 p;
     845             :   u_char nexthop_num;
     846             :   u_char nexthop_type;
     847             :   u_char ifname_len;
     848             :   
     849          33 :   s = client->ibuf;
     850          33 :   ifindex = 0;
     851          33 :   nexthop.s_addr = 0;
     852          33 :   nexthop_p = NULL;
     853             : 
     854             :   /* Type, flags, message. */
     855          33 :   api.type = stream_getc (s);
     856          33 :   api.flags = stream_getc (s);
     857          33 :   api.message = stream_getc (s);
     858          33 :   api.safi = stream_getw (s);
     859             : 
     860             :   /* IPv4 prefix. */
     861          33 :   memset (&p, 0, sizeof (struct prefix_ipv4));
     862          33 :   p.family = AF_INET;
     863          33 :   p.prefixlen = stream_getc (s);
     864          33 :   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
     865             : 
     866             :   /* Nexthop, ifindex, distance, metric. */
     867          33 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
     868             :     {
     869          33 :       nexthop_num = stream_getc (s);
     870             : 
     871         199 :       for (i = 0; i < nexthop_num; i++)
     872             :         {
     873         166 :           nexthop_type = stream_getc (s);
     874             : 
     875         166 :           switch (nexthop_type)
     876             :             {
     877             :             case ZEBRA_NEXTHOP_IFINDEX:
     878           8 :               ifindex = stream_getl (s);
     879           8 :               break;
     880             :             case ZEBRA_NEXTHOP_IFNAME:
     881           0 :               ifname_len = stream_getc (s);
     882           0 :               stream_forward_getp (s, ifname_len);
     883           0 :               break;
     884             :             case ZEBRA_NEXTHOP_IPV4:
     885         153 :               nexthop.s_addr = stream_get_ipv4 (s);
     886         153 :               nexthop_p = &nexthop;
     887         153 :               break;
     888             :             case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     889           5 :               nexthop.s_addr = stream_get_ipv4 (s);
     890           5 :               nexthop_p = &nexthop;
     891           5 :               ifindex = stream_getl (s);
     892           5 :               break;
     893             :             case ZEBRA_NEXTHOP_IPV6:
     894           0 :               stream_forward_getp (s, IPV6_MAX_BYTELEN);
     895           0 :               break;
     896             :             }
     897             :         }
     898             :     }
     899             : 
     900             :   /* Distance. */
     901          33 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     902           0 :     api.distance = stream_getc (s);
     903             :   else
     904          33 :     api.distance = 0;
     905             : 
     906             :   /* Metric. */
     907          33 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
     908           0 :     api.metric = stream_getl (s);
     909             :   else
     910          33 :     api.metric = 0;
     911             :     
     912          66 :   rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
     913          66 :                    client->rtm_table, api.safi);
     914          33 :   return 0;
     915             : }
     916             : 
     917             : /* Nexthop lookup for IPv4. */
     918             : static int
     919           0 : zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
     920             : {
     921             :   struct in_addr addr;
     922             :   char buf[BUFSIZ];
     923             : 
     924           0 :   addr.s_addr = stream_get_ipv4 (client->ibuf);
     925           0 :   if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
     926           0 :     zlog_debug("%s: looking up %s", __func__,
     927             :                inet_ntop (AF_INET, &addr, buf, BUFSIZ));
     928           0 :   return zsend_ipv4_nexthop_lookup (client, addr);
     929             : }
     930             : 
     931             : /* Nexthop lookup for IPv4. */
     932             : static int
     933           0 : zread_ipv4_import_lookup (struct zserv *client, u_short length)
     934             : {
     935             :   struct prefix_ipv4 p;
     936             : 
     937           0 :   p.family = AF_INET;
     938           0 :   p.prefixlen = stream_getc (client->ibuf);
     939           0 :   p.prefix.s_addr = stream_get_ipv4 (client->ibuf);
     940             : 
     941           0 :   return zsend_ipv4_import_lookup (client, &p);
     942             : }
     943             : 
     944             : #ifdef HAVE_IPV6
     945             : /* Zebra server IPv6 prefix add function. */
     946             : static int
     947          28 : zread_ipv6_add (struct zserv *client, u_short length)
     948             : {
     949             :   int i;
     950             :   struct stream *s;
     951             :   struct zapi_ipv6 api;
     952             :   struct in6_addr nexthop;
     953             :   unsigned long ifindex;
     954             :   struct prefix_ipv6 p, src_p, *src_pp;
     955             :   
     956          28 :   s = client->ibuf;
     957          28 :   ifindex = 0;
     958          28 :   memset (&nexthop, 0, sizeof (struct in6_addr));
     959             : 
     960             :   /* Type, flags, message. */
     961          28 :   api.type = stream_getc (s);
     962          28 :   api.flags = stream_getc (s);
     963          28 :   api.message = stream_getc (s);
     964          28 :   api.safi = stream_getw (s);
     965             : 
     966             :   /* IPv4 prefix. */
     967          28 :   memset (&p, 0, sizeof (struct prefix_ipv6));
     968          28 :   p.family = AF_INET6;
     969          28 :   p.prefixlen = stream_getc (s);
     970          28 :   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
     971             : 
     972          28 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX))
     973             :     {
     974           6 :       memset (&src_p, 0, sizeof (struct prefix_ipv6));
     975           6 :       src_p.family = AF_INET6;
     976           6 :       src_p.prefixlen = stream_getc (s);
     977           6 :       stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen));
     978           6 :       src_pp = &src_p;
     979             :     }
     980             :   else
     981          22 :     src_pp = NULL;
     982             : 
     983             :   /* Nexthop, ifindex, distance, metric. */
     984          28 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
     985             :     {
     986             :       u_char nexthop_type;
     987             : 
     988          28 :       api.nexthop_num = stream_getc (s);
     989          64 :       for (i = 0; i < api.nexthop_num; i++)
     990             :         {
     991          36 :           nexthop_type = stream_getc (s);
     992             : 
     993          36 :           switch (nexthop_type)
     994             :             {
     995             :             case ZEBRA_NEXTHOP_IPV6:
     996          22 :               stream_get (&nexthop, s, 16);
     997          22 :               break;
     998             :             case ZEBRA_NEXTHOP_IFINDEX:
     999          14 :               ifindex = stream_getl (s);
    1000          14 :               break;
    1001             :             }
    1002             :         }
    1003             :     }
    1004             : 
    1005          28 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    1006           0 :     api.distance = stream_getc (s);
    1007             :   else
    1008          28 :     api.distance = 0;
    1009             : 
    1010          28 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    1011           0 :     api.metric = stream_getl (s);
    1012             :   else
    1013          28 :     api.metric = 0;
    1014             :     
    1015          28 :   if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    1016          12 :     rib_add_ipv6 (api.type, api.flags, &p, src_pp, NULL, ifindex, zebrad.rtm_table_default, api.metric,
    1017          12 :                   api.distance, api.safi);
    1018             :   else
    1019          44 :     rib_add_ipv6 (api.type, api.flags, &p, src_pp, &nexthop, ifindex, zebrad.rtm_table_default, api.metric,
    1020          44 :                   api.distance, api.safi);
    1021          28 :   return 0;
    1022             : }
    1023             : 
    1024             : /* Zebra server IPv6 prefix delete function. */
    1025             : static int
    1026          14 : zread_ipv6_delete (struct zserv *client, u_short length)
    1027             : {
    1028             :   int i;
    1029             :   struct stream *s;
    1030             :   struct zapi_ipv6 api;
    1031             :   struct in6_addr nexthop;
    1032             :   unsigned long ifindex;
    1033             :   struct prefix_ipv6 p, src_p, *src_pp;
    1034             :   
    1035          14 :   s = client->ibuf;
    1036          14 :   ifindex = 0;
    1037          14 :   memset (&nexthop, 0, sizeof (struct in6_addr));
    1038             : 
    1039             :   /* Type, flags, message. */
    1040          14 :   api.type = stream_getc (s);
    1041          14 :   api.flags = stream_getc (s);
    1042          14 :   api.message = stream_getc (s);
    1043          14 :   api.safi = stream_getw (s);
    1044             : 
    1045             :   /* IPv4 prefix. */
    1046          14 :   memset (&p, 0, sizeof (struct prefix_ipv6));
    1047          14 :   p.family = AF_INET6;
    1048          14 :   p.prefixlen = stream_getc (s);
    1049          14 :   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
    1050             : 
    1051          14 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX))
    1052             :     {
    1053           5 :       memset (&src_p, 0, sizeof (struct prefix_ipv6));
    1054           5 :       src_p.family = AF_INET6;
    1055           5 :       src_p.prefixlen = stream_getc (s);
    1056           5 :       stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen));
    1057           5 :       src_pp = &src_p;
    1058             :     }
    1059             :   else
    1060           9 :     src_pp = NULL;
    1061             : 
    1062             :   /* Nexthop, ifindex, distance, metric. */
    1063          14 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    1064             :     {
    1065             :       u_char nexthop_type;
    1066             : 
    1067          14 :       api.nexthop_num = stream_getc (s);
    1068          32 :       for (i = 0; i < api.nexthop_num; i++)
    1069             :         {
    1070          18 :           nexthop_type = stream_getc (s);
    1071             : 
    1072          18 :           switch (nexthop_type)
    1073             :             {
    1074             :             case ZEBRA_NEXTHOP_IPV6:
    1075          12 :               stream_get (&nexthop, s, 16);
    1076          12 :               break;
    1077             :             case ZEBRA_NEXTHOP_IFINDEX:
    1078           6 :               ifindex = stream_getl (s);
    1079           6 :               break;
    1080             :             }
    1081             :         }
    1082             :     }
    1083             : 
    1084          14 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    1085           0 :     api.distance = stream_getc (s);
    1086             :   else
    1087          14 :     api.distance = 0;
    1088          14 :   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    1089           0 :     api.metric = stream_getl (s);
    1090             :   else
    1091          14 :     api.metric = 0;
    1092             :     
    1093          14 :   if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    1094           2 :     rib_delete_ipv6 (api.type, api.flags, &p, src_pp, NULL, ifindex, client->rtm_table, api.safi);
    1095             :   else
    1096          12 :     rib_delete_ipv6 (api.type, api.flags, &p, src_pp, &nexthop, ifindex, client->rtm_table, api.safi);
    1097          14 :   return 0;
    1098             : }
    1099             : 
    1100             : static int
    1101           0 : zread_ipv6_nexthop_lookup (struct zserv *client, u_short length)
    1102             : {
    1103             :   struct in6_addr addr;
    1104             :   char buf[BUFSIZ];
    1105             : 
    1106           0 :   stream_get (&addr, client->ibuf, 16);
    1107           0 :   if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    1108           0 :     zlog_debug("%s: looking up %s", __func__,
    1109             :                inet_ntop (AF_INET6, &addr, buf, BUFSIZ));
    1110             : 
    1111           0 :   return zsend_ipv6_nexthop_lookup (client, &addr);
    1112             : }
    1113             : #endif /* HAVE_IPV6 */
    1114             : 
    1115             : /* Register zebra server router-id information.  Send current router-id */
    1116             : static int
    1117           0 : zread_router_id_add (struct zserv *client, u_short length)
    1118             : {
    1119             :   struct prefix p;
    1120             : 
    1121             :   /* Router-id information is needed. */
    1122           0 :   client->ridinfo = 1;
    1123             : 
    1124           0 :   router_id_get (&p);
    1125             : 
    1126           0 :   return zsend_router_id_update (client,&p);
    1127             : }
    1128             : 
    1129             : /* Unregister zebra server router-id information. */
    1130             : static int
    1131           0 : zread_router_id_delete (struct zserv *client, u_short length)
    1132             : {
    1133           0 :   client->ridinfo = 0;
    1134           0 :   return 0;
    1135             : }
    1136             : 
    1137             : /* Tie up route-type and client->sock */
    1138             : static void
    1139          52 : zread_hello (struct zserv *client)
    1140             : {
    1141             :   /* type of protocol (lib/zebra.h) */
    1142             :   u_char proto;
    1143          52 :   proto = stream_getc (client->ibuf);
    1144             : 
    1145             :   /* accept only dynamic routing protocols */
    1146          52 :   if ((proto < ZEBRA_ROUTE_MAX)
    1147          52 :   &&  (proto > ZEBRA_ROUTE_STATIC))
    1148             :     {
    1149          52 :       zlog_notice ("client %d says hello and bids fair to announce only %s routes",
    1150             :                     client->sock, zebra_route_string(proto));
    1151             : 
    1152             :       /* if route-type was binded by other client */
    1153          52 :       if (route_type_oaths[proto])
    1154           0 :         zlog_warn ("sender of %s routes changed %c->%c",
    1155             :                     zebra_route_string(proto), route_type_oaths[proto],
    1156             :                     client->sock);
    1157             : 
    1158          52 :       route_type_oaths[proto] = client->sock;
    1159             :     }
    1160          52 : }
    1161             : 
    1162             : /* If client sent routes of specific type, zebra removes it
    1163             :  * and returns number of deleted routes.
    1164             :  */
    1165             : static void
    1166          43 : zebra_score_rib (int client_sock)
    1167             : {
    1168             :   int i;
    1169             : 
    1170         150 :   for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++)
    1171         150 :     if (client_sock == route_type_oaths[i])
    1172             :       {
    1173          43 :         zlog_notice ("client %d disconnected. %lu %s routes removed from the rib",
    1174             :                       client_sock, rib_score_proto (i), zebra_route_string (i));
    1175          43 :         route_type_oaths[i] = 0;
    1176          43 :         break;
    1177             :       }
    1178          43 : }
    1179             : 
    1180             : /* Close zebra client. */
    1181             : static void
    1182          43 : zebra_client_close (struct zserv *client)
    1183             : {
    1184             :   /* Close file descriptor. */
    1185          43 :   if (client->sock)
    1186             :     {
    1187          43 :       close (client->sock);
    1188          43 :       zebra_score_rib (client->sock);
    1189          43 :       client->sock = -1;
    1190             :     }
    1191             : 
    1192             :   /* Free stream buffers. */
    1193          43 :   if (client->ibuf)
    1194          43 :     stream_free (client->ibuf);
    1195          43 :   if (client->obuf)
    1196          43 :     stream_free (client->obuf);
    1197          43 :   if (client->wb)
    1198          43 :     buffer_free(client->wb);
    1199             : 
    1200             :   /* Release threads. */
    1201          43 :   if (client->t_read)
    1202           0 :     thread_cancel (client->t_read);
    1203          43 :   if (client->t_write)
    1204           0 :     thread_cancel (client->t_write);
    1205          43 :   if (client->t_suicide)
    1206           0 :     thread_cancel (client->t_suicide);
    1207             : 
    1208             :   /* Free client structure. */
    1209          43 :   listnode_delete (zebrad.client_list, client);
    1210          43 :   XFREE (0, client);
    1211          43 : }
    1212             : 
    1213             : /* Make new client. */
    1214             : static void
    1215          52 : zebra_client_create (int sock)
    1216             : {
    1217             :   struct zserv *client;
    1218             : 
    1219          52 :   client = XCALLOC (0, sizeof (struct zserv));
    1220             : 
    1221             :   /* Make client input/output buffer. */
    1222          52 :   client->sock = sock;
    1223          52 :   client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
    1224          52 :   client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
    1225          52 :   client->wb = buffer_new(0);
    1226             : 
    1227             :   /* Set table number. */
    1228          52 :   client->rtm_table = zebrad.rtm_table_default;
    1229             : 
    1230             :   /* Add this client to linked list. */
    1231          52 :   listnode_add (zebrad.client_list, client);
    1232             :   
    1233             :   /* Make new read thread. */
    1234          52 :   zebra_event (ZEBRA_READ, sock, client);
    1235          52 : }
    1236             : 
    1237             : /* Handler of zebra service request. */
    1238             : static int
    1239         230 : zebra_client_read (struct thread *thread)
    1240             : {
    1241             :   int sock;
    1242             :   struct zserv *client;
    1243             :   size_t already;
    1244             :   uint16_t length, command;
    1245             :   uint8_t marker, version;
    1246             : 
    1247             :   /* Get thread data.  Reset reading thread because I'm running. */
    1248         230 :   sock = THREAD_FD (thread);
    1249         230 :   client = THREAD_ARG (thread);
    1250         230 :   client->t_read = NULL;
    1251             : 
    1252         230 :   if (client->t_suicide)
    1253             :     {
    1254           0 :       zebra_client_close(client);
    1255           0 :       return -1;
    1256             :     }
    1257             : 
    1258             :   /* Read length and command (if we don't have it already). */
    1259         230 :   if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
    1260             :     {
    1261             :       ssize_t nbyte;
    1262         230 :       if (((nbyte = stream_read_try (client->ibuf, sock,
    1263         187 :                                      ZEBRA_HEADER_SIZE-already)) == 0) ||
    1264             :           (nbyte == -1))
    1265             :         {
    1266          43 :           if (IS_ZEBRA_DEBUG_EVENT)
    1267          43 :             zlog_debug ("connection closed socket [%d]", sock);
    1268          43 :           zebra_client_close (client);
    1269          43 :           return -1;
    1270             :         }
    1271         187 :       if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
    1272             :         {
    1273             :           /* Try again later. */
    1274           0 :           zebra_event (ZEBRA_READ, sock, client);
    1275           0 :           return 0;
    1276             :         }
    1277         187 :       already = ZEBRA_HEADER_SIZE;
    1278             :     }
    1279             : 
    1280             :   /* Reset to read from the beginning of the incoming packet. */
    1281         187 :   stream_set_getp(client->ibuf, 0);
    1282             : 
    1283             :   /* Fetch header values */
    1284         187 :   length = stream_getw (client->ibuf);
    1285         187 :   marker = stream_getc (client->ibuf);
    1286         187 :   version = stream_getc (client->ibuf);
    1287         187 :   command = stream_getw (client->ibuf);
    1288             : 
    1289         187 :   if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
    1290             :     {
    1291           0 :       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
    1292             :                __func__, sock, marker, version);
    1293           0 :       zebra_client_close (client);
    1294           0 :       return -1;
    1295             :     }
    1296         187 :   if (length < ZEBRA_HEADER_SIZE) 
    1297             :     {
    1298           0 :       zlog_warn("%s: socket %d message length %u is less than header size %d",
    1299             :                 __func__, sock, length, ZEBRA_HEADER_SIZE);
    1300           0 :       zebra_client_close (client);
    1301           0 :       return -1;
    1302             :     }
    1303         187 :   if (length > STREAM_SIZE(client->ibuf))
    1304             :     {
    1305           0 :       zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
    1306           0 :                 __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
    1307           0 :       zebra_client_close (client);
    1308           0 :       return -1;
    1309             :     }
    1310             : 
    1311             :   /* Read rest of data. */
    1312         187 :   if (already < length)
    1313             :     {
    1314             :       ssize_t nbyte;
    1315         187 :       if (((nbyte = stream_read_try (client->ibuf, sock,
    1316         187 :                                      length-already)) == 0) ||
    1317             :           (nbyte == -1))
    1318             :         {
    1319           0 :           if (IS_ZEBRA_DEBUG_EVENT)
    1320           0 :             zlog_debug ("connection closed [%d] when reading zebra data", sock);
    1321           0 :           zebra_client_close (client);
    1322           0 :           return -1;
    1323             :         }
    1324         187 :       if (nbyte != (ssize_t)(length-already))
    1325             :         {
    1326             :           /* Try again later. */
    1327           0 :           zebra_event (ZEBRA_READ, sock, client);
    1328           0 :           return 0;
    1329             :         }
    1330             :     }
    1331             : 
    1332         187 :   length -= ZEBRA_HEADER_SIZE;
    1333             : 
    1334             :   /* Debug packet information. */
    1335         187 :   if (IS_ZEBRA_DEBUG_EVENT)
    1336         187 :     zlog_debug ("zebra message comes from socket [%d]", sock);
    1337             : 
    1338         187 :   if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    1339         187 :     zlog_debug ("zebra message received [%s] %d", 
    1340             :                zserv_command_string (command), length);
    1341             : 
    1342         187 :   switch (command) 
    1343             :     {
    1344             :     case ZEBRA_ROUTER_ID_ADD:
    1345           0 :       zread_router_id_add (client, length);
    1346           0 :       break;
    1347             :     case ZEBRA_ROUTER_ID_DELETE:
    1348           0 :       zread_router_id_delete (client, length);
    1349           0 :       break;
    1350             :     case ZEBRA_INTERFACE_ADD:
    1351           0 :       zread_interface_add (client, length);
    1352           0 :       break;
    1353             :     case ZEBRA_INTERFACE_DELETE:
    1354           0 :       zread_interface_delete (client, length);
    1355           0 :       break;
    1356             :     case ZEBRA_IPV4_ROUTE_ADD:
    1357          60 :       zread_ipv4_add (client, length);
    1358          60 :       break;
    1359             :     case ZEBRA_IPV4_ROUTE_DELETE:
    1360          33 :       zread_ipv4_delete (client, length);
    1361          33 :       break;
    1362             : #ifdef HAVE_IPV6
    1363             :     case ZEBRA_IPV6_ROUTE_ADD:
    1364          28 :       zread_ipv6_add (client, length);
    1365          28 :       break;
    1366             :     case ZEBRA_IPV6_ROUTE_DELETE:
    1367          14 :       zread_ipv6_delete (client, length);
    1368          14 :       break;
    1369             : #endif /* HAVE_IPV6 */
    1370             :     case ZEBRA_REDISTRIBUTE_ADD:
    1371           0 :       zebra_redistribute_add (command, client, length);
    1372           0 :       break;
    1373             :     case ZEBRA_REDISTRIBUTE_DELETE:
    1374           0 :       zebra_redistribute_delete (command, client, length);
    1375           0 :       break;
    1376             :     case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
    1377           0 :       zebra_redistribute_default_add (command, client, length);
    1378           0 :       break;
    1379             :     case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
    1380           0 :       zebra_redistribute_default_delete (command, client, length);
    1381           0 :       break;
    1382             :     case ZEBRA_IPV4_NEXTHOP_LOOKUP:
    1383           0 :       zread_ipv4_nexthop_lookup (client, length);
    1384           0 :       break;
    1385             : #ifdef HAVE_IPV6
    1386             :     case ZEBRA_IPV6_NEXTHOP_LOOKUP:
    1387           0 :       zread_ipv6_nexthop_lookup (client, length);
    1388           0 :       break;
    1389             : #endif /* HAVE_IPV6 */
    1390             :     case ZEBRA_IPV4_IMPORT_LOOKUP:
    1391           0 :       zread_ipv4_import_lookup (client, length);
    1392           0 :       break;
    1393             :     case ZEBRA_HELLO:
    1394          52 :       zread_hello (client);
    1395          52 :       break;
    1396             :     default:
    1397           0 :       zlog_info ("Zebra received unknown command %d", command);
    1398           0 :       break;
    1399             :     }
    1400             : 
    1401         187 :   if (client->t_suicide)
    1402             :     {
    1403             :       /* No need to wait for thread callback, just kill immediately. */
    1404           0 :       zebra_client_close(client);
    1405           0 :       return -1;
    1406             :     }
    1407             : 
    1408         187 :   stream_reset (client->ibuf);
    1409         187 :   zebra_event (ZEBRA_READ, sock, client);
    1410         187 :   return 0;
    1411             : }
    1412             : 
    1413             : 
    1414             : /* Accept code of zebra server socket. */
    1415             : static int
    1416          52 : zebra_accept (struct thread *thread)
    1417             : {
    1418             :   int accept_sock;
    1419             :   int client_sock;
    1420             :   struct sockaddr_in client;
    1421             :   socklen_t len;
    1422             : 
    1423          52 :   accept_sock = THREAD_FD (thread);
    1424             : 
    1425             :   /* Reregister myself. */
    1426          52 :   zebra_event (ZEBRA_SERV, accept_sock, NULL);
    1427             : 
    1428          52 :   len = sizeof (struct sockaddr_in);
    1429          52 :   client_sock = accept (accept_sock, (struct sockaddr *) &client, &len);
    1430             : 
    1431          52 :   if (client_sock < 0)
    1432             :     {
    1433           0 :       zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno));
    1434           0 :       return -1;
    1435             :     }
    1436             : 
    1437             :   /* Make client socket non-blocking.  */
    1438          52 :   set_nonblocking(client_sock);
    1439             :   
    1440             :   /* Create new zebra client. */
    1441          52 :   zebra_client_create (client_sock);
    1442             : 
    1443          52 :   return 0;
    1444             : }
    1445             : 
    1446             : #ifdef HAVE_TCP_ZEBRA
    1447             : /* Make zebra's server socket. */
    1448             : static void
    1449             : zebra_serv ()
    1450             : {
    1451             :   int ret;
    1452             :   int accept_sock;
    1453             :   struct sockaddr_in addr;
    1454             : 
    1455             :   accept_sock = socket (AF_INET, SOCK_STREAM, 0);
    1456             : 
    1457             :   if (accept_sock < 0) 
    1458             :     {
    1459             :       zlog_warn ("Can't create zserv stream socket: %s", 
    1460             :                  safe_strerror (errno));
    1461             :       zlog_warn ("zebra can't provice full functionality due to above error");
    1462             :       return;
    1463             :     }
    1464             : 
    1465             :   memset (&route_type_oaths, 0, sizeof (route_type_oaths));
    1466             :   memset (&addr, 0, sizeof (struct sockaddr_in));
    1467             :   addr.sin_family = AF_INET;
    1468             :   addr.sin_port = htons (ZEBRA_PORT);
    1469             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
    1470             :   addr.sin_len = sizeof (struct sockaddr_in);
    1471             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
    1472             :   addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    1473             : 
    1474             :   sockopt_reuseaddr (accept_sock);
    1475             :   sockopt_reuseport (accept_sock);
    1476             : 
    1477             :   if ( zserv_privs.change(ZPRIVS_RAISE) )
    1478             :     zlog (NULL, LOG_ERR, "Can't raise privileges");
    1479             :     
    1480             :   ret  = bind (accept_sock, (struct sockaddr *)&addr, 
    1481             :                sizeof (struct sockaddr_in));
    1482             :   if (ret < 0)
    1483             :     {
    1484             :       zlog_warn ("Can't bind to stream socket: %s", 
    1485             :                  safe_strerror (errno));
    1486             :       zlog_warn ("zebra can't provice full functionality due to above error");
    1487             :       close (accept_sock);      /* Avoid sd leak. */
    1488             :       return;
    1489             :     }
    1490             :     
    1491             :   if ( zserv_privs.change(ZPRIVS_LOWER) )
    1492             :     zlog (NULL, LOG_ERR, "Can't lower privileges");
    1493             : 
    1494             :   ret = listen (accept_sock, 1);
    1495             :   if (ret < 0)
    1496             :     {
    1497             :       zlog_warn ("Can't listen to stream socket: %s", 
    1498             :                  safe_strerror (errno));
    1499             :       zlog_warn ("zebra can't provice full functionality due to above error");
    1500             :       close (accept_sock);      /* Avoid sd leak. */
    1501             :       return;
    1502             :     }
    1503             : 
    1504             :   zebra_event (ZEBRA_SERV, accept_sock, NULL);
    1505             : }
    1506             : #endif /* HAVE_TCP_ZEBRA */
    1507             : 
    1508             : /* For sockaddr_un. */
    1509             : #include <sys/un.h>
    1510             : 
    1511             : /* zebra server UNIX domain socket. */
    1512             : static void
    1513          45 : zebra_serv_un (const char *path)
    1514             : {
    1515             :   int ret;
    1516             :   int sock, len;
    1517             :   struct sockaddr_un serv;
    1518             :   mode_t old_mask;
    1519             : 
    1520             :   /* First of all, unlink existing socket */
    1521          45 :   unlink (path);
    1522             : 
    1523             :   /* Set umask */
    1524          45 :   old_mask = umask (0077);
    1525             : 
    1526             :   /* Make UNIX domain socket. */
    1527          45 :   sock = socket (AF_UNIX, SOCK_STREAM, 0);
    1528          45 :   if (sock < 0)
    1529             :     {
    1530           0 :       zlog_warn ("Can't create zserv unix socket: %s", 
    1531           0 :                  safe_strerror (errno));
    1532           0 :       zlog_warn ("zebra can't provide full functionality due to above error");
    1533           0 :       return;
    1534             :     }
    1535             : 
    1536          45 :   memset (&route_type_oaths, 0, sizeof (route_type_oaths));
    1537             : 
    1538             :   /* Make server socket. */
    1539          45 :   memset (&serv, 0, sizeof (struct sockaddr_un));
    1540          45 :   serv.sun_family = AF_UNIX;
    1541          45 :   strncpy (serv.sun_path, path, strlen (path));
    1542             : #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
    1543             :   len = serv.sun_len = SUN_LEN(&serv);
    1544             : #else
    1545          45 :   len = sizeof (serv.sun_family) + strlen (serv.sun_path);
    1546             : #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
    1547             : 
    1548          45 :   ret = bind (sock, (struct sockaddr *) &serv, len);
    1549          45 :   if (ret < 0)
    1550             :     {
    1551           0 :       zlog_warn ("Can't bind to unix socket %s: %s", 
    1552           0 :                  path, safe_strerror (errno));
    1553           0 :       zlog_warn ("zebra can't provide full functionality due to above error");
    1554           0 :       close (sock);
    1555           0 :       return;
    1556             :     }
    1557             : 
    1558          45 :   ret = listen (sock, 5);
    1559          45 :   if (ret < 0)
    1560             :     {
    1561           0 :       zlog_warn ("Can't listen to unix socket %s: %s", 
    1562           0 :                  path, safe_strerror (errno));
    1563           0 :       zlog_warn ("zebra can't provide full functionality due to above error");
    1564           0 :       close (sock);
    1565           0 :       return;
    1566             :     }
    1567             : 
    1568          45 :   umask (old_mask);
    1569             : 
    1570          45 :   zebra_event (ZEBRA_SERV, sock, NULL);
    1571             : }
    1572             : 
    1573             : 
    1574             : static void
    1575         336 : zebra_event (enum event event, int sock, struct zserv *client)
    1576             : {
    1577         336 :   switch (event)
    1578             :     {
    1579             :     case ZEBRA_SERV:
    1580          97 :       thread_add_read (zebrad.master, zebra_accept, client, sock);
    1581          97 :       break;
    1582             :     case ZEBRA_READ:
    1583         239 :       client->t_read = 
    1584         239 :         thread_add_read (zebrad.master, zebra_client_read, client, sock);
    1585         239 :       break;
    1586             :     case ZEBRA_WRITE:
    1587             :       /**/
    1588           0 :       break;
    1589             :     }
    1590         336 : }
    1591             : 
    1592             : /* Display default rtm_table for all clients. */
    1593           0 : DEFUN (show_table,
    1594             :        show_table_cmd,
    1595             :        "show table",
    1596             :        SHOW_STR
    1597             :        "default routing table to use for all clients\n")
    1598             : {
    1599           0 :   vty_out (vty, "table %d%s", zebrad.rtm_table_default,
    1600           0 :            VTY_NEWLINE);
    1601           0 :   return CMD_SUCCESS;
    1602             : }
    1603             : 
    1604           0 : DEFUN (config_table, 
    1605             :        config_table_cmd,
    1606             :        "table TABLENO",
    1607             :        "Configure target kernel routing table\n"
    1608             :        "TABLE integer\n")
    1609             : {
    1610           0 :   zebrad.rtm_table_default = strtol (argv[0], (char**)0, 10);
    1611           0 :   return CMD_SUCCESS;
    1612             : }
    1613             : 
    1614           0 : DEFUN (ip_forwarding,
    1615             :        ip_forwarding_cmd,
    1616             :        "ip forwarding",
    1617             :        IP_STR
    1618             :        "Turn on IP forwarding")
    1619             : {
    1620             :   int ret;
    1621             : 
    1622           0 :   ret = ipforward ();
    1623           0 :   if (ret == 0)
    1624           0 :     ret = ipforward_on ();
    1625             : 
    1626           0 :   if (ret == 0)
    1627             :     {
    1628           0 :       vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
    1629           0 :       return CMD_WARNING;
    1630             :     }
    1631             : 
    1632           0 :   return CMD_SUCCESS;
    1633             : }
    1634             : 
    1635           0 : DEFUN (no_ip_forwarding,
    1636             :        no_ip_forwarding_cmd,
    1637             :        "no ip forwarding",
    1638             :        NO_STR
    1639             :        IP_STR
    1640             :        "Turn off IP forwarding")
    1641             : {
    1642             :   int ret;
    1643             : 
    1644           0 :   ret = ipforward ();
    1645           0 :   if (ret != 0)
    1646           0 :     ret = ipforward_off ();
    1647             : 
    1648           0 :   if (ret != 0)
    1649             :     {
    1650           0 :       vty_out (vty, "Can't turn off IP forwarding%s", VTY_NEWLINE);
    1651           0 :       return CMD_WARNING;
    1652             :     }
    1653             : 
    1654           0 :   return CMD_SUCCESS;
    1655             : }
    1656             : 
    1657             : /* This command is for debugging purpose. */
    1658           0 : DEFUN (show_zebra_client,
    1659             :        show_zebra_client_cmd,
    1660             :        "show zebra client",
    1661             :        SHOW_STR
    1662             :        "Zebra information"
    1663             :        "Client information")
    1664             : {
    1665             :   struct listnode *node;
    1666             :   struct zserv *client;
    1667             : 
    1668           0 :   for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
    1669           0 :     vty_out (vty, "Client fd %d%s", client->sock, VTY_NEWLINE);
    1670             :   
    1671           0 :   return CMD_SUCCESS;
    1672             : }
    1673             : 
    1674             : /* Table configuration write function. */
    1675             : static int
    1676           0 : config_write_table (struct vty *vty)
    1677             : {
    1678           0 :   if (zebrad.rtm_table_default)
    1679           0 :     vty_out (vty, "table %d%s", zebrad.rtm_table_default,
    1680           0 :              VTY_NEWLINE);
    1681           0 :   return 0;
    1682             : }
    1683             : 
    1684             : /* table node for routing tables. */
    1685             : static struct cmd_node table_node =
    1686             : {
    1687             :   TABLE_NODE,
    1688             :   "",                         /* This node has no interface. */
    1689             :   1
    1690             : };
    1691             : 
    1692             : /* Only display ip forwarding is enabled or not. */
    1693           0 : DEFUN (show_ip_forwarding,
    1694             :        show_ip_forwarding_cmd,
    1695             :        "show ip forwarding",
    1696             :        SHOW_STR
    1697             :        IP_STR
    1698             :        "IP forwarding status\n")
    1699             : {
    1700             :   int ret;
    1701             : 
    1702           0 :   ret = ipforward ();
    1703             : 
    1704           0 :   if (ret == 0)
    1705           0 :     vty_out (vty, "IP forwarding is off%s", VTY_NEWLINE);
    1706             :   else
    1707           0 :     vty_out (vty, "IP forwarding is on%s", VTY_NEWLINE);
    1708           0 :   return CMD_SUCCESS;
    1709             : }
    1710             : 
    1711             : #ifdef HAVE_IPV6
    1712             : /* Only display ipv6 forwarding is enabled or not. */
    1713           0 : DEFUN (show_ipv6_forwarding,
    1714             :        show_ipv6_forwarding_cmd,
    1715             :        "show ipv6 forwarding",
    1716             :        SHOW_STR
    1717             :        "IPv6 information\n"
    1718             :        "Forwarding status\n")
    1719             : {
    1720             :   int ret;
    1721             : 
    1722           0 :   ret = ipforward_ipv6 ();
    1723             : 
    1724           0 :   switch (ret)
    1725             :     {
    1726             :     case -1:
    1727           0 :       vty_out (vty, "ipv6 forwarding is unknown%s", VTY_NEWLINE);
    1728           0 :       break;
    1729             :     case 0:
    1730           0 :       vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
    1731           0 :       break;
    1732             :     case 1:
    1733           0 :       vty_out (vty, "ipv6 forwarding is %s%s", "on", VTY_NEWLINE);
    1734           0 :       break;
    1735             :     default:
    1736           0 :       vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
    1737           0 :       break;
    1738             :     }
    1739           0 :   return CMD_SUCCESS;
    1740             : }
    1741             : 
    1742           0 : DEFUN (ipv6_forwarding,
    1743             :        ipv6_forwarding_cmd,
    1744             :        "ipv6 forwarding",
    1745             :        IPV6_STR
    1746             :        "Turn on IPv6 forwarding")
    1747             : {
    1748             :   int ret;
    1749             : 
    1750           0 :   ret = ipforward_ipv6 ();
    1751           0 :   if (ret == 0)
    1752           0 :     ret = ipforward_ipv6_on ();
    1753             : 
    1754           0 :   if (ret == 0)
    1755             :     {
    1756           0 :       vty_out (vty, "Can't turn on IPv6 forwarding%s", VTY_NEWLINE);
    1757           0 :       return CMD_WARNING;
    1758             :     }
    1759             : 
    1760           0 :   return CMD_SUCCESS;
    1761             : }
    1762             : 
    1763           0 : DEFUN (no_ipv6_forwarding,
    1764             :        no_ipv6_forwarding_cmd,
    1765             :        "no ipv6 forwarding",
    1766             :        NO_STR
    1767             :        IPV6_STR
    1768             :        "Turn off IPv6 forwarding")
    1769             : {
    1770             :   int ret;
    1771             : 
    1772           0 :   ret = ipforward_ipv6 ();
    1773           0 :   if (ret != 0)
    1774           0 :     ret = ipforward_ipv6_off ();
    1775             : 
    1776           0 :   if (ret != 0)
    1777             :     {
    1778           0 :       vty_out (vty, "Can't turn off IPv6 forwarding%s", VTY_NEWLINE);
    1779           0 :       return CMD_WARNING;
    1780             :     }
    1781             : 
    1782           0 :   return CMD_SUCCESS;
    1783             : }
    1784             : 
    1785             : #endif /* HAVE_IPV6 */
    1786             : 
    1787             : /* IPForwarding configuration write function. */
    1788             : static int
    1789           0 : config_write_forwarding (struct vty *vty)
    1790             : {
    1791             :   /* FIXME: Find better place for that. */
    1792           0 :   router_id_write (vty);
    1793             : 
    1794           0 :   if (ipforward ())
    1795           0 :     vty_out (vty, "ip forwarding%s", VTY_NEWLINE);
    1796             : #ifdef HAVE_IPV6
    1797           0 :   if (ipforward_ipv6 ())
    1798           0 :     vty_out (vty, "ipv6 forwarding%s", VTY_NEWLINE);
    1799             : #endif /* HAVE_IPV6 */
    1800           0 :   vty_out (vty, "!%s", VTY_NEWLINE);
    1801           0 :   return 0;
    1802             : }
    1803             : 
    1804             : /* table node for routing tables. */
    1805             : static struct cmd_node forwarding_node =
    1806             : {
    1807             :   FORWARDING_NODE,
    1808             :   "",                         /* This node has no interface. */
    1809             :   1
    1810             : };
    1811             : 
    1812             : 
    1813             : /* Initialisation of zebra and installation of commands. */
    1814             : void
    1815          45 : zebra_init (void)
    1816             : {
    1817             :   /* Client list init. */
    1818          45 :   zebrad.client_list = list_new ();
    1819             : 
    1820             :   /* Install configuration write function. */
    1821          45 :   install_node (&table_node, config_write_table);
    1822          45 :   install_node (&forwarding_node, config_write_forwarding);
    1823             : 
    1824          45 :   install_element (VIEW_NODE, &show_ip_forwarding_cmd);
    1825          45 :   install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
    1826          45 :   install_element (CONFIG_NODE, &ip_forwarding_cmd);
    1827          45 :   install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
    1828          45 :   install_element (ENABLE_NODE, &show_zebra_client_cmd);
    1829             : 
    1830             : #ifdef HAVE_NETLINK
    1831          45 :   install_element (VIEW_NODE, &show_table_cmd);
    1832          45 :   install_element (ENABLE_NODE, &show_table_cmd);
    1833          45 :   install_element (CONFIG_NODE, &config_table_cmd);
    1834             : #endif /* HAVE_NETLINK */
    1835             : 
    1836             : #ifdef HAVE_IPV6
    1837          45 :   install_element (VIEW_NODE, &show_ipv6_forwarding_cmd);
    1838          45 :   install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd);
    1839          45 :   install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
    1840          45 :   install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
    1841             : #endif /* HAVE_IPV6 */
    1842             : 
    1843             :   /* Route-map */
    1844          45 :   zebra_route_map_init ();
    1845          45 : }
    1846             : 
    1847             : /* Make zebra server socket, wiping any existing one (see bug #403). */
    1848             : void
    1849          45 : zebra_zserv_socket_init (char *path)
    1850             : {
    1851             : #ifdef HAVE_TCP_ZEBRA
    1852             :   zebra_serv ();
    1853             : #else
    1854          45 :   zebra_serv_un (path ? path : ZEBRA_SERV_PATH);
    1855             : #endif /* HAVE_TCP_ZEBRA */
    1856          45 : }

Generated by: LCOV version 1.10