Annotation of embedaddon/quagga/lib/zclient.c, revision 1.1.1.4

1.1       misho       1: /* Zebra's client library.
                      2:  * Copyright (C) 1999 Kunihiro Ishiguro
                      3:  * Copyright (C) 2005 Andrew J. Schorr
                      4:  *
                      5:  * This file is part of GNU Zebra.
                      6:  *
                      7:  * GNU Zebra is free software; you can redistribute it and/or modify
                      8:  * it under the terms of the GNU General Public License as published
                      9:  * by the Free Software Foundation; either version 2, or (at your
                     10:  * option) any later version.
                     11:  *
                     12:  * GNU Zebra is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with GNU Zebra; see the file COPYING.  If not, write to the
                     19:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20:  * MA 02111-1307, USA.
                     21:  */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "prefix.h"
                     26: #include "stream.h"
                     27: #include "buffer.h"
                     28: #include "network.h"
                     29: #include "if.h"
                     30: #include "log.h"
                     31: #include "thread.h"
                     32: #include "zclient.h"
                     33: #include "memory.h"
                     34: #include "table.h"
1.1.1.4 ! misho      35: 
1.1       misho      36: /* Zebra client events. */
                     37: enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT};
                     38: 
                     39: /* Prototype for event manager. */
                     40: static void zclient_event (enum event, struct zclient *);
                     41: 
1.1.1.4 ! misho      42: const char *zclient_serv_path = NULL;
1.1.1.2   misho      43: 
1.1       misho      44: /* This file local debug flag. */
                     45: int zclient_debug = 0;
1.1.1.4 ! misho      46: 
1.1       misho      47: /* Allocate zclient structure. */
                     48: struct zclient *
1.1.1.4 ! misho      49: zclient_new (struct thread_master *master)
1.1       misho      50: {
                     51:   struct zclient *zclient;
                     52:   zclient = XCALLOC (MTYPE_ZCLIENT, sizeof (struct zclient));
                     53: 
                     54:   zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
                     55:   zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
                     56:   zclient->wb = buffer_new(0);
1.1.1.4 ! misho      57:   zclient->master = master;
1.1       misho      58: 
                     59:   return zclient;
                     60: }
                     61: 
                     62: /* This function is only called when exiting, because
                     63:    many parts of the code do not check for I/O errors, so they could
                     64:    reference an invalid pointer if the structure was ever freed.
                     65: 
                     66:    Free zclient structure. */
                     67: void
                     68: zclient_free (struct zclient *zclient)
                     69: {
                     70:   if (zclient->ibuf)
                     71:     stream_free(zclient->ibuf);
                     72:   if (zclient->obuf)
                     73:     stream_free(zclient->obuf);
                     74:   if (zclient->wb)
                     75:     buffer_free(zclient->wb);
                     76: 
                     77:   XFREE (MTYPE_ZCLIENT, zclient);
                     78: }
                     79: 
                     80: /* Initialize zebra client.  Argument redist_default is unwanted
                     81:    redistribute route type. */
                     82: void
                     83: zclient_init (struct zclient *zclient, int redist_default)
                     84: {
                     85:   int i;
                     86:   
                     87:   /* Enable zebra client connection by default. */
                     88:   zclient->enable = 1;
                     89: 
                     90:   /* Set -1 to the default socket value. */
                     91:   zclient->sock = -1;
                     92: 
                     93:   /* Clear redistribution flags. */
                     94:   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1.1.1.4 ! misho      95:     zclient->redist[i] = vrf_bitmap_init ();
1.1       misho      96: 
                     97:   /* Set unwanted redistribute route.  bgpd does not need BGP route
                     98:      redistribution. */
                     99:   zclient->redist_default = redist_default;
                    100: 
                    101:   /* Set default-information redistribute to zero. */
1.1.1.4 ! misho     102:   zclient->default_information = vrf_bitmap_init ();
1.1       misho     103: 
                    104:   /* Schedule first zclient connection. */
                    105:   if (zclient_debug)
                    106:     zlog_debug ("zclient start scheduled");
                    107: 
                    108:   zclient_event (ZCLIENT_SCHEDULE, zclient);
                    109: }
                    110: 
                    111: /* Stop zebra client services. */
                    112: void
                    113: zclient_stop (struct zclient *zclient)
                    114: {
1.1.1.4 ! misho     115:   int i;
        !           116: 
1.1       misho     117:   if (zclient_debug)
                    118:     zlog_debug ("zclient stopped");
                    119: 
                    120:   /* Stop threads. */
                    121:   THREAD_OFF(zclient->t_read);
                    122:   THREAD_OFF(zclient->t_connect);
                    123:   THREAD_OFF(zclient->t_write);
                    124: 
                    125:   /* Reset streams. */
                    126:   stream_reset(zclient->ibuf);
                    127:   stream_reset(zclient->obuf);
                    128: 
                    129:   /* Empty the write buffer. */
                    130:   buffer_reset(zclient->wb);
                    131: 
                    132:   /* Close socket. */
                    133:   if (zclient->sock >= 0)
                    134:     {
                    135:       close (zclient->sock);
                    136:       zclient->sock = -1;
                    137:     }
                    138:   zclient->fail = 0;
1.1.1.4 ! misho     139: 
        !           140:   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
        !           141:     {
        !           142:       vrf_bitmap_free(zclient->redist[i]);
        !           143:       zclient->redist[i] = VRF_BITMAP_NULL;
        !           144:     }
        !           145:   vrf_bitmap_free(zclient->default_information);
        !           146:   zclient->default_information = VRF_BITMAP_NULL;
1.1       misho     147: }
                    148: 
                    149: void
                    150: zclient_reset (struct zclient *zclient)
                    151: {
                    152:   zclient_stop (zclient);
                    153:   zclient_init (zclient, zclient->redist_default);
                    154: }
                    155: 
1.1.1.2   misho     156: #ifdef HAVE_TCP_ZEBRA
                    157: 
