Coverage Report

Created: 2025-08-28 06:29

/src/frr/ospfd/ospf_apiserver.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * Server side of OSPF API.
4
 * Copyright (C) 2001, 2002 Ralph Keller
5
 * Copyright (c) 2022, LabN Consulting, L.L.C.
6
 */
7
8
#include <zebra.h>
9
10
#ifdef SUPPORT_OSPF_API
11
12
#include "linklist.h"
13
#include "prefix.h"
14
#include "if.h"
15
#include "table.h"
16
#include "memory.h"
17
#include "command.h"
18
#include "vty.h"
19
#include "stream.h"
20
#include "log.h"
21
#include "frrevent.h"
22
#include "hash.h"
23
#include "sockunion.h" /* for inet_aton() */
24
#include "buffer.h"
25
26
#include <sys/types.h>
27
28
#include "ospfd/ospfd.h" /* for "struct event_loop" */
29
#include "ospfd/ospf_interface.h"
30
#include "ospfd/ospf_ism.h"
31
#include "ospfd/ospf_asbr.h"
32
#include "ospfd/ospf_lsa.h"
33
#include "ospfd/ospf_lsdb.h"
34
#include "ospfd/ospf_neighbor.h"
35
#include "ospfd/ospf_nsm.h"
36
#include "ospfd/ospf_flood.h"
37
#include "ospfd/ospf_packet.h"
38
#include "ospfd/ospf_spf.h"
39
#include "ospfd/ospf_dump.h"
40
#include "ospfd/ospf_route.h"
41
#include "ospfd/ospf_ase.h"
42
#include "ospfd/ospf_zebra.h"
43
#include "ospfd/ospf_errors.h"
44
#include "ospfd/ospf_memory.h"
45
46
#include "ospfd/ospf_api.h"
47
#include "ospfd/ospf_apiserver.h"
48
49
DEFINE_MTYPE_STATIC(OSPFD, APISERVER, "API Server");
50
DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
51
52
/* This is an implementation of an API to the OSPF daemon that allows
53
 * external applications to access the OSPF daemon through socket
54
 * connections. The application can use this API to inject its own
55
 * opaque LSAs and flood them to other OSPF daemons. Other OSPF
56
 * daemons then receive these LSAs and inform applications through the
57
 * API by sending a corresponding message. The application can also
58
 * register to receive all LSA types (in addition to opaque types) and
59
 * use this information to reconstruct the OSPF's LSDB. The OSPF
60
 * daemon supports multiple applications concurrently.  */
61
62
/* List of all active connections. */
63
struct list *apiserver_list;
64
65
/* -----------------------------------------------------------
66
 * Functions to lookup interfaces
67
 * -----------------------------------------------------------
68
 */
69
70
struct ospf_interface *ospf_apiserver_if_lookup_by_addr(struct in_addr address)
71
0
{
72
0
  struct listnode *node, *nnode;
73
0
  struct ospf_interface *oi;
74
0
  struct ospf *ospf = NULL;
75
76
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
77
0
  if (!ospf)
78
0
    return NULL;
79
80
0
  for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
81
0
    if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
82
0
      if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4))
83
0
        return oi;
84
85
0
  return NULL;
86
0
}
87
88
struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
89
0
{
90
0
  struct listnode *node, *nnode;
91
0
  struct ospf_interface *oi;
92
0
  struct ospf *ospf = NULL;
93
94
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
95
0
  if (!ospf)
96
0
    return NULL;
97
98
0
  for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
99
0
    if (oi->ifp == ifp)
100
0
      return oi;
101
102
0
  return NULL;
103
0
}
104
105
/* -----------------------------------------------------------
106
 * Initialization
107
 * -----------------------------------------------------------
108
 */
109
110
unsigned short ospf_apiserver_getport(void)
111
0
{
112
0
  struct servent *sp = getservbyname("ospfapi", "tcp");
113
114
0
  return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
115
0
}
116
117
/* Initialize OSPF API module. Invoked from ospf_opaque_init() */
118
int ospf_apiserver_init(void)
119
0
{
120
0
  int fd;
121
0
  int rc = -1;
122
123
  /* Create new socket for synchronous messages. */
124
0
  fd = ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET);
125
126
0
  if (fd < 0)
127
0
    goto out;
128
129
  /* Schedule new thread that handles accepted connections. */
130
0
  ospf_apiserver_event(OSPF_APISERVER_ACCEPT, fd, NULL);
131
132
  /* Initialize list that keeps track of all connections. */
133
0
  apiserver_list = list_new();
134
135
  /* Register opaque-independent call back functions. These functions
136
     are invoked on ISM, NSM changes and LSA update and LSA deletes */
137
0
  rc = ospf_register_opaque_functab(
138
0
    0 /* all LSAs */, 0 /* all opaque types */,
139
0
    ospf_apiserver_new_if, ospf_apiserver_del_if,
140
0
    ospf_apiserver_ism_change, ospf_apiserver_nsm_change, NULL,
141
0
    NULL, NULL, NULL, /* ospf_apiserver_show_info */
142
0
    NULL,     /* originator_func */
143
0
    NULL,     /* ospf_apiserver_lsa_refresher */
144
0
    ospf_apiserver_lsa_update, ospf_apiserver_lsa_delete);
145
0
  if (rc != 0) {
146
0
    flog_warn(
147
0
      EC_OSPF_OPAQUE_REGISTRATION,
148
0
      "ospf_apiserver_init: Failed to register opaque type [0/0]");
149
0
  }
150
151
0
  rc = 0;
152
153
0
out:
154
0
  return rc;
155
0
}
156
157
/* Terminate OSPF API module. */
158
void ospf_apiserver_term(void)
159
0
{
160
0
  struct ospf_apiserver *apiserv;
161
162
  /* Unregister wildcard [0/0] type */
163
0
  ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */);
164
165
  /*
166
   * Free all client instances.  ospf_apiserver_free removes the node
167
   * from the list, so we examine the head of the list anew each time.
168
   */
169
0
  if (!apiserver_list)
170
0
    return;
171
172
0
  while (listcount(apiserver_list)) {
173
0
    apiserv = listgetdata(listhead(apiserver_list));
174
175
0
    ospf_apiserver_free(apiserv);
176
0
  }
177
178
  /* Free client list itself */
179
0
  if (apiserver_list)
180
0
    list_delete(&apiserver_list);
181
182
  /* Free wildcard list */
183
  /* XXX  */
184
0
}
185
186
static struct ospf_apiserver *lookup_apiserver(uint8_t lsa_type,
187
                 uint8_t opaque_type)
188
0
{
189
0
  struct listnode *n1, *n2;
190
0
  struct registered_opaque_type *r;
191
0
  struct ospf_apiserver *apiserv, *found = NULL;
192
193
  /* XXX: this approaches O(n**2) */
194
0
  for (ALL_LIST_ELEMENTS_RO(apiserver_list, n1, apiserv)) {
195
0
    for (ALL_LIST_ELEMENTS_RO(apiserv->opaque_types, n2, r))
196
0
      if (r->lsa_type == lsa_type
197
0
          && r->opaque_type == opaque_type) {
198
0
        found = apiserv;
199
0
        goto out;
200
0
      }
201
0
  }
202
0
out:
203
0
  return found;
204
0
}
205
206
static struct ospf_apiserver *lookup_apiserver_by_lsa(struct ospf_lsa *lsa)
207
0
{
208
0
  struct lsa_header *lsah = lsa->data;
209
0
  struct ospf_apiserver *found = NULL;
210
211
0
  if (IS_OPAQUE_LSA(lsah->type)) {
212
0
    found = lookup_apiserver(
213
0
      lsah->type, GET_OPAQUE_TYPE(ntohl(lsah->id.s_addr)));
214
0
  }
215
0
  return found;
216
0
}
217
218
/* -----------------------------------------------------------
219
 * Following are functions to manage client connections.
220
 * -----------------------------------------------------------
221
 */
222
static int ospf_apiserver_new_lsa_hook(struct ospf_lsa *lsa)
223
0
{
224
0
  if (IS_DEBUG_OSPF_EVENT)
225
0
    zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld",
226
0
         (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
227
0
  return 0;
228
0
}
229
230
static int ospf_apiserver_del_lsa_hook(struct ospf_lsa *lsa)
231
0
{
232
0
  if (IS_DEBUG_OSPF_EVENT)
233
0
    zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld",
234
0
         (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total);
235
0
  return 0;
236
0
}
237
238
/* Allocate new connection structure. */
239
struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async)
240
0
{
241
0
  struct ospf_apiserver *new =
242
0
    XMALLOC(MTYPE_APISERVER, sizeof(struct ospf_apiserver));
243
244
0
  new->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER,
245
0
            sizeof(struct lsa_filter_type));
246
247
0
  new->fd_sync = fd_sync;
248
0
  new->fd_async = fd_async;
249
250
  /* list of registered opaque types that application uses */
251
0
  new->opaque_types = list_new();
252
253
  /* Initialize temporary strage for LSA instances to be refreshed. */
254
0
  memset(&new->reserve, 0, sizeof(struct ospf_lsdb));
255
0
  ospf_lsdb_init(&new->reserve);
256
257
0
  new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */
258
0
  new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */
259
260
0
  new->out_sync_fifo = msg_fifo_new();
261
0
  new->out_async_fifo = msg_fifo_new();
262
0
  new->t_sync_read = NULL;
263
#ifdef USE_ASYNC_READ
264
  new->t_async_read = NULL;
265
#endif /* USE_ASYNC_READ */
266
0
  new->t_sync_write = NULL;
267
0
  new->t_async_write = NULL;
268
269
0
  new->filter->typemask = 0; /* filter all LSAs */
270
0
  new->filter->origin = ANY_ORIGIN;
271
0
  new->filter->num_areas = 0;
272
273
0
  return new;
274
0
}
275
276
void ospf_apiserver_event(enum ospf_apiserver_event event, int fd,
277
        struct ospf_apiserver *apiserv)
278
0
{
279
0
  switch (event) {
280
0
  case OSPF_APISERVER_ACCEPT:
281
0
    (void)event_add_read(master, ospf_apiserver_accept, apiserv, fd,
282
0
             NULL);
283
0
    break;
284
0
  case OSPF_APISERVER_SYNC_READ:
285
0
    apiserv->t_sync_read = NULL;
286
0
    event_add_read(master, ospf_apiserver_read, apiserv, fd,
287
0
             &apiserv->t_sync_read);
288
0
    break;
289
#ifdef USE_ASYNC_READ
290
  case OSPF_APISERVER_ASYNC_READ:
291
    apiserv->t_async_read = NULL;
292
    event_add_read(master, ospf_apiserver_read, apiserv, fd,
293
             &apiserv->t_async_read);
294
    break;
295
#endif /* USE_ASYNC_READ */
296
0
  case OSPF_APISERVER_SYNC_WRITE:
297
0
    event_add_write(master, ospf_apiserver_sync_write, apiserv, fd,
298
0
        &apiserv->t_sync_write);
299
0
    break;
300
0
  case OSPF_APISERVER_ASYNC_WRITE:
301
0
    event_add_write(master, ospf_apiserver_async_write, apiserv, fd,
302
0
        &apiserv->t_async_write);
303
0
    break;
304
0
  }
305
0
}
306
307
/* Free instance. First unregister all opaque types used by
308
   application, flush opaque LSAs injected by application
309
   from network and close connection. */
