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>