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