310
void ospf_apiserver_free(struct ospf_apiserver *apiserv)
311
0
{
312
0
  struct listnode *node;
313
314
  /* Cancel read and write threads. */
315
0
  EVENT_OFF(apiserv->t_sync_read);
316
#ifdef USE_ASYNC_READ
317
  EVENT_OFF(apiserv->t_async_read);
318
#endif /* USE_ASYNC_READ */
319
0
  EVENT_OFF(apiserv->t_sync_write);
320
0
  EVENT_OFF(apiserv->t_async_write);
321
322
  /* Unregister all opaque types that application registered
323
     and flush opaque LSAs if still in LSDB. */
324
325
0
  while ((node = listhead(apiserv->opaque_types)) != NULL) {
326
0
    struct registered_opaque_type *regtype = listgetdata(node);
327
328
0
    ospf_apiserver_unregister_opaque_type(
329
0
      apiserv, regtype->lsa_type, regtype->opaque_type);
330
0
  }
331
0
  list_delete(&apiserv->opaque_types);
332
333
  /* Close connections to OSPFd. */
334
0
  if (apiserv->fd_sync > 0) {
335
0
    close(apiserv->fd_sync);
336
0
  }
337
338
0
  if (apiserv->fd_async > 0) {
339
0
    close(apiserv->fd_async);
340
0
  }
341
342
  /* Free fifos */
343
0
  msg_fifo_free(apiserv->out_sync_fifo);
344
0
  msg_fifo_free(apiserv->out_async_fifo);
345
346
  /* Clear temporary strage for LSA instances to be refreshed. */
347
0
  ospf_lsdb_delete_all(&apiserv->reserve);
348
0
  ospf_lsdb_cleanup(&apiserv->reserve);
349
350
  /* Remove from the list of active clients. */
351
0
  listnode_delete(apiserver_list, apiserv);
352
353
0
  XFREE(MTYPE_APISERVER_MSGFILTER, apiserv->filter);
354
355
0
  if (IS_DEBUG_OSPF_EVENT)
356
0
    zlog_debug("API: Delete apiserv(%p), total#(%d)",
357
0
         (void *)apiserv, apiserver_list->count);
358
359
  /* And free instance. */
360
0
  XFREE(MTYPE_APISERVER, apiserv);
361
0
}
362
363
void ospf_apiserver_read(struct event *thread)
364
0
{
365
0
  struct ospf_apiserver *apiserv;
366
0
  struct msg *msg;
367
0
  int fd;
368
0
  enum ospf_apiserver_event event;
369
370
0
  apiserv = EVENT_ARG(thread);
371
0
  fd = EVENT_FD(thread);
372
373
0
  if (fd == apiserv->fd_sync) {
374
0
    event = OSPF_APISERVER_SYNC_READ;
375
0
    apiserv->t_sync_read = NULL;
376
377
0
    if (IS_DEBUG_OSPF_EVENT)
378
0
      zlog_debug("API: %s: Peer: %pI4/%u", __func__,
379
0
           &apiserv->peer_sync.sin_addr,
380
0
           ntohs(apiserv->peer_sync.sin_port));
381
0
  }
382
#ifdef USE_ASYNC_READ
383
  else if (fd == apiserv->fd_async) {
384
    event = OSPF_APISERVER_ASYNC_READ;
385
    apiserv->t_async_read = NULL;
386
387
    if (IS_DEBUG_OSPF_EVENT)
388
      zlog_debug("API: %s: Peer: %pI4/%u", __func__,
389
           &apiserv->peer_async.sin_addr,
390
           ntohs(apiserv->peer_async.sin_port));
391
  }
392
#endif /* USE_ASYNC_READ */
393
0
  else {
394
0
    zlog_warn("%s: Unknown fd(%d)", __func__, fd);
395
0
    ospf_apiserver_free(apiserv);
396
0
    return;
397
0
  }
398
399
  /* Read message from fd. */
400
0
  msg = msg_read(fd);
401
0
  if (msg == NULL) {
402
0
    zlog_warn("%s: read failed on fd=%d, closing connection",
403
0
        __func__, fd);
404
405
    /* Perform cleanup. */
406
0
    ospf_apiserver_free(apiserv);
407
0
    return;
408
0
  }
409
410
0
  if (IS_DEBUG_OSPF_EVENT)
411
0
    msg_print(msg);
412
413
  /* Dispatch to corresponding message handler. */
414
0
  ospf_apiserver_handle_msg(apiserv, msg);
415
416
  /* Prepare for next message, add read thread. */
417
0
  ospf_apiserver_event(event, fd, apiserv);
418
419
0
  msg_free(msg);
420
0
}
421
422
void ospf_apiserver_sync_write(struct event *thread)
423
0
{
424
0
  struct ospf_apiserver *apiserv;
425
0
  struct msg *msg;
426
0
  int fd;
427
0
  int rc = -1;
428
429
0
  apiserv = EVENT_ARG(thread);
430
0
  assert(apiserv);
431
0
  fd = EVENT_FD(thread);
432
433
0
  apiserv->t_sync_write = NULL;
434
435
  /* Sanity check */
436
0
  if (fd != apiserv->fd_sync) {
437
0
    zlog_warn("%s: Unknown fd=%d", __func__, fd);
438
0
    goto out;
439
0
  }
440
441
0
  if (IS_DEBUG_OSPF_EVENT)
442
0
    zlog_debug("API: %s: Peer: %pI4/%u", __func__,
443
0
         &apiserv->peer_sync.sin_addr,
444
0
         ntohs(apiserv->peer_sync.sin_port));
445
446
  /* Check whether there is really a message in the fifo. */
447
0
  msg = msg_fifo_pop(apiserv->out_sync_fifo);
448
0
  if (!msg) {
449
0
    zlog_warn("API: %s: No message in Sync-FIFO?", __func__);
450
0
    return;
451
0
  }
452
453
0
  if (IS_DEBUG_OSPF_EVENT)
454
0
    msg_print(msg);
455
456
0
  rc = msg_write(fd, msg);
457
458
  /* Once a message is dequeued, it should be freed anyway. */
459
0
  msg_free(msg);
460
461
0
  if (rc < 0) {
462
0
    zlog_warn("%s: write failed on fd=%d", __func__, fd);
463
0
    goto out;
464
0
  }
465
466
467
  /* If more messages are in sync message fifo, schedule write thread. */
468
0
  if (msg_fifo_head(apiserv->out_sync_fifo)) {
469
0
    ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE,
470
0
             apiserv->fd_sync, apiserv);
471
0
  }
472
473
0
out:
474
475
0
  if (rc < 0) {
476
    /* Perform cleanup and disconnect with peer */
477
0
    ospf_apiserver_free(apiserv);
478
0
  }
479
0
}
480
481
482
void ospf_apiserver_async_write(struct event *thread)
483
0
{
484
0
  struct ospf_apiserver *apiserv;
485
0
  struct msg *msg;
486
0
  int fd;
487
0
  int rc = -1;
488
489
0
  apiserv = EVENT_ARG(thread);
490
0
  assert(apiserv);
491
0
  fd = EVENT_FD(thread);
492
493
0
  apiserv->t_async_write = NULL;
494
495
  /* Sanity check */
496
0
  if (fd != apiserv->fd_async) {
497
0
    zlog_warn("%s: Unknown fd=%d", __func__, fd);
498
0
    goto out;
499
0
  }
500
501
0
  if (IS_DEBUG_OSPF_EVENT)
502
0
    zlog_debug("API: %s: Peer: %pI4/%u", __func__,
503
0
         &apiserv->peer_async.sin_addr,
504
0
         ntohs(apiserv->peer_async.sin_port));
505
506
  /* Check whether there is really a message in the fifo. */
507
0
  msg = msg_fifo_pop(apiserv->out_async_fifo);
508
0
  if (!msg) {
509
0
    zlog_warn("API: %s: No message in Async-FIFO?", __func__);
510
0
    return;
511
0
  }
512
513
0
  if (IS_DEBUG_OSPF_EVENT)
514
0
    msg_print(msg);
515
516
0
  rc = msg_write(fd, msg);
517
518
  /* Once a message is dequeued, it should be freed anyway. */
519
0
  msg_free(msg);
520
521
0
  if (rc < 0) {
522
0
    zlog_warn("%s: write failed on fd=%d", __func__, fd);
523
0
    goto out;
524
0
  }
525
526
527
  /* If more messages are in async message fifo, schedule write thread. */
528
0
  if (msg_fifo_head(apiserv->out_async_fifo)) {
529
0
    ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE,
530
0
             apiserv->fd_async, apiserv);
531
0
  }
532
533
0
out:
534
535
0
  if (rc < 0) {
536
    /* Perform cleanup and disconnect with peer */
537
0
    ospf_apiserver_free(apiserv);
538
0
  }
539
0
}
540
541
542
int ospf_apiserver_serv_sock_family(unsigned short port, int family)
543
0
{
544
0
  union sockunion su;
545
0
  int accept_sock;
546
0
  int rc;
547
548
0
  memset(&su, 0, sizeof(union sockunion));
549
0
  su.sa.sa_family = family;
550
551
  /* Make new socket */
552
0
  accept_sock = sockunion_stream_socket(&su);
553
0
  if (accept_sock < 0)
554
0
    return accept_sock;
555
556
  /* This is a server, so reuse address and port */
557
0
  sockopt_reuseaddr(accept_sock);
558
0
  sockopt_reuseport(accept_sock);
559
560
  /* Bind socket to address and given port. */
561
0
  rc = sockunion_bind(accept_sock, &su, port, NULL);
562
0
  if (rc < 0) {
563
0
    close(accept_sock); /* Close socket */
564
0
    return rc;
565
0
  }
566
567
  /* Listen socket under queue length 3. */
568
0
  rc = listen(accept_sock, 3);
569
0
  if (rc < 0) {
570
0
    zlog_warn("%s: listen: %s", __func__, safe_strerror(errno));
571
0
    close(accept_sock); /* Close socket */
572
0
    return rc;
573
0
  }
574
0
  return accept_sock;
575
0
}
576
577
578
/* Accept connection request from external applications. For each
579
   accepted connection allocate own connection instance. */
580
void ospf_apiserver_accept(struct event *thread)
581
0
{
582
0
  int accept_sock;
583
0
  int new_sync_sock;
584
0
  int new_async_sock;
585
0
  union sockunion su;
586
0
  struct ospf_apiserver *apiserv;
587
0
  struct sockaddr_in peer_async;
588
0
  struct sockaddr_in peer_sync;
589
0
  unsigned int peerlen;
590
0
  int ret;
591
592
  /* EVENT_ARG (thread) is NULL */
593
0
  accept_sock = EVENT_FD(thread);
594
595
  /* Keep hearing on socket for further connections. */
596
0
  ospf_apiserver_event(OSPF_APISERVER_ACCEPT, accept_sock, NULL);
597
598
0
  memset(&su, 0, sizeof(union sockunion));
599
  /* Accept connection for synchronous messages */
600
0
  new_sync_sock = sockunion_accept(accept_sock, &su);
601
0
  if (new_sync_sock < 0) {
602
0
    zlog_warn("%s: accept: %s", __func__, safe_strerror(errno));
603
0
    return;
604
0
  }
605
606
  /* Get port address and port number of peer to make reverse connection.
607
     The reverse channel uses the port number of the peer port+1. */
608
609
0
  memset(&peer_sync, 0, sizeof(peer_sync));
610
0
  peerlen = sizeof(struct sockaddr_in);
611
612
0
  ret = getpeername(new_sync_sock, (struct sockaddr *)&peer_sync,
613
0
        &peerlen);
614
0
  if (ret < 0) {
615
0
    zlog_warn("%s: getpeername: %s", __func__,
616
0
        safe_strerror(errno));
617
0
    close(new_sync_sock);
618
0
    return;
619
0
  }
620
621
0
  if (IS_DEBUG_OSPF_EVENT)
622
0
    zlog_debug("API: %s: New peer: %pI4/%u", __func__,
623
0
         &peer_sync.sin_addr, ntohs(peer_sync.sin_port));
624
625
  /* Create new socket for asynchronous messages. */
626
0
  peer_async = peer_sync;
627
0
  peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1);
628
629
  /* Check if remote port number to make reverse connection is valid one.
630
   */
631
0
  if (ntohs(peer_async.sin_port) == ospf_apiserver_getport()) {
632
0
    zlog_warn("API: %s: Peer(%pI4/%u): Invalid async port number?",
633
0
        __func__, &peer_async.sin_addr,
634
0
        ntohs(peer_async.sin_port));
635
0
    close(new_sync_sock);
636
0
    return;
637
0
  }
638
639
0
  new_async_sock = socket(AF_INET, SOCK_STREAM, 0);
640
0
  if (new_async_sock < 0) {
641
0
    zlog_warn("%s: socket: %s", __func__, safe_strerror(errno));
642
0
    close(new_sync_sock);
643
0
    return;
644
0
  }
645
646
0
  ret = connect(new_async_sock, (struct sockaddr *)&peer_async,
647
0
          sizeof(struct sockaddr_in));
648
649
0
  if (ret < 0) {
650
0
    zlog_warn("%s: connect: %s", __func__, safe_strerror(errno));
651
0
    close(new_sync_sock);
652
0
    close(new_async_sock);
653
0
    return;
654
0
  }
655
656
#ifdef USE_ASYNC_READ
657
#else  /* USE_ASYNC_READ */
658
  /* Make the asynchronous channel write-only. */
659
0
  ret = shutdown(new_async_sock, SHUT_RD);
660
0
  if (ret < 0) {
661
0
    zlog_warn("%s: shutdown: %s", __func__, safe_strerror(errno));
662
0
    close(new_sync_sock);
663
0
    close(new_async_sock);
664
0
    return;
665
0
  }
666
0
#endif /* USE_ASYNC_READ */
667
668
  /* Allocate new server-side connection structure */
