Annotation of embedaddon/quagga/ospfd/ospf_api.c, revision 1.1
1.1 ! misho 1: /*
! 2: * API message handling module for OSPF daemon and client.
! 3: * Copyright (C) 2001, 2002 Ralph Keller
! 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,
! 20: * Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24:
! 25: #ifdef SUPPORT_OSPF_API
! 26: #ifndef HAVE_OPAQUE_LSA
! 27: #error "Core Opaque-LSA module must be configured."
! 28: #endif /* HAVE_OPAQUE_LSA */
! 29:
! 30: #include "linklist.h"
! 31: #include "prefix.h"
! 32: #include "if.h"
! 33: #include "table.h"
! 34: #include "memory.h"
! 35: #include "command.h"
! 36: #include "vty.h"
! 37: #include "stream.h"
! 38: #include "log.h"
! 39: #include "thread.h"
! 40: #include "hash.h"
! 41: #include "sockunion.h" /* for inet_aton() */
! 42: #include "buffer.h"
! 43: #include "network.h"
! 44:
! 45: #include "ospfd/ospfd.h"
! 46: #include "ospfd/ospf_interface.h"
! 47: #include "ospfd/ospf_ism.h"
! 48: #include "ospfd/ospf_asbr.h"
! 49: #include "ospfd/ospf_lsa.h"
! 50: #include "ospfd/ospf_lsdb.h"
! 51: #include "ospfd/ospf_neighbor.h"
! 52: #include "ospfd/ospf_nsm.h"
! 53: #include "ospfd/ospf_flood.h"
! 54: #include "ospfd/ospf_packet.h"
! 55: #include "ospfd/ospf_spf.h"
! 56: #include "ospfd/ospf_dump.h"
! 57: #include "ospfd/ospf_route.h"
! 58: #include "ospfd/ospf_ase.h"
! 59: #include "ospfd/ospf_zebra.h"
! 60:
! 61: #include "ospfd/ospf_api.h"
! 62:
! 63:
! 64: /* For debugging only, will be removed */
! 65: void
! 66: api_opaque_lsa_print (struct lsa_header *data)
! 67: {
! 68: struct opaque_lsa
! 69: {
! 70: struct lsa_header header;
! 71: u_char mydata[];
! 72: };
! 73:
! 74: struct opaque_lsa *olsa;
! 75: int opaquelen;
! 76: int i;
! 77:
! 78: ospf_lsa_header_dump (data);
! 79:
! 80: olsa = (struct opaque_lsa *) data;
! 81:
! 82: opaquelen = ntohs (data->length) - OSPF_LSA_HEADER_SIZE;
! 83: zlog_debug ("apiserver_lsa_print: opaquelen=%d\n", opaquelen);
! 84:
! 85: for (i = 0; i < opaquelen; i++)
! 86: {
! 87: zlog_debug ("0x%x ", olsa->mydata[i]);
! 88: }
! 89: zlog_debug ("\n");
! 90: }
! 91:
! 92: /* -----------------------------------------------------------
! 93: * Generic messages
! 94: * -----------------------------------------------------------
! 95: */
! 96:
! 97: struct msg *
! 98: msg_new (u_char msgtype, void *msgbody, u_int32_t seqnum, u_int16_t msglen)
! 99: {
! 100: struct msg *new;
! 101:
! 102: new = XCALLOC (MTYPE_OSPF_API_MSG, sizeof (struct msg));
! 103:
! 104: new->hdr.version = OSPF_API_VERSION;
! 105: new->hdr.msgtype = msgtype;
! 106: new->hdr.msglen = htons (msglen);
! 107: new->hdr.msgseq = htonl (seqnum);
! 108:
! 109: new->s = stream_new (msglen);
! 110: assert (new->s);
! 111: stream_put (new->s, msgbody, msglen);
! 112:
! 113: return new;
! 114: }
! 115:
! 116:
! 117: /* Duplicate a message by copying content. */
! 118: struct msg *
! 119: msg_dup (struct msg *msg)
! 120: {
! 121: struct msg *new;
! 122:
! 123: assert (msg);
! 124:
! 125: new = msg_new (msg->hdr.msgtype, STREAM_DATA (msg->s),
! 126: ntohl (msg->hdr.msgseq), ntohs (msg->hdr.msglen));
! 127: return new;
! 128: }
! 129:
! 130:
! 131: /* XXX only for testing, will be removed */
! 132:
! 133: struct nametab {
! 134: int value;
! 135: const char *name;
! 136: };
! 137:
! 138: const char *
! 139: ospf_api_typename (int msgtype)
! 140: {
! 141: struct nametab NameTab[] = {
! 142: { MSG_REGISTER_OPAQUETYPE, "Register opaque-type", },
! 143: { MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type", },
! 144: { MSG_REGISTER_EVENT, "Register event", },
! 145: { MSG_SYNC_LSDB, "Sync LSDB", },
! 146: { MSG_ORIGINATE_REQUEST, "Originate request", },
! 147: { MSG_DELETE_REQUEST, "Delete request", },
! 148: { MSG_REPLY, "Reply", },
! 149: { MSG_READY_NOTIFY, "Ready notify", },
! 150: { MSG_LSA_UPDATE_NOTIFY, "LSA update notify", },
! 151: { MSG_LSA_DELETE_NOTIFY, "LSA delete notify", },
! 152: { MSG_NEW_IF, "New interface", },
! 153: { MSG_DEL_IF, "Del interface", },
! 154: { MSG_ISM_CHANGE, "ISM change", },
! 155: { MSG_NSM_CHANGE, "NSM change", },
! 156: };
! 157:
! 158: int i, n = sizeof (NameTab) / sizeof (NameTab[0]);
! 159: const char *name = NULL;
! 160:
! 161: for (i = 0; i < n; i++)
! 162: {
! 163: if (NameTab[i].value == msgtype)
! 164: {
! 165: name = NameTab[i].name;
! 166: break;
! 167: }
! 168: }
! 169:
! 170: return name ? name : "?";
! 171: }
! 172:
! 173: const char *
! 174: ospf_api_errname (int errcode)
! 175: {
! 176: struct nametab NameTab[] = {
! 177: { OSPF_API_OK, "OK", },
! 178: { OSPF_API_NOSUCHINTERFACE, "No such interface", },
! 179: { OSPF_API_NOSUCHAREA, "No such area", },
! 180: { OSPF_API_NOSUCHLSA, "No such LSA", },
! 181: { OSPF_API_ILLEGALLSATYPE, "Illegal LSA type", },
! 182: { OSPF_API_OPAQUETYPEINUSE, "Opaque type in use", },
! 183: { OSPF_API_OPAQUETYPENOTREGISTERED, "Opaque type not registered", },
! 184: { OSPF_API_NOTREADY, "Not ready", },
! 185: { OSPF_API_NOMEMORY, "No memory", },
! 186: { OSPF_API_ERROR, "Other error", },
! 187: { OSPF_API_UNDEF, "Undefined", },
! 188: };
! 189:
! 190: int i, n = sizeof (NameTab) / sizeof (NameTab[0]);
! 191: const char *name = NULL;
! 192:
! 193: for (i = 0; i < n; i++)
! 194: {
! 195: if (NameTab[i].value == errcode)
! 196: {
! 197: name = NameTab[i].name;
! 198: break;
! 199: }
! 200: }
! 201:
! 202: return name ? name : "?";
! 203: }
! 204:
! 205: void
! 206: msg_print (struct msg *msg)
! 207: {
! 208: if (!msg)
! 209: {
! 210: zlog_debug ("msg_print msg=NULL!\n");
! 211: return;
! 212: }
! 213:
! 214: #ifdef ORIGINAL_CODING
! 215: zlog_debug
! 216: ("msg=%p msgtype=%d msglen=%d msgseq=%d streamdata=%p streamsize=%lu\n",
! 217: msg, msg->hdr.msgtype, ntohs (msg->hdr.msglen), ntohl (msg->hdr.msgseq),
! 218: STREAM_DATA (msg->s), STREAM_SIZE (msg->s));
! 219: #else /* ORIGINAL_CODING */
! 220: /* API message common header part. */
! 221: zlog_debug
! 222: ("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%zd)",
! 223: ospf_api_typename (msg->hdr.msgtype), msg->hdr.msgtype,
! 224: ntohs (msg->hdr.msglen), (unsigned long) ntohl (msg->hdr.msgseq),
! 225: STREAM_DATA (msg->s), STREAM_SIZE (msg->s));
! 226:
! 227: /* API message body part. */
! 228: #ifdef ndef
! 229: /* Generic Hex/Ascii dump */
! 230: DumpBuf (STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); /* Sorry, deleted! */
! 231: #else /* ndef */
! 232: /* Message-type dependent dump function. */
! 233: #endif /* ndef */
! 234:
! 235: return;
! 236: #endif /* ORIGINAL_CODING */
! 237: }
! 238:
! 239: void
! 240: msg_free (struct msg *msg)
! 241: {
! 242: if (msg->s)
! 243: stream_free (msg->s);
! 244:
! 245: XFREE (MTYPE_OSPF_API_MSG, msg);
! 246: }
! 247:
! 248:
! 249: /* Set sequence number of message */
! 250: void
! 251: msg_set_seq (struct msg *msg, u_int32_t seqnr)
! 252: {
! 253: assert (msg);
! 254: msg->hdr.msgseq = htonl (seqnr);
! 255: }
! 256:
! 257: /* Get sequence number of message */
! 258: u_int32_t
! 259: msg_get_seq (struct msg *msg)
! 260: {
! 261: assert (msg);
! 262: return ntohl (msg->hdr.msgseq);
! 263: }
! 264:
! 265: /* -----------------------------------------------------------
! 266: * Message fifo queues
! 267: * -----------------------------------------------------------
! 268: */
! 269:
! 270: struct msg_fifo *
! 271: msg_fifo_new ()
! 272: {
! 273: return XCALLOC (MTYPE_OSPF_API_FIFO, sizeof (struct msg_fifo));
! 274: }
! 275:
! 276: /* Add new message to fifo. */
! 277: void
! 278: msg_fifo_push (struct msg_fifo *fifo, struct msg *msg)
! 279: {
! 280: if (fifo->tail)
! 281: fifo->tail->next = msg;
! 282: else
! 283: fifo->head = msg;
! 284:
! 285: fifo->tail = msg;
! 286: fifo->count++;
! 287: }
! 288:
! 289:
! 290: /* Remove first message from fifo. */
! 291: struct msg *
! 292: msg_fifo_pop (struct msg_fifo *fifo)
! 293: {
! 294: struct msg *msg;
! 295:
! 296: msg = fifo->head;
! 297: if (msg)
! 298: {
! 299: fifo->head = msg->next;
! 300:
! 301: if (fifo->head == NULL)
! 302: fifo->tail = NULL;
! 303:
! 304: fifo->count--;
! 305: }
! 306: return msg;
! 307: }
! 308:
! 309: /* Return first fifo entry but do not remove it. */
! 310: struct msg *
! 311: msg_fifo_head (struct msg_fifo *fifo)
! 312: {
! 313: return fifo->head;
! 314: }
! 315:
! 316: /* Flush message fifo. */
! 317: void
! 318: msg_fifo_flush (struct msg_fifo *fifo)
! 319: {
! 320: struct msg *op;
! 321: struct msg *next;
! 322:
! 323: for (op = fifo->head; op; op = next)
! 324: {
! 325: next = op->next;
! 326: msg_free (op);
! 327: }
! 328:
! 329: fifo->head = fifo->tail = NULL;
! 330: fifo->count = 0;
! 331: }
! 332:
! 333: /* Free API message fifo. */
! 334: void
! 335: msg_fifo_free (struct msg_fifo *fifo)
! 336: {
! 337: msg_fifo_flush (fifo);
! 338:
! 339: XFREE (MTYPE_OSPF_API_FIFO, fifo);
! 340: }
! 341:
! 342: struct msg *
! 343: msg_read (int fd)
! 344: {
! 345: struct msg *msg;
! 346: struct apimsghdr hdr;
! 347: u_char buf[OSPF_API_MAX_MSG_SIZE];
! 348: int bodylen;
! 349: int rlen;
! 350:
! 351: /* Read message header */
! 352: rlen = readn (fd, (u_char *) &hdr, sizeof (struct apimsghdr));
! 353:
! 354: if (rlen < 0)
! 355: {
! 356: zlog_warn ("msg_read: readn %s", safe_strerror (errno));
! 357: return NULL;
! 358: }
! 359: else if (rlen == 0)
! 360: {
! 361: zlog_warn ("msg_read: Connection closed by peer");
! 362: return NULL;
! 363: }
! 364: else if (rlen != sizeof (struct apimsghdr))
! 365: {
! 366: zlog_warn ("msg_read: Cannot read message header!");
! 367: return NULL;
! 368: }
! 369:
! 370: /* Check version of API protocol */
! 371: if (hdr.version != OSPF_API_VERSION)
! 372: {
! 373: zlog_warn ("msg_read: OSPF API protocol version mismatch");
! 374: return NULL;
! 375: }
! 376:
! 377: /* Determine body length. */
! 378: bodylen = ntohs (hdr.msglen);
! 379: if (bodylen > 0)
! 380: {
! 381:
! 382: /* Read message body */
! 383: rlen = readn (fd, buf, bodylen);
! 384: if (rlen < 0)
! 385: {
! 386: zlog_warn ("msg_read: readn %s", safe_strerror (errno));
! 387: return NULL;
! 388: }
! 389: else if (rlen == 0)
! 390: {
! 391: zlog_warn ("msg_read: Connection closed by peer");
! 392: return NULL;
! 393: }
! 394: else if (rlen != bodylen)
! 395: {
! 396: zlog_warn ("msg_read: Cannot read message body!");
! 397: return NULL;
! 398: }
! 399: }
! 400:
! 401: /* Allocate new message */
! 402: msg = msg_new (hdr.msgtype, buf, ntohl (hdr.msgseq), ntohs (hdr.msglen));
! 403:
! 404: return msg;
! 405: }
! 406:
! 407: int
! 408: msg_write (int fd, struct msg *msg)
! 409: {
! 410: u_char buf[OSPF_API_MAX_MSG_SIZE];
! 411: int l;
! 412: int wlen;
! 413:
! 414: assert (msg);
! 415: assert (msg->s);
! 416:
! 417: /* Length of message including header */
! 418: l = sizeof (struct apimsghdr) + ntohs (msg->hdr.msglen);
! 419:
! 420: /* Make contiguous memory buffer for message */
! 421: memcpy (buf, &msg->hdr, sizeof (struct apimsghdr));
! 422: memcpy (buf + sizeof (struct apimsghdr), STREAM_DATA (msg->s),
! 423: ntohs (msg->hdr.msglen));
! 424:
! 425: wlen = writen (fd, buf, l);
! 426: if (wlen < 0)
! 427: {
! 428: zlog_warn ("msg_write: writen %s", safe_strerror (errno));
! 429: return -1;
! 430: }
! 431: else if (wlen == 0)
! 432: {
! 433: zlog_warn ("msg_write: Connection closed by peer");
! 434: return -1;
! 435: }
! 436: else if (wlen != l)
! 437: {
! 438: zlog_warn ("msg_write: Cannot write API message");
! 439: return -1;
! 440: }
! 441: return 0;
! 442: }
! 443:
! 444: /* -----------------------------------------------------------
! 445: * Specific messages
! 446: * -----------------------------------------------------------
! 447: */
! 448:
! 449: struct msg *
! 450: new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype, u_char otype)
! 451: {
! 452: struct msg_register_opaque_type rmsg;
! 453:
! 454: rmsg.lsatype = ltype;
! 455: rmsg.opaquetype = otype;
! 456: memset (&rmsg.pad, 0, sizeof (rmsg.pad));
! 457:
! 458: return msg_new (MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum,
! 459: sizeof (struct msg_register_opaque_type));
! 460: }
! 461:
! 462: struct msg *
! 463: new_msg_register_event (u_int32_t seqnum, struct lsa_filter_type *filter)
! 464: {
! 465: u_char buf[OSPF_API_MAX_MSG_SIZE];
! 466: struct msg_register_event *emsg;
! 467: int len;
! 468:
! 469: emsg = (struct msg_register_event *) buf;
! 470: len = sizeof (struct msg_register_event) +
! 471: filter->num_areas * sizeof (struct in_addr);
! 472: emsg->filter.typemask = htons (filter->typemask);
! 473: emsg->filter.origin = filter->origin;
! 474: emsg->filter.num_areas = filter->num_areas;
! 475: return msg_new (MSG_REGISTER_EVENT, emsg, seqnum, len);
! 476: }
! 477:
! 478: struct msg *
! 479: new_msg_sync_lsdb (u_int32_t seqnum, struct lsa_filter_type *filter)
! 480: {
! 481: u_char buf[OSPF_API_MAX_MSG_SIZE];
! 482: struct msg_sync_lsdb *smsg;
! 483: int len;
! 484:
! 485: smsg = (struct msg_sync_lsdb *) buf;
! 486: len = sizeof (struct msg_sync_lsdb) +
! 487: filter->num_areas * sizeof (struct in_addr);
! 488: smsg->filter.typemask = htons (filter->typemask);
! 489: smsg->filter.origin = filter->origin;
! 490: smsg->filter.num_areas = filter->num_areas;
! 491: return msg_new (MSG_SYNC_LSDB, smsg, seqnum, len);
! 492: }
! 493:
! 494:
! 495: struct msg *
! 496: new_msg_originate_request (u_int32_t seqnum,
! 497: struct in_addr ifaddr,
! 498: struct in_addr area_id, struct lsa_header *data)
! 499: {
! 500: struct msg_originate_request *omsg;
! 501: int omsglen;
! 502: char buf[OSPF_API_MAX_MSG_SIZE];
! 503:
! 504: omsglen = sizeof (struct msg_originate_request) - sizeof (struct lsa_header)
! 505: + ntohs (data->length);
! 506:
! 507: omsg = (struct msg_originate_request *) buf;
! 508: omsg->ifaddr = ifaddr;
! 509: omsg->area_id = area_id;
! 510: memcpy (&omsg->data, data, ntohs (data->length));
! 511:
! 512: return msg_new (MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen);
! 513: }
! 514:
! 515: struct msg *
! 516: new_msg_delete_request (u_int32_t seqnum,
! 517: struct in_addr area_id, u_char lsa_type,
! 518: u_char opaque_type, u_int32_t opaque_id)
! 519: {
! 520: struct msg_delete_request dmsg;
! 521: dmsg.area_id = area_id;
! 522: dmsg.lsa_type = lsa_type;
! 523: dmsg.opaque_type = opaque_type;
! 524: dmsg.opaque_id = htonl (opaque_id);
! 525: memset (&dmsg.pad, 0, sizeof (dmsg.pad));
! 526:
! 527: return msg_new (MSG_DELETE_REQUEST, &dmsg, seqnum,
! 528: sizeof (struct msg_delete_request));
! 529: }
! 530:
! 531:
! 532: struct msg *
! 533: new_msg_reply (u_int32_t seqnr, u_char rc)
! 534: {
! 535: struct msg *msg;
! 536: struct msg_reply rmsg;
! 537:
! 538: /* Set return code */
! 539: rmsg.errcode = rc;
! 540: memset (&rmsg.pad, 0, sizeof (rmsg.pad));
! 541:
! 542: msg = msg_new (MSG_REPLY, &rmsg, seqnr, sizeof (struct msg_reply));
! 543:
! 544: return msg;
! 545: }
! 546:
! 547: struct msg *
! 548: new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type,
! 549: u_char opaque_type, struct in_addr addr)
! 550: {
! 551: struct msg_ready_notify rmsg;
! 552:
! 553: rmsg.lsa_type = lsa_type;
! 554: rmsg.opaque_type = opaque_type;
! 555: memset (&rmsg.pad, 0, sizeof (rmsg.pad));
! 556: rmsg.addr = addr;
! 557:
! 558: return msg_new (MSG_READY_NOTIFY, &rmsg, seqnr,
! 559: sizeof (struct msg_ready_notify));
! 560: }
! 561:
! 562: struct msg *
! 563: new_msg_new_if (u_int32_t seqnr,
! 564: struct in_addr ifaddr, struct in_addr area_id)
! 565: {
! 566: struct msg_new_if nmsg;
! 567:
! 568: nmsg.ifaddr = ifaddr;
! 569: nmsg.area_id = area_id;
! 570:
! 571: return msg_new (MSG_NEW_IF, &nmsg, seqnr, sizeof (struct msg_new_if));
! 572: }
! 573:
! 574: struct msg *
! 575: new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr)
! 576: {
! 577: struct msg_del_if dmsg;
! 578:
! 579: dmsg.ifaddr = ifaddr;
! 580:
! 581: return msg_new (MSG_DEL_IF, &dmsg, seqnr, sizeof (struct msg_del_if));
! 582: }
! 583:
! 584: struct msg *
! 585: new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr,
! 586: struct in_addr area_id, u_char status)
! 587: {
! 588: struct msg_ism_change imsg;
! 589:
! 590: imsg.ifaddr = ifaddr;
! 591: imsg.area_id = area_id;
! 592: imsg.status = status;
! 593: memset (&imsg.pad, 0, sizeof (imsg.pad));
! 594:
! 595: return msg_new (MSG_ISM_CHANGE, &imsg, seqnr,
! 596: sizeof (struct msg_ism_change));
! 597: }
! 598:
! 599: struct msg *
! 600: new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr,
! 601: struct in_addr nbraddr,
! 602: struct in_addr router_id, u_char status)
! 603: {
! 604: struct msg_nsm_change nmsg;
! 605:
! 606: nmsg.ifaddr = ifaddr;
! 607: nmsg.nbraddr = nbraddr;
! 608: nmsg.router_id = router_id;
! 609: nmsg.status = status;
! 610: memset (&nmsg.pad, 0, sizeof (nmsg.pad));
! 611:
! 612: return msg_new (MSG_NSM_CHANGE, &nmsg, seqnr,
! 613: sizeof (struct msg_nsm_change));
! 614: }
! 615:
! 616: struct msg *
! 617: new_msg_lsa_change_notify (u_char msgtype,
! 618: u_int32_t seqnum,
! 619: struct in_addr ifaddr,
! 620: struct in_addr area_id,
! 621: u_char is_self_originated, struct lsa_header *data)
! 622: {
! 623: u_char buf[OSPF_API_MAX_MSG_SIZE];
! 624: struct msg_lsa_change_notify *nmsg;
! 625: int len;
! 626:
! 627: assert (data);
! 628:
! 629: nmsg = (struct msg_lsa_change_notify *) buf;
! 630: len = ntohs (data->length) + sizeof (struct msg_lsa_change_notify)
! 631: - sizeof (struct lsa_header);
! 632: nmsg->ifaddr = ifaddr;
! 633: nmsg->area_id = area_id;
! 634: nmsg->is_self_originated = is_self_originated;
! 635: memset (&nmsg->pad, 0, sizeof (nmsg->pad));
! 636: memcpy (&nmsg->data, data, ntohs (data->length));
! 637:
! 638: return msg_new (msgtype, nmsg, seqnum, len);
! 639: }
! 640:
! 641: #endif /* SUPPORT_OSPF_API */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>