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

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

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