1.1       misho     158: /* Make socket to zebra daemon. Return zebra socket. */
1.1.1.2   misho     159: static int
1.1       misho     160: zclient_socket(void)
                    161: {
                    162:   int sock;
                    163:   int ret;
                    164:   struct sockaddr_in serv;
                    165: 
                    166:   /* We should think about IPv6 connection. */
                    167:   sock = socket (AF_INET, SOCK_STREAM, 0);
                    168:   if (sock < 0)
                    169:     return -1;
                    170:   
                    171:   /* Make server socket. */ 
                    172:   memset (&serv, 0, sizeof (struct sockaddr_in));
                    173:   serv.sin_family = AF_INET;
                    174:   serv.sin_port = htons (ZEBRA_PORT);
                    175: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
                    176:   serv.sin_len = sizeof (struct sockaddr_in);
                    177: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
                    178:   serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
                    179: 
                    180:   /* Connect to zebra. */
                    181:   ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv));
                    182:   if (ret < 0)
                    183:     {
                    184:       close (sock);
                    185:       return -1;
                    186:     }
                    187:   return sock;
                    188: }
                    189: 
1.1.1.2   misho     190: #else
                    191: 
1.1       misho     192: /* For sockaddr_un. */
                    193: #include <sys/un.h>
                    194: 
1.1.1.2   misho     195: static int
1.1       misho     196: zclient_socket_un (const char *path)
                    197: {
                    198:   int ret;
                    199:   int sock, len;
                    200:   struct sockaddr_un addr;
                    201: 
                    202:   sock = socket (AF_UNIX, SOCK_STREAM, 0);
                    203:   if (sock < 0)
                    204:     return -1;
                    205:   
                    206:   /* Make server socket. */ 
                    207:   memset (&addr, 0, sizeof (struct sockaddr_un));
                    208:   addr.sun_family = AF_UNIX;
                    209:   strncpy (addr.sun_path, path, strlen (path));
                    210: #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
                    211:   len = addr.sun_len = SUN_LEN(&addr);
                    212: #else
                    213:   len = sizeof (addr.sun_family) + strlen (addr.sun_path);
                    214: #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
                    215: 
                    216:   ret = connect (sock, (struct sockaddr *) &addr, len);
                    217:   if (ret < 0)
                    218:     {
                    219:       close (sock);
                    220:       return -1;
                    221:     }
                    222:   return sock;
                    223: }
                    224: 
1.1.1.2   misho     225: #endif /* HAVE_TCP_ZEBRA */
                    226: 
                    227: /**
                    228:  * Connect to zebra daemon.
                    229:  * @param zclient a pointer to zclient structure
                    230:  * @return socket fd just to make sure that connection established
                    231:  * @see zclient_init
                    232:  * @see zclient_new
                    233:  */
                    234: int
                    235: zclient_socket_connect (struct zclient *zclient)
                    236: {
                    237: #ifdef HAVE_TCP_ZEBRA
                    238:   zclient->sock = zclient_socket ();
                    239: #else
1.1.1.4 ! misho     240:   zclient->sock = zclient_socket_un (zclient_serv_path_get());
1.1.1.2   misho     241: #endif
                    242:   return zclient->sock;
                    243: }
                    244: 
1.1       misho     245: static int
                    246: zclient_failed(struct zclient *zclient)
                    247: {
                    248:   zclient->fail++;
                    249:   zclient_stop(zclient);
                    250:   zclient_event(ZCLIENT_CONNECT, zclient);
                    251:   return -1;
                    252: }
                    253: 
                    254: static int
                    255: zclient_flush_data(struct thread *thread)
                    256: {
                    257:   struct zclient *zclient = THREAD_ARG(thread);
                    258: 
                    259:   zclient->t_write = NULL;
                    260:   if (zclient->sock < 0)
                    261:     return -1;
                    262:   switch (buffer_flush_available(zclient->wb, zclient->sock))
                    263:     {
                    264:     case BUFFER_ERROR:
                    265:       zlog_warn("%s: buffer_flush_available failed on zclient fd %d, closing",
                    266:                __func__, zclient->sock);
                    267:       return zclient_failed(zclient);
                    268:       break;
                    269:     case BUFFER_PENDING:
1.1.1.4 ! misho     270:       zclient->t_write = thread_add_write (zclient->master, zclient_flush_data,
        !           271:                                           zclient, zclient->sock);
1.1       misho     272:       break;
                    273:     case BUFFER_EMPTY:
                    274:       break;
                    275:     }
                    276:   return 0;
                    277: }
                    278: 
                    279: int
                    280: zclient_send_message(struct zclient *zclient)
                    281: {
                    282:   if (zclient->sock < 0)
                    283:     return -1;
                    284:   switch (buffer_write(zclient->wb, zclient->sock, STREAM_DATA(zclient->obuf),
                    285:                       stream_get_endp(zclient->obuf)))
                    286:     {
                    287:     case BUFFER_ERROR:
                    288:       zlog_warn("%s: buffer_write failed to zclient fd %d, closing",
                    289:                 __func__, zclient->sock);
                    290:       return zclient_failed(zclient);
                    291:       break;
                    292:     case BUFFER_EMPTY:
                    293:       THREAD_OFF(zclient->t_write);
                    294:       break;
                    295:     case BUFFER_PENDING:
1.1.1.4 ! misho     296:       THREAD_WRITE_ON (zclient->master, zclient->t_write,
        !           297:                       zclient_flush_data, zclient, zclient->sock);
1.1       misho     298:       break;
                    299:     }
                    300:   return 0;
                    301: }
                    302: 
                    303: void
1.1.1.4 ! misho     304: zclient_create_header (struct stream *s, uint16_t command, vrf_id_t vrf_id)
1.1       misho     305: {
                    306:   /* length placeholder, caller can update */
                    307:   stream_putw (s, ZEBRA_HEADER_SIZE);
                    308:   stream_putc (s, ZEBRA_HEADER_MARKER);
                    309:   stream_putc (s, ZSERV_VERSION);
1.1.1.4 ! misho     310:   stream_putw (s, vrf_id);
1.1       misho     311:   stream_putw (s, command);
                    312: }
                    313: 