669
0
  apiserv = ospf_apiserver_new(new_sync_sock, new_async_sock);
670
671
  /* Add to active connection list */
672
0
  listnode_add(apiserver_list, apiserv);
673
0
  apiserv->peer_sync = peer_sync;
674
0
  apiserv->peer_async = peer_async;
675
676
  /* And add read threads for new connection */
677
0
  ospf_apiserver_event(OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv);
678
#ifdef USE_ASYNC_READ
679
  ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ, new_async_sock,
680
           apiserv);
681
#endif /* USE_ASYNC_READ */
682
683
0
  if (IS_DEBUG_OSPF_EVENT)
684
0
    zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv,
685
0
         apiserver_list->count);
686
0
}
687
688
689
/* -----------------------------------------------------------
690
 * Send reply with return code to client application
691
 * -----------------------------------------------------------
692
 */
693
694
static int ospf_apiserver_send_msg(struct ospf_apiserver *apiserv,
695
           struct msg *msg)
696
0
{
697
0
  struct msg_fifo *fifo;
698
0
  struct msg *msg2;
699
0
  enum ospf_apiserver_event event;
700
0
  int fd;
701
702
0
  switch (msg->hdr.msgtype) {
703
0
  case MSG_REPLY:
704
0
    fifo = apiserv->out_sync_fifo;
705
0
    fd = apiserv->fd_sync;
706
0
    event = OSPF_APISERVER_SYNC_WRITE;
707
0
    break;
708
0
  case MSG_READY_NOTIFY:
709
0
  case MSG_LSA_UPDATE_NOTIFY:
710
0
  case MSG_LSA_DELETE_NOTIFY:
711
0
  case MSG_NEW_IF:
712
0
  case MSG_DEL_IF:
713
0
  case MSG_ISM_CHANGE:
714
0
  case MSG_NSM_CHANGE:
715
0
  case MSG_REACHABLE_CHANGE:
716
0
  case MSG_ROUTER_ID_CHANGE:
717
0
    fifo = apiserv->out_async_fifo;
718
0
    fd = apiserv->fd_async;
719
0
    event = OSPF_APISERVER_ASYNC_WRITE;
720
0
    break;
721
0
  default:
722
0
    zlog_warn("%s: Unknown message type %d", __func__,
723
0
        msg->hdr.msgtype);
724
0
    return -1;
725
0
  }
726
727
  /* Make a copy of the message and put in the fifo. Once the fifo
728
     gets drained by the write thread, the message will be freed. */
729
  /* NB: Given "msg" is untouched in this function. */
730
0
  msg2 = msg_dup(msg);
731
732
  /* Enqueue message into corresponding fifo queue */
733
0
  msg_fifo_push(fifo, msg2);
734
735
  /* Schedule write thread */
736
0
  ospf_apiserver_event(event, fd, apiserv);
737
0
  return 0;
738
0
}
739
740
int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, uint32_t seqnr,
741
            uint8_t rc)
742
0
{
743
0
  struct msg *msg = new_msg_reply(seqnr, rc);
744
0
  int ret;
745
746
0
  if (!msg) {
747
0
    zlog_warn("%s: msg_new failed", __func__);
748
#ifdef NOTYET
749
    /* Cannot allocate new message. What should we do? */
750
    ospf_apiserver_free(apiserv);
751
#endif
752
0
    return -1;
753
0
  }
754
755
0
  ret = ospf_apiserver_send_msg(apiserv, msg);
756
0
  msg_free(msg);
757
0
  return ret;
758
0
}
759
760
761
/* -----------------------------------------------------------
762
 * Generic message dispatching handler function
763
 * -----------------------------------------------------------
764
 */
765
766
int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg)
767
0
{
768
0
  int rc;
769
770
  /* Call corresponding message handler function. */
771
0
  switch (msg->hdr.msgtype) {
772
0
  case MSG_REGISTER_OPAQUETYPE:
773
0
    rc = ospf_apiserver_handle_register_opaque_type(apiserv, msg);
774
0
    break;
775
0
  case MSG_UNREGISTER_OPAQUETYPE:
776
0
    rc = ospf_apiserver_handle_unregister_opaque_type(apiserv, msg);
777
0
    break;
778
0
  case MSG_REGISTER_EVENT:
779
0
    rc = ospf_apiserver_handle_register_event(apiserv, msg);
780
0
    break;
781
0
  case MSG_SYNC_LSDB:
782
0
    rc = ospf_apiserver_handle_sync_lsdb(apiserv, msg);
783
0
    break;
784
0
  case MSG_ORIGINATE_REQUEST:
785
0
    rc = ospf_apiserver_handle_originate_request(apiserv, msg);
786
0
    break;
787
0
  case MSG_DELETE_REQUEST:
788
0
    rc = ospf_apiserver_handle_delete_request(apiserv, msg);
789
0
    break;
790
0
  case MSG_SYNC_REACHABLE:
791
0
    rc = ospf_apiserver_handle_sync_reachable(apiserv, msg);
792
0
    break;
793
0
  case MSG_SYNC_ISM:
794
0
    rc = ospf_apiserver_handle_sync_ism(apiserv, msg);
795
0
    break;
796
0
  case MSG_SYNC_NSM:
797
0
    rc = ospf_apiserver_handle_sync_nsm(apiserv, msg);
798
0
    break;
799
0
  case MSG_SYNC_ROUTER_ID:
800
0
    rc = ospf_apiserver_handle_sync_router_id(apiserv, msg);
801
0
    break;
802
0
  default:
803
0
    zlog_warn("%s: Unknown message type: %d", __func__,
804
0
        msg->hdr.msgtype);
805
0
    rc = -1;
806
0
  }
807
0
  return rc;
808
0
}
809
810
811
/* -----------------------------------------------------------
812
 * Following are functions for opaque type registration
813
 * -----------------------------------------------------------
814
 */
815
816
int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv,
817
          uint8_t lsa_type, uint8_t opaque_type)
818
0
{
819
0
  struct registered_opaque_type *regtype;
820
0
  int (*originator_func)(void *arg);
821
0
  int rc;
822
823
0
  switch (lsa_type) {
824
0
  case OSPF_OPAQUE_LINK_LSA:
825
0
    originator_func = ospf_apiserver_lsa9_originator;
826
0
    break;
827
0
  case OSPF_OPAQUE_AREA_LSA:
828
0
    originator_func = ospf_apiserver_lsa10_originator;
829
0
    break;
830
0
  case OSPF_OPAQUE_AS_LSA:
831
0
    originator_func = ospf_apiserver_lsa11_originator;
832
0
    break;
833
0
  default:
834
0
    zlog_warn("%s: lsa_type(%d)", __func__, lsa_type);
835
0
    return OSPF_API_ILLEGALLSATYPE;
836
0
  }
837
838
839
  /* Register opaque function table */
840
  /* NB: Duplicated registration will be detected inside the function. */
841
0
  rc = ospf_register_opaque_functab(
842
0
    lsa_type, opaque_type, NULL, /* ospf_apiserver_new_if */
843
0
    NULL,          /* ospf_apiserver_del_if */
844
0
    NULL,          /* ospf_apiserver_ism_change */
845
0
    NULL,          /* ospf_apiserver_nsm_change */
846
0
    NULL, NULL, NULL, ospf_apiserver_show_info, originator_func,
847
0
    ospf_apiserver_lsa_refresher,
848
0
    NULL, /* ospf_apiserver_lsa_update */
849
0
    NULL /* ospf_apiserver_lsa_delete */);
850
851
0
  if (rc != 0) {
852
0
    flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
853
0
        "Failed to register opaque type [%d/%d]", lsa_type,
854
0
        opaque_type);
855
0
    return OSPF_API_OPAQUETYPEINUSE;
856
0
  }
857
858
  /* Remember the opaque type that application registers so when
859
     connection shuts down, we can flush all LSAs of this opaque
860
     type. */
861
862
0
  regtype =
863
0
    XCALLOC(MTYPE_APISERVER, sizeof(struct registered_opaque_type));
864
0
  regtype->lsa_type = lsa_type;
865
0
  regtype->opaque_type = opaque_type;
866
867
  /* Add to list of registered opaque types */
868
0
  listnode_add(apiserv->opaque_types, regtype);
869
870
0
  if (IS_DEBUG_OSPF_EVENT)
871
0
    zlog_debug(
872
0
      "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)",
873
0
      lsa_type, opaque_type, (void *)apiserv,
874
0
      listcount(apiserv->opaque_types));
875
876
0
  return 0;
877
0
}
878
879
int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserv,
880
            uint8_t lsa_type, uint8_t opaque_type)
881
0
{
882
0
  struct listnode *node, *nnode;
883
0
  struct registered_opaque_type *regtype;
884
885
0
  for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
886
    /* Check if we really registered this opaque type */
887
0
    if (regtype->lsa_type == lsa_type
888
0
        && regtype->opaque_type == opaque_type) {
889
890
      /* Yes, we registered this opaque type. Flush
891
         all existing opaque LSAs of this type */
892
893
0
      ospf_apiserver_flush_opaque_lsa(apiserv, lsa_type,
894
0
              opaque_type);
895
0
      ospf_delete_opaque_functab(lsa_type, opaque_type);
896
897
      /* Remove from list of registered opaque types */
898
0
      listnode_delete(apiserv->opaque_types, regtype);
899
900
0
      XFREE(MTYPE_APISERVER, regtype);
901
0
      if (IS_DEBUG_OSPF_EVENT)
902
0
        zlog_debug(
903
0
          "API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)",
904
0
          lsa_type, opaque_type, (void *)apiserv,
905
0
          listcount(apiserv->opaque_types));
906
907
0
      return 0;
908
0
    }
909
0
  }
910
911
  /* Opaque type is not registered */
912
0
  zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type,
913
0
      opaque_type);
914
0
  return OSPF_API_OPAQUETYPENOTREGISTERED;
915
0
}
916
917
918
static int apiserver_is_opaque_type_registered(struct ospf_apiserver *apiserv,
919
                 uint8_t lsa_type,
920
                 uint8_t opaque_type)
921
0
{
922
0
  struct listnode *node, *nnode;
923
0
  struct registered_opaque_type *regtype;
924
925
  /* XXX: how many types are there? if few, why not just a bitmap? */
926
0
  for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) {
927
    /* Check if we really registered this opaque type */
928
0
    if (regtype->lsa_type == lsa_type
929
0
        && regtype->opaque_type == opaque_type) {
930
      /* Yes registered */
931
0
      return 1;
932
0
    }
933
0
  }
934
  /* Not registered */
935
0
  return 0;
936
0
}
937
938
int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver *apiserv,
939
                 struct msg *msg)
940
0
{
941
0
  struct msg_register_opaque_type *rmsg;
942
0
  uint8_t lsa_type;
943
0
  uint8_t opaque_type;
944
0
  int rc = 0;
945
946
  /* Extract parameters from register opaque type message */
947
0
  rmsg = (struct msg_register_opaque_type *)STREAM_DATA(msg->s);
948
949
0
  lsa_type = rmsg->lsatype;
950
0
  opaque_type = rmsg->opaquetype;
951
952
0
  rc = ospf_apiserver_register_opaque_type(apiserv, lsa_type,
953
0
             opaque_type);
954
955
  /* Send a reply back to client including return code */
956
0
  rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
957
0
  if (rc < 0)
958
0
    goto out;
959
960
  /* Now inform application about opaque types that are ready */
961
0
  switch (lsa_type) {
962
0
  case OSPF_OPAQUE_LINK_LSA:
963
0
    ospf_apiserver_notify_ready_type9(apiserv);
964
0
    break;
965
0
  case OSPF_OPAQUE_AREA_LSA:
966
0
    ospf_apiserver_notify_ready_type10(apiserv);
967
0
    break;
968
0
  case OSPF_OPAQUE_AS_LSA:
969
0
    ospf_apiserver_notify_ready_type11(apiserv);
970
0
    break;
971
0
  }
972
0
out:
973
0
  return rc;
974
0
}
975
976
977
/* Notify specific client about all opaque types 9 that are ready. */
978
void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv)
979
0
{
980
0
  struct listnode *node, *nnode;
981
0
  struct listnode *node2, *nnode2;
982
0
  struct ospf *ospf;
983
0
  struct ospf_interface *oi;
984
0
  struct registered_opaque_type *r;
985
986
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
987
988
0
  for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
989
    /* Check if this interface is indeed ready for type 9 */
990
0
    if (!ospf_apiserver_is_ready_type9(oi))
991
0
      continue;
992
993
    /* Check for registered opaque type 9 types */
994
    /* XXX: loop-de-loop - optimise me */
995
0
    for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
996
0
               r)) {
997
0
      struct msg *msg;
998
999
0
      if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
1000
1001
        /* Yes, this opaque type is ready */
1002
0
        msg = new_msg_ready_notify(
1003
0
          0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
1004
0
          oi->address->u.prefix4);
1005
0
        if (!msg) {
1006
0
          zlog_warn("%s: msg_new failed",
1007
0
              __func__);
1008
#ifdef NOTYET
1009
          /* Cannot allocate new message. What
1010
           * should we do? */
1011
          ospf_apiserver_free(apiserv);
1012
#endif
1013
0
          goto out;
1014
0
        }
1015
0
        ospf_apiserver_send_msg(apiserv, msg);
1016
0
        msg_free(msg);
1017
0
      }
