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