1.1.1.4 ! misho     314: int
        !           315: zclient_read_header (struct stream *s, int sock, u_int16_t *size, u_char *marker,
        !           316:                      u_char *version, u_int16_t *vrf_id, u_int16_t *cmd)
        !           317: {
        !           318:   if (stream_read (s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE)
        !           319:     return -1;
        !           320: 
        !           321:   *size = stream_getw (s) - ZEBRA_HEADER_SIZE;
        !           322:   *marker = stream_getc (s);
        !           323:   *version = stream_getc (s);
        !           324:   *vrf_id = stream_getw (s);
        !           325:   *cmd = stream_getw (s);
        !           326: 
        !           327:   if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER)
        !           328:     {
        !           329:       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
        !           330:                __func__, sock, *marker, *version);
        !           331:       return -1;
        !           332:     }
        !           333: 
        !           334:   if (*size && stream_read (s, sock, *size) != *size)
        !           335:     return -1;
        !           336: 
        !           337:   return 0;
        !           338: }
        !           339: 
1.1       misho     340: /* Send simple Zebra message. */
                    341: static int
1.1.1.4 ! misho     342: zebra_message_send (struct zclient *zclient, int command, vrf_id_t vrf_id)
1.1       misho     343: {
                    344:   struct stream *s;
                    345: 
                    346:   /* Get zclient output buffer. */
                    347:   s = zclient->obuf;
                    348:   stream_reset (s);
                    349: 
                    350:   /* Send very simple command only Zebra message. */
1.1.1.4 ! misho     351:   zclient_create_header (s, command, vrf_id);
1.1       misho     352:   
                    353:   return zclient_send_message(zclient);
                    354: }
                    355: 
1.1.1.2   misho     356: static int
                    357: zebra_hello_send (struct zclient *zclient)
                    358: {
                    359:   struct stream *s;
                    360: 
                    361:   if (zclient->redist_default)
                    362:     {
                    363:       s = zclient->obuf;
                    364:       stream_reset (s);
                    365: 
1.1.1.4 ! misho     366:       /* The VRF ID in the HELLO message is always 0. */
        !           367:       zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT);
1.1.1.2   misho     368:       stream_putc (s, zclient->redist_default);
                    369:       stream_putw_at (s, 0, stream_get_endp (s));
                    370:       return zclient_send_message(zclient);
                    371:     }
                    372: 
                    373:   return 0;
                    374: }
                    375: 
1.1.1.4 ! misho     376: /* Send requests to zebra daemon for the information in a VRF. */
        !           377: void
        !           378: zclient_send_requests (struct zclient *zclient, vrf_id_t vrf_id)
        !           379: {
        !           380:   int i;
        !           381: 
        !           382:   /* zclient is disabled. */
        !           383:   if (! zclient->enable)
        !           384:     return;
        !           385: 
        !           386:   /* If not connected to the zebra yet. */
        !           387:   if (zclient->sock < 0)
        !           388:     return;
        !           389: 
        !           390:   if (zclient_debug)
        !           391:     zlog_debug ("%s: send messages for VRF %u", __func__, vrf_id);
        !           392: 
        !           393:   /* We need router-id information. */
        !           394:   zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);
        !           395: 
        !           396:   /* We need interface information. */
        !           397:   zebra_message_send (zclient, ZEBRA_INTERFACE_ADD, vrf_id);
        !           398: 
        !           399:   /* Set unwanted redistribute route. */
        !           400:   vrf_bitmap_set (zclient->redist[zclient->redist_default], vrf_id);
        !           401: 
        !           402:   /* Flush all redistribute request. */
        !           403:   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
        !           404:     if (i != zclient->redist_default &&
        !           405:         vrf_bitmap_check (zclient->redist[i], vrf_id))
        !           406:       zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, i, vrf_id);
        !           407: 
        !           408:   /* If default information is needed. */
        !           409:   if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT))
        !           410:     zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id);
        !           411: }
        !           412: 
1.1       misho     413: /* Make connection to zebra daemon. */
                    414: int
                    415: zclient_start (struct zclient *zclient)
                    416: {
                    417:   if (zclient_debug)
                    418:     zlog_debug ("zclient_start is called");
                    419: 
                    420:   /* zclient is disabled. */
                    421:   if (! zclient->enable)
                    422:     return 0;
                    423: 
                    424:   /* If already connected to the zebra. */
                    425:   if (zclient->sock >= 0)
                    426:     return 0;
                    427: 
                    428:   /* Check connect thread. */
                    429:   if (zclient->t_connect)
                    430:     return 0;
                    431: 
1.1.1.2   misho     432:   if (zclient_socket_connect(zclient) < 0)
1.1       misho     433:     {
                    434:       if (zclient_debug)
                    435:        zlog_debug ("zclient connection fail");
                    436:       zclient->fail++;
                    437:       zclient_event (ZCLIENT_CONNECT, zclient);
                    438:       return -1;
                    439:     }
                    440: 
                    441:   if (set_nonblocking(zclient->sock) < 0)
                    442:     zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock);
                    443: 
                    444:   /* Clear fail count. */
                    445:   zclient->fail = 0;
                    446:   if (zclient_debug)
                    447:     zlog_debug ("zclient connect success with socket [%d]", zclient->sock);
                    448:       
                    449:   /* Create read thread. */
                    450:   zclient_event (ZCLIENT_READ, zclient);
                    451: 
1.1.1.2   misho     452:   zebra_hello_send (zclient);
                    453: 
1.1.1.4 ! misho     454:   /* Inform the successful connection. */
        !           455:   if (zclient->zebra_connected)
        !           456:     (*zclient->zebra_connected) (zclient);
