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