1018
0
    }
1019
0
  }
1020
1021
0
out:
1022
0
  return;
1023
0
}
1024
1025
1026
/* Notify specific client about all opaque types 10 that are ready. */
1027
void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv)
1028
0
{
1029
0
  struct listnode *node, *nnode;
1030
0
  struct listnode *node2, *nnode2;
1031
0
  struct ospf *ospf;
1032
0
  struct ospf_area *area;
1033
1034
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1035
1036
0
  for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1037
0
    struct registered_opaque_type *r;
1038
1039
0
    if (!ospf_apiserver_is_ready_type10(area)) {
1040
0
      continue;
1041
0
    }
1042
1043
    /* Check for registered opaque type 10 types */
1044
    /* XXX: loop in loop - optimise me */
1045
0
    for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
1046
0
               r)) {
1047
0
      struct msg *msg;
1048
1049
0
      if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
1050
        /* Yes, this opaque type is ready */
1051
0
        msg = new_msg_ready_notify(
1052
0
          0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
1053
0
          area->area_id);
1054
0
        if (!msg) {
1055
0
          zlog_warn("%s: msg_new failed",
1056
0
              __func__);
1057
#ifdef NOTYET
1058
          /* Cannot allocate new message. What
1059
           * should we do? */
1060
          ospf_apiserver_free(apiserv);
1061
#endif
1062
0
          goto out;
1063
0
        }
1064
0
        ospf_apiserver_send_msg(apiserv, msg);
1065
0
        msg_free(msg);
1066
0
      }
1067
0
    }
1068
0
  }
1069
1070
0
out:
1071
0
  return;
1072
0
}
1073
1074
/* Notify specific client about all opaque types 11 that are ready */
1075
void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv)
1076
0
{
1077
0
  struct listnode *node, *nnode;
1078
0
  struct ospf *ospf;
1079
0
  struct registered_opaque_type *r;
1080
1081
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1082
1083
  /* Can type 11 be originated? */
1084
0
  if (!ospf_apiserver_is_ready_type11(ospf))
1085
0
    goto out;
1086
1087
  /* Check for registered opaque type 11 types */
1088
0
  for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, r)) {
1089
0
    struct msg *msg;
1090
0
    struct in_addr noarea_id = {.s_addr = 0L};
1091
1092
0
    if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
1093
      /* Yes, this opaque type is ready */
1094
0
      msg = new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA,
1095
0
               r->opaque_type, noarea_id);
1096
1097
0
      if (!msg) {
1098
0
        zlog_warn("%s: msg_new failed", __func__);
1099
#ifdef NOTYET
1100
        /* Cannot allocate new message. What should we
1101
         * do? */
1102
        ospf_apiserver_free(apiserv);
1103
#endif
1104
0
        goto out;
1105
0
      }
1106
0
      ospf_apiserver_send_msg(apiserv, msg);
1107
0
      msg_free(msg);
1108
0
    }
1109
0
  }
1110
1111
0
out:
1112
0
  return;
1113
0
}
1114
1115
int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver *apiserv,
1116
             struct msg *msg)
1117
0
{
1118
0
  struct msg_unregister_opaque_type *umsg;
1119
0
  uint8_t ltype;
1120
0
  uint8_t otype;
1121
0
  int rc = 0;
1122
1123
  /* Extract parameters from unregister opaque type message */
1124
0
  umsg = (struct msg_unregister_opaque_type *)STREAM_DATA(msg->s);
1125
1126
0
  ltype = umsg->lsatype;
1127
0
  otype = umsg->opaquetype;
1128
1129
0
  rc = ospf_apiserver_unregister_opaque_type(apiserv, ltype, otype);
1130
1131
  /* Send a reply back to client including return code */
1132
0
  rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1133
1134
0
  return rc;
1135
0
}
1136
1137
1138
/* -----------------------------------------------------------
1139
 * Following are functions for event (filter) registration.
1140
 * -----------------------------------------------------------
1141
 */
1142
int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
1143
           struct msg *msg)
1144
0
{
1145
0
  struct msg_register_event *rmsg;
1146
0
  int rc;
1147
0
  uint32_t seqnum;
1148
0
  size_t size;
1149
1150
0
  rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
1151
1152
  /* Get request sequence number */
1153
0
  seqnum = msg_get_seq(msg);
1154
1155
  /* Free existing filter in apiserv. */
1156
0
  XFREE(MTYPE_APISERVER_MSGFILTER, apiserv->filter);
1157
  /* Alloc new space for filter. */
1158
0
  size = ntohs(msg->hdr.msglen);
1159
0
  if (size < OSPF_MAX_LSA_SIZE) {
1160
1161
0
    apiserv->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER, size);
1162
1163
    /* copy it over. */
1164
0
    memcpy(apiserv->filter, &rmsg->filter, size);
1165
0
    rc = OSPF_API_OK;
1166
0
  } else
1167
0
    rc = OSPF_API_NOMEMORY;
1168
1169
  /* Send a reply back to client with return code */
1170
0
  rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1171
0
  return rc;
1172
0
}
1173
1174
1175
/* -----------------------------------------------------------
1176
 * Following are functions for LSDB synchronization.
1177
 * -----------------------------------------------------------
1178
 */
1179
1180
static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
1181
           int int_arg)
1182
0
{
1183
0
  struct ospf_apiserver *apiserv;
1184
0
  int seqnum;
1185
0
  struct msg *msg;
1186
0
  struct param_t {
1187
0
    struct ospf_apiserver *apiserv;
1188
0
    struct lsa_filter_type *filter;
1189
0
  } * param;
1190
0
  int rc = -1;
1191
1192
  /* Sanity check */
1193
0
  assert(lsa->data);
1194
0
  assert(p_arg);
1195
1196
0
  param = (struct param_t *)p_arg;
1197
0
  apiserv = param->apiserv;
1198
0
  seqnum = (uint32_t)int_arg;
1199
1200
  /* Check origin in filter. */
1201
0
  if ((param->filter->origin == ANY_ORIGIN)
1202
0
      || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) {
1203
1204
    /* Default area for AS-External and Opaque11 LSAs */
1205
0
    struct in_addr area_id = {.s_addr = 0L};
1206
1207
    /* Default interface for non Opaque9 LSAs */
1208
0
    struct in_addr ifaddr = {.s_addr = 0L};
1209
1210
0
    if (lsa->area) {
1211
0
      area_id = lsa->area->area_id;
1212
0
    }
1213
0
    if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
1214
0
      ifaddr = lsa->oi->address->u.prefix4;
1215
0
    }
1216
1217
0
    msg = new_msg_lsa_change_notify(
1218
0
      MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
1219
0
      lsa->flags & OSPF_LSA_SELF, lsa->data);
1220
0
    if (!msg) {
1221
0
      zlog_warn("%s: new_msg_update failed", __func__);
1222
#ifdef NOTYET
1223
      /* Cannot allocate new message. What should we do? */
1224
      /*        ospf_apiserver_free (apiserv);*/ /* Do nothing
1225
                      here XXX
1226
                      */
1227
#endif
1228
0
      goto out;
1229
0
    }
1230
1231
    /* Send LSA */
1232
0
    ospf_apiserver_send_msg(apiserv, msg);
1233
0
    msg_free(msg);
1234
0
  }
1235
0
  rc = 0;
1236
1237
0
out:
1238
0
  return rc;
1239
0
}
1240
1241
int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
1242
            struct msg *msg)
1243
0
{
1244
0
  struct listnode *node, *nnode;
1245
0
  uint32_t seqnum;
1246
0
  int rc = 0;
1247
0
  struct msg_sync_lsdb *smsg;
1248
0
  struct ospf_apiserver_param_t {
1249
0
    struct ospf_apiserver *apiserv;
1250
0
    struct lsa_filter_type *filter;
1251
0
  } param;
1252
0
  uint16_t mask;
1253
0
  struct route_node *rn;
1254
0
  struct ospf_lsa *lsa;
1255
0
  struct ospf *ospf;
1256
0
  struct ospf_area *area;
1257
1258
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1259
1260
  /* Get request sequence number */
1261
0
  seqnum = msg_get_seq(msg);
1262
  /* Set sync msg. */
1263
0
  smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s);
1264
1265
  /* Set parameter struct. */
1266
0
  param.apiserv = apiserv;
1267
0
  param.filter = &smsg->filter;
1268
1269
  /* Remember mask. */
1270
0
  mask = ntohs(smsg->filter.typemask);
1271
1272
  /* Iterate over all areas. */
1273
0
  for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
1274
0
    int i;
1275
0
    uint32_t *area_id = NULL;
1276
1277
    /* Compare area_id with area_ids in sync request. */
1278
0
    if ((i = smsg->filter.num_areas) > 0) {
1279
      /* Let area_id point to the list of area IDs,
1280
       * which is at the end of smsg->filter. */
1281
0
      area_id = (uint32_t *)(&smsg->filter + 1);
1282
0
      while (i) {
1283
0
        if (*area_id == area->area_id.s_addr) {
1284
0
          break;
1285
0
        }
1286
0
        i--;
1287
0
        area_id++;
1288
0
      }
1289
0
    } else {
1290
0
      i = 1;
1291
0
    }
1292
1293
    /* If area was found, then i>0 here. */
1294
0
    if (i) {
1295
      /* Check msg type. */
1296
0
      if (mask & Power2[OSPF_ROUTER_LSA])
1297
0
        LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
1298
0
          apiserver_sync_callback(
1299
0
            lsa, (void *)&param, seqnum);
1300
0
      if (mask & Power2[OSPF_NETWORK_LSA])
1301
0
        LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
1302
0
          apiserver_sync_callback(
1303
0
            lsa, (void *)&param, seqnum);
1304
0
      if (mask & Power2[OSPF_SUMMARY_LSA])
1305
0
        LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
1306
0
          apiserver_sync_callback(
1307
0
            lsa, (void *)&param, seqnum);
1308
0
      if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
1309
0
        LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
1310
0
          apiserver_sync_callback(
1311
0
            lsa, (void *)&param, seqnum);
1312
0
      if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
1313
0
        LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
1314
0
          apiserver_sync_callback(
1315
0
            lsa, (void *)&param, seqnum);
1316
0
      if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
1317
0
        LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
1318
0
          apiserver_sync_callback(
1319
0
            lsa, (void *)&param, seqnum);
1320
0
    }
1321
0
  }
1322
1323
  /* For AS-external LSAs */
1324
0
  if (ospf->lsdb) {
1325
0
    if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
1326
0
      LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
1327
0
        apiserver_sync_callback(lsa, (void *)&param,
1328
0
              seqnum);
1329
0
  }
1330
1331
  /* For AS-external opaque LSAs */
1332
0
  if (ospf->lsdb) {
1333
0
    if (mask & Power2[OSPF_OPAQUE_AS_LSA])
1334
0
      LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
1335
0
        apiserver_sync_callback(lsa, (void *)&param,
1336
0
              seqnum);
1337
0
  }
1338
1339
  /* Send a reply back to client with return code */
1340
0
  rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1341
0
  return rc;
1342
0
}
1343
1344
/*
1345
 * -----------------------------------------------------------
1346
 * Followings are functions for synchronization.
1347
 * -----------------------------------------------------------
1348
 */
1349
1350
int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver *apiserv,
1351
           struct msg *msg)
