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

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

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