ospf_apiclient.c 19 KB

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