1352
0
{
1353
0
  struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1354
0
  struct route_table *rt = ospf->all_rtrs;
1355
0
  uint32_t seqnum = msg_get_seq(msg);
1356
0
  struct in_addr *a, *abuf;
1357
0
  struct msg_reachable_change *areach;
1358
0
  struct msg *amsg;
1359
0
  uint mcount, count;
1360
0
  int _rc, rc = 0;
1361
1362
0
  if (!rt)
1363
0
    goto out;
1364
1365
  /* send all adds based on current reachable routers */
1366
0
  a = abuf = XCALLOC(MTYPE_APISERVER, sizeof(struct in_addr) * rt->count);
1367
0
  for (struct route_node *rn = route_top(rt); rn; rn = route_next(rn))
1368
0
    if (listhead((struct list *)rn->info))
1369
0
      *a++ = rn->p.u.prefix4;
1370
1371
0
  assert((a - abuf) <= (long)rt->count);
1372
0
  count = (a - abuf);
1373
1374
0
  a = abuf;
1375
0
  while (count && !rc) {
1376
0
    amsg = new_msg_reachable_change(seqnum, count, a, 0, NULL);
1377
0
    areach = (struct msg_reachable_change *)STREAM_DATA(amsg->s);
1378
0
    mcount = ntohs(areach->nadd) + ntohs(areach->nremove);
1379
0
    assert(mcount <= count);
1380
0
    a = a + mcount;
1381
0
    count -= mcount;
1382
0
    rc = ospf_apiserver_send_msg(apiserv, amsg);
1383
0
    msg_free(amsg);
1384
0
  }
1385
0
  XFREE(MTYPE_APISERVER, abuf);
1386
1387
0
out:
1388
  /* Send a reply back to client with return code */
1389
0
  _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1390
0
  rc = rc ? rc : _rc;
1391
0
  apiserv->reachable_sync = !rc;
1392
0
  return rc;
1393
0
}
1394
1395
int ospf_apiserver_handle_sync_ism(struct ospf_apiserver *apiserv,
1396
           struct msg *msg)
1397
0
{
1398
0
  struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1399
0
  struct listnode *anode, *inode;
1400
0
  struct ospf_area *area;
1401
0
  struct ospf_interface *oi;
1402
0
  struct msg *m;
1403
0
  uint32_t seqnum = msg_get_seq(msg);
1404
0
  int _rc, rc = 0;
1405
1406
  /* walk all areas */
1407
0
  for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
1408
    /* walk all interfaces */
1409
0
    for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) {
1410
0
      m = new_msg_ism_change(seqnum, oi->address->u.prefix4,
1411
0
                 area->area_id, oi->state);
1412
0
      rc = ospf_apiserver_send_msg(apiserv, m);
1413
0
      msg_free(m);
1414
0
      if (rc)
1415
0
        break;
1416
0
    }
1417
0
    if (rc)
1418
0
      break;
1419
0
  }
1420
  /* Send a reply back to client with return code */
1421
0
  _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1422
0
  return rc ? rc : _rc;
1423
0
}
1424
1425
1426
int ospf_apiserver_handle_sync_nsm(struct ospf_apiserver *apiserv,
1427
           struct msg *msg)
1428
0
{
1429
0
  struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1430
0
  struct listnode *anode, *inode;
1431
0
  struct ospf_area *area;
1432
0
  struct ospf_interface *oi;
1433
0
  struct ospf_neighbor *nbr;
1434
0
  struct route_node *rn;
1435
0
  struct msg *m;
1436
0
  uint32_t seqnum = msg_get_seq(msg);
1437
0
  int _rc, rc = 0;
1438
1439
  /* walk all areas */
1440
0
  for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
1441
    /* walk all interfaces */
1442
0
    for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) {
1443
      /* walk all neighbors */
1444
0
      for (rn = route_top(oi->nbrs); rn;
1445
0
           rn = route_next(rn)) {
1446
0
        nbr = rn->info;
1447
0
        if (!nbr)
1448
0
          continue;
1449
0
        m = new_msg_nsm_change(
1450
0
          seqnum, oi->address->u.prefix4,
1451
0
          nbr->src, nbr->router_id, nbr->state);
1452
0
        rc = ospf_apiserver_send_msg(apiserv, m);
1453
0
        msg_free(m);
1454
0
        if (rc)
1455
0
          break;
1456
0
      }
1457
0
      if (rc)
1458
0
        break;
1459
0
    }
1460
0
    if (rc)
1461
0
      break;
1462
0
  }
1463
  /* Send a reply back to client with return code */
1464
0
  _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1465
0
  return rc ? rc : _rc;
1466
0
}
1467
1468
1469
int ospf_apiserver_handle_sync_router_id(struct ospf_apiserver *apiserv,
1470
           struct msg *msg)
1471
0
{
1472
0
  struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1473
0
  uint32_t seqnum = msg_get_seq(msg);
1474
0
  struct msg *m;
1475
0
  int _rc, rc = 0;
1476
1477
0
  m = new_msg_router_id_change(seqnum, ospf->router_id);
1478
0
  rc = ospf_apiserver_send_msg(apiserv, m);
1479
0
  msg_free(m);
1480
1481
  /* Send a reply back to client with return code */
1482
0
  _rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
1483
0
  return rc ? rc : _rc;
1484
0
}
1485
1486
/* -----------------------------------------------------------
1487
 * Following are functions to originate or update LSA
1488
 * from an application.
1489
 * -----------------------------------------------------------
1490
 */
1491
1492
/* Create a new internal opaque LSA by taking prototype and filling in
1493
   missing fields such as age, sequence number, advertising router,
1494
   checksum and so on. The interface parameter is used for type 9
1495
   LSAs, area parameter for type 10. Type 11 LSAs do neither need area
1496
   nor interface. */
1497
1498
struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
1499
                 struct ospf_interface *oi,
1500
                 struct lsa_header *protolsa)
1501
0
{
1502
0
  struct stream *s;
1503
0
  struct lsa_header *newlsa;
1504
0
  struct ospf_lsa *new = NULL;
1505
0
  uint8_t options = 0x0;
1506
0
  uint16_t length;
1507
1508
0
  struct ospf *ospf;
1509
1510
0
  if (oi && oi->ospf)
1511
0
    ospf = oi->ospf;
1512
0
  else
1513
0
    ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1514
1515
0
  assert(ospf);
1516
1517
  /* Create a stream for internal opaque LSA */
1518
0
  if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
1519
0
    zlog_warn("%s: stream_new failed", __func__);
1520
0
    return NULL;
1521
0
  }
1522
1523
0
  newlsa = (struct lsa_header *)STREAM_DATA(s);
1524
1525
  /* XXX If this is a link-local LSA or an AS-external LSA, how do we
1526
     have to set options? */
1527
1528
0
  if (area) {
1529
0
    options = LSA_OPTIONS_GET(area);
1530
0
    options |= LSA_OPTIONS_NSSA_GET(area);
1531
0
  }
1532
1533
0
  options |= OSPF_OPTION_O; /* Don't forget to set option bit */
1534
1535
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1536
0
    zlog_debug("LSA[Type%d:%pI4]: Creating an Opaque-LSA instance",
1537
0
         protolsa->type, &protolsa->id);
1538
0
  }
1539
1540
  /* Set opaque-LSA header fields. */
1541
0
  lsa_header_set(s, options, protolsa->type, protolsa->id,
1542
0
           ospf->router_id);
1543
1544
  /* Set opaque-LSA body fields. */
1545
0
  stream_put(s, ((uint8_t *)protolsa) + sizeof(struct lsa_header),
1546
0
       ntohs(protolsa->length) - sizeof(struct lsa_header));
1547
1548
  /* Determine length of LSA. */
1549
0
  length = stream_get_endp(s);
1550
0
  newlsa->length = htons(length);
1551
1552
  /* Create OSPF LSA. */
1553
0
  new = ospf_lsa_new_and_data(length);
1554
1555
0
  new->area = area;
1556
0
  new->oi = oi;
1557
0
  new->vrf_id = ospf->vrf_id;
1558
1559
0
  SET_FLAG(new->flags, OSPF_LSA_SELF);
1560
0
  memcpy(new->data, newlsa, length);
1561
0
  stream_free(s);
1562
1563
0
  return new;
1564
0
}
1565
1566
1567
int ospf_apiserver_is_ready_type9(struct ospf_interface *oi)
1568
0
{
1569
  /* We can always handle getting opaque's even if we can't flood them */
1570
0
  return 1;
1571
0
}
1572
1573
int ospf_apiserver_is_ready_type10(struct ospf_area *area)
1574
0
{
1575
  /* We can always handle getting opaque's even if we can't flood them */
1576
0
  return 1;
1577
0
}
1578
1579
int ospf_apiserver_is_ready_type11(struct ospf *ospf)
1580
0
{
1581
  /* We can always handle getting opaque's even if we can't flood them */
1582
0
  return 1;
1583
0
}
1584
1585
1586
int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
1587
              struct msg *msg)
1588
0
{
1589
0
  struct msg_originate_request *omsg;
1590
0
  struct lsa_header *data;
1591
0
  struct ospf_lsa *new;
1592
0
  struct ospf_lsa *old;
1593
0
  struct ospf_area *area = NULL;
1594
0
  struct ospf_interface *oi = NULL;
1595
0
  struct ospf_lsdb *lsdb = NULL;
1596
0
  struct ospf *ospf;
1597
0
  int lsa_type, opaque_type;
1598
0
  int ready = 0;
1599
0
  int rc = 0;
1600
1601
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1602
1603
  /* Extract opaque LSA data from message */
1604
0
  omsg = (struct msg_originate_request *)STREAM_DATA(msg->s);
1605
0
  data = &omsg->data;
1606
1607
  /* Determine interface for type9 or area for type10 LSAs. */
1608
0
  switch (data->type) {
1609
0
  case OSPF_OPAQUE_LINK_LSA:
1610
0
    oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr);
1611
0
    if (!oi) {
1612
0
      zlog_warn("%s: unknown interface %pI4", __func__,
1613
0
          &omsg->ifaddr);
1614
0
      rc = OSPF_API_NOSUCHINTERFACE;
1615
0
      goto out;
1616
0
    }
1617
0
    area = oi->area;
1618
0
    lsdb = area->lsdb;
1619
0
    break;
1620
0
  case OSPF_OPAQUE_AREA_LSA:
1621
0
    area = ospf_area_lookup_by_area_id(ospf, omsg->area_id);
1622
0
    if (!area) {
1623
0
      zlog_warn("%s: unknown area %pI4", __func__,
1624
0
          &omsg->area_id);
1625
0
      rc = OSPF_API_NOSUCHAREA;
1626
0
      goto out;
1627
0
    }
1628
0
    lsdb = area->lsdb;
1629
0
    break;
1630
0
  case OSPF_OPAQUE_AS_LSA:
1631
0
    lsdb = ospf->lsdb;
1632
0
    break;
1633
0
  default:
1634
    /* We can only handle opaque types here */
1635
0
    zlog_warn("%s: Cannot originate non-opaque LSA type %d",
1636
0
        __func__, data->type);
1637
0
    rc = OSPF_API_ILLEGALLSATYPE;
1638
0
    goto out;
1639
0
  }
1640
1641
  /* Check if we registered this opaque type */
1642
0
  lsa_type = data->type;
1643
0
  opaque_type = GET_OPAQUE_TYPE(ntohl(data->id.s_addr));
1644
1645
0
  if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1646
0
             opaque_type)) {
1647
0
    zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1648
0
        __func__, lsa_type, opaque_type);
1649
0
    rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1650
0
    goto out;
1651
0
  }
1652
1653
  /* Make sure that the neighbors are ready before we can originate */
1654
0
  switch (data->type) {
1655
0
  case OSPF_OPAQUE_LINK_LSA:
1656
0
    ready = ospf_apiserver_is_ready_type9(oi);
1657
0
    break;
1658
0
  case OSPF_OPAQUE_AREA_LSA:
1659
0
    ready = ospf_apiserver_is_ready_type10(area);
1660
0
    break;
1661
0
  case OSPF_OPAQUE_AS_LSA:
1662
0
    ready = ospf_apiserver_is_ready_type11(ospf);
1663
0
    break;
1664
0
  default:
1665
0
    break;
1666
0
  }
1667
1668
0
  if (!ready) {
1669
0
    zlog_warn("Neighbors not ready to originate type %d",
1670
0
        data->type);
1671
0
    rc = OSPF_API_NOTREADY;
1672
0
    goto out;
1673
0
  }
1674
1675
  /* Create OSPF's internal opaque LSA representation */
1676
0
  new = ospf_apiserver_opaque_lsa_new(area, oi, data);
1677
0
  if (!new) {
1678
0
    rc = OSPF_API_NOMEMORY; /* XXX */
1679
0
    goto out;
1680
0
  }
1681
1682
  /* Determine if LSA is new or an update for an existing one. */
1683
0
  old = ospf_lsdb_lookup(lsdb, new);
