Annotation of embedaddon/quagga/ospfclient/ospf_apiclient.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Client side of OSPF API.
! 3: * Copyright (C) 2001, 2002, 2003 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: #include <lib/version.h>
! 26: #include "getopt.h"
! 27: #include "thread.h"
! 28: #include "prefix.h"
! 29: #include "linklist.h"
! 30: #include "if.h"
! 31: #include "vector.h"
! 32: #include "vty.h"
! 33: #include "command.h"
! 34: #include "filter.h"
! 35: #include "stream.h"
! 36: #include "log.h"
! 37: #include "memory.h"
! 38:
! 39: #include "ospfd/ospfd.h"
! 40: #include "ospfd/ospf_interface.h"
! 41: #include "ospfd/ospf_asbr.h"
! 42: #include "ospfd/ospf_lsa.h"
! 43: #include "ospfd/ospf_opaque.h"
! 44: #include "ospfd/ospf_lsdb.h"
! 45: #include "ospfd/ospf_neighbor.h"
! 46: #include "ospfd/ospf_dump.h"
! 47: #include "ospfd/ospf_zebra.h"
! 48: #include "ospfd/ospf_api.h"
! 49:
! 50: #include "ospf_apiclient.h"
! 51:
! 52: /* Backlog for listen */
! 53: #define BACKLOG 5
! 54:
! 55: /* -----------------------------------------------------------
! 56: * Forward declarations
! 57: * -----------------------------------------------------------
! 58: */
! 59:
! 60: void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient,
! 61: struct msg *msg);
! 62: void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient,
! 63: struct msg *msg);
! 64: void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient,
! 65: struct msg *msg);
! 66:
! 67: /* -----------------------------------------------------------
! 68: * Initialization
! 69: * -----------------------------------------------------------
! 70: */
! 71:
! 72: static unsigned short
! 73: ospf_apiclient_getport (void)
! 74: {
! 75: struct servent *sp = getservbyname ("ospfapi", "tcp");
! 76:
! 77: return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
! 78: }
! 79:
! 80: /* -----------------------------------------------------------
! 81: * Followings are functions for connection management
! 82: * -----------------------------------------------------------
! 83: */
! 84:
! 85: struct ospf_apiclient *
! 86: ospf_apiclient_connect (char *host, int syncport)
! 87: {
! 88: struct sockaddr_in myaddr_sync;
! 89: struct sockaddr_in myaddr_async;
! 90: struct sockaddr_in peeraddr;
! 91: struct hostent *hp;
! 92: struct ospf_apiclient *new;
! 93: int size = 0;
! 94: unsigned int peeraddrlen;
! 95: int async_server_sock;
! 96: int fd1, fd2;
! 97: int ret;
! 98: int on = 1;
! 99:
! 100: /* There are two connections between the client and the server.
! 101: First the client opens a connection for synchronous requests/replies
! 102: to the server. The server will accept this connection and
! 103: as a reaction open a reverse connection channel for
! 104: asynchronous messages. */
! 105:
! 106: async_server_sock = socket (AF_INET, SOCK_STREAM, 0);
! 107: if (async_server_sock < 0)
! 108: {
! 109: fprintf (stderr,
! 110: "ospf_apiclient_connect: creating async socket failed\n");
! 111: return NULL;
! 112: }
! 113:
! 114: /* Prepare socket for asynchronous messages */
! 115: /* Initialize async address structure */
! 116: memset (&myaddr_async, 0, sizeof (struct sockaddr_in));
! 117: myaddr_async.sin_family = AF_INET;
! 118: myaddr_async.sin_addr.s_addr = htonl (INADDR_ANY);
! 119: myaddr_async.sin_port = htons (syncport+1);
! 120: size = sizeof (struct sockaddr_in);
! 121: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
! 122: myaddr_async.sin_len = size;
! 123: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
! 124:
! 125: /* This is a server socket, reuse addr and port */
! 126: ret = setsockopt (async_server_sock, SOL_SOCKET,
! 127: SO_REUSEADDR, (void *) &on, sizeof (on));
! 128: if (ret < 0)
! 129: {
! 130: fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
! 131: close (async_server_sock);
! 132: return NULL;
! 133: }
! 134:
! 135: #ifdef SO_REUSEPORT
! 136: ret = setsockopt (async_server_sock, SOL_SOCKET, SO_REUSEPORT,
! 137: (void *) &on, sizeof (on));
! 138: if (ret < 0)
! 139: {
! 140: fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
! 141: close (async_server_sock);
! 142: return NULL;
! 143: }
! 144: #endif /* SO_REUSEPORT */
! 145:
! 146: /* Bind socket to address structure */
! 147: ret = bind (async_server_sock, (struct sockaddr *) &myaddr_async, size);
! 148: if (ret < 0)
! 149: {
! 150: fprintf (stderr, "ospf_apiclient_connect: bind async socket failed\n");
! 151: close (async_server_sock);
! 152: return NULL;
! 153: }
! 154:
! 155: /* Wait for reverse channel connection establishment from server */
! 156: ret = listen (async_server_sock, BACKLOG);
! 157: if (ret < 0)
! 158: {
! 159: fprintf (stderr, "ospf_apiclient_connect: listen: %s\n", safe_strerror (errno));
! 160: close (async_server_sock);
! 161: return NULL;
! 162: }
! 163:
! 164: /* Make connection for synchronous requests and connect to server */
! 165: /* Resolve address of server */
! 166: hp = gethostbyname (host);
! 167: if (!hp)
! 168: {
! 169: fprintf (stderr, "ospf_apiclient_connect: no such host %s\n", host);
! 170: close (async_server_sock);
! 171: return NULL;
! 172: }
! 173:
! 174: fd1 = socket (AF_INET, SOCK_STREAM, 0);
! 175: if (fd1 < 0)
! 176: {
! 177: fprintf (stderr,
! 178: "ospf_apiclient_connect: creating sync socket failed\n");
! 179: return NULL;
! 180: }
! 181:
! 182:
! 183: /* Reuse addr and port */
! 184: ret = setsockopt (fd1, SOL_SOCKET,
! 185: SO_REUSEADDR, (void *) &on, sizeof (on));
! 186: if (ret < 0)
! 187: {
! 188: fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
! 189: close (fd1);
! 190: return NULL;
! 191: }
! 192:
! 193: #ifdef SO_REUSEPORT
! 194: ret = setsockopt (fd1, SOL_SOCKET, SO_REUSEPORT,
! 195: (void *) &on, sizeof (on));
! 196: if (ret < 0)
! 197: {
! 198: fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
! 199: close (fd1);
! 200: return NULL;
! 201: }
! 202: #endif /* SO_REUSEPORT */
! 203:
! 204:
! 205: /* Bind sync socket to address structure. This is needed since we
! 206: want the sync port number on a fixed port number. The reverse
! 207: async channel will be at this port+1 */
! 208:
! 209: memset (&myaddr_sync, 0, sizeof (struct sockaddr_in));
! 210: myaddr_sync.sin_family = AF_INET;
! 211: myaddr_sync.sin_port = htons (syncport);
! 212: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
! 213: myaddr_sync.sin_len = sizeof (struct sockaddr_in);
! 214: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
! 215:
! 216: ret = bind (fd1, (struct sockaddr *) &myaddr_sync, size);
! 217: if (ret < 0)
! 218: {
! 219: fprintf (stderr, "ospf_apiclient_connect: bind sync socket failed\n");
! 220: close (fd1);
! 221: return NULL;
! 222: }
! 223:
! 224: /* Prepare address structure for connect */
! 225: memcpy (&myaddr_sync.sin_addr, hp->h_addr, hp->h_length);
! 226: myaddr_sync.sin_family = AF_INET;
! 227: myaddr_sync.sin_port = htons(ospf_apiclient_getport ());
! 228: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
! 229: myaddr_sync.sin_len = sizeof (struct sockaddr_in);
! 230: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
! 231:
! 232: /* Now establish synchronous channel with OSPF daemon */
! 233: ret = connect (fd1, (struct sockaddr *) &myaddr_sync,
! 234: sizeof (struct sockaddr_in));
! 235: if (ret < 0)
! 236: {
! 237: fprintf (stderr, "ospf_apiclient_connect: sync connect failed\n");
! 238: close (async_server_sock);
! 239: close (fd1);
! 240: return NULL;
! 241: }
! 242:
! 243: /* Accept reverse connection */
! 244: peeraddrlen = sizeof (struct sockaddr_in);
! 245: memset (&peeraddr, 0, peeraddrlen);
! 246:
! 247: fd2 =
! 248: accept (async_server_sock, (struct sockaddr *) &peeraddr, &peeraddrlen);
! 249: if (fd2 < 0)
! 250: {
! 251: fprintf (stderr, "ospf_apiclient_connect: accept async failed\n");
! 252: close (async_server_sock);
! 253: close (fd1);
! 254: return NULL;
! 255: }
! 256:
! 257: /* Server socket is not needed anymore since we are not accepting more
! 258: connections */
! 259: close (async_server_sock);
! 260:
! 261: /* Create new client-side instance */
! 262: new = XCALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient));
! 263:
! 264: /* Initialize socket descriptors for sync and async channels */
! 265: new->fd_sync = fd1;
! 266: new->fd_async = fd2;
! 267:
! 268: return new;
! 269: }
! 270:
! 271: int
! 272: ospf_apiclient_close (struct ospf_apiclient *oclient)
! 273: {
! 274:
! 275: if (oclient->fd_sync >= 0)
! 276: {
! 277: close (oclient->fd_sync);
! 278: }
! 279:
! 280: if (oclient->fd_async >= 0)
! 281: {
! 282: close (oclient->fd_async);
! 283: }
! 284:
! 285: /* Free client structure */
! 286: XFREE (MTYPE_OSPF_APICLIENT, oclient);
! 287: return 0;
! 288: }
! 289:
! 290: /* -----------------------------------------------------------
! 291: * Followings are functions to send a request to OSPFd
! 292: * -----------------------------------------------------------
! 293: */
! 294:
! 295: /* Send synchronous request, wait for reply */
! 296: static int
! 297: ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg)
! 298: {
! 299: u_int32_t reqseq;
! 300: struct msg_reply *msgreply;
! 301: int rc;
! 302:
! 303: /* NB: Given "msg" is freed inside this function. */
! 304:
! 305: /* Remember the sequence number of the request */
! 306: reqseq = ntohl (msg->hdr.msgseq);
! 307:
! 308: /* Write message to OSPFd */
! 309: rc = msg_write (oclient->fd_sync, msg);
! 310: msg_free (msg);
! 311:
! 312: if (rc < 0)
! 313: {
! 314: return -1;
! 315: }
! 316:
! 317: /* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */
! 318: msg = msg_read (oclient->fd_sync);
! 319: if (!msg)
! 320: return -1;
! 321:
! 322: assert (msg->hdr.msgtype == MSG_REPLY);
! 323: assert (ntohl (msg->hdr.msgseq) == reqseq);
! 324:
! 325: msgreply = (struct msg_reply *) STREAM_DATA (msg->s);
! 326: rc = msgreply->errcode;
! 327: msg_free (msg);
! 328:
! 329: return rc;
! 330: }
! 331:
! 332:
! 333: /* -----------------------------------------------------------
! 334: * Helper functions
! 335: * -----------------------------------------------------------
! 336: */
! 337:
! 338: static u_int32_t
! 339: ospf_apiclient_get_seqnr (void)
! 340: {
! 341: static u_int32_t seqnr = MIN_SEQ;
! 342: u_int32_t tmp;
! 343:
! 344: tmp = seqnr;
! 345: /* Increment sequence number */
! 346: if (seqnr < MAX_SEQ)
! 347: {
! 348: seqnr++;
! 349: }
! 350: else
! 351: {
! 352: seqnr = MIN_SEQ;
! 353: }
! 354: return tmp;
! 355: }
! 356:
! 357: /* -----------------------------------------------------------
! 358: * API to access OSPF daemon by client applications.
! 359: * -----------------------------------------------------------
! 360: */
! 361:
! 362: /*
! 363: * Synchronous request to register opaque type.
! 364: */
! 365: int
! 366: ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl,
! 367: u_char ltype, u_char otype)
! 368: {
! 369: struct msg *msg;
! 370: int rc;
! 371:
! 372: /* just put 1 as a sequence number. */
! 373: msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (),
! 374: ltype, otype);
! 375: if (!msg)
! 376: {
! 377: fprintf (stderr, "new_msg_register_opaque_type failed\n");
! 378: return -1;
! 379: }
! 380:
! 381: rc = ospf_apiclient_send_request (cl, msg);
! 382: return rc;
! 383: }
! 384:
! 385: /*
! 386: * Synchronous request to synchronize with OSPF's LSDB.
! 387: * Two steps required: register_event in order to get
! 388: * dynamic updates and LSDB_Sync.
! 389: */
! 390: int
! 391: ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient)
! 392: {
! 393: struct msg *msg;
! 394: int rc;
! 395: struct lsa_filter_type filter;
! 396:
! 397: filter.typemask = 0xFFFF; /* all LSAs */
! 398: filter.origin = ANY_ORIGIN;
! 399: filter.num_areas = 0; /* all Areas. */
! 400:
! 401: msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter);
! 402: if (!msg)
! 403: {
! 404: fprintf (stderr, "new_msg_register_event failed\n");
! 405: return -1;
! 406: }
! 407: rc = ospf_apiclient_send_request (oclient, msg);
! 408:
! 409: if (rc != 0)
! 410: goto out;
! 411:
! 412: msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter);
! 413: if (!msg)
! 414: {
! 415: fprintf (stderr, "new_msg_sync_lsdb failed\n");
! 416: return -1;
! 417: }
! 418: rc = ospf_apiclient_send_request (oclient, msg);
! 419:
! 420: out:
! 421: return rc;
! 422: }
! 423:
! 424: /*
! 425: * Synchronous request to originate or update an LSA.
! 426: */
! 427:
! 428: int
! 429: ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient,
! 430: struct in_addr ifaddr,
! 431: struct in_addr area_id,
! 432: u_char lsa_type,
! 433: u_char opaque_type, u_int32_t opaque_id,
! 434: void *opaquedata, int opaquelen)
! 435: {
! 436: struct msg *msg;
! 437: int rc;
! 438: u_char buf[OSPF_MAX_LSA_SIZE];
! 439: struct lsa_header *lsah;
! 440: u_int32_t tmp;
! 441:
! 442:
! 443: /* We can only originate opaque LSAs */
! 444: if (!IS_OPAQUE_LSA (lsa_type))
! 445: {
! 446: fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type);
! 447: return OSPF_API_ILLEGALLSATYPE;
! 448: }
! 449:
! 450: /* Make a new LSA from parameters */
! 451: lsah = (struct lsa_header *) buf;
! 452: lsah->ls_age = 0;
! 453: lsah->options = 0;
! 454: lsah->type = lsa_type;
! 455:
! 456: tmp = SET_OPAQUE_LSID (opaque_type, opaque_id);
! 457: lsah->id.s_addr = htonl (tmp);
! 458: lsah->adv_router.s_addr = 0;
! 459: lsah->ls_seqnum = 0;
! 460: lsah->checksum = 0;
! 461: lsah->length = htons (sizeof (struct lsa_header) + opaquelen);
! 462:
! 463: memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata,
! 464: opaquelen);
! 465:
! 466: msg = new_msg_originate_request (ospf_apiclient_get_seqnr (),
! 467: ifaddr, area_id, lsah);
! 468: if (!msg)
! 469: {
! 470: fprintf (stderr, "new_msg_originate_request failed\n");
! 471: return OSPF_API_NOMEMORY;
! 472: }
! 473:
! 474: rc = ospf_apiclient_send_request (oclient, msg);
! 475: return rc;
! 476: }
! 477:
! 478: int
! 479: ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient,
! 480: struct in_addr area_id, u_char lsa_type,
! 481: u_char opaque_type, u_int32_t opaque_id)
! 482: {
! 483: struct msg *msg;
! 484: int rc;
! 485:
! 486: /* Only opaque LSA can be deleted */
! 487: if (!IS_OPAQUE_LSA (lsa_type))
! 488: {
! 489: fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type);
! 490: return OSPF_API_ILLEGALLSATYPE;
! 491: }
! 492:
! 493: /* opaque_id is in host byte order and will be converted
! 494: * to network byte order by new_msg_delete_request */
! 495: msg = new_msg_delete_request (ospf_apiclient_get_seqnr (),
! 496: area_id, lsa_type, opaque_type, opaque_id);
! 497:
! 498: rc = ospf_apiclient_send_request (oclient, msg);
! 499: return rc;
! 500: }
! 501:
! 502: /* -----------------------------------------------------------
! 503: * Followings are handlers for messages from OSPF daemon
! 504: * -----------------------------------------------------------
! 505: */
! 506:
! 507: static void
! 508: ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg)
! 509: {
! 510: struct msg_ready_notify *r;
! 511: r = (struct msg_ready_notify *) STREAM_DATA (msg->s);
! 512:
! 513: /* Invoke registered callback function. */
! 514: if (oclient->ready_notify)
! 515: {
! 516: (oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr);
! 517: }
! 518: }
! 519:
! 520: static void
! 521: ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg)
! 522: {
! 523: struct msg_new_if *n;
! 524: n = (struct msg_new_if *) STREAM_DATA (msg->s);
! 525:
! 526: /* Invoke registered callback function. */
! 527: if (oclient->new_if)
! 528: {
! 529: (oclient->new_if) (n->ifaddr, n->area_id);
! 530: }
! 531: }
! 532:
! 533: static void
! 534: ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg)
! 535: {
! 536: struct msg_del_if *d;
! 537: d = (struct msg_del_if *) STREAM_DATA (msg->s);
! 538:
! 539: /* Invoke registered callback function. */
! 540: if (oclient->del_if)
! 541: {
! 542: (oclient->del_if) (d->ifaddr);
! 543: }
! 544: }
! 545:
! 546: static void
! 547: ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient,
! 548: struct msg *msg)
! 549: {
! 550: struct msg_ism_change *m;
! 551: m = (struct msg_ism_change *) STREAM_DATA (msg->s);
! 552:
! 553: /* Invoke registered callback function. */
! 554: if (oclient->ism_change)
! 555: {
! 556: (oclient->ism_change) (m->ifaddr, m->area_id, m->status);
! 557: }
! 558:
! 559: }
! 560:
! 561: static void
! 562: ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient,
! 563: struct msg *msg)
! 564: {
! 565: struct msg_nsm_change *m;
! 566: m = (struct msg_nsm_change *) STREAM_DATA (msg->s);
! 567:
! 568: /* Invoke registered callback function. */
! 569: if (oclient->nsm_change)
! 570: {
! 571: (oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status);
! 572: }
! 573: }
! 574:
! 575: static void
! 576: ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient,
! 577: struct msg *msg)
! 578: {
! 579: struct msg_lsa_change_notify *cn;
! 580: struct lsa_header *lsa;
! 581: int lsalen;
! 582:
! 583: cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
! 584:
! 585: /* Extract LSA from message */
! 586: lsalen = ntohs (cn->data.length);
! 587: lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
! 588: if (!lsa)
! 589: {
! 590: fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n");
! 591: return;
! 592: }
! 593: memcpy (lsa, &(cn->data), lsalen);
! 594:
! 595: /* Invoke registered update callback function */
! 596: if (oclient->update_notify)
! 597: {
! 598: (oclient->update_notify) (cn->ifaddr, cn->area_id,
! 599: cn->is_self_originated, lsa);
! 600: }
! 601:
! 602: /* free memory allocated by ospf apiclient library */
! 603: XFREE (MTYPE_OSPF_APICLIENT, lsa);
! 604: }
! 605:
! 606: static void
! 607: ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient,
! 608: struct msg *msg)
! 609: {
! 610: struct msg_lsa_change_notify *cn;
! 611: struct lsa_header *lsa;
! 612: int lsalen;
! 613:
! 614: cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
! 615:
! 616: /* Extract LSA from message */
! 617: lsalen = ntohs (cn->data.length);
! 618: lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
! 619: if (!lsa)
! 620: {
! 621: fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n");
! 622: return;
! 623: }
! 624: memcpy (lsa, &(cn->data), lsalen);
! 625:
! 626: /* Invoke registered update callback function */
! 627: if (oclient->delete_notify)
! 628: {
! 629: (oclient->delete_notify) (cn->ifaddr, cn->area_id,
! 630: cn->is_self_originated, lsa);
! 631: }
! 632:
! 633: /* free memory allocated by ospf apiclient library */
! 634: XFREE (MTYPE_OSPF_APICLIENT, lsa);
! 635: }
! 636:
! 637: static void
! 638: ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg)
! 639: {
! 640: /* Call message handler function. */
! 641: switch (msg->hdr.msgtype)
! 642: {
! 643: case MSG_READY_NOTIFY:
! 644: ospf_apiclient_handle_ready (oclient, msg);
! 645: break;
! 646: case MSG_NEW_IF:
! 647: ospf_apiclient_handle_new_if (oclient, msg);
! 648: break;
! 649: case MSG_DEL_IF:
! 650: ospf_apiclient_handle_del_if (oclient, msg);
! 651: break;
! 652: case MSG_ISM_CHANGE:
! 653: ospf_apiclient_handle_ism_change (oclient, msg);
! 654: break;
! 655: case MSG_NSM_CHANGE:
! 656: ospf_apiclient_handle_nsm_change (oclient, msg);
! 657: break;
! 658: case MSG_LSA_UPDATE_NOTIFY:
! 659: ospf_apiclient_handle_lsa_update (oclient, msg);
! 660: break;
! 661: case MSG_LSA_DELETE_NOTIFY:
! 662: ospf_apiclient_handle_lsa_delete (oclient, msg);
! 663: break;
! 664: default:
! 665: fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n",
! 666: msg->hdr.msgtype);
! 667: break;
! 668: }
! 669: }
! 670:
! 671: /* -----------------------------------------------------------
! 672: * Callback handler registration
! 673: * -----------------------------------------------------------
! 674: */
! 675:
! 676: void
! 677: ospf_apiclient_register_callback (struct ospf_apiclient *oclient,
! 678: void (*ready_notify) (u_char lsa_type,
! 679: u_char opaque_type,
! 680: struct in_addr addr),
! 681: void (*new_if) (struct in_addr ifaddr,
! 682: struct in_addr area_id),
! 683: void (*del_if) (struct in_addr ifaddr),
! 684: void (*ism_change) (struct in_addr ifaddr,
! 685: struct in_addr area_id,
! 686: u_char status),
! 687: void (*nsm_change) (struct in_addr ifaddr,
! 688: struct in_addr nbraddr,
! 689: struct in_addr
! 690: router_id,
! 691: u_char status),
! 692: void (*update_notify) (struct in_addr
! 693: ifaddr,
! 694: struct in_addr
! 695: area_id,
! 696: u_char self_origin,
! 697: struct lsa_header *
! 698: lsa),
! 699: void (*delete_notify) (struct in_addr
! 700: ifaddr,
! 701: struct in_addr
! 702: area_id,
! 703: u_char self_origin,
! 704: struct lsa_header *
! 705: lsa))
! 706: {
! 707: assert (oclient);
! 708: assert (update_notify);
! 709:
! 710: /* Register callback function */
! 711: oclient->ready_notify = ready_notify;
! 712: oclient->new_if = new_if;
! 713: oclient->del_if = del_if;
! 714: oclient->ism_change = ism_change;
! 715: oclient->nsm_change = nsm_change;
! 716: oclient->update_notify = update_notify;
! 717: oclient->delete_notify = delete_notify;
! 718: }
! 719:
! 720: /* -----------------------------------------------------------
! 721: * Asynchronous message handling
! 722: * -----------------------------------------------------------
! 723: */
! 724:
! 725: int
! 726: ospf_apiclient_handle_async (struct ospf_apiclient *oclient)
! 727: {
! 728: struct msg *msg;
! 729:
! 730: /* Get a message */
! 731: msg = msg_read (oclient->fd_async);
! 732:
! 733: if (!msg)
! 734: {
! 735: /* Connection broke down */
! 736: return -1;
! 737: }
! 738:
! 739: /* Handle message */
! 740: ospf_apiclient_msghandle (oclient, msg);
! 741:
! 742: /* Don't forget to free this message */
! 743: msg_free (msg);
! 744:
! 745: return 0;
! 746: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>