]> git.proxmox.com Git - mirror_frr.git/blame - ospfclient/ospf_apiclient.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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"
b2fa8c0f 37#include "xref.h"
2d33f157 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"
19c0412a 50#include "ospfd/ospf_route.h"
2d33f157 51#include "ospfd/ospf_zebra.h"
52#include "ospfd/ospf_api.h"
d7b4f53a 53#include "ospfd/ospf_errors.h"
2d33f157 54
55#include "ospf_apiclient.h"
56
80413c20 57XREF_SETUP();
b2fa8c0f 58
bf8d3d6a
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
d62a17ae 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
d62a17ae 82static unsigned short ospf_apiclient_getport(void)
2d33f157 83{
d62a17ae 84 struct servent *sp = getservbyname("ospfapi", "tcp");
2d33f157 85
d62a17ae 86 return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
2d33f157 87}
88
89/* -----------------------------------------------------------
78dfa0c7 90 * Following are functions for connection management
2d33f157 91 * -----------------------------------------------------------
92 */
93
d62a17ae 94struct ospf_apiclient *ospf_apiclient_connect(char *host, int syncport)
2d33f157 95{
d62a17ae 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 */
6006b807 123 memset(&myaddr_async, 0, sizeof(myaddr_async));
d62a17ae 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
d62a17ae 129 myaddr_async.sin_len = size;
6f0e3f6e 130#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
2d33f157 131
d62a17ae 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
d62a17ae 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
d62a17ae 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 close(async_server_sock);
184 fprintf(stderr,
185 "ospf_apiclient_connect: creating sync socket failed\n");
186 return NULL;
187 }
188
189
190 /* Reuse addr and port */
191 ret = setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
192 sizeof(on));
193 if (ret < 0) {
194 fprintf(stderr,
195 "ospf_apiclient_connect: SO_REUSEADDR failed\n");
196 close(fd1);
197 close(async_server_sock);
198 return NULL;
199 }
2d33f157 200
201#ifdef SO_REUSEPORT
d62a17ae 202 ret = setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, (void *)&on,
203 sizeof(on));
204 if (ret < 0) {
205 fprintf(stderr,
206 "ospf_apiclient_connect: SO_REUSEPORT failed\n");
207 close(fd1);
208 close(async_server_sock);
209 return NULL;
210 }
2d33f157 211#endif /* SO_REUSEPORT */
212
213
d62a17ae 214 /* Bind sync socket to address structure. This is needed since we
215 want the sync port number on a fixed port number. The reverse
216 async channel will be at this port+1 */
2d33f157 217
6006b807 218 memset(&myaddr_sync, 0, sizeof(myaddr_sync));
d62a17ae 219 myaddr_sync.sin_family = AF_INET;
220 myaddr_sync.sin_port = htons(syncport);
6f0e3f6e 221#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 222 myaddr_sync.sin_len = sizeof(struct sockaddr_in);
6f0e3f6e 223#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
2d33f157 224
d62a17ae 225 ret = bind(fd1, (struct sockaddr *)&myaddr_sync, size);
226 if (ret < 0) {
227 fprintf(stderr,
228 "ospf_apiclient_connect: bind sync socket failed\n");
229 close(fd1);
230 close(async_server_sock);
231 return NULL;
232 }
233
234 /* Prepare address structure for connect */
235 memcpy(&myaddr_sync.sin_addr, hp->h_addr, hp->h_length);
236 myaddr_sync.sin_family = AF_INET;
237 myaddr_sync.sin_port = htons(ospf_apiclient_getport());
6f0e3f6e 238#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 239 myaddr_sync.sin_len = sizeof(struct sockaddr_in);
6f0e3f6e 240#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
2d33f157 241
d62a17ae 242 /* Now establish synchronous channel with OSPF daemon */
243 ret = connect(fd1, (struct sockaddr *)&myaddr_sync,
244 sizeof(struct sockaddr_in));
245 if (ret < 0) {
246 fprintf(stderr,
247 "ospf_apiclient_connect: sync connect failed\n");
248 close(async_server_sock);
249 close(fd1);
250 return NULL;
251 }
252
253 /* Accept reverse connection */
254 peeraddrlen = sizeof(struct sockaddr_in);
255 memset(&peeraddr, 0, peeraddrlen);
256
257 fd2 = accept(async_server_sock, (struct sockaddr *)&peeraddr,
258 &peeraddrlen);
259 if (fd2 < 0) {
260 fprintf(stderr,
261 "ospf_apiclient_connect: accept async failed\n");
262 close(async_server_sock);
263 close(fd1);
264 close(fd2);
265 return NULL;
266 }
267
268 /* Server socket is not needed anymore since we are not accepting more
269 connections */
270 close(async_server_sock);
271
272 /* Create new client-side instance */
273 new = XCALLOC(MTYPE_OSPF_APICLIENT, sizeof(struct ospf_apiclient));
274
275 /* Initialize socket descriptors for sync and async channels */
276 new->fd_sync = fd1;
277 new->fd_async = fd2;
278
279 return new;
2d33f157 280}
281
d62a17ae 282int ospf_apiclient_close(struct ospf_apiclient *oclient)
2d33f157 283{
284
d62a17ae 285 if (oclient->fd_sync >= 0) {
286 close(oclient->fd_sync);
287 }
2d33f157 288
d62a17ae 289 if (oclient->fd_async >= 0) {
290 close(oclient->fd_async);
291 }
2d33f157 292
d62a17ae 293 /* Free client structure */
294 XFREE(MTYPE_OSPF_APICLIENT, oclient);
295 return 0;
2d33f157 296}
297
298/* -----------------------------------------------------------
78dfa0c7 299 * Following are functions to send a request to OSPFd
2d33f157 300 * -----------------------------------------------------------
301 */
302
303/* Send synchronous request, wait for reply */
d62a17ae 304static int ospf_apiclient_send_request(struct ospf_apiclient *oclient,
305 struct msg *msg)
2d33f157 306{
d7c0a89a 307 uint32_t reqseq;
d62a17ae 308 struct msg_reply *msgreply;
309 int rc;
2d33f157 310
d62a17ae 311 /* NB: Given "msg" is freed inside this function. */
2d33f157 312
d62a17ae 313 /* Remember the sequence number of the request */
314 reqseq = ntohl(msg->hdr.msgseq);
2d33f157 315
d62a17ae 316 /* Write message to OSPFd */
317 rc = msg_write(oclient->fd_sync, msg);
318 msg_free(msg);
2d33f157 319
d62a17ae 320 if (rc < 0) {
321 return -1;
322 }
2d33f157 323
d62a17ae 324 /* Wait for reply */ /* NB: New "msg" is allocated by "msg_read()". */
325 msg = msg_read(oclient->fd_sync);
326 if (!msg)
327 return -1;
2d33f157 328
d62a17ae 329 assert(msg->hdr.msgtype == MSG_REPLY);
330 assert(ntohl(msg->hdr.msgseq) == reqseq);
2d33f157 331
d62a17ae 332 msgreply = (struct msg_reply *)STREAM_DATA(msg->s);
333 rc = msgreply->errcode;
334 msg_free(msg);
2d33f157 335
d62a17ae 336 return rc;
2d33f157 337}
338
339
340/* -----------------------------------------------------------
341 * Helper functions
342 * -----------------------------------------------------------
343 */
344
d7c0a89a 345static uint32_t ospf_apiclient_get_seqnr(void)
2d33f157 346{
d7c0a89a
QY
347 static uint32_t seqnr = MIN_SEQ;
348 uint32_t tmp;
d62a17ae 349
350 tmp = seqnr;
351 /* Increment sequence number */
352 if (seqnr < MAX_SEQ) {
353 seqnr++;
354 } else {
355 seqnr = MIN_SEQ;
356 }
357 return tmp;
2d33f157 358}
359
360/* -----------------------------------------------------------
361 * API to access OSPF daemon by client applications.
362 * -----------------------------------------------------------
363 */
364
365/*
366 * Synchronous request to register opaque type.
367 */
d7c0a89a
QY
368int ospf_apiclient_register_opaque_type(struct ospf_apiclient *cl,
369 uint8_t ltype, uint8_t otype)
2d33f157 370{
d62a17ae 371 struct msg *msg;
372 int rc;
373
374 /* just put 1 as a sequence number. */
375 msg = new_msg_register_opaque_type(ospf_apiclient_get_seqnr(), ltype,
376 otype);
377 if (!msg) {
378 fprintf(stderr, "new_msg_register_opaque_type failed\n");
379 return -1;
380 }
381
382 rc = ospf_apiclient_send_request(cl, msg);
383 return rc;
2d33f157 384}
385
d62a17ae 386/*
2d33f157 387 * Synchronous request to synchronize with OSPF's LSDB.
388 * Two steps required: register_event in order to get
389 * dynamic updates and LSDB_Sync.
390 */
d62a17ae 391int ospf_apiclient_sync_lsdb(struct ospf_apiclient *oclient)
2d33f157 392{
d62a17ae 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 fprintf(stderr, "new_msg_register_event failed\n");
404 return -1;
405 }
406 rc = ospf_apiclient_send_request(oclient, msg);
407
408 if (rc != 0)
409 goto out;
410
411 msg = new_msg_sync_lsdb(ospf_apiclient_get_seqnr(), &filter);
412 if (!msg) {
413 fprintf(stderr, "new_msg_sync_lsdb failed\n");
414 return -1;
415 }
416 rc = ospf_apiclient_send_request(oclient, msg);
2d33f157 417
418out:
d62a17ae 419 return rc;
2d33f157 420}
421
d62a17ae 422/*
2d33f157 423 * Synchronous request to originate or update an LSA.
424 */
425
d62a17ae 426int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
427 struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a
QY
428 uint8_t lsa_type, uint8_t opaque_type,
429 uint32_t opaque_id, void *opaquedata,
d62a17ae 430 int opaquelen)
2d33f157 431{
d62a17ae 432 struct msg *msg;
433 int rc;
d7c0a89a 434 uint8_t buf[OSPF_MAX_LSA_SIZE];
d62a17ae 435 struct lsa_header *lsah;
d7c0a89a 436 uint32_t tmp;
d62a17ae 437
ac62d9fd 438 /* Validate opaque LSA length */
439 if ((size_t)opaquelen > sizeof(buf) - sizeof(struct lsa_header)) {
440 fprintf(stderr, "opaquelen(%d) is larger than buf size %zu\n",
441 opaquelen, sizeof(buf));
442 return OSPF_API_NOMEMORY;
443 }
d62a17ae 444
445 /* We can only originate opaque LSAs */
446 if (!IS_OPAQUE_LSA(lsa_type)) {
447 fprintf(stderr, "Cannot originate non-opaque LSA type %d\n",
448 lsa_type);
449 return OSPF_API_ILLEGALLSATYPE;
450 }
451
452 /* Make a new LSA from parameters */
453 lsah = (struct lsa_header *)buf;
454 lsah->ls_age = 0;
455 lsah->options = 0;
456 lsah->type = lsa_type;
457
458 tmp = SET_OPAQUE_LSID(opaque_type, opaque_id);
459 lsah->id.s_addr = htonl(tmp);
975a328e 460 lsah->adv_router.s_addr = INADDR_ANY;
d62a17ae 461 lsah->ls_seqnum = 0;
462 lsah->checksum = 0;
463 lsah->length = htons(sizeof(struct lsa_header) + opaquelen);
464
d7c0a89a 465 memcpy(((uint8_t *)lsah) + sizeof(struct lsa_header), opaquedata,
d62a17ae 466 opaquelen);
467
468 msg = new_msg_originate_request(ospf_apiclient_get_seqnr(), ifaddr,
469 area_id, lsah);
470 if (!msg) {
471 fprintf(stderr, "new_msg_originate_request failed\n");
472 return OSPF_API_NOMEMORY;
473 }
474
475 rc = ospf_apiclient_send_request(oclient, msg);
476 return rc;
2d33f157 477}
478
d62a17ae 479int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient,
08172828 480 struct in_addr addr, uint8_t lsa_type,
2f30cb25
LB
481 uint8_t opaque_type, uint32_t opaque_id,
482 uint8_t flags)
2d33f157 483{
d62a17ae 484 struct msg *msg;
485 int rc;
486
487 /* Only opaque LSA can be deleted */
488 if (!IS_OPAQUE_LSA(lsa_type)) {
489 fprintf(stderr, "Cannot delete non-opaque LSA type %d\n",
490 lsa_type);
491 return OSPF_API_ILLEGALLSATYPE;
492 }
493
494 /* opaque_id is in host byte order and will be converted
495 * to network byte order by new_msg_delete_request */
08172828 496 msg = new_msg_delete_request(ospf_apiclient_get_seqnr(), addr, lsa_type,
2f30cb25 497 opaque_type, opaque_id, flags);
d62a17ae 498
499 rc = ospf_apiclient_send_request(oclient, msg);
500 return rc;
2d33f157 501}
502
503/* -----------------------------------------------------------
78dfa0c7 504 * Following are handlers for messages from OSPF daemon
2d33f157 505 * -----------------------------------------------------------
506 */
507
d62a17ae 508static void ospf_apiclient_handle_ready(struct ospf_apiclient *oclient,
509 struct msg *msg)
2d33f157 510{
d62a17ae 511 struct msg_ready_notify *r;
512 r = (struct msg_ready_notify *)STREAM_DATA(msg->s);
513
514 /* Invoke registered callback function. */
515 if (oclient->ready_notify) {
516 (oclient->ready_notify)(r->lsa_type, r->opaque_type, r->addr);
517 }
2d33f157 518}
519
d62a17ae 520static void ospf_apiclient_handle_new_if(struct ospf_apiclient *oclient,
521 struct msg *msg)
2d33f157 522{
d62a17ae 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 (oclient->new_if)(n->ifaddr, n->area_id);
529 }
2d33f157 530}
531
d62a17ae 532static void ospf_apiclient_handle_del_if(struct ospf_apiclient *oclient,
533 struct msg *msg)
2d33f157 534{
d62a17ae 535 struct msg_del_if *d;
536 d = (struct msg_del_if *)STREAM_DATA(msg->s);
537
538 /* Invoke registered callback function. */
539 if (oclient->del_if) {
540 (oclient->del_if)(d->ifaddr);
541 }
2d33f157 542}
543
d62a17ae 544static void ospf_apiclient_handle_ism_change(struct ospf_apiclient *oclient,
545 struct msg *msg)
2d33f157 546{
d62a17ae 547 struct msg_ism_change *m;
548 m = (struct msg_ism_change *)STREAM_DATA(msg->s);
2d33f157 549
d62a17ae 550 /* Invoke registered callback function. */
551 if (oclient->ism_change) {
552 (oclient->ism_change)(m->ifaddr, m->area_id, m->status);
553 }
2d33f157 554}
555
d62a17ae 556static void ospf_apiclient_handle_nsm_change(struct ospf_apiclient *oclient,
557 struct msg *msg)
2d33f157 558{
d62a17ae 559 struct msg_nsm_change *m;
560 m = (struct msg_nsm_change *)STREAM_DATA(msg->s);
561
562 /* Invoke registered callback function. */
563 if (oclient->nsm_change) {
564 (oclient->nsm_change)(m->ifaddr, m->nbraddr, m->router_id,
565 m->status);
566 }
2d33f157 567}
568
d62a17ae 569static void ospf_apiclient_handle_lsa_update(struct ospf_apiclient *oclient,
570 struct msg *msg)
2d33f157 571{
d62a17ae 572 struct msg_lsa_change_notify *cn;
573 struct lsa_header *lsa;
d8193748 574 void *p;
d7b4f53a 575 uint16_t lsalen;
d62a17ae 576
577 cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s);
578
579 /* Extract LSA from message */
580 lsalen = ntohs(cn->data.length);
d7b4f53a
DS
581 if (lsalen > OSPF_MAX_LSA_SIZE) {
582 flog_warn(
583 EC_OSPF_LARGE_LSA,
584 "%s: message received size: %d is greater than a LSA size: %d",
585 __func__, lsalen, OSPF_MAX_LSA_SIZE);
586 return;
587 }
0ce1ca80 588
d8193748
MS
589 p = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
590
591 memcpy(p, &(cn->data), lsalen);
592 lsa = p;
d62a17ae 593
594 /* Invoke registered update callback function */
595 if (oclient->update_notify) {
596 (oclient->update_notify)(cn->ifaddr, cn->area_id,
597 cn->is_self_originated, lsa);
598 }
599
600 /* free memory allocated by ospf apiclient library */
d8193748 601 XFREE(MTYPE_OSPF_APICLIENT, p);
2d33f157 602}
603
d62a17ae 604static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient,
605 struct msg *msg)
2d33f157 606{
d62a17ae 607 struct msg_lsa_change_notify *cn;
608 struct lsa_header *lsa;
d8193748 609 void *p;
d7b4f53a 610 uint16_t lsalen;
d62a17ae 611
612 cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s);
613
614 /* Extract LSA from message */
615 lsalen = ntohs(cn->data.length);
d7b4f53a
DS
616 if (lsalen > OSPF_MAX_LSA_SIZE) {
617 flog_warn(
618 EC_OSPF_LARGE_LSA,
619 "%s: message received size: %d is greater than a LSA size: %d",
620 __func__, lsalen, OSPF_MAX_LSA_SIZE);
621 return;
622 }
0ce1ca80 623
d8193748
MS
624 p = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
625
626 memcpy(p, &(cn->data), lsalen);
627 lsa = p;
d62a17ae 628
629 /* Invoke registered update callback function */
630 if (oclient->delete_notify) {
631 (oclient->delete_notify)(cn->ifaddr, cn->area_id,
632 cn->is_self_originated, lsa);
633 }
634
635 /* free memory allocated by ospf apiclient library */
d8193748 636 XFREE(MTYPE_OSPF_APICLIENT, p);
2d33f157 637}
638
d62a17ae 639static void ospf_apiclient_msghandle(struct ospf_apiclient *oclient,
640 struct msg *msg)
2d33f157 641{
d62a17ae 642 /* Call message handler function. */
643 switch (msg->hdr.msgtype) {
644 case MSG_READY_NOTIFY:
645 ospf_apiclient_handle_ready(oclient, msg);
646 break;
647 case MSG_NEW_IF:
648 ospf_apiclient_handle_new_if(oclient, msg);
649 break;
650 case MSG_DEL_IF:
651 ospf_apiclient_handle_del_if(oclient, msg);
652 break;
653 case MSG_ISM_CHANGE:
654 ospf_apiclient_handle_ism_change(oclient, msg);
655 break;
656 case MSG_NSM_CHANGE:
657 ospf_apiclient_handle_nsm_change(oclient, msg);
658 break;
659 case MSG_LSA_UPDATE_NOTIFY:
660 ospf_apiclient_handle_lsa_update(oclient, msg);
661 break;
662 case MSG_LSA_DELETE_NOTIFY:
663 ospf_apiclient_handle_lsa_delete(oclient, msg);
664 break;
665 default:
666 fprintf(stderr,
667 "ospf_apiclient_read: Unknown message type: %d\n",
668 msg->hdr.msgtype);
669 break;
670 }
2d33f157 671}
672
673/* -----------------------------------------------------------
674 * Callback handler registration
675 * -----------------------------------------------------------
676 */
677
d62a17ae 678void ospf_apiclient_register_callback(
679 struct ospf_apiclient *oclient,
d7c0a89a 680 void (*ready_notify)(uint8_t lsa_type, uint8_t opaque_type,
d62a17ae 681 struct in_addr addr),
682 void (*new_if)(struct in_addr ifaddr, struct in_addr area_id),
683 void (*del_if)(struct in_addr ifaddr),
684 void (*ism_change)(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 685 uint8_t status),
d62a17ae 686 void (*nsm_change)(struct in_addr ifaddr, struct in_addr nbraddr,
d7c0a89a 687 struct in_addr router_id, uint8_t status),
d62a17ae 688 void (*update_notify)(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 689 uint8_t self_origin, struct lsa_header *lsa),
d62a17ae 690 void (*delete_notify)(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 691 uint8_t self_origin, struct lsa_header *lsa))
2d33f157 692{
d62a17ae 693 assert(oclient);
694 assert(update_notify);
695
696 /* Register callback function */
697 oclient->ready_notify = ready_notify;
698 oclient->new_if = new_if;
699 oclient->del_if = del_if;
700 oclient->ism_change = ism_change;
701 oclient->nsm_change = nsm_change;
702 oclient->update_notify = update_notify;
703 oclient->delete_notify = delete_notify;
2d33f157 704}
705
706/* -----------------------------------------------------------
707 * Asynchronous message handling
708 * -----------------------------------------------------------
709 */
710
d62a17ae 711int ospf_apiclient_handle_async(struct ospf_apiclient *oclient)
2d33f157 712{
d62a17ae 713 struct msg *msg;
2d33f157 714
d62a17ae 715 /* Get a message */
716 msg = msg_read(oclient->fd_async);
2d33f157 717
d62a17ae 718 if (!msg) {
719 /* Connection broke down */
720 return -1;
721 }
2d33f157 722
d62a17ae 723 /* Handle message */
724 ospf_apiclient_msghandle(oclient, msg);
2d33f157 725
d62a17ae 726 /* Don't forget to free this message */
727 msg_free(msg);
2d33f157 728
d62a17ae 729 return 0;
2d33f157 730}