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 = XCALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient));
  229. /* Initialize socket descriptors for sync and async channels */
  230. new->fd_sync = fd1;
  231. new->fd_async = fd2;
  232. return new;
  233. }
  234. int
  235. ospf_apiclient_close (struct ospf_apiclient *oclient)
  236. {
  237. if (oclient->fd_sync >= 0)
  238. {
  239. close (oclient->fd_sync);
  240. }
  241. if (oclient->fd_async >= 0)
  242. {
  243. close (oclient->fd_async);
  244. }
  245. /* Free client structure */
  246. XFREE (MTYPE_OSPF_APICLIENT, oclient);
  247. return 0;
  248. }
  249. /* -----------------------------------------------------------
  250. * Followings are functions to send a request to OSPFd
  251. * -----------------------------------------------------------
  252. */
  253. /* Send synchronous request, wait for reply */
  254. static int
  255. ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg)
  256. {
  257. u_int32_t reqseq;
  258. struct msg_reply *msgreply;
  259. int rc;
  260. /* NB: Given "msg" is freed inside this function. */
  261. /* Remember the sequence number of the request */
  262. reqseq = ntohl (msg->hdr.msgseq);
  263. /* Write message to OSPFd */
  264. rc = msg_write (oclient->fd_sync, msg);
  265. msg_free (msg);
  266. if (rc < 0)
  267. {
  268. return -1;
  269. }
  270. /* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */
  271. msg = msg_read (oclient->fd_sync);
  272. if (!msg)
  273. return -1;
  274. assert (msg->hdr.msgtype == MSG_REPLY);
  275. assert (ntohl (msg->hdr.msgseq) == reqseq);
  276. msgreply = (struct msg_reply *) STREAM_DATA (msg->s);
  277. rc = msgreply->errcode;
  278. msg_free (msg);
  279. return rc;
  280. }
  281. /* -----------------------------------------------------------
  282. * Helper functions
  283. * -----------------------------------------------------------
  284. */
  285. static u_int32_t
  286. ospf_apiclient_get_seqnr (void)
  287. {
  288. static u_int32_t seqnr = MIN_SEQ;
  289. u_int32_t tmp;
  290. tmp = seqnr;
  291. /* Increment sequence number */
  292. if (seqnr < MAX_SEQ)
  293. {
  294. seqnr++;
  295. }
  296. else
  297. {
  298. seqnr = MIN_SEQ;
  299. }
  300. return tmp;
  301. }
  302. /* -----------------------------------------------------------
  303. * API to access OSPF daemon by client applications.
  304. * -----------------------------------------------------------
  305. */
  306. /*
  307. * Synchronous request to register opaque type.
  308. */
  309. int
  310. ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl,
  311. u_char ltype, u_char otype)
  312. {
  313. struct msg *msg;
  314. int rc;
  315. /* just put 1 as a sequence number. */
  316. msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (),
  317. ltype, otype);
  318. if (!msg)
  319. {
  320. fprintf (stderr, "new_msg_register_opaque_type failed\n");
  321. return -1;
  322. }
  323. rc = ospf_apiclient_send_request (cl, msg);
  324. return rc;
  325. }
  326. /*
  327. * Synchronous request to synchronize with OSPF's LSDB.
  328. * Two steps required: register_event in order to get
  329. * dynamic updates and LSDB_Sync.
  330. */
  331. int
  332. ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient)
  333. {
  334. struct msg *msg;
  335. int rc;
  336. struct lsa_filter_type filter;
  337. filter.typemask = 0xFFFF; /* all LSAs */
  338. filter.origin = ANY_ORIGIN;
  339. filter.num_areas = 0; /* all Areas. */
  340. msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter);
  341. if (!msg)
  342. {
  343. fprintf (stderr, "new_msg_register_event failed\n");
  344. return -1;
  345. }
  346. rc = ospf_apiclient_send_request (oclient, msg);
  347. if (rc != 0)
  348. goto out;
  349. msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter);
  350. if (!msg)
  351. {
  352. fprintf (stderr, "new_msg_sync_lsdb failed\n");
  353. return -1;
  354. }
  355. rc = ospf_apiclient_send_request (oclient, msg);
  356. out:
  357. return rc;
  358. }
  359. /*
  360. * Synchronous request to originate or update an LSA.
  361. */
  362. int
  363. ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient,
  364. struct in_addr ifaddr,
  365. struct in_addr area_id,
  366. u_char lsa_type,
  367. u_char opaque_type, u_int32_t opaque_id,
  368. void *opaquedata, int opaquelen)
  369. {
  370. struct msg *msg;
  371. int rc;
  372. u_char buf[OSPF_MAX_LSA_SIZE];
  373. struct lsa_header *lsah;
  374. u_int32_t tmp;
  375. /* We can only originate opaque LSAs */
  376. if (!IS_OPAQUE_LSA (lsa_type))
  377. {
  378. fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type);
  379. return OSPF_API_ILLEGALLSATYPE;
  380. }
  381. /* Make a new LSA from parameters */
  382. lsah = (struct lsa_header *) buf;
  383. lsah->ls_age = 0;
  384. lsah->options = 0;
  385. lsah->type = lsa_type;
  386. tmp = SET_OPAQUE_LSID (opaque_type, opaque_id);
  387. lsah->id.s_addr = htonl (tmp);
  388. lsah->adv_router.s_addr = 0;
  389. lsah->ls_seqnum = 0;
  390. lsah->checksum = 0;
  391. lsah->length = htons (sizeof (struct lsa_header) + opaquelen);
  392. memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata,
  393. opaquelen);
  394. msg = new_msg_originate_request (ospf_apiclient_get_seqnr (),
  395. ifaddr, area_id, lsah);
  396. if (!msg)
  397. {
  398. fprintf (stderr, "new_msg_originate_request failed\n");
  399. return OSPF_API_NOMEMORY;
  400. }
  401. rc = ospf_apiclient_send_request (oclient, msg);
  402. return rc;
  403. }
  404. int
  405. ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient,
  406. struct in_addr area_id, u_char lsa_type,
  407. u_char opaque_type, u_int32_t opaque_id)
  408. {
  409. struct msg *msg;
  410. int rc;
  411. /* Only opaque LSA can be deleted */
  412. if (!IS_OPAQUE_LSA (lsa_type))
  413. {
  414. fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type);
  415. return OSPF_API_ILLEGALLSATYPE;
  416. }
  417. /* opaque_id is in host byte order and will be converted
  418. * to network byte order by new_msg_delete_request */
  419. msg = new_msg_delete_request (ospf_apiclient_get_seqnr (),
  420. area_id, lsa_type, opaque_type, opaque_id);
  421. rc = ospf_apiclient_send_request (oclient, msg);
  422. return rc;
  423. }
  424. /* -----------------------------------------------------------
  425. * Followings are handlers for messages from OSPF daemon
  426. * -----------------------------------------------------------
  427. */
  428. static void
  429. ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg)
  430. {
  431. struct msg_ready_notify *r;
  432. r = (struct msg_ready_notify *) STREAM_DATA (msg->s);
  433. /* Invoke registered callback function. */
  434. if (oclient->ready_notify)
  435. {
  436. (oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr);
  437. }
  438. }
  439. static void
  440. ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg)
  441. {
  442. struct msg_new_if *n;
  443. n = (struct msg_new_if *) STREAM_DATA (msg->s);
  444. /* Invoke registered callback function. */
  445. if (oclient->new_if)
  446. {
  447. (oclient->new_if) (n->ifaddr, n->area_id);
  448. }
  449. }
  450. static void
  451. ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg)
  452. {
  453. struct msg_del_if *d;
  454. d = (struct msg_del_if *) STREAM_DATA (msg->s);
  455. /* Invoke registered callback function. */
  456. if (oclient->del_if)
  457. {
  458. (oclient->del_if) (d->ifaddr);
  459. }
  460. }
  461. static void
  462. ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient,
  463. struct msg *msg)
  464. {
  465. struct msg_ism_change *m;
  466. m = (struct msg_ism_change *) STREAM_DATA (msg->s);
  467. /* Invoke registered callback function. */
  468. if (oclient->ism_change)
  469. {
  470. (oclient->ism_change) (m->ifaddr, m->area_id, m->status);
  471. }
  472. }
  473. static void
  474. ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient,
  475. struct msg *msg)
  476. {
  477. struct msg_nsm_change *m;
  478. m = (struct msg_nsm_change *) STREAM_DATA (msg->s);
  479. /* Invoke registered callback function. */
  480. if (oclient->nsm_change)
  481. {
  482. (oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status);
  483. }
  484. }
  485. static void
  486. ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient,
  487. struct msg *msg)
  488. {
  489. struct msg_lsa_change_notify *cn;
  490. struct lsa_header *lsa;
  491. int lsalen;
  492. cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
  493. /* Extract LSA from message */
  494. lsalen = ntohs (cn->data.length);
  495. lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
  496. if (!lsa)
  497. {
  498. fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n");
  499. return;
  500. }
  501. memcpy (lsa, &(cn->data), lsalen);
  502. /* Invoke registered update callback function */
  503. if (oclient->update_notify)
  504. {
  505. (oclient->update_notify) (cn->ifaddr, cn->area_id,
  506. cn->is_self_originated, lsa);
  507. }
  508. /* free memory allocated by ospf apiclient library */
  509. XFREE (MTYPE_OSPF_APICLIENT, lsa);
  510. }
  511. static void
  512. ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient,
  513. struct msg *msg)
  514. {
  515. struct msg_lsa_change_notify *cn;
  516. struct lsa_header *lsa;
  517. int lsalen;
  518. cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
  519. /* Extract LSA from message */
  520. lsalen = ntohs (cn->data.length);
  521. lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
  522. if (!lsa)
  523. {
  524. fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n");
  525. return;
  526. }
  527. memcpy (lsa, &(cn->data), lsalen);
  528. /* Invoke registered update callback function */
  529. if (oclient->delete_notify)
  530. {
  531. (oclient->delete_notify) (cn->ifaddr, cn->area_id,
  532. cn->is_self_originated, lsa);
  533. }
  534. /* free memory allocated by ospf apiclient library */
  535. XFREE (MTYPE_OSPF_APICLIENT, lsa);
  536. }
  537. static void
  538. ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg)
  539. {
  540. /* Call message handler function. */
  541. switch (msg->hdr.msgtype)
  542. {
  543. case MSG_READY_NOTIFY:
  544. ospf_apiclient_handle_ready (oclient, msg);
  545. break;
  546. case MSG_NEW_IF:
  547. ospf_apiclient_handle_new_if (oclient, msg);
  548. break;
  549. case MSG_DEL_IF:
  550. ospf_apiclient_handle_del_if (oclient, msg);
  551. break;
  552. case MSG_ISM_CHANGE:
  553. ospf_apiclient_handle_ism_change (oclient, msg);
  554. break;
  555. case MSG_NSM_CHANGE:
  556. ospf_apiclient_handle_nsm_change (oclient, msg);
  557. break;
  558. case MSG_LSA_UPDATE_NOTIFY:
  559. ospf_apiclient_handle_lsa_update (oclient, msg);
  560. break;
  561. case MSG_LSA_DELETE_NOTIFY:
  562. ospf_apiclient_handle_lsa_delete (oclient, msg);
  563. break;
  564. default:
  565. fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n",
  566. msg->hdr.msgtype);
  567. break;
  568. }
  569. }
  570. /* -----------------------------------------------------------
  571. * Callback handler registration
  572. * -----------------------------------------------------------
  573. */
  574. void
  575. ospf_apiclient_register_callback (struct ospf_apiclient *oclient,
  576. void (*ready_notify) (u_char lsa_type,
  577. u_char opaque_type,
  578. struct in_addr addr),
  579. void (*new_if) (struct in_addr ifaddr,
  580. struct in_addr area_id),
  581. void (*del_if) (struct in_addr ifaddr),
  582. void (*ism_change) (struct in_addr ifaddr,
  583. struct in_addr area_id,
  584. u_char status),
  585. void (*nsm_change) (struct in_addr ifaddr,
  586. struct in_addr nbraddr,
  587. struct in_addr
  588. router_id,
  589. u_char status),
  590. void (*update_notify) (struct in_addr
  591. ifaddr,
  592. struct in_addr
  593. area_id,
  594. u_char self_origin,
  595. struct lsa_header *
  596. lsa),
  597. void (*delete_notify) (struct in_addr
  598. ifaddr,
  599. struct in_addr
  600. area_id,
  601. u_char self_origin,
  602. struct lsa_header *
  603. lsa))
  604. {
  605. assert (oclient);
  606. assert (update_notify);
  607. /* Register callback function */
  608. oclient->ready_notify = ready_notify;
  609. oclient->new_if = new_if;
  610. oclient->del_if = del_if;
  611. oclient->ism_change = ism_change;
  612. oclient->nsm_change = nsm_change;
  613. oclient->update_notify = update_notify;
  614. oclient->delete_notify = delete_notify;
  615. }
  616. /* -----------------------------------------------------------
  617. * Asynchronous message handling
  618. * -----------------------------------------------------------
  619. */
  620. int
  621. ospf_apiclient_handle_async (struct ospf_apiclient *oclient)
  622. {
  623. struct msg *msg;
  624. /* Get a message */
  625. msg = msg_read (oclient->fd_async);
  626. if (!msg)
  627. {
  628. /* Connection broke down */
  629. return -1;
  630. }
  631. /* Handle message */
  632. ospf_apiclient_msghandle (oclient, msg);
  633. /* Don't forget to free this message */
  634. msg_free (msg);
  635. return 0;
  636. }