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