1684
1685
0
  if (!old || !ospf_opaque_is_owned(old)) {
1686
    /* New LSA install in LSDB. */
1687
0
    rc = ospf_apiserver_originate1(new, old);
1688
0
  } else {
1689
    /*
1690
     * Keep the new LSA instance in the "waiting place" until the
1691
     * next
1692
     * refresh timing. If several LSA update requests for the same
1693
     * LSID
1694
     * have issued by peer, the last one takes effect.
1695
     */
1696
0
    new->lsdb = &apiserv->reserve;
1697
0
    ospf_lsdb_add(&apiserv->reserve, new);
1698
1699
    /* Kick the scheduler function. */
1700
0
    ospf_opaque_lsa_refresh_schedule(old);
1701
0
  }
1702
1703
0
out:
1704
1705
  /* Send a reply back to client with return code */
1706
0
  rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
1707
0
  return rc;
1708
0
}
1709
1710
1711
/* -----------------------------------------------------------
1712
 * Flood an LSA within its flooding scope.
1713
 * -----------------------------------------------------------
1714
 */
1715
1716
/* XXX We can probably use ospf_flood_through instead of this function
1717
   but then we need the neighbor parameter. If we set nbr to
1718
   NULL then ospf_flood_through crashes due to dereferencing NULL. */
1719
1720
void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
1721
0
{
1722
0
  assert(lsa);
1723
1724
0
  switch (lsa->data->type) {
1725
0
  case OSPF_OPAQUE_LINK_LSA:
1726
    /* Increment counters? XXX */
1727
1728
    /* Flood LSA through local network. */
1729
0
    ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1730
0
    break;
1731
0
  case OSPF_OPAQUE_AREA_LSA:
1732
    /* Update LSA origination count. */
1733
0
    assert(lsa->area);
1734
0
    lsa->area->ospf->lsa_originate_count++;
1735
1736
    /* Flood LSA through area. */
1737
0
    ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa);
1738
0
    break;
1739
0
  case OSPF_OPAQUE_AS_LSA: {
1740
0
    struct ospf *ospf;
1741
1742
0
    ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1743
0
    assert(ospf);
1744
1745
    /* Increment counters? XXX */
1746
1747
    /* Flood LSA through AS. */
1748
0
    ospf_flood_through_as(ospf, NULL /*nbr */, lsa);
1749
0
    break;
1750
0
  }
1751
0
  }
1752
0
}
1753
1754
int ospf_apiserver_originate1(struct ospf_lsa *lsa, struct ospf_lsa *old)
1755
0
{
1756
0
  struct ospf *ospf;
1757
1758
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1759
0
  assert(ospf);
1760
1761
0
  if (old) {
1762
    /*
1763
     * An old LSA exists that we didn't originate it in this
1764
     * session. Dump it, but increment past it's seqnum.
1765
     */
1766
0
    assert(!ospf_opaque_is_owned(old));
1767
0
    if (IS_DEBUG_OSPF_CLIENT_API)
1768
0
      zlog_debug(
1769
0
        "LSA[Type%d:%pI4]: OSPF API Server Originate LSA Old Seq: 0x%x Age: %d",
1770
0
        old->data->type, &old->data->id,
1771
0
        ntohl(old->data->ls_seqnum),
1772
0
        ntohl(old->data->ls_age));
1773
0
    if (IS_LSA_MAX_SEQ(old)) {
1774
0
      flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1775
0
          "%s: old LSA at maxseq", __func__);
1776
0
      return -1;
1777
0
    }
1778
0
    lsa->data->ls_seqnum = lsa_seqnum_increment(old);
1779
0
    ospf_discard_from_db(ospf, old->lsdb, old);
1780
0
  }
1781
0
  if (IS_DEBUG_OSPF_CLIENT_API)
1782
0
    zlog_debug(
1783
0
      "LSA[Type%d:%pI4]: OSPF API Server Originate LSA New Seq: 0x%x Age: %d",
1784
0
      lsa->data->type, &lsa->data->id,
1785
0
      ntohl(lsa->data->ls_seqnum), ntohl(lsa->data->ls_age));
1786
1787
  /* Install this LSA into LSDB. */
1788
0
  if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
1789
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1790
0
        "%s: ospf_lsa_install failed", __func__);
1791
0
    return -1;
1792
0
  }
1793
1794
/* Flood LSA within scope */
1795
1796
#ifdef NOTYET
1797
  /*
1798
   * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr"
1799
   *     parameter, and thus it does not cause SIGSEGV error.
1800
   */
1801
  ospf_flood_through(NULL /*nbr */, lsa);
1802
#else  /* NOTYET */
1803
1804
0
  ospf_apiserver_flood_opaque_lsa(lsa);
1805
0
#endif /* NOTYET */
1806
1807
0
  return 0;
1808
0
}
1809
1810
1811
/* Opaque LSAs of type 9 on a specific interface can now be
1812
   originated. Tell clients that registered type 9. */
1813
int ospf_apiserver_lsa9_originator(void *arg)
1814
0
{
1815
0
  struct ospf_interface *oi;
1816
1817
0
  oi = (struct ospf_interface *)arg;
1818
0
  if (listcount(apiserver_list) > 0) {
1819
0
    ospf_apiserver_clients_notify_ready_type9(oi);
1820
0
  }
1821
0
  return 0;
1822
0
}
1823
1824
int ospf_apiserver_lsa10_originator(void *arg)
1825
0
{
1826
0
  struct ospf_area *area;
1827
1828
0
  area = (struct ospf_area *)arg;
1829
0
  if (listcount(apiserver_list) > 0) {
1830
0
    ospf_apiserver_clients_notify_ready_type10(area);
1831
0
  }
1832
0
  return 0;
1833
0
}
1834
1835
int ospf_apiserver_lsa11_originator(void *arg)
1836
0
{
1837
0
  struct ospf *ospf;
1838
1839
0
  ospf = (struct ospf *)arg;
1840
0
  if (listcount(apiserver_list) > 0) {
1841
0
    ospf_apiserver_clients_notify_ready_type11(ospf);
1842
0
  }
1843
0
  return 0;
1844
0
}
1845
1846
1847
/* Periodically refresh opaque LSAs so that they do not expire in
1848
   other routers. */
1849
struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
1850
0
{
1851
0
  struct ospf_apiserver *apiserv;
1852
0
  struct ospf_lsa *new = NULL;
1853
0
  struct ospf *ospf;
1854
1855
0
  assert(lsa);
1856
1857
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1858
0
  assert(ospf);
1859
1860
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1861
0
    zlog_debug("LSA[Type%d:%pI4]: OSPF API Server LSA Refresher",
1862
0
         lsa->data->type, &lsa->data->id);
1863
0
  }
1864
1865
0
  apiserv = lookup_apiserver_by_lsa(lsa);
1866
0
  if (!apiserv) {
1867
0
    zlog_warn("%s: LSA[%s]: No apiserver?", __func__,
1868
0
        dump_lsa_key(lsa));
1869
0
    lsa->data->ls_age =
1870
0
      htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1871
0
    goto out;
1872
0
  }
1873
1874
  /* Check if updated version of LSA instance has already prepared. */
1875
0
  new = ospf_lsdb_lookup(&apiserv->reserve, lsa);
1876
0
  if (!new) {
1877
0
    if (IS_LSA_MAXAGE(lsa)) {
1878
0
      ospf_opaque_lsa_flush_schedule(lsa);
1879
0
      goto out;
1880
0
    }
1881
1882
    /* This is a periodic refresh, driven by core OSPF mechanism. */
1883
0
    new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
1884
0
                lsa->data);
1885
0
    if (!new) {
1886
0
      zlog_warn("%s: Cannot create a new LSA?", __func__);
1887
0
      goto out;
1888
0
    }
1889
0
  } else {
1890
    /* This is a forcible refresh, requested by OSPF-API client. */
1891
0
    ospf_lsdb_delete(&apiserv->reserve, new);
1892
0
    new->lsdb = NULL;
1893
0
  }
1894
1895
  /* Increment sequence number */
1896
0
  new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1897
1898
  /* New LSA is in same area. */
1899
0
  new->area = lsa->area;
1900
0
  SET_FLAG(new->flags, OSPF_LSA_SELF);
1901
1902
  /* Install LSA into LSDB. */
1903
0
  if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
1904
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1905
0
        "%s: ospf_lsa_install failed", __func__);
1906
0
    ospf_lsa_unlock(&new);
1907
0
    goto out;
1908
0
  }
1909
1910
/* Flood updated LSA through interface, area or AS */
1911
1912
#ifdef NOTYET
1913
  ospf_flood_through(NULL /*nbr */, new);
1914
#endif /* NOTYET */
1915
0
  ospf_apiserver_flood_opaque_lsa(new);
1916
1917
  /* Debug logging. */
1918
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1919
0
    zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque LSA",
1920
0
         new->data->type, &new->data->id);
1921
0
    ospf_lsa_header_dump(new->data);
1922
0
  }
1923
1924
0
out:
1925
0
  return new;
1926
0
}
1927
1928
1929
/* -----------------------------------------------------------
1930
 * Following are functions to delete LSAs
1931
 * -----------------------------------------------------------
1932
 */
1933
1934
int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
1935
           struct msg *msg)
1936
0
{
1937
0
  struct msg_delete_request *dmsg;
1938
0
  struct ospf_lsa *old;
1939
0
  struct ospf_area *area = NULL;
1940
0
  struct ospf_interface *oi = NULL;
1941
0
  struct in_addr id;
1942
0
  int lsa_type, opaque_type;
1943
0
  int rc = 0;
1944
0
  struct ospf *ospf;
1945
1946
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1947
0
  assert(ospf);
1948
1949
  /* Extract opaque LSA from message */
1950
0
  dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s);
1951
1952
  /* Lookup area for link-local and area-local opaque LSAs */
1953
0
  switch (dmsg->lsa_type) {
1954
0
  case OSPF_OPAQUE_LINK_LSA:
1955
0
    oi = ospf_apiserver_if_lookup_by_addr(dmsg->addr);
1956
0
    if (!oi) {
1957
0
      zlog_warn("%s: unknown interface %pI4", __func__,
1958
0
          &dmsg->addr);
1959
0
      rc = OSPF_API_NOSUCHINTERFACE;
1960
0
      goto out;
1961
0
    }
1962
0
    area = oi->area;
1963
0
    break;
1964
0
  case OSPF_OPAQUE_AREA_LSA:
1965
0
    area = ospf_area_lookup_by_area_id(ospf, dmsg->addr);
1966
0
    if (!area) {
1967
0
      zlog_warn("%s: unknown area %pI4", __func__,
1968
0
          &dmsg->addr);
1969
0
      rc = OSPF_API_NOSUCHAREA;
1970
0
      goto out;
1971
0
    }
1972
0
    break;
1973
0
  case OSPF_OPAQUE_AS_LSA:
1974
    /* AS-external opaque LSAs have no designated area */
1975
0
    area = NULL;
1976
0
    break;
1977
0
  default:
1978
0
    zlog_warn("%s: Cannot delete non-opaque LSA type %d", __func__,
1979
0
        dmsg->lsa_type);
1980
0
    rc = OSPF_API_ILLEGALLSATYPE;
1981
0
    goto out;
1982
0
  }
1983
1984
  /* Check if we registered this opaque type */
1985
0
  lsa_type = dmsg->lsa_type;
1986
0
  opaque_type = dmsg->opaque_type;
1987
1988
0
  if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
1989
0
             opaque_type)) {
1990
0
    zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
1991
0
        __func__, lsa_type, opaque_type);
1992
0
    rc = OSPF_API_OPAQUETYPENOTREGISTERED;
1993
0
    goto out;
1994
0
  }
1995
1996
  /* opaque_id is in network byte order */
1997
0
  id.s_addr = htonl(
1998
0
    SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id)));
1999
2000
  /*
2001
   * Even if the target LSA has once scheduled to flush, it remains in
2002
   * the LSDB until it is finally handled by the maxage remover thread.
2003
   * Therefore, the lookup function below may return non-NULL result.
2004
   */
2005
0
  old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
2006
0
  if (!old) {
2007
0
    zlog_warn("%s: LSA[Type%d:%pI4] not in LSDB", __func__,
2008
0
        dmsg->lsa_type, &id);
2009
0
    rc = OSPF_API_NOSUCHLSA;
2010
0
    goto out;
2011
0
  }
2012
2013
0
  if (IS_DEL_ZERO_LEN_LSA(dmsg)) {
2014
    /* minimize the size of the withdrawal: */
2015
0
    old->opaque_zero_len_delete = 1;
2016
0
  }
2017
2018
  /* Schedule flushing of LSA from LSDB */
2019
  /* NB: Multiple scheduling will produce a warning message, but harmless.
2020
   */
2021
0
  ospf_opaque_lsa_flush_schedule(old);
2022
2023
0
out:
2024
2025
  /* Send reply back to client including return code */
2026
0
  rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc);
2027
0
  return rc;
