Annotation of embedaddon/quagga/zebra/zserv.c, revision 1.1

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

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