1.1       misho     457: 
                    458:   return 0;
                    459: }
                    460: 
                    461: /* This function is a wrapper function for calling zclient_start from
                    462:    timer or event thread. */
                    463: static int
                    464: zclient_connect (struct thread *t)
                    465: {
                    466:   struct zclient *zclient;
                    467: 
                    468:   zclient = THREAD_ARG (t);
                    469:   zclient->t_connect = NULL;
                    470: 
                    471:   if (zclient_debug)
                    472:     zlog_debug ("zclient_connect is called");
                    473: 
                    474:   return zclient_start (zclient);
                    475: }
1.1.1.4 ! misho     476: 
1.1       misho     477:  /* 
                    478:   * "xdr_encode"-like interface that allows daemon (client) to send
                    479:   * a message to zebra server for a route that needs to be
                    480:   * added/deleted to the kernel. Info about the route is specified
                    481:   * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
                    482:   * the info down the zclient socket using the stream_* functions.
                    483:   * 
                    484:   * The corresponding read ("xdr_decode") function on the server
                    485:   * side is zread_ipv4_add()/zread_ipv4_delete().
                    486:   *
                    487:   *  0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
                    488:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    489:   * |            Length (2)         |    Command    | Route Type    |
                    490:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    491:   * | ZEBRA Flags   | Message Flags | Prefix length |
                    492:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    493:   * | Destination IPv4 Prefix for route                             |
                    494:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    495:   * | Nexthop count | 
                    496:   * +-+-+-+-+-+-+-+-+
                    497:   *
                    498:   * 
                    499:   * A number of IPv4 nexthop(s) or nexthop interface index(es) are then 
                    500:   * described, as per the Nexthop count. Each nexthop described as:
                    501:   *
                    502:   * +-+-+-+-+-+-+-+-+
                    503:   * | Nexthop Type  |  Set to one of ZEBRA_NEXTHOP_*
                    504:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    505:   * |       IPv4 Nexthop address or Interface Index number          |
                    506:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    507:   *
                    508:   * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or
                    509:   * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ 
                    510:   * nexthop information is provided, and the message describes a prefix
                    511:   * to blackhole or reject route.
                    512:   *
                    513:   * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
                    514:   * byte value.
                    515:   * 
                    516:   * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8
                    517:   * byte value.
                    518:   *
                    519:   * XXX: No attention paid to alignment.
                    520:   */ 
                    521: int
                    522: zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
                    523:                  struct zapi_ipv4 *api)
                    524: {
                    525:   int i;
                    526:   int psize;
                    527:   struct stream *s;
                    528: 
                    529:   /* Reset stream. */
                    530:   s = zclient->obuf;
                    531:   stream_reset (s);
1.1.1.4 ! misho     532: 
        !           533:   zclient_create_header (s, cmd, api->vrf_id);
1.1       misho     534:   
                    535:   /* Put type and nexthop. */
                    536:   stream_putc (s, api->type);
                    537:   stream_putc (s, api->flags);
                    538:   stream_putc (s, api->message);
1.1.1.2   misho     539:   stream_putw (s, api->safi);
1.1       misho     540: 
                    541:   /* Put prefix information. */
                    542:   psize = PSIZE (p->prefixlen);
                    543:   stream_putc (s, p->prefixlen);
                    544:   stream_write (s, (u_char *) & p->prefix, psize);
                    545: 
                    546:   /* Nexthop, ifindex, distance and metric information. */
                    547:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
                    548:     {
                    549:       if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
                    550:         {
                    551:           stream_putc (s, 1);
                    552:           stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
                    553:           /* XXX assert(api->nexthop_num == 0); */
                    554:           /* XXX assert(api->ifindex_num == 0); */
                    555:         }
                    556:       else
                    557:         stream_putc (s, api->nexthop_num + api->ifindex_num);
                    558: 
                    559:       for (i = 0; i < api->nexthop_num; i++)
                    560:         {
                    561:           stream_putc (s, ZEBRA_NEXTHOP_IPV4);
                    562:           stream_put_in_addr (s, api->nexthop[i]);
                    563:         }
                    564:       for (i = 0; i < api->ifindex_num; i++)
                    565:         {
                    566:           stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
                    567:           stream_putl (s, api->ifindex[i]);
                    568:         }
                    569:     }
                    570: 
                    571:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
                    572:     stream_putc (s, api->distance);
                    573:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
                    574:     stream_putl (s, api->metric);
1.1.1.4 ! misho     575:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
        !           576:     stream_putl (s, api->mtu);
1.1       misho     577: 
                    578:   /* Put length at the first point of the stream. */
                    579:   stream_putw_at (s, 0, stream_get_endp (s));
                    580: 
                    581:   return zclient_send_message(zclient);
                    582: }
                    583: 
                    584: #ifdef HAVE_IPV6
                    585: int
                    586: zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
                    587:               struct zapi_ipv6 *api)
                    588: {
                    589:   int i;
                    590:   int psize;
                    591:   struct stream *s;
                    592: 
                    593:   /* Reset stream. */
                    594:   s = zclient->obuf;
                    595:   stream_reset (s);
                    596: 
1.1.1.4 ! misho     597:   zclient_create_header (s, cmd, api->vrf_id);
1.1       misho     598: 
                    599:   /* Put type and nexthop. */
                    600:   stream_putc (s, api->type);
                    601:   stream_putc (s, api->flags);
                    602:   stream_putc (s, api->message);
1.1.1.2   misho     603:   stream_putw (s, api->safi);
1.1       misho     604:   
                    605:   /* Put prefix information. */
                    606:   psize = PSIZE (p->prefixlen);
                    607:   stream_putc (s, p->prefixlen);
                    608:   stream_write (s, (u_char *)&p->prefix, psize);
                    609: 
                    610:   /* Nexthop, ifindex, distance and metric information. */
                    611:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
                    612:     {
                    613:       stream_putc (s, api->nexthop_num + api->ifindex_num);
                    614: 
                    615:       for (i = 0; i < api->nexthop_num; i++)
                    616:        {
                    617:          stream_putc (s, ZEBRA_NEXTHOP_IPV6);
                    618:          stream_write (s, (u_char *)api->nexthop[i], 16);
                    619:        }
                    620:       for (i = 0; i < api->ifindex_num; i++)
                    621:        {
                    622:          stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
                    623:          stream_putl (s, api->ifindex[i]);
                    624:        }
                    625:     }
                    626: 
                    627:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
                    628:     stream_putc (s, api->distance);
                    629:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
                    630:     stream_putl (s, api->metric);
1.1.1.4 ! misho     631:   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
        !           632:     stream_putl (s, api->mtu);
1.1       misho     633: 
                    634:   /* Put length at the first point of the stream. */
                    635:   stream_putw_at (s, 0, stream_get_endp (s));
                    636: 
                    637:   return zclient_send_message(zclient);
                    638: }
                    639: #endif /* HAVE_IPV6 */
                    640: 
                    641: /* 
                    642:  * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
                    643:  * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
                    644:  * then set/unset redist[type] in the client handle (a struct zserv) for the 
                    645:  * sending client
                    646:  */
                    647: int