2028
0
}
2029
2030
/* Flush self-originated opaque LSA */
2031
static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa,
2032
            void *p_arg, int int_arg)
2033
0
{
2034
0
  struct param_t {
2035
0
    struct ospf_apiserver *apiserv;
2036
0
    uint8_t lsa_type;
2037
0
    uint8_t opaque_type;
2038
0
  } * param;
2039
2040
  /* Sanity check */
2041
0
  assert(lsa->data);
2042
0
  assert(p_arg);
2043
0
  param = (struct param_t *)p_arg;
2044
2045
  /* If LSA matches type and opaque type then delete it */
2046
0
  if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type
2047
0
      && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
2048
0
           == param->opaque_type) {
2049
0
    ospf_opaque_lsa_flush_schedule(lsa);
2050
0
  }
2051
0
  return 0;
2052
0
}
2053
2054
/* Delete self-originated opaque LSAs of a given opaque type. This
2055
   function is called when an application unregisters a given opaque
2056
   type or a connection to an application closes and all those opaque
2057
   LSAs need to be flushed the LSDB. */
2058
void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
2059
             uint8_t lsa_type, uint8_t opaque_type)
2060
0
{
2061
0
  struct param_t {
2062
0
    struct ospf_apiserver *apiserv;
2063
0
    uint8_t lsa_type;
2064
0
    uint8_t opaque_type;
2065
0
  } param;
2066
0
  struct listnode *node, *nnode;
2067
0
  struct ospf *ospf;
2068
0
  struct ospf_area *area;
2069
2070
0
  ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2071
0
  assert(ospf);
2072
2073
  /* Set parameter struct. */
2074
0
  param.apiserv = apiserv;
2075
0
  param.lsa_type = lsa_type;
2076
0
  param.opaque_type = opaque_type;
2077
2078
0
  switch (lsa_type) {
2079
0
    struct route_node *rn;
2080
0
    struct ospf_lsa *lsa;
2081
2082
0
  case OSPF_OPAQUE_LINK_LSA:
2083
0
    for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
2084
0
      LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
2085
0
        apiserver_flush_opaque_type_callback(
2086
0
          lsa, (void *)&param, 0);
2087
0
    break;
2088
0
  case OSPF_OPAQUE_AREA_LSA:
2089
0
    for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
2090
0
      LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
2091
0
        apiserver_flush_opaque_type_callback(
2092
0
          lsa, (void *)&param, 0);
2093
0
    break;
2094
0
  case OSPF_OPAQUE_AS_LSA:
2095
0
    LSDB_LOOP (OPAQUE_LINK_LSDB(ospf), rn, lsa)
2096
0
      apiserver_flush_opaque_type_callback(lsa,
2097
0
                   (void *)&param, 0);
2098
0
    break;
2099
0
  default:
2100
0
    break;
2101
0
  }
2102
0
  return;
2103
0
}
2104
2105
2106
/* -----------------------------------------------------------
2107
 * Following are callback functions to handle opaque types
2108
 * -----------------------------------------------------------
2109
 */
2110
2111
int ospf_apiserver_new_if(struct interface *ifp)
2112
0
{
2113
0
  struct ospf_interface *oi;
2114
2115
  /* For some strange reason it seems possible that we are invoked
2116
     with an interface that has no name. This seems to happen during
2117
     initialization. Return if this happens */
2118
2119
0
  if (ifp->name[0] == '\0') {
2120
    /* interface has empty name */
2121
0
    zlog_warn("%s: interface has no name?", __func__);
2122
0
    return 0;
2123
0
  }
2124
2125
  /* zlog_warn for debugging */
2126
0
  zlog_warn("ospf_apiserver_new_if");
2127
0
  zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
2128
0
      ifp->ifindex);
2129
2130
0
  if (ifp->name[0] == '\0') {
2131
    /* interface has empty name */
2132
0
    zlog_warn("%s: interface has no name?", __func__);
2133
0
    return 0;
2134
0
  }
2135
2136
0
  oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2137
2138
0
  if (!oi) {
2139
    /* This interface is known to Zebra but not to OSPF daemon yet.
2140
     */
2141
0
    zlog_warn("%s: interface %s not known to OSPFd?", __func__,
2142
0
        ifp->name);
2143
0
    return 0;
2144
0
  }
2145
2146
0
  assert(oi);
2147
2148
  /* New interface added to OSPF, tell clients about it */
2149
0
  if (listcount(apiserver_list) > 0) {
2150
0
    ospf_apiserver_clients_notify_new_if(oi);
2151
0
  }
2152
0
  return 0;
2153
0
}
2154
2155
int ospf_apiserver_del_if(struct interface *ifp)
2156
0
{
2157
0
  struct ospf_interface *oi;
2158
2159
  /* zlog_warn for debugging */
2160
0
  zlog_warn("%s ifp name=%s status=%d index=%d", __func__, ifp->name,
2161
0
      ifp->status, ifp->ifindex);
2162
2163
0
  oi = ospf_apiserver_if_lookup_by_ifp(ifp);
2164
2165
0
  if (!oi) {
2166
    /* This interface is known to Zebra but not to OSPF daemon
2167
       anymore. No need to tell clients about it */
2168
0
    zlog_warn("ifp name=%s not known to OSPFd", ifp->name);
2169
0
    return 0;
2170
0
  }
2171
2172
  /* Interface deleted, tell clients about it */
2173
0
  if (listcount(apiserver_list) > 0) {
2174
0
    ospf_apiserver_clients_notify_del_if(oi);
2175
0
  }
2176
0
  return 0;
2177
0
}
2178
2179
void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
2180
0
{
2181
  /* Tell clients about interface change */
2182
2183
  /* zlog_warn for debugging */
2184
0
  zlog_warn("%s", __func__);
2185
0
  if (listcount(apiserver_list) > 0) {
2186
0
    ospf_apiserver_clients_notify_ism_change(oi);
2187
0
  }
2188
2189
0
  zlog_warn("%s oi->ifp->name=%s old_state=%d oi->state=%d", __func__,
2190
0
      oi->ifp->name, old_state, oi->state);
2191
0
}
2192
2193
void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
2194
0
{
2195
  /* Neighbor status changed, tell clients about it */
2196
0
  zlog_warn("%s", __func__);
2197
0
  if (listcount(apiserver_list) > 0) {
2198
0
    ospf_apiserver_clients_notify_nsm_change(nbr);
2199
0
  }
2200
0
}
2201
2202
void ospf_apiserver_show_info(struct vty *vty, struct json_object *json,
2203
            struct ospf_lsa *lsa)
2204
0
{
2205
0
  struct opaque_lsa {
2206
0
    struct lsa_header header;
2207
0
    uint8_t data[1]; /* opaque data have variable length. This is
2208
           start
2209
           address */
2210
0
  };
2211
0
  struct opaque_lsa *olsa;
2212
0
  int opaquelen;
2213
2214
0
  olsa = (struct opaque_lsa *)lsa->data;
2215
2216
0
  if (VALID_OPAQUE_INFO_LEN(lsa->data))
2217
0
    opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE;
2218
0
  else
2219
0
    opaquelen = 0;
2220
2221
  /* Output information about opaque LSAs */
2222
0
  if (json)
2223
0
    json_object_string_addf(json, "opaqueData", "%*pHXn",
2224
0
          (int)opaquelen, olsa->data);
2225
0
  else if (vty != NULL) {
2226
0
    int i;
2227
0
    vty_out(vty,
2228
0
      "  Added using OSPF API: %u octets of opaque data %s\n",
2229
0
      opaquelen,
2230
0
      VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2231
0
               : "(Invalid length?)");
2232
0
    vty_out(vty, "  Opaque data: ");
2233
2234
0
    for (i = 0; i < opaquelen; i++) {
2235
0
      vty_out(vty, "0x%x ", olsa->data[i]);
2236
0
    }
2237
0
    vty_out(vty, "\n");
2238
0
  } else {
2239
0
    int i;
2240
0
    zlog_debug(
2241
0
      "    Added using OSPF API: %u octets of opaque data %s",
2242
0
      opaquelen,
2243
0
      VALID_OPAQUE_INFO_LEN(lsa->data) ? ""
2244
0
               : "(Invalid length?)");
2245
0
    zlog_debug("    Opaque data: ");
2246
2247
0
    for (i = 0; i < opaquelen; i++) {
2248
0
      zlog_debug("0x%x ", olsa->data[i]);
2249
0
    }
2250
0
  }
2251
0
  return;
2252
0
}
2253
2254
/* -----------------------------------------------------------
2255
 * Following are functions to notify clients about events
2256
 * -----------------------------------------------------------
2257
 */
2258
2259
/* Send a message to all clients. This is useful for messages
2260
   that need to be notified to all clients (such as interface
2261
   changes) */
2262
2263
void ospf_apiserver_clients_notify_all(struct msg *msg)
2264
0
{
2265
0
  struct listnode *node, *nnode;
2266
0
  struct ospf_apiserver *apiserv;
2267
2268
  /* Send message to all clients */
2269
0
  for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv))
2270
0
    ospf_apiserver_send_msg(apiserv, msg);
2271
0
}
2272
2273
/* An interface is now ready to accept opaque LSAs. Notify all
2274
   clients that registered to use this opaque type */
2275
void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
2276
0
{
2277
0
  struct listnode *node, *nnode;
2278
0
  struct msg *msg;
2279
0
  struct ospf_apiserver *apiserv;
2280
2281
0
  assert(oi);
2282
0
  if (!oi->address) {
2283
0
    zlog_warn("Interface has no address?");
2284
0
    return;
2285
0
  }
2286
2287
0
  if (!ospf_apiserver_is_ready_type9(oi)) {
2288
0
    zlog_warn("Interface not ready for type 9?");
2289
0
    return;
2290
0
  }
2291
2292
0
  for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2293
0
    struct listnode *node2, *nnode2;
2294
0
    struct registered_opaque_type *r;
2295
2296
0
    for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2297
0
               r)) {
2298
0
      if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) {
2299
0
        msg = new_msg_ready_notify(
2300
0
          0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
2301
0
          oi->address->u.prefix4);
2302
0
        if (!msg) {
2303
0
          zlog_warn(
2304
0
            "%s: new_msg_ready_notify failed",
2305
0
            __func__);
2306
#ifdef NOTYET
2307
          /* Cannot allocate new message. What
2308
           * should we do? */
2309
          ospf_apiserver_free(apiserv);
2310
#endif
2311
0
          goto out;
2312
0
        }
2313
2314
0
        ospf_apiserver_send_msg(apiserv, msg);
2315
0
        msg_free(msg);
2316
0
      }
2317
0
    }
2318
0
  }
2319
2320
0
out:
2321
0
  return;
2322
0
}
2323
2324
void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
2325
0
{
2326
0
  struct listnode *node, *nnode;
2327
0
  struct msg *msg;
2328
0
  struct ospf_apiserver *apiserv;
2329
2330
0
  assert(area);
2331
2332
0
  if (!ospf_apiserver_is_ready_type10(area)) {
2333
0
    zlog_warn("Area not ready for type 10?");
2334
0
    return;
2335
0
  }
2336
2337
0
  for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2338
0
    struct listnode *node2, *nnode2;
2339
0
    struct registered_opaque_type *r;
2340
2341
0
    for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2342
0
               r)) {
2343
0
      if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) {
2344
0
        msg = new_msg_ready_notify(
2345
0
          0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
2346
0
          area->area_id);
2347
0
        if (!msg) {
2348
0
          zlog_warn(
2349
0
            "%s: new_msg_ready_nofity failed",
2350
0
            __func__);
2351
#ifdef NOTYET
2352
          /* Cannot allocate new message. What
2353
           * should we do? */
2354
          ospf_apiserver_free(apiserv);
2355
#endif
2356
0
          goto out;
2357
0
        }
2358
2359
0
        ospf_apiserver_send_msg(apiserv, msg);
2360
0
        msg_free(msg);
2361
0
      }
2362
0
    }
2363
0
  }
2364
2365
0
out:
2366
0
  return;
