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