1.1.1.4 ! misho     648: zebra_redistribute_send (int command, struct zclient *zclient, int type,
        !           649:     vrf_id_t vrf_id)
1.1       misho     650: {
                    651:   struct stream *s;
                    652: 
                    653:   s = zclient->obuf;
                    654:   stream_reset(s);
                    655:   
1.1.1.4 ! misho     656:   zclient_create_header (s, command, vrf_id);
1.1       misho     657:   stream_putc (s, type);
                    658:   
                    659:   stream_putw_at (s, 0, stream_get_endp (s));
                    660:   
                    661:   return zclient_send_message(zclient);
                    662: }
                    663: 
1.1.1.4 ! misho     664: /* Get prefix in ZServ format; family should be filled in on prefix */
        !           665: static void
        !           666: zclient_stream_get_prefix (struct stream *s, struct prefix *p)
        !           667: {
        !           668:   size_t plen = prefix_blen (p);
        !           669:   u_char c;
        !           670:   p->prefixlen = 0;
        !           671:   
        !           672:   if (plen == 0)
        !           673:     return;
        !           674:   
        !           675:   stream_get (&p->u.prefix, s, plen);
        !           676:   c = stream_getc(s);
        !           677:   p->prefixlen = MIN(plen * 8, c);
        !           678: }
        !           679: 
1.1       misho     680: /* Router-id update from zebra daemon. */
                    681: void
                    682: zebra_router_id_update_read (struct stream *s, struct prefix *rid)
                    683: {
                    684:   /* Fetch interface address. */
                    685:   rid->family = stream_getc (s);
1.1.1.4 ! misho     686:   
        !           687:   zclient_stream_get_prefix (s, rid);
1.1       misho     688: }
                    689: 
                    690: /* Interface addition from zebra daemon. */
                    691: /*  
                    692:  * The format of the message sent with type ZEBRA_INTERFACE_ADD or
                    693:  * ZEBRA_INTERFACE_DELETE from zebra to the client is:
                    694:  *     0                   1                   2                   3
                    695:  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                    696:  * +-+-+-+-+-+-+-+-+
                    697:  * |   type        |
                    698:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    699:  * |  ifname                                                       |
                    700:  * |                                                               |
                    701:  * |                                                               |
                    702:  * |                                                               |
                    703:  * |                                                               |
                    704:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    705:  * |         ifindex                                               |
                    706:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    707:  * |         if_flags                                              |
                    708:  * |                                                               |
                    709:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    710:  * |         metric                                                |
                    711:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    712:  * |         ifmtu                                                 |
                    713:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    714:  * |         ifmtu6                                                |
                    715:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    716:  * |         bandwidth                                             |
                    717:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    718:  * |         sockaddr_dl                                           |
                    719:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    720:  */
                    721: 
                    722: struct interface *
1.1.1.4 ! misho     723: zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id)
1.1       misho     724: {
                    725:   struct interface *ifp;
                    726:   char ifname_tmp[INTERFACE_NAMSIZ];
                    727: 
                    728:   /* Read interface name. */
                    729:   stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
                    730: 
                    731:   /* Lookup/create interface by name. */
1.1.1.4 ! misho     732:   ifp = if_get_by_name_len_vrf (ifname_tmp,
        !           733:                                 strnlen (ifname_tmp, INTERFACE_NAMSIZ),
        !           734:                                 vrf_id);
1.1       misho     735: 
1.1.1.2   misho     736:   zebra_interface_if_set_value (s, ifp);
1.1       misho     737: 
                    738:   return ifp;
                    739: }
                    740: 
                    741: /* 
                    742:  * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
                    743:  * from zebra server.  The format of this message is the same as
                    744:  * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE (see
                    745:  * comments for zebra_interface_add_read), except that no sockaddr_dl
                    746:  * is sent at the tail of the message.
                    747:  */
                    748: struct interface *
