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