Annotation of embedaddon/quagga/ospfd/ospf_apiserver.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Server side of OSPF API.
! 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:
! 44: #include <sys/types.h>
! 45:
! 46: #include "ospfd/ospfd.h" /* for "struct thread_master" */
! 47: #include "ospfd/ospf_interface.h"
! 48: #include "ospfd/ospf_ism.h"
! 49: #include "ospfd/ospf_asbr.h"
! 50: #include "ospfd/ospf_lsa.h"
! 51: #include "ospfd/ospf_lsdb.h"
! 52: #include "ospfd/ospf_neighbor.h"
! 53: #include "ospfd/ospf_nsm.h"
! 54: #include "ospfd/ospf_flood.h"
! 55: #include "ospfd/ospf_packet.h"
! 56: #include "ospfd/ospf_spf.h"
! 57: #include "ospfd/ospf_dump.h"
! 58: #include "ospfd/ospf_route.h"
! 59: #include "ospfd/ospf_ase.h"
! 60: #include "ospfd/ospf_zebra.h"
! 61:
! 62: #include "ospfd/ospf_api.h"
! 63: #include "ospfd/ospf_apiserver.h"
! 64:
! 65: /* This is an implementation of an API to the OSPF daemon that allows
! 66: * external applications to access the OSPF daemon through socket
! 67: * connections. The application can use this API to inject its own
! 68: * opaque LSAs and flood them to other OSPF daemons. Other OSPF
! 69: * daemons then receive these LSAs and inform applications through the
! 70: * API by sending a corresponding message. The application can also
! 71: * register to receive all LSA types (in addition to opaque types) and
! 72: * use this information to reconstruct the OSPF's LSDB. The OSPF
! 73: * daemon supports multiple applications concurrently. */
! 74:
! 75: /* List of all active connections. */
! 76: struct list *apiserver_list;
! 77:
! 78: /* -----------------------------------------------------------
! 79: * Functions to lookup interfaces
! 80: * -----------------------------------------------------------
! 81: */
! 82:
! 83: struct ospf_interface *
! 84: ospf_apiserver_if_lookup_by_addr (struct in_addr address)
! 85: {
! 86: struct listnode *node, *nnode;
! 87: struct ospf_interface *oi;
! 88: struct ospf *ospf;
! 89:
! 90: if (!(ospf = ospf_lookup ()))
! 91: return NULL;
! 92:
! 93: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 94: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
! 95: if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
! 96: return oi;
! 97:
! 98: return NULL;
! 99: }
! 100:
! 101: struct ospf_interface *
! 102: ospf_apiserver_if_lookup_by_ifp (struct interface *ifp)
! 103: {
! 104: struct listnode *node, *nnode;
! 105: struct ospf_interface *oi;
! 106: struct ospf *ospf;
! 107:
! 108: if (!(ospf = ospf_lookup ()));
! 109: return NULL;
! 110:
! 111: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 112: if (oi->ifp == ifp)
! 113: return oi;
! 114:
! 115: return NULL;
! 116: }
! 117:
! 118: /* -----------------------------------------------------------
! 119: * Initialization
! 120: * -----------------------------------------------------------
! 121: */
! 122:
! 123: unsigned short
! 124: ospf_apiserver_getport (void)
! 125: {
! 126: struct servent *sp = getservbyname ("ospfapi", "tcp");
! 127:
! 128: return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
! 129: }
! 130:
! 131: /* Initialize OSPF API module. Invoked from ospf_opaque_init() */
! 132: int
! 133: ospf_apiserver_init (void)
! 134: {
! 135: int fd;
! 136: int rc = -1;
! 137:
! 138: /* Create new socket for synchronous messages. */
! 139: fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET);
! 140:
! 141: if (fd < 0)
! 142: goto out;
! 143:
! 144: /* Schedule new thread that handles accepted connections. */
! 145: ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL);
! 146:
! 147: /* Initialize list that keeps track of all connections. */
! 148: apiserver_list = list_new ();
! 149:
! 150: /* Register opaque-independent call back functions. These functions
! 151: are invoked on ISM, NSM changes and LSA update and LSA deletes */
! 152: rc =
! 153: ospf_register_opaque_functab (0 /* all LSAs */,
! 154: 0 /* all opaque types */,
! 155: ospf_apiserver_new_if,
! 156: ospf_apiserver_del_if,
! 157: ospf_apiserver_ism_change,
! 158: ospf_apiserver_nsm_change,
! 159: NULL,
! 160: NULL,
! 161: NULL,
! 162: NULL, /* ospf_apiserver_show_info */
! 163: NULL, /* originator_func */
! 164: NULL, /* ospf_apiserver_lsa_refresher */
! 165: ospf_apiserver_lsa_update,
! 166: ospf_apiserver_lsa_delete);
! 167: if (rc != 0)
! 168: {
! 169: zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]");
! 170: }
! 171:
! 172: rc = 0;
! 173:
! 174: out:
! 175: return rc;
! 176: }
! 177:
! 178: /* Terminate OSPF API module. */
! 179: void
! 180: ospf_apiserver_term (void)
! 181: {
! 182: struct ospf_apiserver *apiserv;
! 183:
! 184: /* Unregister wildcard [0/0] type */
! 185: ospf_delete_opaque_functab (0 /* all LSAs */,
! 186: 0 /* all opaque types */);
! 187:
! 188: /*
! 189: * Free all client instances. ospf_apiserver_free removes the node
! 190: * from the list, so we examine the head of the list anew each time.
! 191: */
! 192: while ( apiserver_list &&
! 193: (apiserv = listgetdata (listhead (apiserver_list))) != NULL)
! 194: ospf_apiserver_free (apiserv);
! 195:
! 196: /* Free client list itself */
! 197: if (apiserver_list)
! 198: list_delete (apiserver_list);
! 199:
! 200: /* Free wildcard list */
! 201: /* XXX */
! 202: }
! 203:
! 204: static struct ospf_apiserver *
! 205: lookup_apiserver (u_char lsa_type, u_char opaque_type)
! 206: {
! 207: struct listnode *n1, *n2;
! 208: struct registered_opaque_type *r;
! 209: struct ospf_apiserver *apiserv, *found = NULL;
! 210:
! 211: /* XXX: this approaches O(n**2) */
! 212: for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv))
! 213: {
! 214: for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r))
! 215: if (r->lsa_type == lsa_type && r->opaque_type == opaque_type)
! 216: {
! 217: found = apiserv;
! 218: goto out;
! 219: }
! 220: }
! 221: out:
! 222: return found;
! 223: }
! 224:
! 225: static struct ospf_apiserver *
! 226: lookup_apiserver_by_lsa (struct ospf_lsa *lsa)
! 227: {
! 228: struct lsa_header *lsah = lsa->data;
! 229: struct ospf_apiserver *found = NULL;
! 230:
! 231: if (IS_OPAQUE_LSA (lsah->type))
! 232: {
! 233: found = lookup_apiserver (lsah->type,
! 234: GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr)));
! 235: }
! 236: return found;
! 237: }
! 238:
! 239: /* -----------------------------------------------------------
! 240: * Followings are functions to manage client connections.
! 241: * -----------------------------------------------------------
! 242: */
! 243: static int
! 244: ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa)
! 245: {
! 246: if (IS_DEBUG_OSPF_EVENT)
! 247: zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
! 248: return 0;
! 249: }
! 250:
! 251: static int
! 252: ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa)
! 253: {
! 254: if (IS_DEBUG_OSPF_EVENT)
! 255: zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total);
! 256: return 0;
! 257: }
! 258:
! 259: /* Allocate new connection structure. */
! 260: struct ospf_apiserver *
! 261: ospf_apiserver_new (int fd_sync, int fd_async)
! 262: {
! 263: struct ospf_apiserver *new =
! 264: XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver));
! 265:
! 266: new->filter =
! 267: XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type));
! 268:
! 269: new->fd_sync = fd_sync;
! 270: new->fd_async = fd_async;
! 271:
! 272: /* list of registered opaque types that application uses */
! 273: new->opaque_types = list_new ();
! 274:
! 275: /* Initialize temporary strage for LSA instances to be refreshed. */
! 276: memset (&new->reserve, 0, sizeof (struct ospf_lsdb));
! 277: ospf_lsdb_init (&new->reserve);
! 278:
! 279: new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
! 280: new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
! 281:
! 282: new->out_sync_fifo = msg_fifo_new ();
! 283: new->out_async_fifo = msg_fifo_new ();
! 284: new->t_sync_read = NULL;
! 285: #ifdef USE_ASYNC_READ
! 286: new->t_async_read = NULL;
! 287: #endif /* USE_ASYNC_READ */
! 288: new->t_sync_write = NULL;
! 289: new->t_async_write = NULL;
! 290:
! 291: new->filter->typemask = 0; /* filter all LSAs */
! 292: new->filter->origin = ANY_ORIGIN;
! 293: new->filter->num_areas = 0;
! 294:
! 295: return new;
! 296: }
! 297:
! 298: void
! 299: ospf_apiserver_event (enum event event, int fd,
! 300: struct ospf_apiserver *apiserv)
! 301: {
! 302: struct thread *apiserver_serv_thread;
! 303:
! 304: switch (event)
! 305: {
! 306: case OSPF_APISERVER_ACCEPT:
! 307: apiserver_serv_thread =
! 308: thread_add_read (master, ospf_apiserver_accept, apiserv, fd);
! 309: break;
! 310: case OSPF_APISERVER_SYNC_READ:
! 311: apiserv->t_sync_read =
! 312: thread_add_read (master, ospf_apiserver_read, apiserv, fd);
! 313: break;
! 314: #ifdef USE_ASYNC_READ
! 315: case OSPF_APISERVER_ASYNC_READ:
! 316: apiserv->t_async_read =
! 317: thread_add_read (master, ospf_apiserver_read, apiserv, fd);
! 318: break;
! 319: #endif /* USE_ASYNC_READ */
! 320: case OSPF_APISERVER_SYNC_WRITE:
! 321: if (!apiserv->t_sync_write)
! 322: {
! 323: apiserv->t_sync_write =
! 324: thread_add_write (master, ospf_apiserver_sync_write, apiserv, fd);
! 325: }
! 326: break;
! 327: case OSPF_APISERVER_ASYNC_WRITE:
! 328: if (!apiserv->t_async_write)
! 329: {
! 330: apiserv->t_async_write =
! 331: thread_add_write (master, ospf_apiserver_async_write, apiserv, fd);
! 332: }
! 333: break;
! 334: }
! 335: }
! 336:
! 337: /* Free instance. First unregister all opaque types used by
! 338: application, flush opaque LSAs injected by application
! 339: from network and close connection. */
! 340: void
! 341: ospf_apiserver_free (struct ospf_apiserver *apiserv)
! 342: {
! 343: struct listnode *node;
! 344:
! 345: /* Cancel read and write threads. */
! 346: if (apiserv->t_sync_read)
! 347: {
! 348: thread_cancel (apiserv->t_sync_read);
! 349: }
! 350: #ifdef USE_ASYNC_READ
! 351: if (apiserv->t_async_read)
! 352: {
! 353: thread_cancel (apiserv->t_async_read);
! 354: }
! 355: #endif /* USE_ASYNC_READ */
! 356: if (apiserv->t_sync_write)
! 357: {
! 358: thread_cancel (apiserv->t_sync_write);
! 359: }
! 360:
! 361: if (apiserv->t_async_write)
! 362: {
! 363: thread_cancel (apiserv->t_async_write);
! 364: }
! 365:
! 366: /* Unregister all opaque types that application registered
! 367: and flush opaque LSAs if still in LSDB. */
! 368:
! 369: while ((node = listhead (apiserv->opaque_types)) != NULL)
! 370: {
! 371: struct registered_opaque_type *regtype = listgetdata(node);
! 372:
! 373: ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type,
! 374: regtype->opaque_type);
! 375:
! 376: }
! 377:
! 378: /* Close connections to OSPFd. */
! 379: if (apiserv->fd_sync > 0)
! 380: {
! 381: close (apiserv->fd_sync);
! 382: }
! 383:
! 384: if (apiserv->fd_async > 0)
! 385: {
! 386: close (apiserv->fd_async);
! 387: }
! 388:
! 389: /* Free fifos */
! 390: msg_fifo_free (apiserv->out_sync_fifo);
! 391: msg_fifo_free (apiserv->out_async_fifo);
! 392:
! 393: /* Clear temporary strage for LSA instances to be refreshed. */
! 394: ospf_lsdb_delete_all (&apiserv->reserve);
! 395: ospf_lsdb_cleanup (&apiserv->reserve);
! 396:
! 397: /* Remove from the list of active clients. */
! 398: listnode_delete (apiserver_list, apiserv);
! 399:
! 400: if (IS_DEBUG_OSPF_EVENT)
! 401: zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
! 402:
! 403: /* And free instance. */
! 404: XFREE (MTYPE_OSPF_APISERVER, apiserv);
! 405: }
! 406:
! 407: int
! 408: ospf_apiserver_read (struct thread *thread)
! 409: {
! 410: struct ospf_apiserver *apiserv;
! 411: struct msg *msg;
! 412: int fd;
! 413: int rc = -1;
! 414: enum event event;
! 415:
! 416: apiserv = THREAD_ARG (thread);
! 417: fd = THREAD_FD (thread);
! 418:
! 419: if (fd == apiserv->fd_sync)
! 420: {
! 421: event = OSPF_APISERVER_SYNC_READ;
! 422: apiserv->t_sync_read = NULL;
! 423:
! 424: if (IS_DEBUG_OSPF_EVENT)
! 425: zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
! 426: inet_ntoa (apiserv->peer_sync.sin_addr),
! 427: ntohs (apiserv->peer_sync.sin_port));
! 428: }
! 429: #ifdef USE_ASYNC_READ
! 430: else if (fd == apiserv->fd_async)
! 431: {
! 432: event = OSPF_APISERVER_ASYNC_READ;
! 433: apiserv->t_async_read = NULL;
! 434:
! 435: if (IS_DEBUG_OSPF_EVENT)
! 436: zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u",
! 437: inet_ntoa (apiserv->peer_async.sin_addr),
! 438: ntohs (apiserv->peer_async.sin_port));
! 439: }
! 440: #endif /* USE_ASYNC_READ */
! 441: else
! 442: {
! 443: zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd);
! 444: ospf_apiserver_free (apiserv);
! 445: goto out;
! 446: }
! 447:
! 448: /* Read message from fd. */
! 449: msg = msg_read (fd);
! 450: if (msg == NULL)
! 451: {
! 452: zlog_warn
! 453: ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd);
! 454:
! 455: /* Perform cleanup. */
! 456: ospf_apiserver_free (apiserv);
! 457: goto out;
! 458: }
! 459:
! 460: if (IS_DEBUG_OSPF_EVENT)
! 461: msg_print (msg);
! 462:
! 463: /* Dispatch to corresponding message handler. */
! 464: rc = ospf_apiserver_handle_msg (apiserv, msg);
! 465:
! 466: /* Prepare for next message, add read thread. */
! 467: ospf_apiserver_event (event, fd, apiserv);
! 468:
! 469: msg_free (msg);
! 470:
! 471: out:
! 472: return rc;
! 473: }
! 474:
! 475: int
! 476: ospf_apiserver_sync_write (struct thread *thread)
! 477: {
! 478: struct ospf_apiserver *apiserv;
! 479: struct msg *msg;
! 480: int fd;
! 481: int rc = -1;
! 482:
! 483: apiserv = THREAD_ARG (thread);
! 484: assert (apiserv);
! 485: fd = THREAD_FD (thread);
! 486:
! 487: apiserv->t_sync_write = NULL;
! 488:
! 489: /* Sanity check */
! 490: if (fd != apiserv->fd_sync)
! 491: {
! 492: zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd);
! 493: goto out;
! 494: }
! 495:
! 496: if (IS_DEBUG_OSPF_EVENT)
! 497: zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u",
! 498: inet_ntoa (apiserv->peer_sync.sin_addr),
! 499: ntohs (apiserv->peer_sync.sin_port));
! 500:
! 501: /* Check whether there is really a message in the fifo. */
! 502: msg = msg_fifo_pop (apiserv->out_sync_fifo);
! 503: if (!msg)
! 504: {
! 505: zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
! 506: return 0;
! 507: }
! 508:
! 509: if (IS_DEBUG_OSPF_EVENT)
! 510: msg_print (msg);
! 511:
! 512: rc = msg_write (fd, msg);
! 513:
! 514: /* Once a message is dequeued, it should be freed anyway. */
! 515: msg_free (msg);
! 516:
! 517: if (rc < 0)
! 518: {
! 519: zlog_warn
! 520: ("ospf_apiserver_sync_write: write failed on fd=%d", fd);
! 521: goto out;
! 522: }
! 523:
! 524:
! 525: /* If more messages are in sync message fifo, schedule write thread. */
! 526: if (msg_fifo_head (apiserv->out_sync_fifo))
! 527: {
! 528: ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync,
! 529: apiserv);
! 530: }
! 531:
! 532: out:
! 533:
! 534: if (rc < 0)
! 535: {
! 536: /* Perform cleanup and disconnect with peer */
! 537: ospf_apiserver_free (apiserv);
! 538: }
! 539:
! 540: return rc;
! 541: }
! 542:
! 543:
! 544: int
! 545: ospf_apiserver_async_write (struct thread *thread)
! 546: {
! 547: struct ospf_apiserver *apiserv;
! 548: struct msg *msg;
! 549: int fd;
! 550: int rc = -1;
! 551:
! 552: apiserv = THREAD_ARG (thread);
! 553: assert (apiserv);
! 554: fd = THREAD_FD (thread);
! 555:
! 556: apiserv->t_async_write = NULL;
! 557:
! 558: /* Sanity check */
! 559: if (fd != apiserv->fd_async)
! 560: {
! 561: zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd);
! 562: goto out;
! 563: }
! 564:
! 565: if (IS_DEBUG_OSPF_EVENT)
! 566: zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u",
! 567: inet_ntoa (apiserv->peer_async.sin_addr),
! 568: ntohs (apiserv->peer_async.sin_port));
! 569:
! 570: /* Check whether there is really a message in the fifo. */
! 571: msg = msg_fifo_pop (apiserv->out_async_fifo);
! 572: if (!msg)
! 573: {
! 574: zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?");
! 575: return 0;
! 576: }
! 577:
! 578: if (IS_DEBUG_OSPF_EVENT)
! 579: msg_print (msg);
! 580:
! 581: rc = msg_write (fd, msg);
! 582:
! 583: /* Once a message is dequeued, it should be freed anyway. */
! 584: msg_free (msg);
! 585:
! 586: if (rc < 0)
! 587: {
! 588: zlog_warn
! 589: ("ospf_apiserver_async_write: write failed on fd=%d", fd);
! 590: goto out;
! 591: }
! 592:
! 593:
! 594: /* If more messages are in async message fifo, schedule write thread. */
! 595: if (msg_fifo_head (apiserv->out_async_fifo))
! 596: {
! 597: ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async,
! 598: apiserv);
! 599: }
! 600:
! 601: out:
! 602:
! 603: if (rc < 0)
! 604: {
! 605: /* Perform cleanup and disconnect with peer */
! 606: ospf_apiserver_free (apiserv);
! 607: }
! 608:
! 609: return rc;
! 610: }
! 611:
! 612:
! 613: int
! 614: ospf_apiserver_serv_sock_family (unsigned short port, int family)
! 615: {
! 616: union sockunion su;
! 617: int accept_sock;
! 618: int rc;
! 619:
! 620: memset (&su, 0, sizeof (union sockunion));
! 621: su.sa.sa_family = family;
! 622:
! 623: /* Make new socket */
! 624: accept_sock = sockunion_stream_socket (&su);
! 625: if (accept_sock < 0)
! 626: return accept_sock;
! 627:
! 628: /* This is a server, so reuse address and port */
! 629: sockopt_reuseaddr (accept_sock);
! 630: sockopt_reuseport (accept_sock);
! 631:
! 632: /* Bind socket to address and given port. */
! 633: rc = sockunion_bind (accept_sock, &su, port, NULL);
! 634: if (rc < 0)
! 635: {
! 636: close (accept_sock); /* Close socket */
! 637: return rc;
! 638: }
! 639:
! 640: /* Listen socket under queue length 3. */
! 641: rc = listen (accept_sock, 3);
! 642: if (rc < 0)
! 643: {
! 644: zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s",
! 645: safe_strerror (errno));
! 646: close (accept_sock); /* Close socket */
! 647: return rc;
! 648: }
! 649: return accept_sock;
! 650: }
! 651:
! 652:
! 653: /* Accept connection request from external applications. For each
! 654: accepted connection allocate own connection instance. */
! 655: int
! 656: ospf_apiserver_accept (struct thread *thread)
! 657: {
! 658: int accept_sock;
! 659: int new_sync_sock;
! 660: int new_async_sock;
! 661: union sockunion su;
! 662: struct ospf_apiserver *apiserv;
! 663: struct sockaddr_in peer_async;
! 664: struct sockaddr_in peer_sync;
! 665: unsigned int peerlen;
! 666: int ret;
! 667:
! 668: /* THREAD_ARG (thread) is NULL */
! 669: accept_sock = THREAD_FD (thread);
! 670:
! 671: /* Keep hearing on socket for further connections. */
! 672: ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL);
! 673:
! 674: memset (&su, 0, sizeof (union sockunion));
! 675: /* Accept connection for synchronous messages */
! 676: new_sync_sock = sockunion_accept (accept_sock, &su);
! 677: if (new_sync_sock < 0)
! 678: {
! 679: zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno));
! 680: return -1;
! 681: }
! 682:
! 683: /* Get port address and port number of peer to make reverse connection.
! 684: The reverse channel uses the port number of the peer port+1. */
! 685:
! 686: memset(&peer_sync, 0, sizeof(struct sockaddr_in));
! 687: peerlen = sizeof (struct sockaddr_in);
! 688:
! 689: ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen);
! 690: if (ret < 0)
! 691: {
! 692: zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno));
! 693: close (new_sync_sock);
! 694: return -1;
! 695: }
! 696:
! 697: if (IS_DEBUG_OSPF_EVENT)
! 698: zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u",
! 699: inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port));
! 700:
! 701: /* Create new socket for asynchronous messages. */
! 702: peer_async = peer_sync;
! 703: peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
! 704:
! 705: /* Check if remote port number to make reverse connection is valid one. */
! 706: if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ())
! 707: {
! 708: zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?",
! 709: inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port));
! 710: close (new_sync_sock);
! 711: return -1;
! 712: }
! 713:
! 714: new_async_sock = socket (AF_INET, SOCK_STREAM, 0);
! 715: if (new_async_sock < 0)
! 716: {
! 717: zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno));
! 718: close (new_sync_sock);
! 719: return -1;
! 720: }
! 721:
! 722: ret = connect (new_async_sock, (struct sockaddr *) &peer_async,
! 723: sizeof (struct sockaddr_in));
! 724:
! 725: if (ret < 0)
! 726: {
! 727: zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno));
! 728: close (new_sync_sock);
! 729: close (new_async_sock);
! 730: return -1;
! 731: }
! 732:
! 733: #ifdef USE_ASYNC_READ
! 734: #else /* USE_ASYNC_READ */
! 735: /* Make the asynchronous channel write-only. */
! 736: ret = shutdown (new_async_sock, SHUT_RD);
! 737: if (ret < 0)
! 738: {
! 739: zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno));
! 740: close (new_sync_sock);
! 741: close (new_async_sock);
! 742: return -1;
! 743: }
! 744: #endif /* USE_ASYNC_READ */
! 745:
! 746: /* Allocate new server-side connection structure */
! 747: apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock);
! 748:
! 749: /* Add to active connection list */
! 750: listnode_add (apiserver_list, apiserv);
! 751: apiserv->peer_sync = peer_sync;
! 752: apiserv->peer_async = peer_async;
! 753:
! 754: /* And add read threads for new connection */
! 755: ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
! 756: #ifdef USE_ASYNC_READ
! 757: ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv);
! 758: #endif /* USE_ASYNC_READ */
! 759:
! 760: if (IS_DEBUG_OSPF_EVENT)
! 761: zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count);
! 762:
! 763: return 0;
! 764: }
! 765:
! 766:
! 767: /* -----------------------------------------------------------
! 768: * Send reply with return code to client application
! 769: * -----------------------------------------------------------
! 770: */
! 771:
! 772: static int
! 773: ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg)
! 774: {
! 775: struct msg_fifo *fifo;
! 776: struct msg *msg2;
! 777: enum event event;
! 778: int fd;
! 779:
! 780: switch (msg->hdr.msgtype)
! 781: {
! 782: case MSG_REPLY:
! 783: fifo = apiserv->out_sync_fifo;
! 784: fd = apiserv->fd_sync;
! 785: event = OSPF_APISERVER_SYNC_WRITE;
! 786: break;
! 787: case MSG_READY_NOTIFY:
! 788: case MSG_LSA_UPDATE_NOTIFY:
! 789: case MSG_LSA_DELETE_NOTIFY:
! 790: case MSG_NEW_IF:
! 791: case MSG_DEL_IF:
! 792: case MSG_ISM_CHANGE:
! 793: case MSG_NSM_CHANGE:
! 794: fifo = apiserv->out_async_fifo;
! 795: fd = apiserv->fd_async;
! 796: event = OSPF_APISERVER_ASYNC_WRITE;
! 797: break;
! 798: default:
! 799: zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d",
! 800: msg->hdr.msgtype);
! 801: return -1;
! 802: }
! 803:
! 804: /* Make a copy of the message and put in the fifo. Once the fifo
! 805: gets drained by the write thread, the message will be freed. */
! 806: /* NB: Given "msg" is untouched in this function. */
! 807: msg2 = msg_dup (msg);
! 808:
! 809: /* Enqueue message into corresponding fifo queue */
! 810: msg_fifo_push (fifo, msg2);
! 811:
! 812: /* Schedule write thread */
! 813: ospf_apiserver_event (event, fd, apiserv);
! 814: return 0;
! 815: }
! 816:
! 817: int
! 818: ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr,
! 819: u_char rc)
! 820: {
! 821: struct msg *msg = new_msg_reply (seqnr, rc);
! 822: int ret;
! 823:
! 824: if (!msg)
! 825: {
! 826: zlog_warn ("ospf_apiserver_send_reply: msg_new failed");
! 827: #ifdef NOTYET
! 828: /* Cannot allocate new message. What should we do? */
! 829: ospf_apiserver_free (apiserv);
! 830: #endif
! 831: return -1;
! 832: }
! 833:
! 834: ret = ospf_apiserver_send_msg (apiserv, msg);
! 835: msg_free (msg);
! 836: return ret;
! 837: }
! 838:
! 839:
! 840: /* -----------------------------------------------------------
! 841: * Generic message dispatching handler function
! 842: * -----------------------------------------------------------
! 843: */
! 844:
! 845: int
! 846: ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg)
! 847: {
! 848: int rc;
! 849:
! 850: /* Call corresponding message handler function. */
! 851: switch (msg->hdr.msgtype)
! 852: {
! 853: case MSG_REGISTER_OPAQUETYPE:
! 854: rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg);
! 855: break;
! 856: case MSG_UNREGISTER_OPAQUETYPE:
! 857: rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg);
! 858: break;
! 859: case MSG_REGISTER_EVENT:
! 860: rc = ospf_apiserver_handle_register_event (apiserv, msg);
! 861: break;
! 862: case MSG_SYNC_LSDB:
! 863: rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg);
! 864: break;
! 865: case MSG_ORIGINATE_REQUEST:
! 866: rc = ospf_apiserver_handle_originate_request (apiserv, msg);
! 867: break;
! 868: case MSG_DELETE_REQUEST:
! 869: rc = ospf_apiserver_handle_delete_request (apiserv, msg);
! 870: break;
! 871: default:
! 872: zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d",
! 873: msg->hdr.msgtype);
! 874: rc = -1;
! 875: }
! 876: return rc;
! 877: }
! 878:
! 879:
! 880: /* -----------------------------------------------------------
! 881: * Following are functions for opaque type registration
! 882: * -----------------------------------------------------------
! 883: */
! 884:
! 885: int
! 886: ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv,
! 887: u_char lsa_type, u_char opaque_type)
! 888: {
! 889: struct registered_opaque_type *regtype;
! 890: int (*originator_func) (void *arg);
! 891: int rc;
! 892:
! 893: switch (lsa_type)
! 894: {
! 895: case OSPF_OPAQUE_LINK_LSA:
! 896: originator_func = ospf_apiserver_lsa9_originator;
! 897: break;
! 898: case OSPF_OPAQUE_AREA_LSA:
! 899: originator_func = ospf_apiserver_lsa10_originator;
! 900: break;
! 901: case OSPF_OPAQUE_AS_LSA:
! 902: originator_func = ospf_apiserver_lsa11_originator;
! 903: break;
! 904: default:
! 905: zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)",
! 906: lsa_type);
! 907: return OSPF_API_ILLEGALLSATYPE;
! 908: }
! 909:
! 910:
! 911: /* Register opaque function table */
! 912: /* NB: Duplicated registration will be detected inside the function. */
! 913: rc =
! 914: ospf_register_opaque_functab (lsa_type, opaque_type,
! 915: NULL, /* ospf_apiserver_new_if */
! 916: NULL, /* ospf_apiserver_del_if */
! 917: NULL, /* ospf_apiserver_ism_change */
! 918: NULL, /* ospf_apiserver_nsm_change */
! 919: NULL,
! 920: NULL,
! 921: NULL,
! 922: ospf_apiserver_show_info,
! 923: originator_func,
! 924: ospf_apiserver_lsa_refresher,
! 925: NULL, /* ospf_apiserver_lsa_update */
! 926: NULL /* ospf_apiserver_lsa_delete */);
! 927:
! 928: if (rc != 0)
! 929: {
! 930: zlog_warn ("Failed to register opaque type [%d/%d]",
! 931: lsa_type, opaque_type);
! 932: return OSPF_API_OPAQUETYPEINUSE;
! 933: }
! 934:
! 935: /* Remember the opaque type that application registers so when
! 936: connection shuts down, we can flush all LSAs of this opaque
! 937: type. */
! 938:
! 939: regtype =
! 940: XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type));
! 941: regtype->lsa_type = lsa_type;
! 942: regtype->opaque_type = opaque_type;
! 943:
! 944: /* Add to list of registered opaque types */
! 945: listnode_add (apiserv->opaque_types, regtype);
! 946:
! 947: if (IS_DEBUG_OSPF_EVENT)
! 948: zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into"
! 949: " apiserv(%p), total#(%d)",
! 950: lsa_type, opaque_type, apiserv,
! 951: listcount (apiserv->opaque_types));
! 952:
! 953: return 0;
! 954: }
! 955:
! 956: int
! 957: ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv,
! 958: u_char lsa_type, u_char opaque_type)
! 959: {
! 960: struct listnode *node, *nnode;
! 961: struct registered_opaque_type *regtype;
! 962:
! 963: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
! 964: {
! 965: /* Check if we really registered this opaque type */
! 966: if (regtype->lsa_type == lsa_type &&
! 967: regtype->opaque_type == opaque_type)
! 968: {
! 969:
! 970: /* Yes, we registered this opaque type. Flush
! 971: all existing opaque LSAs of this type */
! 972:
! 973: ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type);
! 974: ospf_delete_opaque_functab (lsa_type, opaque_type);
! 975:
! 976: /* Remove from list of registered opaque types */
! 977: listnode_delete (apiserv->opaque_types, regtype);
! 978:
! 979: if (IS_DEBUG_OSPF_EVENT)
! 980: zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)"
! 981: " from apiserv(%p), total#(%d)",
! 982: lsa_type, opaque_type, apiserv,
! 983: listcount (apiserv->opaque_types));
! 984:
! 985: return 0;
! 986: }
! 987: }
! 988:
! 989: /* Opaque type is not registered */
! 990: zlog_warn ("Failed to unregister opaque type [%d/%d]",
! 991: lsa_type, opaque_type);
! 992: return OSPF_API_OPAQUETYPENOTREGISTERED;
! 993: }
! 994:
! 995:
! 996: static int
! 997: apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv,
! 998: u_char lsa_type, u_char opaque_type)
! 999: {
! 1000: struct listnode *node, *nnode;
! 1001: struct registered_opaque_type *regtype;
! 1002:
! 1003: /* XXX: how many types are there? if few, why not just a bitmap? */
! 1004: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype))
! 1005: {
! 1006: /* Check if we really registered this opaque type */
! 1007: if (regtype->lsa_type == lsa_type &&
! 1008: regtype->opaque_type == opaque_type)
! 1009: {
! 1010: /* Yes registered */
! 1011: return 1;
! 1012: }
! 1013: }
! 1014: /* Not registered */
! 1015: return 0;
! 1016: }
! 1017:
! 1018: int
! 1019: ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv,
! 1020: struct msg *msg)
! 1021: {
! 1022: struct msg_register_opaque_type *rmsg;
! 1023: u_char lsa_type;
! 1024: u_char opaque_type;
! 1025: int rc = 0;
! 1026:
! 1027: /* Extract parameters from register opaque type message */
! 1028: rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s);
! 1029:
! 1030: lsa_type = rmsg->lsatype;
! 1031: opaque_type = rmsg->opaquetype;
! 1032:
! 1033: rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type);
! 1034:
! 1035: /* Send a reply back to client including return code */
! 1036: rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
! 1037: if (rc < 0)
! 1038: goto out;
! 1039:
! 1040: /* Now inform application about opaque types that are ready */
! 1041: switch (lsa_type)
! 1042: {
! 1043: case OSPF_OPAQUE_LINK_LSA:
! 1044: ospf_apiserver_notify_ready_type9 (apiserv);
! 1045: break;
! 1046: case OSPF_OPAQUE_AREA_LSA:
! 1047: ospf_apiserver_notify_ready_type10 (apiserv);
! 1048: break;
! 1049: case OSPF_OPAQUE_AS_LSA:
! 1050: ospf_apiserver_notify_ready_type11 (apiserv);
! 1051: break;
! 1052: }
! 1053: out:
! 1054: return rc;
! 1055: }
! 1056:
! 1057:
! 1058: /* Notify specific client about all opaque types 9 that are ready. */
! 1059: void
! 1060: ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv)
! 1061: {
! 1062: struct listnode *node, *nnode;
! 1063: struct listnode *node2, *nnode2;
! 1064: struct ospf *ospf;
! 1065: struct ospf_interface *oi;
! 1066: struct registered_opaque_type *r;
! 1067:
! 1068: ospf = ospf_lookup ();
! 1069:
! 1070: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 1071: {
! 1072: /* Check if this interface is indeed ready for type 9 */
! 1073: if (!ospf_apiserver_is_ready_type9 (oi))
! 1074: continue;
! 1075:
! 1076: /* Check for registered opaque type 9 types */
! 1077: /* XXX: loop-de-loop - optimise me */
! 1078: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
! 1079: {
! 1080: struct msg *msg;
! 1081:
! 1082: if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
! 1083: {
! 1084:
! 1085: /* Yes, this opaque type is ready */
! 1086: msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
! 1087: r->opaque_type,
! 1088: oi->address->u.prefix4);
! 1089: if (!msg)
! 1090: {
! 1091: zlog_warn ("apiserver_notify_ready_type9: msg_new failed");
! 1092: #ifdef NOTYET
! 1093: /* Cannot allocate new message. What should we do? */
! 1094: ospf_apiserver_free (apiserv);
! 1095: #endif
! 1096: goto out;
! 1097: }
! 1098: ospf_apiserver_send_msg (apiserv, msg);
! 1099: msg_free (msg);
! 1100: }
! 1101: }
! 1102: }
! 1103:
! 1104: out:
! 1105: return;
! 1106: }
! 1107:
! 1108:
! 1109: /* Notify specific client about all opaque types 10 that are ready. */
! 1110: void
! 1111: ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv)
! 1112: {
! 1113: struct listnode *node, *nnode;
! 1114: struct listnode *node2, *nnode2;
! 1115: struct ospf *ospf;
! 1116: struct ospf_area *area;
! 1117:
! 1118: ospf = ospf_lookup ();
! 1119:
! 1120: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 1121: {
! 1122: struct registered_opaque_type *r;
! 1123:
! 1124: if (!ospf_apiserver_is_ready_type10 (area))
! 1125: {
! 1126: continue;
! 1127: }
! 1128:
! 1129: /* Check for registered opaque type 10 types */
! 1130: /* XXX: loop in loop - optimise me */
! 1131: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
! 1132: {
! 1133: struct msg *msg;
! 1134:
! 1135: if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
! 1136: {
! 1137: /* Yes, this opaque type is ready */
! 1138: msg =
! 1139: new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
! 1140: r->opaque_type, area->area_id);
! 1141: if (!msg)
! 1142: {
! 1143: zlog_warn ("apiserver_notify_ready_type10: msg_new failed");
! 1144: #ifdef NOTYET
! 1145: /* Cannot allocate new message. What should we do? */
! 1146: ospf_apiserver_free (apiserv);
! 1147: #endif
! 1148: goto out;
! 1149: }
! 1150: ospf_apiserver_send_msg (apiserv, msg);
! 1151: msg_free (msg);
! 1152: }
! 1153: }
! 1154: }
! 1155:
! 1156: out:
! 1157: return;
! 1158: }
! 1159:
! 1160: /* Notify specific client about all opaque types 11 that are ready */
! 1161: void
! 1162: ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv)
! 1163: {
! 1164: struct listnode *node, *nnode;
! 1165: struct ospf *ospf;
! 1166: struct registered_opaque_type *r;
! 1167:
! 1168: ospf = ospf_lookup ();
! 1169:
! 1170: /* Can type 11 be originated? */
! 1171: if (!ospf_apiserver_is_ready_type11 (ospf))
! 1172: goto out;
! 1173:
! 1174: /* Check for registered opaque type 11 types */
! 1175: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r))
! 1176: {
! 1177: struct msg *msg;
! 1178: struct in_addr noarea_id = { .s_addr = 0L };
! 1179:
! 1180: if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
! 1181: {
! 1182: /* Yes, this opaque type is ready */
! 1183: msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
! 1184: r->opaque_type, noarea_id);
! 1185:
! 1186: if (!msg)
! 1187: {
! 1188: zlog_warn ("apiserver_notify_ready_type11: msg_new failed");
! 1189: #ifdef NOTYET
! 1190: /* Cannot allocate new message. What should we do? */
! 1191: ospf_apiserver_free (apiserv);
! 1192: #endif
! 1193: goto out;
! 1194: }
! 1195: ospf_apiserver_send_msg (apiserv, msg);
! 1196: msg_free (msg);
! 1197: }
! 1198: }
! 1199:
! 1200: out:
! 1201: return;
! 1202: }
! 1203:
! 1204: int
! 1205: ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv,
! 1206: struct msg *msg)
! 1207: {
! 1208: struct msg_unregister_opaque_type *umsg;
! 1209: u_char ltype;
! 1210: u_char otype;
! 1211: int rc = 0;
! 1212:
! 1213: /* Extract parameters from unregister opaque type message */
! 1214: umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s);
! 1215:
! 1216: ltype = umsg->lsatype;
! 1217: otype = umsg->opaquetype;
! 1218:
! 1219: rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype);
! 1220:
! 1221: /* Send a reply back to client including return code */
! 1222: rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
! 1223:
! 1224: return rc;
! 1225: }
! 1226:
! 1227:
! 1228: /* -----------------------------------------------------------
! 1229: * Following are functions for event (filter) registration.
! 1230: * -----------------------------------------------------------
! 1231: */
! 1232: int
! 1233: ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
! 1234: struct msg *msg)
! 1235: {
! 1236: struct msg_register_event *rmsg;
! 1237: int rc;
! 1238: u_int32_t seqnum;
! 1239:
! 1240: rmsg = (struct msg_register_event *) STREAM_DATA (msg->s);
! 1241:
! 1242: /* Get request sequence number */
! 1243: seqnum = msg_get_seq (msg);
! 1244:
! 1245: /* Free existing filter in apiserv. */
! 1246: XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
! 1247: /* Alloc new space for filter. */
! 1248:
! 1249: apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER,
! 1250: ntohs (msg->hdr.msglen));
! 1251: if (apiserv->filter)
! 1252: {
! 1253: /* copy it over. */
! 1254: memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen));
! 1255: rc = OSPF_API_OK;
! 1256: }
! 1257: else
! 1258: {
! 1259: rc = OSPF_API_NOMEMORY;
! 1260: }
! 1261: /* Send a reply back to client with return code */
! 1262: rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
! 1263: return rc;
! 1264: }
! 1265:
! 1266:
! 1267: /* -----------------------------------------------------------
! 1268: * Followings are functions for LSDB synchronization.
! 1269: * -----------------------------------------------------------
! 1270: */
! 1271:
! 1272: static int
! 1273: apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg)
! 1274: {
! 1275: struct ospf_apiserver *apiserv;
! 1276: int seqnum;
! 1277: struct msg *msg;
! 1278: struct param_t
! 1279: {
! 1280: struct ospf_apiserver *apiserv;
! 1281: struct lsa_filter_type *filter;
! 1282: }
! 1283: *param;
! 1284: int rc = -1;
! 1285:
! 1286: /* Sanity check */
! 1287: assert (lsa->data);
! 1288: assert (p_arg);
! 1289:
! 1290: param = (struct param_t *) p_arg;
! 1291: apiserv = param->apiserv;
! 1292: seqnum = (u_int32_t) int_arg;
! 1293:
! 1294: /* Check origin in filter. */
! 1295: if ((param->filter->origin == ANY_ORIGIN) ||
! 1296: (param->filter->origin == (lsa->flags & OSPF_LSA_SELF)))
! 1297: {
! 1298:
! 1299: /* Default area for AS-External and Opaque11 LSAs */
! 1300: struct in_addr area_id = { .s_addr = 0L };
! 1301:
! 1302: /* Default interface for non Opaque9 LSAs */
! 1303: struct in_addr ifaddr = { .s_addr = 0L };
! 1304:
! 1305: if (lsa->area)
! 1306: {
! 1307: area_id = lsa->area->area_id;
! 1308: }
! 1309: if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
! 1310: {
! 1311: ifaddr = lsa->oi->address->u.prefix4;
! 1312: }
! 1313:
! 1314: msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY,
! 1315: seqnum,
! 1316: ifaddr, area_id,
! 1317: lsa->flags & OSPF_LSA_SELF, lsa->data);
! 1318: if (!msg)
! 1319: {
! 1320: zlog_warn ("apiserver_sync_callback: new_msg_update failed");
! 1321: #ifdef NOTYET
! 1322: /* Cannot allocate new message. What should we do? */
! 1323: /* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */
! 1324: #endif
! 1325: goto out;
! 1326: }
! 1327:
! 1328: /* Send LSA */
! 1329: ospf_apiserver_send_msg (apiserv, msg);
! 1330: msg_free (msg);
! 1331: }
! 1332: rc = 0;
! 1333:
! 1334: out:
! 1335: return rc;
! 1336: }
! 1337:
! 1338: int
! 1339: ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
! 1340: struct msg *msg)
! 1341: {
! 1342: struct listnode *node, *nnode;
! 1343: u_int32_t seqnum;
! 1344: int rc = 0;
! 1345: struct msg_sync_lsdb *smsg;
! 1346: struct ospf_apiserver_param_t
! 1347: {
! 1348: struct ospf_apiserver *apiserv;
! 1349: struct lsa_filter_type *filter;
! 1350: } param;
! 1351: u_int16_t mask;
! 1352: struct route_node *rn;
! 1353: struct ospf_lsa *lsa;
! 1354: struct ospf *ospf;
! 1355: struct ospf_area *area;
! 1356:
! 1357: ospf = ospf_lookup ();
! 1358:
! 1359: /* Get request sequence number */
! 1360: seqnum = msg_get_seq (msg);
! 1361: /* Set sync msg. */
! 1362: smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s);
! 1363:
! 1364: /* Set parameter struct. */
! 1365: param.apiserv = apiserv;
! 1366: param.filter = &smsg->filter;
! 1367:
! 1368: /* Remember mask. */
! 1369: mask = ntohs (smsg->filter.typemask);
! 1370:
! 1371: /* Iterate over all areas. */
! 1372: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 1373: {
! 1374: int i;
! 1375: u_int32_t *area_id = NULL;
! 1376:
! 1377: /* Compare area_id with area_ids in sync request. */
! 1378: if ((i = smsg->filter.num_areas) > 0)
! 1379: {
! 1380: /* Let area_id point to the list of area IDs,
! 1381: * which is at the end of smsg->filter. */
! 1382: area_id = (u_int32_t *) (&smsg->filter + 1);
! 1383: while (i)
! 1384: {
! 1385: if (*area_id == area->area_id.s_addr)
! 1386: {
! 1387: break;
! 1388: }
! 1389: i--;
! 1390: area_id++;
! 1391: }
! 1392: }
! 1393: else
! 1394: {
! 1395: i = 1;
! 1396: }
! 1397:
! 1398: /* If area was found, then i>0 here. */
! 1399: if (i)
! 1400: {
! 1401: /* Check msg type. */
! 1402: if (mask & Power2[OSPF_ROUTER_LSA])
! 1403: LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
! 1404: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1405: if (mask & Power2[OSPF_NETWORK_LSA])
! 1406: LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
! 1407: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1408: if (mask & Power2[OSPF_SUMMARY_LSA])
! 1409: LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
! 1410: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1411: if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
! 1412: LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
! 1413: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1414: if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
! 1415: LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
! 1416: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1417: if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
! 1418: LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
! 1419: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1420: }
! 1421: }
! 1422:
! 1423: /* For AS-external LSAs */
! 1424: if (ospf->lsdb)
! 1425: {
! 1426: if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
! 1427: LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
! 1428: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1429: }
! 1430:
! 1431: /* For AS-external opaque LSAs */
! 1432: if (ospf->lsdb)
! 1433: {
! 1434: if (mask & Power2[OSPF_OPAQUE_AS_LSA])
! 1435: LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
! 1436: apiserver_sync_callback(lsa, (void *) ¶m, seqnum);
! 1437: }
! 1438:
! 1439: /* Send a reply back to client with return code */
! 1440: rc = ospf_apiserver_send_reply (apiserv, seqnum, rc);
! 1441: return rc;
! 1442: }
! 1443:
! 1444:
! 1445: /* -----------------------------------------------------------
! 1446: * Followings are functions to originate or update LSA
! 1447: * from an application.
! 1448: * -----------------------------------------------------------
! 1449: */
! 1450:
! 1451: /* Create a new internal opaque LSA by taking prototype and filling in
! 1452: missing fields such as age, sequence number, advertising router,
! 1453: checksum and so on. The interface parameter is used for type 9
! 1454: LSAs, area parameter for type 10. Type 11 LSAs do neither need area
! 1455: nor interface. */
! 1456:
! 1457: struct ospf_lsa *
! 1458: ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
! 1459: struct ospf_interface *oi,
! 1460: struct lsa_header *protolsa)
! 1461: {
! 1462: struct stream *s;
! 1463: struct lsa_header *newlsa;
! 1464: struct ospf_lsa *new = NULL;
! 1465: u_char options = 0x0;
! 1466: u_int16_t length;
! 1467:
! 1468: struct ospf *ospf;
! 1469:
! 1470: ospf = ospf_lookup();
! 1471: assert(ospf);
! 1472:
! 1473: /* Create a stream for internal opaque LSA */
! 1474: if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
! 1475: {
! 1476: zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed");
! 1477: return NULL;
! 1478: }
! 1479:
! 1480: newlsa = (struct lsa_header *) STREAM_DATA (s);
! 1481:
! 1482: /* XXX If this is a link-local LSA or an AS-external LSA, how do we
! 1483: have to set options? */
! 1484:
! 1485: if (area)
! 1486: {
! 1487: options = LSA_OPTIONS_GET (area);
! 1488: options |= LSA_OPTIONS_NSSA_GET (area);
! 1489: }
! 1490:
! 1491: options |= OSPF_OPTION_O; /* Don't forget to set option bit */
! 1492:
! 1493: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1494: {
! 1495: zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance",
! 1496: protolsa->type, inet_ntoa (protolsa->id));
! 1497: }
! 1498:
! 1499: /* Set opaque-LSA header fields. */
! 1500: lsa_header_set (s, options, protolsa->type, protolsa->id,
! 1501: ospf->router_id);
! 1502:
! 1503: /* Set opaque-LSA body fields. */
! 1504: stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header),
! 1505: ntohs (protolsa->length) - sizeof (struct lsa_header));
! 1506:
! 1507: /* Determine length of LSA. */
! 1508: length = stream_get_endp (s);
! 1509: newlsa->length = htons (length);
! 1510:
! 1511: /* Create OSPF LSA. */
! 1512: if ((new = ospf_lsa_new ()) == NULL)
! 1513: {
! 1514: zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
! 1515: stream_free (s);
! 1516: return NULL;
! 1517: }
! 1518:
! 1519: if ((new->data = ospf_lsa_data_new (length)) == NULL)
! 1520: {
! 1521: zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
! 1522: ospf_lsa_unlock (&new);
! 1523: stream_free (s);
! 1524: return NULL;
! 1525: }
! 1526:
! 1527: new->area = area;
! 1528: new->oi = oi;
! 1529:
! 1530: SET_FLAG (new->flags, OSPF_LSA_SELF);
! 1531: memcpy (new->data, newlsa, length);
! 1532: stream_free (s);
! 1533:
! 1534: return new;
! 1535: }
! 1536:
! 1537:
! 1538: int
! 1539: ospf_apiserver_is_ready_type9 (struct ospf_interface *oi)
! 1540: {
! 1541: /* Type 9 opaque LSA can be originated if there is at least one
! 1542: active opaque-capable neighbor attached to the outgoing
! 1543: interface. */
! 1544:
! 1545: return (ospf_nbr_count_opaque_capable (oi) > 0);
! 1546: }
! 1547:
! 1548: int
! 1549: ospf_apiserver_is_ready_type10 (struct ospf_area *area)
! 1550: {
! 1551: /* Type 10 opaque LSA can be originated if there is at least one
! 1552: interface belonging to the area that has an active opaque-capable
! 1553: neighbor. */
! 1554: struct listnode *node, *nnode;
! 1555: struct ospf_interface *oi;
! 1556:
! 1557: for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
! 1558: /* Is there an active neighbor attached to this interface? */
! 1559: if (ospf_apiserver_is_ready_type9 (oi))
! 1560: return 1;
! 1561:
! 1562: /* No active neighbor in area */
! 1563: return 0;
! 1564: }
! 1565:
! 1566: int
! 1567: ospf_apiserver_is_ready_type11 (struct ospf *ospf)
! 1568: {
! 1569: /* Type 11 opaque LSA can be originated if there is at least one interface
! 1570: that has an active opaque-capable neighbor. */
! 1571: struct listnode *node, *nnode;
! 1572: struct ospf_interface *oi;
! 1573:
! 1574: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 1575: /* Is there an active neighbor attached to this interface? */
! 1576: if (ospf_apiserver_is_ready_type9 (oi))
! 1577: return 1;
! 1578:
! 1579: /* No active neighbor at all */
! 1580: return 0;
! 1581: }
! 1582:
! 1583:
! 1584: int
! 1585: ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
! 1586: struct msg *msg)
! 1587: {
! 1588: struct msg_originate_request *omsg;
! 1589: struct lsa_header *data;
! 1590: struct ospf_lsa *new;
! 1591: struct ospf_lsa *old;
! 1592: struct ospf_area *area = NULL;
! 1593: struct ospf_interface *oi = NULL;
! 1594: struct ospf_lsdb *lsdb = NULL;
! 1595: struct ospf *ospf;
! 1596: int lsa_type, opaque_type;
! 1597: int ready = 0;
! 1598: int rc = 0;
! 1599:
! 1600: ospf = ospf_lookup();
! 1601:
! 1602: /* Extract opaque LSA data from message */
! 1603: omsg = (struct msg_originate_request *) STREAM_DATA (msg->s);
! 1604: data = &omsg->data;
! 1605:
! 1606: /* Determine interface for type9 or area for type10 LSAs. */
! 1607: switch (data->type)
! 1608: {
! 1609: case OSPF_OPAQUE_LINK_LSA:
! 1610: oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr);
! 1611: if (!oi)
! 1612: {
! 1613: zlog_warn ("apiserver_originate: unknown interface %s",
! 1614: inet_ntoa (omsg->ifaddr));
! 1615: rc = OSPF_API_NOSUCHINTERFACE;
! 1616: goto out;
! 1617: }
! 1618: area = oi->area;
! 1619: lsdb = area->lsdb;
! 1620: break;
! 1621: case OSPF_OPAQUE_AREA_LSA:
! 1622: area = ospf_area_lookup_by_area_id (ospf, omsg->area_id);
! 1623: if (!area)
! 1624: {
! 1625: zlog_warn ("apiserver_originate: unknown area %s",
! 1626: inet_ntoa (omsg->area_id));
! 1627: rc = OSPF_API_NOSUCHAREA;
! 1628: goto out;
! 1629: }
! 1630: lsdb = area->lsdb;
! 1631: break;
! 1632: case OSPF_OPAQUE_AS_LSA:
! 1633: lsdb = ospf->lsdb;
! 1634: break;
! 1635: default:
! 1636: /* We can only handle opaque types here */
! 1637: zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d",
! 1638: data->type);
! 1639: rc = OSPF_API_ILLEGALLSATYPE;
! 1640: goto out;
! 1641: }
! 1642:
! 1643: /* Check if we registered this opaque type */
! 1644: lsa_type = data->type;
! 1645: opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr));
! 1646:
! 1647: if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
! 1648: {
! 1649: zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
! 1650: rc = OSPF_API_OPAQUETYPENOTREGISTERED;
! 1651: goto out;
! 1652: }
! 1653:
! 1654: /* Make sure that the neighbors are ready before we can originate */
! 1655: switch (data->type)
! 1656: {
! 1657: case OSPF_OPAQUE_LINK_LSA:
! 1658: ready = ospf_apiserver_is_ready_type9 (oi);
! 1659: break;
! 1660: case OSPF_OPAQUE_AREA_LSA:
! 1661: ready = ospf_apiserver_is_ready_type10 (area);
! 1662: break;
! 1663: case OSPF_OPAQUE_AS_LSA:
! 1664: ready = ospf_apiserver_is_ready_type11 (ospf);
! 1665: break;
! 1666: default:
! 1667: break;
! 1668: }
! 1669:
! 1670: if (!ready)
! 1671: {
! 1672: zlog_warn ("Neighbors not ready to originate type %d", data->type);
! 1673: rc = OSPF_API_NOTREADY;
! 1674: goto out;
! 1675: }
! 1676:
! 1677: /* Create OSPF's internal opaque LSA representation */
! 1678: new = ospf_apiserver_opaque_lsa_new (area, oi, data);
! 1679: if (!new)
! 1680: {
! 1681: rc = OSPF_API_NOMEMORY; /* XXX */
! 1682: goto out;
! 1683: }
! 1684:
! 1685: /* Determine if LSA is new or an update for an existing one. */
! 1686: old = ospf_lsdb_lookup (lsdb, new);
! 1687:
! 1688: if (!old)
! 1689: {
! 1690: /* New LSA install in LSDB. */
! 1691: rc = ospf_apiserver_originate1 (new);
! 1692: }
! 1693: else
! 1694: {
! 1695: /*
! 1696: * Keep the new LSA instance in the "waiting place" until the next
! 1697: * refresh timing. If several LSA update requests for the same LSID
! 1698: * have issued by peer, the last one takes effect.
! 1699: */
! 1700: new->lsdb = &apiserv->reserve;
! 1701: ospf_lsdb_add (&apiserv->reserve, new);
! 1702:
! 1703: /* Kick the scheduler function. */
! 1704: ospf_opaque_lsa_refresh_schedule (old);
! 1705: }
! 1706:
! 1707: out:
! 1708:
! 1709: /* Send a reply back to client with return code */
! 1710: rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
! 1711: return rc;
! 1712: }
! 1713:
! 1714:
! 1715: /* -----------------------------------------------------------
! 1716: * Flood an LSA within its flooding scope.
! 1717: * -----------------------------------------------------------
! 1718: */
! 1719:
! 1720: /* XXX We can probably use ospf_flood_through instead of this function
! 1721: but then we need the neighbor parameter. If we set nbr to
! 1722: NULL then ospf_flood_through crashes due to dereferencing NULL. */
! 1723:
! 1724: void
! 1725: ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa)
! 1726: {
! 1727: assert (lsa);
! 1728:
! 1729: switch (lsa->data->type)
! 1730: {
! 1731: case OSPF_OPAQUE_LINK_LSA:
! 1732: /* Increment counters? XXX */
! 1733:
! 1734: /* Flood LSA through local network. */
! 1735: ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
! 1736: break;
! 1737: case OSPF_OPAQUE_AREA_LSA:
! 1738: /* Update LSA origination count. */
! 1739: assert (lsa->area);
! 1740: lsa->area->ospf->lsa_originate_count++;
! 1741:
! 1742: /* Flood LSA through area. */
! 1743: ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa);
! 1744: break;
! 1745: case OSPF_OPAQUE_AS_LSA:
! 1746: {
! 1747: struct ospf *ospf;
! 1748:
! 1749: ospf = ospf_lookup();
! 1750: assert(ospf);
! 1751:
! 1752: /* Increment counters? XXX */
! 1753:
! 1754: /* Flood LSA through AS. */
! 1755: ospf_flood_through_as (ospf, NULL /*nbr */ , lsa);
! 1756: break;
! 1757: }
! 1758: }
! 1759: }
! 1760:
! 1761: int
! 1762: ospf_apiserver_originate1 (struct ospf_lsa *lsa)
! 1763: {
! 1764: struct ospf *ospf;
! 1765:
! 1766: ospf = ospf_lookup();
! 1767: assert(ospf);
! 1768:
! 1769: /* Install this LSA into LSDB. */
! 1770: if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL)
! 1771: {
! 1772: zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed");
! 1773: return -1;
! 1774: }
! 1775:
! 1776: /* Flood LSA within scope */
! 1777:
! 1778: #ifdef NOTYET
! 1779: /*
! 1780: * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
! 1781: * parameter, and thus it does not cause SIGSEGV error.
! 1782: */
! 1783: ospf_flood_through (NULL /*nbr */ , lsa);
! 1784: #else /* NOTYET */
! 1785:
! 1786: ospf_apiserver_flood_opaque_lsa (lsa);
! 1787: #endif /* NOTYET */
! 1788:
! 1789: return 0;
! 1790: }
! 1791:
! 1792:
! 1793: /* Opaque LSAs of type 9 on a specific interface can now be
! 1794: originated. Tell clients that registered type 9. */
! 1795: int
! 1796: ospf_apiserver_lsa9_originator (void *arg)
! 1797: {
! 1798: struct ospf_interface *oi;
! 1799:
! 1800: oi = (struct ospf_interface *) arg;
! 1801: if (listcount (apiserver_list) > 0) {
! 1802: ospf_apiserver_clients_notify_ready_type9 (oi);
! 1803: }
! 1804: return 0;
! 1805: }
! 1806:
! 1807: int
! 1808: ospf_apiserver_lsa10_originator (void *arg)
! 1809: {
! 1810: struct ospf_area *area;
! 1811:
! 1812: area = (struct ospf_area *) arg;
! 1813: if (listcount (apiserver_list) > 0) {
! 1814: ospf_apiserver_clients_notify_ready_type10 (area);
! 1815: }
! 1816: return 0;
! 1817: }
! 1818:
! 1819: int
! 1820: ospf_apiserver_lsa11_originator (void *arg)
! 1821: {
! 1822: struct ospf *ospf;
! 1823:
! 1824: ospf = (struct ospf *) arg;
! 1825: if (listcount (apiserver_list) > 0) {
! 1826: ospf_apiserver_clients_notify_ready_type11 (ospf);
! 1827: }
! 1828: return 0;
! 1829: }
! 1830:
! 1831:
! 1832: /* Periodically refresh opaque LSAs so that they do not expire in
! 1833: other routers. */
! 1834: struct ospf_lsa *
! 1835: ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
! 1836: {
! 1837: struct ospf_apiserver *apiserv;
! 1838: struct ospf_lsa *new = NULL;
! 1839: struct ospf * ospf;
! 1840:
! 1841: ospf = ospf_lookup();
! 1842: assert(ospf);
! 1843:
! 1844: apiserv = lookup_apiserver_by_lsa (lsa);
! 1845: if (!apiserv)
! 1846: {
! 1847: zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa));
! 1848: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
! 1849: }
! 1850:
! 1851: if (IS_LSA_MAXAGE (lsa))
! 1852: {
! 1853: ospf_opaque_lsa_flush_schedule (lsa);
! 1854: goto out;
! 1855: }
! 1856:
! 1857: /* Check if updated version of LSA instance has already prepared. */
! 1858: new = ospf_lsdb_lookup (&apiserv->reserve, lsa);
! 1859: if (!new)
! 1860: {
! 1861: /* This is a periodic refresh, driven by core OSPF mechanism. */
! 1862: new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data);
! 1863: if (!new)
! 1864: {
! 1865: zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
! 1866: goto out;
! 1867: }
! 1868: }
! 1869: else
! 1870: {
! 1871: /* This is a forcible refresh, requested by OSPF-API client. */
! 1872: ospf_lsdb_delete (&apiserv->reserve, new);
! 1873: new->lsdb = NULL;
! 1874: }
! 1875:
! 1876: /* Increment sequence number */
! 1877: new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 1878:
! 1879: /* New LSA is in same area. */
! 1880: new->area = lsa->area;
! 1881: SET_FLAG (new->flags, OSPF_LSA_SELF);
! 1882:
! 1883: /* Install LSA into LSDB. */
! 1884: if (ospf_lsa_install (ospf, new->oi, new) == NULL)
! 1885: {
! 1886: zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
! 1887: ospf_lsa_unlock (&new);
! 1888: goto out;
! 1889: }
! 1890:
! 1891: /* Flood updated LSA through interface, area or AS */
! 1892:
! 1893: #ifdef NOTYET
! 1894: ospf_flood_through (NULL /*nbr */ , new);
! 1895: #endif /* NOTYET */
! 1896: ospf_apiserver_flood_opaque_lsa (new);
! 1897:
! 1898: /* Debug logging. */
! 1899: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1900: {
! 1901: zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA",
! 1902: new->data->type, inet_ntoa (new->data->id));
! 1903: ospf_lsa_header_dump (new->data);
! 1904: }
! 1905:
! 1906: out:
! 1907: return new;
! 1908: }
! 1909:
! 1910:
! 1911: /* -----------------------------------------------------------
! 1912: * Followings are functions to delete LSAs
! 1913: * -----------------------------------------------------------
! 1914: */
! 1915:
! 1916: int
! 1917: ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
! 1918: struct msg *msg)
! 1919: {
! 1920: struct msg_delete_request *dmsg;
! 1921: struct ospf_lsa *old;
! 1922: struct ospf_area *area = NULL;
! 1923: struct in_addr id;
! 1924: int lsa_type, opaque_type;
! 1925: int rc = 0;
! 1926: struct ospf * ospf;
! 1927:
! 1928: ospf = ospf_lookup();
! 1929: assert(ospf);
! 1930:
! 1931: /* Extract opaque LSA from message */
! 1932: dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s);
! 1933:
! 1934: /* Lookup area for link-local and area-local opaque LSAs */
! 1935: switch (dmsg->lsa_type)
! 1936: {
! 1937: case OSPF_OPAQUE_LINK_LSA:
! 1938: case OSPF_OPAQUE_AREA_LSA:
! 1939: area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id);
! 1940: if (!area)
! 1941: {
! 1942: zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s",
! 1943: inet_ntoa (dmsg->area_id));
! 1944: rc = OSPF_API_NOSUCHAREA;
! 1945: goto out;
! 1946: }
! 1947: break;
! 1948: case OSPF_OPAQUE_AS_LSA:
! 1949: /* AS-external opaque LSAs have no designated area */
! 1950: area = NULL;
! 1951: break;
! 1952: default:
! 1953: zlog_warn
! 1954: ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
! 1955: dmsg->lsa_type);
! 1956: rc = OSPF_API_ILLEGALLSATYPE;
! 1957: goto out;
! 1958: }
! 1959:
! 1960: /* Check if we registered this opaque type */
! 1961: lsa_type = dmsg->lsa_type;
! 1962: opaque_type = dmsg->opaque_type;
! 1963:
! 1964: if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type))
! 1965: {
! 1966: zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type);
! 1967: rc = OSPF_API_OPAQUETYPENOTREGISTERED;
! 1968: goto out;
! 1969: }
! 1970:
! 1971: /* opaque_id is in network byte order */
! 1972: id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type,
! 1973: ntohl (dmsg->opaque_id)));
! 1974:
! 1975: /*
! 1976: * Even if the target LSA has once scheduled to flush, it remains in
! 1977: * the LSDB until it is finally handled by the maxage remover thread.
! 1978: * Therefore, the lookup function below may return non-NULL result.
! 1979: */
! 1980: old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id);
! 1981: if (!old)
! 1982: {
! 1983: zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB",
! 1984: dmsg->lsa_type, inet_ntoa (id));
! 1985: rc = OSPF_API_NOSUCHLSA;
! 1986: goto out;
! 1987: }
! 1988:
! 1989: /* Schedule flushing of LSA from LSDB */
! 1990: /* NB: Multiple scheduling will produce a warning message, but harmless. */
! 1991: ospf_opaque_lsa_flush_schedule (old);
! 1992:
! 1993: out:
! 1994:
! 1995: /* Send reply back to client including return code */
! 1996: rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc);
! 1997: return rc;
! 1998: }
! 1999:
! 2000: /* Flush self-originated opaque LSA */
! 2001: static int
! 2002: apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa,
! 2003: void *p_arg, int int_arg)
! 2004: {
! 2005: struct param_t
! 2006: {
! 2007: struct ospf_apiserver *apiserv;
! 2008: u_char lsa_type;
! 2009: u_char opaque_type;
! 2010: }
! 2011: *param;
! 2012:
! 2013: /* Sanity check */
! 2014: assert (lsa->data);
! 2015: assert (p_arg);
! 2016: param = (struct param_t *) p_arg;
! 2017:
! 2018: /* If LSA matches type and opaque type then delete it */
! 2019: if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type
! 2020: && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type)
! 2021: {
! 2022: ospf_opaque_lsa_flush_schedule (lsa);
! 2023: }
! 2024: return 0;
! 2025: }
! 2026:
! 2027: /* Delete self-originated opaque LSAs of a given opaque type. This
! 2028: function is called when an application unregisters a given opaque
! 2029: type or a connection to an application closes and all those opaque
! 2030: LSAs need to be flushed the LSDB. */
! 2031: void
! 2032: ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
! 2033: u_char lsa_type, u_char opaque_type)
! 2034: {
! 2035: struct param_t
! 2036: {
! 2037: struct ospf_apiserver *apiserv;
! 2038: u_char lsa_type;
! 2039: u_char opaque_type;
! 2040: } param;
! 2041: struct listnode *node, *nnode;
! 2042: struct ospf * ospf;
! 2043: struct ospf_area *area;
! 2044:
! 2045: ospf = ospf_lookup();
! 2046: assert(ospf);
! 2047:
! 2048: /* Set parameter struct. */
! 2049: param.apiserv = apiserv;
! 2050: param.lsa_type = lsa_type;
! 2051: param.opaque_type = opaque_type;
! 2052:
! 2053: switch (lsa_type)
! 2054: {
! 2055: struct route_node *rn;
! 2056: struct ospf_lsa *lsa;
! 2057:
! 2058: case OSPF_OPAQUE_LINK_LSA:
! 2059: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 2060: LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
! 2061: apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
! 2062: break;
! 2063: case OSPF_OPAQUE_AREA_LSA:
! 2064: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 2065: LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
! 2066: apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
! 2067: break;
! 2068: case OSPF_OPAQUE_AS_LSA:
! 2069: LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa)
! 2070: apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0);
! 2071: break;
! 2072: default:
! 2073: break;
! 2074: }
! 2075: return;
! 2076: }
! 2077:
! 2078:
! 2079: /* -----------------------------------------------------------
! 2080: * Followings are callback functions to handle opaque types
! 2081: * -----------------------------------------------------------
! 2082: */
! 2083:
! 2084: int
! 2085: ospf_apiserver_new_if (struct interface *ifp)
! 2086: {
! 2087: struct ospf_interface *oi;
! 2088:
! 2089: /* For some strange reason it seems possible that we are invoked
! 2090: with an interface that has no name. This seems to happen during
! 2091: initialization. Return if this happens */
! 2092:
! 2093: if (ifp->name[0] == '\0') {
! 2094: /* interface has empty name */
! 2095: zlog_warn ("ospf_apiserver_new_if: interface has no name?");
! 2096: return 0;
! 2097: }
! 2098:
! 2099: /* zlog_warn for debugging */
! 2100: zlog_warn ("ospf_apiserver_new_if");
! 2101: zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
! 2102: ifp->ifindex);
! 2103:
! 2104: if (ifp->name[0] == '\0') {
! 2105: /* interface has empty name */
! 2106: zlog_warn ("ospf_apiserver_new_if: interface has no name?");
! 2107: return 0;
! 2108: }
! 2109:
! 2110: oi = ospf_apiserver_if_lookup_by_ifp (ifp);
! 2111:
! 2112: if (!oi) {
! 2113: /* This interface is known to Zebra but not to OSPF daemon yet. */
! 2114: zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?",
! 2115: ifp->name);
! 2116: return 0;
! 2117: }
! 2118:
! 2119: assert (oi);
! 2120:
! 2121: /* New interface added to OSPF, tell clients about it */
! 2122: if (listcount (apiserver_list) > 0) {
! 2123: ospf_apiserver_clients_notify_new_if (oi);
! 2124: }
! 2125: return 0;
! 2126: }
! 2127:
! 2128: int
! 2129: ospf_apiserver_del_if (struct interface *ifp)
! 2130: {
! 2131: struct ospf_interface *oi;
! 2132:
! 2133: /* zlog_warn for debugging */
! 2134: zlog_warn ("ospf_apiserver_del_if");
! 2135: zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
! 2136: ifp->ifindex);
! 2137:
! 2138: oi = ospf_apiserver_if_lookup_by_ifp (ifp);
! 2139:
! 2140: if (!oi) {
! 2141: /* This interface is known to Zebra but not to OSPF daemon
! 2142: anymore. No need to tell clients about it */
! 2143: return 0;
! 2144: }
! 2145:
! 2146: /* Interface deleted, tell clients about it */
! 2147: if (listcount (apiserver_list) > 0) {
! 2148: ospf_apiserver_clients_notify_del_if (oi);
! 2149: }
! 2150: return 0;
! 2151: }
! 2152:
! 2153: void
! 2154: ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state)
! 2155: {
! 2156: /* Tell clients about interface change */
! 2157:
! 2158: /* zlog_warn for debugging */
! 2159: zlog_warn ("ospf_apiserver_ism_change");
! 2160: if (listcount (apiserver_list) > 0) {
! 2161: ospf_apiserver_clients_notify_ism_change (oi);
! 2162: }
! 2163:
! 2164: zlog_warn ("oi->ifp->name=%s", oi->ifp->name);
! 2165: zlog_warn ("old_state=%d", old_state);
! 2166: zlog_warn ("oi->state=%d", oi->state);
! 2167: }
! 2168:
! 2169: void
! 2170: ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status)
! 2171: {
! 2172: /* Neighbor status changed, tell clients about it */
! 2173: zlog_warn ("ospf_apiserver_nsm_change");
! 2174: if (listcount (apiserver_list) > 0) {
! 2175: ospf_apiserver_clients_notify_nsm_change (nbr);
! 2176: }
! 2177: }
! 2178:
! 2179: void
! 2180: ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa)
! 2181: {
! 2182: struct opaque_lsa
! 2183: {
! 2184: struct lsa_header header;
! 2185: u_char data[1]; /* opaque data have variable length. This is start
! 2186: address */
! 2187: };
! 2188: struct opaque_lsa *olsa;
! 2189: int opaquelen;
! 2190:
! 2191: olsa = (struct opaque_lsa *) lsa->data;
! 2192:
! 2193: if (VALID_OPAQUE_INFO_LEN (lsa->data))
! 2194: opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE;
! 2195: else
! 2196: opaquelen = 0;
! 2197:
! 2198: /* Output information about opaque LSAs */
! 2199: if (vty != NULL)
! 2200: {
! 2201: int i;
! 2202: vty_out (vty, " Added using OSPF API: %u octets of opaque data %s%s",
! 2203: opaquelen,
! 2204: VALID_OPAQUE_INFO_LEN (lsa->data) ? "" : "(Invalid length?)",
! 2205: VTY_NEWLINE);
! 2206: vty_out (vty, " Opaque data: ");
! 2207:
! 2208: for (i = 0; i < opaquelen; i++)
! 2209: {
! 2210: vty_out (vty, "0x%x ", olsa->data[i]);
! 2211: }
! 2212: vty_out (vty, "%s", VTY_NEWLINE);
! 2213: }
! 2214: else
! 2215: {
! 2216: int i;
! 2217: zlog_debug (" Added using OSPF API: %u octets of opaque data %s",
! 2218: opaquelen,
! 2219: VALID_OPAQUE_INFO_LEN (lsa->
! 2220: data) ? "" : "(Invalid length?)");
! 2221: zlog_debug (" Opaque data: ");
! 2222:
! 2223: for (i = 0; i < opaquelen; i++)
! 2224: {
! 2225: zlog_debug ("0x%x ", olsa->data[i]);
! 2226: }
! 2227: zlog_debug ("\n");
! 2228: }
! 2229: return;
! 2230: }
! 2231:
! 2232: /* -----------------------------------------------------------
! 2233: * Followings are functions to notify clients about events
! 2234: * -----------------------------------------------------------
! 2235: */
! 2236:
! 2237: /* Send a message to all clients. This is useful for messages
! 2238: that need to be notified to all clients (such as interface
! 2239: changes) */
! 2240:
! 2241: void
! 2242: ospf_apiserver_clients_notify_all (struct msg *msg)
! 2243: {
! 2244: struct listnode *node, *nnode;
! 2245: struct ospf_apiserver *apiserv;
! 2246:
! 2247: /* Send message to all clients */
! 2248: for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
! 2249: ospf_apiserver_send_msg (apiserv, msg);
! 2250: }
! 2251:
! 2252: /* An interface is now ready to accept opaque LSAs. Notify all
! 2253: clients that registered to use this opaque type */
! 2254: void
! 2255: ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi)
! 2256: {
! 2257: struct listnode *node, *nnode;
! 2258: struct msg *msg;
! 2259: struct ospf_apiserver *apiserv;
! 2260:
! 2261: assert (oi);
! 2262: if (!oi->address)
! 2263: {
! 2264: zlog_warn ("Interface has no address?");
! 2265: return;
! 2266: }
! 2267:
! 2268: if (!ospf_apiserver_is_ready_type9 (oi))
! 2269: {
! 2270: zlog_warn ("Interface not ready for type 9?");
! 2271: return;
! 2272: }
! 2273:
! 2274: for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
! 2275: {
! 2276: struct listnode *node2, *nnode2;
! 2277: struct registered_opaque_type *r;
! 2278:
! 2279: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
! 2280: {
! 2281: if (r->lsa_type == OSPF_OPAQUE_LINK_LSA)
! 2282: {
! 2283: msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA,
! 2284: r->opaque_type,
! 2285: oi->address->u.prefix4);
! 2286: if (!msg)
! 2287: {
! 2288: zlog_warn
! 2289: ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
! 2290: #ifdef NOTYET
! 2291: /* Cannot allocate new message. What should we do? */
! 2292: ospf_apiserver_free (apiserv);
! 2293: #endif
! 2294: goto out;
! 2295: }
! 2296:
! 2297: ospf_apiserver_send_msg (apiserv, msg);
! 2298: msg_free (msg);
! 2299: }
! 2300: }
! 2301: }
! 2302:
! 2303: out:
! 2304: return;
! 2305: }
! 2306:
! 2307: void
! 2308: ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area)
! 2309: {
! 2310: struct listnode *node, *nnode;
! 2311: struct msg *msg;
! 2312: struct ospf_apiserver *apiserv;
! 2313:
! 2314: assert (area);
! 2315:
! 2316: if (!ospf_apiserver_is_ready_type10 (area))
! 2317: {
! 2318: zlog_warn ("Area not ready for type 10?");
! 2319: return;
! 2320: }
! 2321:
! 2322: for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
! 2323: {
! 2324: struct listnode *node2, *nnode2;
! 2325: struct registered_opaque_type *r;
! 2326:
! 2327: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
! 2328: {
! 2329: if (r->lsa_type == OSPF_OPAQUE_AREA_LSA)
! 2330: {
! 2331: msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA,
! 2332: r->opaque_type, area->area_id);
! 2333: if (!msg)
! 2334: {
! 2335: zlog_warn
! 2336: ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
! 2337: #ifdef NOTYET
! 2338: /* Cannot allocate new message. What should we do? */
! 2339: ospf_apiserver_free (apiserv);
! 2340: #endif
! 2341: goto out;
! 2342: }
! 2343:
! 2344: ospf_apiserver_send_msg (apiserv, msg);
! 2345: msg_free (msg);
! 2346: }
! 2347: }
! 2348: }
! 2349:
! 2350: out:
! 2351: return;
! 2352: }
! 2353:
! 2354:
! 2355: void
! 2356: ospf_apiserver_clients_notify_ready_type11 (struct ospf *top)
! 2357: {
! 2358: struct listnode *node, *nnode;
! 2359: struct msg *msg;
! 2360: struct in_addr id_null = { .s_addr = 0L };
! 2361: struct ospf_apiserver *apiserv;
! 2362:
! 2363: assert (top);
! 2364:
! 2365: if (!ospf_apiserver_is_ready_type11 (top))
! 2366: {
! 2367: zlog_warn ("AS not ready for type 11?");
! 2368: return;
! 2369: }
! 2370:
! 2371: for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
! 2372: {
! 2373: struct listnode *node2, *nnode2;
! 2374: struct registered_opaque_type *r;
! 2375:
! 2376: for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r))
! 2377: {
! 2378: if (r->lsa_type == OSPF_OPAQUE_AS_LSA)
! 2379: {
! 2380: msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA,
! 2381: r->opaque_type, id_null);
! 2382: if (!msg)
! 2383: {
! 2384: zlog_warn
! 2385: ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
! 2386: #ifdef NOTYET
! 2387: /* Cannot allocate new message. What should we do? */
! 2388: ospf_apiserver_free (apiserv);
! 2389: #endif
! 2390: goto out;
! 2391: }
! 2392:
! 2393: ospf_apiserver_send_msg (apiserv, msg);
! 2394: msg_free (msg);
! 2395: }
! 2396: }
! 2397: }
! 2398:
! 2399: out:
! 2400: return;
! 2401: }
! 2402:
! 2403: void
! 2404: ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi)
! 2405: {
! 2406: struct msg *msg;
! 2407:
! 2408: msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id);
! 2409: if (msg != NULL)
! 2410: {
! 2411: ospf_apiserver_clients_notify_all (msg);
! 2412: msg_free (msg);
! 2413: }
! 2414: }
! 2415:
! 2416: void
! 2417: ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi)
! 2418: {
! 2419: struct msg *msg;
! 2420:
! 2421: msg = new_msg_del_if (0, oi->address->u.prefix4);
! 2422: if (msg != NULL)
! 2423: {
! 2424: ospf_apiserver_clients_notify_all (msg);
! 2425: msg_free (msg);
! 2426: }
! 2427: }
! 2428:
! 2429: void
! 2430: ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi)
! 2431: {
! 2432: struct msg *msg;
! 2433: struct in_addr ifaddr = { .s_addr = 0L };
! 2434: struct in_addr area_id = { .s_addr = 0L };
! 2435:
! 2436: assert (oi);
! 2437: assert (oi->ifp);
! 2438:
! 2439: if (oi->address)
! 2440: {
! 2441: ifaddr = oi->address->u.prefix4;
! 2442: }
! 2443: if (oi->area)
! 2444: {
! 2445: area_id = oi->area->area_id;
! 2446: }
! 2447:
! 2448: msg = new_msg_ism_change (0, ifaddr, area_id, oi->state);
! 2449: if (!msg)
! 2450: {
! 2451: zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed");
! 2452: return;
! 2453: }
! 2454:
! 2455: ospf_apiserver_clients_notify_all (msg);
! 2456: msg_free (msg);
! 2457: }
! 2458:
! 2459: void
! 2460: ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr)
! 2461: {
! 2462: struct msg *msg;
! 2463: struct in_addr ifaddr = { .s_addr = 0L };
! 2464: struct in_addr nbraddr = { .s_addr = 0L };
! 2465:
! 2466: assert (nbr);
! 2467:
! 2468: if (nbr->oi)
! 2469: {
! 2470: ifaddr = nbr->oi->address->u.prefix4;
! 2471: }
! 2472:
! 2473: nbraddr = nbr->address.u.prefix4;
! 2474:
! 2475: msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state);
! 2476: if (!msg)
! 2477: {
! 2478: zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed");
! 2479: return;
! 2480: }
! 2481:
! 2482: ospf_apiserver_clients_notify_all (msg);
! 2483: msg_free (msg);
! 2484: }
! 2485:
! 2486: static void
! 2487: apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa)
! 2488: {
! 2489: struct msg *msg;
! 2490: struct listnode *node, *nnode;
! 2491: struct ospf_apiserver *apiserv;
! 2492:
! 2493: /* Default area for AS-External and Opaque11 LSAs */
! 2494: struct in_addr area_id = { .s_addr = 0L };
! 2495:
! 2496: /* Default interface for non Opaque9 LSAs */
! 2497: struct in_addr ifaddr = { .s_addr = 0L };
! 2498:
! 2499: if (lsa->area)
! 2500: {
! 2501: area_id = lsa->area->area_id;
! 2502: }
! 2503: if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
! 2504: {
! 2505: assert (lsa->oi);
! 2506: ifaddr = lsa->oi->address->u.prefix4;
! 2507: }
! 2508:
! 2509: /* Prepare message that can be sent to clients that have a matching
! 2510: filter */
! 2511: msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
! 2512: ifaddr, area_id,
! 2513: lsa->flags & OSPF_LSA_SELF, lsa->data);
! 2514: if (!msg)
! 2515: {
! 2516: zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed");
! 2517: return;
! 2518: }
! 2519:
! 2520: /* Now send message to all clients with a matching filter */
! 2521: for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv))
! 2522: {
! 2523: struct lsa_filter_type *filter;
! 2524: u_int16_t mask;
! 2525: u_int32_t *area;
! 2526: int i;
! 2527:
! 2528: /* Check filter for this client. */
! 2529: filter = apiserv->filter;
! 2530:
! 2531: /* Check area IDs in case of non AS-E LSAs.
! 2532: * If filter has areas (num_areas > 0),
! 2533: * then one of the areas must match the area ID of this LSA. */
! 2534:
! 2535: i = filter->num_areas;
! 2536: if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) ||
! 2537: (lsa->data->type == OSPF_OPAQUE_AS_LSA))
! 2538: {
! 2539: i = 0;
! 2540: }
! 2541:
! 2542: if (i > 0)
! 2543: {
! 2544: area = (u_int32_t *) (filter + 1);
! 2545: while (i)
! 2546: {
! 2547: if (*area == area_id.s_addr)
! 2548: {
! 2549: break;
! 2550: }
! 2551: i--;
! 2552: area++;
! 2553: }
! 2554: }
! 2555: else
! 2556: {
! 2557: i = 1;
! 2558: }
! 2559:
! 2560: if (i > 0)
! 2561: {
! 2562: /* Area match. Check LSA type. */
! 2563: mask = ntohs (filter->typemask);
! 2564:
! 2565: if (mask & Power2[lsa->data->type])
! 2566: {
! 2567: /* Type also matches. Check origin. */
! 2568: if ((filter->origin == ANY_ORIGIN) ||
! 2569: (filter->origin == IS_LSA_SELF (lsa)))
! 2570: {
! 2571: ospf_apiserver_send_msg (apiserv, msg);
! 2572: }
! 2573: }
! 2574: }
! 2575: }
! 2576: /* Free message since it is not used anymore */
! 2577: msg_free (msg);
! 2578: }
! 2579:
! 2580:
! 2581: /* -------------------------------------------------------------
! 2582: * Followings are hooks invoked when LSAs are updated or deleted
! 2583: * -------------------------------------------------------------
! 2584: */
! 2585:
! 2586:
! 2587: static int
! 2588: apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa)
! 2589: {
! 2590: struct msg *msg;
! 2591: /* default area for AS-External and Opaque11 LSAs */
! 2592: struct in_addr area_id = { .s_addr = 0L };
! 2593:
! 2594: /* default interface for non Opaque9 LSAs */
! 2595: struct in_addr ifaddr = { .s_addr = 0L };
! 2596:
! 2597: /* Only notify this update if the LSA's age is smaller than
! 2598: MAXAGE. Otherwise clients would see LSA updates with max age just
! 2599: before they are deleted from the LSDB. LSA delete messages have
! 2600: MAXAGE too but should not be filtered. */
! 2601: if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) {
! 2602: return 0;
! 2603: }
! 2604:
! 2605: if (lsa->area)
! 2606: {
! 2607: area_id = lsa->area->area_id;
! 2608: }
! 2609: if (lsa->data->type == OSPF_OPAQUE_LINK_LSA)
! 2610: {
! 2611: ifaddr = lsa->oi->address->u.prefix4;
! 2612: }
! 2613: msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */
! 2614: ifaddr, area_id,
! 2615: lsa->flags & OSPF_LSA_SELF, lsa->data);
! 2616: if (!msg)
! 2617: {
! 2618: zlog_warn ("notify_clients_lsa: msg_new failed");
! 2619: return -1;
! 2620: }
! 2621: /* Notify all clients that new LSA is added/updated */
! 2622: apiserver_clients_lsa_change_notify (msgtype, lsa);
! 2623:
! 2624: /* Clients made their own copies of msg so we can free msg here */
! 2625: msg_free (msg);
! 2626:
! 2627: return 0;
! 2628: }
! 2629:
! 2630: int
! 2631: ospf_apiserver_lsa_update (struct ospf_lsa *lsa)
! 2632: {
! 2633: return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa);
! 2634: }
! 2635:
! 2636: int
! 2637: ospf_apiserver_lsa_delete (struct ospf_lsa *lsa)
! 2638: {
! 2639: return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa);
! 2640: }
! 2641:
! 2642: #endif /* SUPPORT_OSPF_API */
! 2643:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>