1.1.1.4 ! misho     749: zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id)
1.1       misho     750: {
                    751:   struct interface *ifp;
                    752:   char ifname_tmp[INTERFACE_NAMSIZ];
                    753: 
                    754:   /* Read interface name. */
                    755:   stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
                    756: 
                    757:   /* Lookup this by interface index. */
1.1.1.4 ! misho     758:   ifp = if_lookup_by_name_len_vrf (ifname_tmp,
        !           759:                                    strnlen (ifname_tmp, INTERFACE_NAMSIZ),
        !           760:                                    vrf_id);
1.1       misho     761: 
                    762:   /* If such interface does not exist, indicate an error */
                    763:   if (! ifp)
                    764:      return NULL;
                    765: 
1.1.1.2   misho     766:   zebra_interface_if_set_value (s, ifp);
1.1       misho     767: 
                    768:   return ifp;
                    769: }
                    770: 
                    771: /* 
                    772:  * format of message for address additon is:
                    773:  *    0
                    774:  *  0 1 2 3 4 5 6 7
                    775:  * +-+-+-+-+-+-+-+-+
                    776:  * |   type        |  ZEBRA_INTERFACE_ADDRESS_ADD or
                    777:  * +-+-+-+-+-+-+-+-+  ZEBRA_INTERFACE_ADDRES_DELETE
                    778:  * |               |
                    779:  * +               +
                    780:  * |   ifindex     |
                    781:  * +               +
                    782:  * |               |
                    783:  * +               +
                    784:  * |               |
                    785:  * +-+-+-+-+-+-+-+-+
                    786:  * |   ifc_flags   |  flags for connected address
                    787:  * +-+-+-+-+-+-+-+-+
                    788:  * |  addr_family  |
                    789:  * +-+-+-+-+-+-+-+-+
                    790:  * |    addr...    |
                    791:  * :               :
                    792:  * |               |
                    793:  * +-+-+-+-+-+-+-+-+
                    794:  * |    addr_len   |  len of addr. E.g., addr_len = 4 for ipv4 addrs.
                    795:  * +-+-+-+-+-+-+-+-+
                    796:  * |     daddr..   |
                    797:  * :               :
                    798:  * |               |
                    799:  * +-+-+-+-+-+-+-+-+
                    800:  *
                    801:  */
                    802: 
                    803: void
                    804: zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
                    805: {
                    806:   /* Read interface's index. */
                    807:   ifp->ifindex = stream_getl (s);
                    808:   ifp->status = stream_getc (s);
                    809: 
                    810:   /* Read interface's value. */
                    811:   ifp->flags = stream_getq (s);
                    812:   ifp->metric = stream_getl (s);
                    813:   ifp->mtu = stream_getl (s);
                    814:   ifp->mtu6 = stream_getl (s);
                    815:   ifp->bandwidth = stream_getl (s);
1.1.1.4 ! misho     816:   ifp->ll_type = stream_getl (s);
1.1.1.2   misho     817:   ifp->hw_addr_len = stream_getl (s);
                    818:   if (ifp->hw_addr_len)
1.1.1.4 ! misho     819:     stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
1.1       misho     820: }
                    821: 
                    822: static int
                    823: memconstant(const void *s, int c, size_t n)
                    824: {
                    825:   const u_char *p = s;
                    826: 
                    827:   while (n-- > 0)
                    828:     if (*p++ != c)
                    829:       return 0;
                    830:   return 1;
                    831: }
                    832: 
                    833: struct connected *
1.1.1.4 ! misho     834: zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
1.1       misho     835: {
1.1.1.4 ! misho     836:   ifindex_t ifindex;
1.1       misho     837:   struct interface *ifp;
                    838:   struct connected *ifc;
1.1.1.4 ! misho     839:   struct prefix p, d, *dp;
1.1       misho     840:   int plen;
                    841:   u_char ifc_flags;
                    842: 
                    843:   memset (&p, 0, sizeof(p));
                    844:   memset (&d, 0, sizeof(d));
                    845: 
                    846:   /* Get interface index. */
                    847:   ifindex = stream_getl (s);
                    848: 
                    849:   /* Lookup index. */
1.1.1.4 ! misho     850:   ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
1.1       misho     851:   if (ifp == NULL)
                    852:     {
                    853:       zlog_warn ("zebra_interface_address_read(%s): "
                    854:                  "Can't find interface by ifindex: %d ",
                    855:                  (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
                    856:                  ifindex);
                    857:       return NULL;
                    858:     }
                    859: 
                    860:   /* Fetch flag. */
                    861:   ifc_flags = stream_getc (s);
                    862: 
                    863:   /* Fetch interface address. */
1.1.1.4 ! misho     864:   d.family = p.family = stream_getc (s);
        !           865:   plen = prefix_blen (&d);
        !           866:   
        !           867:   zclient_stream_get_prefix (s, &p);
1.1       misho     868: 
                    869:   /* Fetch destination address. */
                    870:   stream_get (&d.u.prefix, s, plen);
1.1.1.4 ! misho     871:   
        !           872:   /* N.B. NULL destination pointers are encoded as all zeroes */
        !           873:   dp = memconstant(&d.u.prefix,0,plen) ? NULL : &d;
        !           874:   
1.1       misho     875:   if (type == ZEBRA_INTERFACE_ADDRESS_ADD) 
                    876:     {
                    877:        /* N.B. NULL destination pointers are encoded as all zeroes */
1.1.1.4 ! misho     878:        ifc = connected_add_by_prefix(ifp, &p, dp);
1.1       misho     879:        if (ifc != NULL)
                    880:         {
                    881:           ifc->flags = ifc_flags;
                    882:           if (ifc->destination)
                    883:             ifc->destination->prefixlen = ifc->address->prefixlen;
1.1.1.4 ! misho     884:           else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
        !           885:             {
        !           886:               /* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */
        !           887:               char buf[PREFIX_STRLEN];
        !           888:               zlog_warn("warning: interface %s address %s "
        !           889:                    "with peer flag set, but no peer address!",
        !           890:                    ifp->name,
        !           891:                    prefix2str (ifc->address, buf, sizeof buf));
        !           892:               UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
        !           893:             }
1.1       misho     894:         }
                    895:     }
                    896:   else
                    897:     {
                    898:       assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
                    899:       ifc = connected_delete_by_prefix(ifp, &p);
                    900:     }
                    901: 
                    902:   return ifc;
                    903: }
                    904: 
1.1.1.4 ! misho     905: 
1.1       misho     906: /* Zebra client message read function. */
                    907: static int
                    908: zclient_read (struct thread *thread)
                    909: {
                    910:   size_t already;
                    911:   uint16_t length, command;
                    912:   uint8_t marker, version;
1.1.1.4 ! misho     913:   vrf_id_t vrf_id;
1.1       misho     914:   struct zclient *zclient;
                    915: 
                    916:   /* Get socket to zebra. */
                    917:   zclient = THREAD_ARG (thread);
                    918:   zclient->t_read = NULL;
                    919: 
                    920:   /* Read zebra header (if we don't have it already). */
                    921:   if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE)
                    922:     {
                    923:       ssize_t nbyte;
                    924:       if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
                    925:                                     ZEBRA_HEADER_SIZE-already)) == 0) ||
                    926:          (nbyte == -1))
                    927:        {
                    928:          if (zclient_debug)
                    929:           zlog_debug ("zclient connection closed socket [%d].", zclient->sock);
                    930:          return zclient_failed(zclient);
                    931:        }
                    932:       if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
                    933:        {
                    934:          /* Try again later. */
                    935:          zclient_event (ZCLIENT_READ, zclient);
                    936:          return 0;
                    937:        }
                    938:       already = ZEBRA_HEADER_SIZE;
                    939:     }
                    940: 
                    941:   /* Reset to read from the beginning of the incoming packet. */
                    942:   stream_set_getp(zclient->ibuf, 0);
                    943: 
                    944:   /* Fetch header values. */
                    945:   length = stream_getw (zclient->ibuf);
                    946:   marker = stream_getc (zclient->ibuf);
                    947:   version = stream_getc (zclient->ibuf);