2367
0
}
2368
2369
2370
void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
2371
0
{
2372
0
  struct listnode *node, *nnode;
2373
0
  struct msg *msg;
2374
0
  struct in_addr id_null = {.s_addr = 0L};
2375
0
  struct ospf_apiserver *apiserv;
2376
2377
0
  assert(top);
2378
2379
0
  if (!ospf_apiserver_is_ready_type11(top)) {
2380
0
    zlog_warn("AS not ready for type 11?");
2381
0
    return;
2382
0
  }
2383
2384
0
  for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2385
0
    struct listnode *node2, *nnode2;
2386
0
    struct registered_opaque_type *r;
2387
2388
0
    for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2,
2389
0
               r)) {
2390
0
      if (r->lsa_type == OSPF_OPAQUE_AS_LSA) {
2391
0
        msg = new_msg_ready_notify(
2392
0
          0, OSPF_OPAQUE_AS_LSA, r->opaque_type,
2393
0
          id_null);
2394
0
        if (!msg) {
2395
0
          zlog_warn(
2396
0
            "%s: new_msg_ready_notify failed",
2397
0
            __func__);
2398
#ifdef NOTYET
2399
          /* Cannot allocate new message. What
2400
           * should we do? */
2401
          ospf_apiserver_free(apiserv);
2402
#endif
2403
0
          goto out;
2404
0
        }
2405
2406
0
        ospf_apiserver_send_msg(apiserv, msg);
2407
0
        msg_free(msg);
2408
0
      }
2409
0
    }
2410
0
  }
2411
2412
0
out:
2413
0
  return;
2414
0
}
2415
2416
void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi)
2417
0
{
2418
0
  struct msg *msg;
2419
2420
0
  msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id);
2421
0
  if (msg != NULL) {
2422
0
    ospf_apiserver_clients_notify_all(msg);
2423
0
    msg_free(msg);
2424
0
  }
2425
0
}
2426
2427
void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi)
2428
0
{
2429
0
  struct msg *msg;
2430
2431
0
  msg = new_msg_del_if(0, oi->address->u.prefix4);
2432
0
  if (msg != NULL) {
2433
0
    ospf_apiserver_clients_notify_all(msg);
2434
0
    msg_free(msg);
2435
0
  }
2436
0
}
2437
2438
void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
2439
0
{
2440
0
  struct msg *msg;
2441
0
  struct in_addr ifaddr = {.s_addr = 0L};
2442
0
  struct in_addr area_id = {.s_addr = 0L};
2443
2444
0
  assert(oi);
2445
0
  assert(oi->ifp);
2446
2447
0
  if (oi->address) {
2448
0
    ifaddr = oi->address->u.prefix4;
2449
0
  }
2450
0
  if (oi->area) {
2451
0
    area_id = oi->area->area_id;
2452
0
  }
2453
2454
0
  msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
2455
0
  if (!msg) {
2456
0
    zlog_warn("%s: msg_new failed", __func__);
2457
0
    return;
2458
0
  }
2459
2460
0
  ospf_apiserver_clients_notify_all(msg);
2461
0
  msg_free(msg);
2462
0
}
2463
2464
void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
2465
0
{
2466
0
  struct msg *msg;
2467
0
  struct in_addr ifaddr;
2468
0
  struct in_addr nbraddr;
2469
2470
0
  assert(nbr);
2471
2472
0
  ifaddr = nbr->oi->address->u.prefix4;
2473
2474
0
  nbraddr = nbr->address.u.prefix4;
2475
2476
0
  msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
2477
0
         nbr->state);
2478
0
  if (!msg) {
2479
0
    zlog_warn("%s: msg_new failed", __func__);
2480
0
    return;
2481
0
  }
2482
2483
0
  ospf_apiserver_clients_notify_all(msg);
2484
0
  msg_free(msg);
2485
0
}
2486
2487
static int apiserver_clients_lsa_change_notify(uint8_t msgtype,
2488
                 struct ospf_lsa *lsa)
2489
0
{
2490
0
  struct msg *msg;
2491
0
  struct listnode *node, *nnode;
2492
0
  struct ospf_apiserver *apiserv;
2493
2494
  /* Default area for AS-External and Opaque11 LSAs */
2495
0
  struct in_addr area_id = {.s_addr = 0L};
2496
2497
  /* Default interface for non Opaque9 LSAs */
2498
0
  struct in_addr ifaddr = {.s_addr = 0L};
2499
2500
0
  if (lsa->area) {
2501
0
    area_id = lsa->area->area_id;
2502
0
  }
2503
0
  if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) {
2504
0
    assert(lsa->oi);
2505
0
    ifaddr = lsa->oi->address->u.prefix4;
2506
0
  }
2507
2508
  /* Prepare message that can be sent to clients that have a matching
2509
     filter */
2510
0
  msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */
2511
0
          ifaddr, area_id,
2512
0
          lsa->flags & OSPF_LSA_SELF, lsa->data);
2513
0
  if (!msg) {
2514
0
    zlog_warn("%s: msg_new failed", __func__);
2515
0
    return -1;
2516
0
  }
2517
2518
  /* Now send message to all clients with a matching filter */
2519
0
  for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) {
2520
0
    struct lsa_filter_type *filter;
2521
0
    uint16_t mask;
2522
0
    uint32_t *area;
2523
0
    int i;
2524
2525
    /* Check filter for this client. */
2526
0
    filter = apiserv->filter;
2527
2528
    /* Check area IDs in case of non AS-E LSAs.
2529
     * If filter has areas (num_areas > 0),
2530
     * then one of the areas must match the area ID of this LSA. */
2531
2532
0
    i = filter->num_areas;
2533
0
    if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
2534
0
        || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) {
2535
0
      i = 0;
2536
0
    }
2537
2538
0
    if (i > 0) {
2539
0
      area = (uint32_t *)(filter + 1);
2540
0
      while (i) {
2541
0
        if (*area == area_id.s_addr) {
2542
0
          break;
2543
0
        }
2544
0
        i--;
2545
0
        area++;
2546
0
      }
2547
0
    } else {
2548
0
      i = 1;
2549
0
    }
2550
2551
0
    if (i > 0) {
2552
      /* Area match. Check LSA type. */
2553
0
      mask = ntohs(filter->typemask);
2554
2555
0
      if (mask & Power2[lsa->data->type]) {
2556
        /* Type also matches. Check origin. */
2557
0
        if ((filter->origin == ANY_ORIGIN)
2558
0
            || (filter->origin == IS_LSA_SELF(lsa))) {
2559
0
          ospf_apiserver_send_msg(apiserv, msg);
2560
0
        }
2561
0
      }
2562
0
    }
2563
0
  }
2564
  /* Free message since it is not used anymore */
2565
0
  msg_free(msg);
2566
2567
0
  return 0;
2568
0
}
2569
2570
2571
/* -------------------------------------------------------------
2572
 * Following are hooks invoked when LSAs are updated or deleted
2573
 * -------------------------------------------------------------
2574
 */
2575
2576
2577
int ospf_apiserver_lsa_update(struct ospf_lsa *lsa)
2578
0
{
2579
2580
  /* Only notify this update if the LSA's age is smaller than
2581
     MAXAGE. Otherwise clients would see LSA updates with max age just
2582
     before they are deleted from the LSDB. LSA delete messages have
2583
     MAXAGE too but should not be filtered. */
2584
0
  if (IS_LSA_MAXAGE(lsa))
2585
0
    return 0;
2586
0
  return apiserver_clients_lsa_change_notify(MSG_LSA_UPDATE_NOTIFY, lsa);
2587
0
}
2588
2589
int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa)
2590
0
{
2591
0
  return apiserver_clients_lsa_change_notify(MSG_LSA_DELETE_NOTIFY, lsa);
2592
0
}
2593
2594
/* -------------------------------------------------------------
2595
 * Reachable functions
2596
 * -------------------------------------------------------------
2597
 */
2598
2599
static inline int cmp_route_nodes(struct route_node *orn,
2600
          struct route_node *nrn)
2601
0
{
2602
0
  if (!orn)
2603
0
    return 1;
2604
0
  else if (!nrn)
2605
0
    return -1;
2606
2607
0
  uint32_t opn = ntohl(orn->p.u.prefix4.s_addr);
2608
0
  uint32_t npn = ntohl(nrn->p.u.prefix4.s_addr);
2609
0
  if (opn < npn)
2610
0
    return -1;
2611
0
  else if (opn > npn)
2612
0
    return 1;
2613
0
  else
2614
0
    return 0;
2615
0
}
2616
2617
void ospf_apiserver_notify_reachable(struct route_table *ort,
2618
             struct route_table *nrt)
2619
0
{
2620
0
  struct msg *msg;
2621
0
  struct msg_reachable_change *areach;
2622
0
  struct route_node *orn, *nrn;
2623
0
  const uint insz = sizeof(struct in_addr);
2624
0
  struct in_addr *abuf = NULL, *dbuf = NULL;
2625
0
  struct in_addr *a = NULL, *d = NULL;
2626
0
  uint nadd, nremove;
2627
0
  int cmp;
2628
2629
0
  if (!ort && !nrt) {
2630
0
    if (IS_DEBUG_OSPF_CLIENT_API)
2631
0
      zlog_debug("%s: no routing tables", __func__);
2632
0
    return;
2633
0
  }
2634
0
  if (nrt && nrt->count)
2635
0
    a = abuf = XCALLOC(MTYPE_APISERVER, insz * nrt->count);
2636
0
  if (ort && ort->count)
2637
0
    d = dbuf = XCALLOC(MTYPE_APISERVER, insz * ort->count);
2638
2639
  /* walk both tables */
2640
0
  orn = ort ? route_top(ort) : NULL;
2641
0
  nrn = nrt ? route_top(nrt) : NULL;
2642
0
  while (orn || nrn) {
2643
0
    if (orn && !listhead((struct list *)orn->info)) {
2644
0
      orn = route_next(orn);
2645
0
      continue;
2646
0
    }
2647
0
    if (nrn && !listhead((struct list *)nrn->info)) {
2648
0
      nrn = route_next(nrn);
2649
0
      continue;
2650
0
    }
2651
0
    cmp = cmp_route_nodes(orn, nrn);
2652
0
    if (!cmp) {
2653
      /* if old == new advance old and new */
2654
0
      if (IS_DEBUG_OSPF_CLIENT_API)
2655
0
        zlog_debug("keeping router id: %pI4",
2656
0
             &orn->p.u.prefix4);
2657
0
      orn = route_next(orn);
2658
0
      nrn = route_next(nrn);
2659
0
    } else if (cmp < 0) {
2660
0
      assert(d != NULL); /* Silence SA warning */
2661
2662
      /* if old < new, delete old, advance old */
2663
0
      *d++ = orn->p.u.prefix4;
2664
0
      if (IS_DEBUG_OSPF_CLIENT_API)
2665
0
        zlog_debug("removing router id: %pI4",
2666
0
             &orn->p.u.prefix4);
2667
0
      orn = route_next(orn);
2668
0
    } else {
2669
0
      assert(a != NULL); /* Silence SA warning */
2670
2671
      /* if new < old, add new, advance new */
2672
0
      *a++ = nrn->p.u.prefix4;
2673
0
      if (IS_DEBUG_OSPF_CLIENT_API)
2674
0
        zlog_debug("adding router id: %pI4",
2675
0
             &nrn->p.u.prefix4);
2676
0
      nrn = route_next(nrn);
2677
0
    }
2678
0
  }
2679
2680
0
  nadd = abuf ? (a - abuf) : 0;
2681
0
  nremove = dbuf ? (d - dbuf) : 0;
2682
0
  a = abuf;
2683
0
  d = dbuf;
2684
2685
0
  while (nadd + nremove) {
2686
0
    msg = new_msg_reachable_change(0, nadd, a, nremove, d);
2687
0
    areach = (struct msg_reachable_change *)STREAM_DATA(msg->s);
2688
2689
0
    a += ntohs(areach->nadd);
2690
0
    nadd = nadd - ntohs(areach->nadd);
2691
2692
0
    d += ntohs(areach->nremove);
2693
0
    nremove = nremove - ntohs(areach->nremove);
2694
2695
0
    if (IS_DEBUG_OSPF_CLIENT_API)
2696
0
      zlog_debug("%s: adding %d removing %d", __func__,
2697
0
           ntohs(areach->nadd), ntohs(areach->nremove));
2698
0
    ospf_apiserver_clients_notify_all(msg);
2699
0
    msg_free(msg);
2700
0
  }
2701
0
  if (abuf)
2702
0
    XFREE(MTYPE_APISERVER, abuf);
2703
0
  if (dbuf)
2704
0
    XFREE(MTYPE_APISERVER, dbuf);
2705
0
}
2706
2707
2708
void ospf_apiserver_clients_notify_router_id_change(struct in_addr router_id)
2709
0
{
2710
0
  struct msg *msg;
2711
2712
0
  msg = new_msg_router_id_change(0, router_id);
2713
0
  if (!msg) {
2714
0
    zlog_warn("%s: new_msg_router_id_change failed", __func__);
2715
0
    return;
2716
0
  }
2717
2718
0
  ospf_apiserver_clients_notify_all(msg);
2719
0
  msg_free(msg);
2720
0
}
2721
2722
2723
#endif /* SUPPORT_OSPF_API */