1.1.1.4 ! misho     948:   vrf_id = stream_getw (zclient->ibuf);
1.1       misho     949:   command = stream_getw (zclient->ibuf);
                    950:   
                    951:   if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
                    952:     {
                    953:       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
                    954:                __func__, zclient->sock, marker, version);
                    955:       return zclient_failed(zclient);
                    956:     }
                    957:   
                    958:   if (length < ZEBRA_HEADER_SIZE) 
                    959:     {
                    960:       zlog_err("%s: socket %d message length %u is less than %d ",
                    961:               __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
                    962:       return zclient_failed(zclient);
                    963:     }
                    964: 
                    965:   /* Length check. */
                    966:   if (length > STREAM_SIZE(zclient->ibuf))
                    967:     {
                    968:       struct stream *ns;
                    969:       zlog_warn("%s: message size %u exceeds buffer size %lu, expanding...",
                    970:                __func__, length, (u_long)STREAM_SIZE(zclient->ibuf));
                    971:       ns = stream_new(length);
                    972:       stream_copy(ns, zclient->ibuf);
                    973:       stream_free (zclient->ibuf);
                    974:       zclient->ibuf = ns;
                    975:     }
                    976: 
                    977:   /* Read rest of zebra packet. */
                    978:   if (already < length)
                    979:     {
                    980:       ssize_t nbyte;
                    981:       if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
                    982:                                     length-already)) == 0) ||
                    983:          (nbyte == -1))
                    984:        {
                    985:          if (zclient_debug)
                    986:            zlog_debug("zclient connection closed socket [%d].", zclient->sock);
                    987:          return zclient_failed(zclient);
                    988:        }
                    989:       if (nbyte != (ssize_t)(length-already))
                    990:        {
                    991:          /* Try again later. */
                    992:          zclient_event (ZCLIENT_READ, zclient);
                    993:          return 0;
                    994:        }
                    995:     }
                    996: 
                    997:   length -= ZEBRA_HEADER_SIZE;
                    998: 
                    999:   if (zclient_debug)
1.1.1.4 ! misho    1000:     zlog_debug("zclient 0x%p command 0x%x VRF %u\n", (void *)zclient, command, vrf_id);
1.1       misho    1001: 
                   1002:   switch (command)
                   1003:     {
                   1004:     case ZEBRA_ROUTER_ID_UPDATE:
                   1005:       if (zclient->router_id_update)
1.1.1.4 ! misho    1006:        (*zclient->router_id_update) (command, zclient, length, vrf_id);
1.1       misho    1007:       break;
                   1008:     case ZEBRA_INTERFACE_ADD:
                   1009:       if (zclient->interface_add)
1.1.1.4 ! misho    1010:        (*zclient->interface_add) (command, zclient, length, vrf_id);
1.1       misho    1011:       break;
                   1012:     case ZEBRA_INTERFACE_DELETE:
                   1013:       if (zclient->interface_delete)
1.1.1.4 ! misho    1014:        (*zclient->interface_delete) (command, zclient, length, vrf_id);
1.1       misho    1015:       break;
                   1016:     case ZEBRA_INTERFACE_ADDRESS_ADD:
                   1017:       if (zclient->interface_address_add)
1.1.1.4 ! misho    1018:        (*zclient->interface_address_add) (command, zclient, length, vrf_id);
1.1       misho    1019:       break;
                   1020:     case ZEBRA_INTERFACE_ADDRESS_DELETE:
                   1021:       if (zclient->interface_address_delete)
1.1.1.4 ! misho    1022:        (*zclient->interface_address_delete) (command, zclient, length, vrf_id);
1.1       misho    1023:       break;
                   1024:     case ZEBRA_INTERFACE_UP:
                   1025:       if (zclient->interface_up)
1.1.1.4 ! misho    1026:        (*zclient->interface_up) (command, zclient, length, vrf_id);
1.1       misho    1027:       break;
                   1028:     case ZEBRA_INTERFACE_DOWN:
                   1029:       if (zclient->interface_down)
1.1.1.4 ! misho    1030:        (*zclient->interface_down) (command, zclient, length, vrf_id);
1.1       misho    1031:       break;
                   1032:     case ZEBRA_IPV4_ROUTE_ADD:
                   1033:       if (zclient->ipv4_route_add)
1.1.1.4 ! misho    1034:        (*zclient->ipv4_route_add) (command, zclient, length, vrf_id);
1.1       misho    1035:       break;
                   1036:     case ZEBRA_IPV4_ROUTE_DELETE:
                   1037:       if (zclient->ipv4_route_delete)
1.1.1.4 ! misho    1038:        (*zclient->ipv4_route_delete) (command, zclient, length, vrf_id);
1.1       misho    1039:       break;
                   1040:     case ZEBRA_IPV6_ROUTE_ADD:
                   1041:       if (zclient->ipv6_route_add)
1.1.1.4 ! misho    1042:        (*zclient->ipv6_route_add) (command, zclient, length, vrf_id);
1.1       misho    1043:       break;
                   1044:     case ZEBRA_IPV6_ROUTE_DELETE:
                   1045:       if (zclient->ipv6_route_delete)
1.1.1.4 ! misho    1046:        (*zclient->ipv6_route_delete) (command, zclient, length, vrf_id);
1.1       misho    1047:       break;
                   1048:     default:
                   1049:       break;
                   1050:     }
                   1051: 
                   1052:   if (zclient->sock < 0)
                   1053:     /* Connection was closed during packet processing. */
                   1054:     return -1;
                   1055: 
                   1056:   /* Register read thread. */
                   1057:   stream_reset(zclient->ibuf);
                   1058:   zclient_event (ZCLIENT_READ, zclient);
                   1059: 
                   1060:   return 0;
                   1061: }
                   1062: 
                   1063: void
1.1.1.4 ! misho    1064: zclient_redistribute (int command, struct zclient *zclient, int type,
        !          1065:     vrf_id_t vrf_id)
1.1       misho    1066: {
                   1067: 
                   1068:   if (command == ZEBRA_REDISTRIBUTE_ADD) 
                   1069:     {
1.1.1.4 ! misho    1070:       if (vrf_bitmap_check (zclient->redist[type], vrf_id))
1.1       misho    1071:          return;
1.1.1.4 ! misho    1072:       vrf_bitmap_set (zclient->redist[type], vrf_id);
1.1       misho    1073:     }
                   1074:   else
                   1075:     {
1.1.1.4 ! misho    1076:       if (!vrf_bitmap_check (zclient->redist[type], vrf_id))
1.1       misho    1077:          return;
1.1.1.4 ! misho    1078:       vrf_bitmap_unset (zclient->redist[type], vrf_id);
1.1       misho    1079:     }
                   1080: 
                   1081:   if (zclient->sock > 0)
1.1.1.4 ! misho    1082:     zebra_redistribute_send (command, zclient, type, vrf_id);
1.1       misho    1083: }
                   1084: 
                   1085: 
                   1086: void
1.1.1.4 ! misho    1087: zclient_redistribute_default (int command, struct zclient *zclient,
        !          1088:     vrf_id_t vrf_id)
1.1       misho    1089: {
                   1090: 
                   1091:   if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD)
                   1092:     {
1.1.1.4 ! misho    1093:       if (vrf_bitmap_check (zclient->default_information, vrf_id))
1.1       misho    1094:         return;
1.1.1.4 ! misho    1095:       vrf_bitmap_set (zclient->default_information, vrf_id);
1.1       misho    1096:     }
                   1097:   else 
                   1098:     {
1.1.1.4 ! misho    1099:       if (!vrf_bitmap_check (zclient->default_information, vrf_id))
1.1       misho    1100:         return;
1.1.1.4 ! misho    1101:       vrf_bitmap_unset (zclient->default_information, vrf_id);
1.1       misho    1102:     }
                   1103: 
                   1104:   if (zclient->sock > 0)
1.1.1.4 ! misho    1105:     zebra_message_send (zclient, command, vrf_id);
1.1       misho    1106: }
                   1107: 
                   1108: static void
                   1109: zclient_event (enum event event, struct zclient *zclient)
                   1110: {
                   1111:   switch (event)
                   1112:     {
                   1113:     case ZCLIENT_SCHEDULE:
                   1114:       if (! zclient->t_connect)
                   1115:        zclient->t_connect =
1.1.1.4 ! misho    1116:          thread_add_event (zclient->master, zclient_connect, zclient, 0);
1.1       misho    1117:       break;
                   1118:     case ZCLIENT_CONNECT:
                   1119:       if (zclient->fail >= 10)
                   1120:        return;
                   1121:       if (zclient_debug)
                   1122:        zlog_debug ("zclient connect schedule interval is %d", 
                   1123:                   zclient->fail < 3 ? 10 : 60);
                   1124:       if (! zclient->t_connect)
                   1125:        zclient->t_connect = 
1.1.1.4 ! misho    1126:          thread_add_timer (zclient->master, zclient_connect, zclient,
1.1       misho    1127:                            zclient->fail < 3 ? 10 : 60);
                   1128:       break;
                   1129:     case ZCLIENT_READ:
                   1130:       zclient->t_read = 
1.1.1.4 ! misho    1131:        thread_add_read (zclient->master, zclient_read, zclient, zclient->sock);
1.1       misho    1132:       break;
                   1133:     }
1.1.1.4 ! misho    1134: }
        !          1135: 
        !          1136: const char *zclient_serv_path_get()
        !          1137: {
        !          1138:   return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH;
1.1       misho    1139: }
1.1.1.2   misho    1140: 
                   1141: void
                   1142: zclient_serv_path_set (char *path)
                   1143: {
                   1144:   struct stat sb;
                   1145: 
                   1146:   /* reset */
                   1147:   zclient_serv_path = NULL;
                   1148: 
                   1149:   /* test if `path' is socket. don't set it otherwise. */
                   1150:   if (stat(path, &sb) == -1)
                   1151:     {
                   1152:       zlog_warn ("%s: zebra socket `%s' does not exist", __func__, path);
                   1153:       return;
                   1154:     }
                   1155: 
                   1156:   if ((sb.st_mode & S_IFMT) != S_IFSOCK)
                   1157:     {
                   1158:       zlog_warn ("%s: `%s' is not unix socket, sir", __func__, path);
                   1159:       return;
                   1160:     }
                   1161: 
                   1162:   /* it seems that path is unix socket */
                   1163:   zclient_serv_path = path;
                   1164: }
                   1165: 

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