Coverage Report

Created: 2025-07-14 06:48

/src/frr/ospfd/ospf_neighbor.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * OSPF Neighbor functions.
4
 * Copyright (C) 1999, 2000 Toshiaki Takada
5
 */
6
7
#include <zebra.h>
8
9
#include "lib/bfd.h"
10
#include "linklist.h"
11
#include "prefix.h"
12
#include "memory.h"
13
#include "command.h"
14
#include "frrevent.h"
15
#include "stream.h"
16
#include "table.h"
17
#include "log.h"
18
#include "json.h"
19
20
#include "ospfd/ospfd.h"
21
#include "ospfd/ospf_interface.h"
22
#include "ospfd/ospf_asbr.h"
23
#include "ospfd/ospf_lsa.h"
24
#include "ospfd/ospf_lsdb.h"
25
#include "ospfd/ospf_neighbor.h"
26
#include "ospfd/ospf_nsm.h"
27
#include "ospfd/ospf_packet.h"
28
#include "ospfd/ospf_network.h"
29
#include "ospfd/ospf_flood.h"
30
#include "ospfd/ospf_dump.h"
31
#include "ospfd/ospf_bfd.h"
32
#include "ospfd/ospf_gr.h"
33
34
/* Fill in the the 'key' as appropriate to retrieve the entry for nbr
35
 * from the ospf_interface's nbrs table. Indexed by interface address
36
 * for all cases except Virtual-link and PointToPoint interfaces, where
37
 * neighbours are indexed by router-ID instead.
38
 */
39
static void ospf_nbr_key(struct ospf_interface *oi, struct ospf_neighbor *nbr,
40
       struct prefix *key)
41
1
{
42
1
  key->family = AF_INET;
43
1
  key->prefixlen = IPV4_MAX_BITLEN;
44
45
  /* vlinks are indexed by router-id */
46
1
  if (oi->type == OSPF_IFTYPE_VIRTUALLINK
47
1
      || oi->type == OSPF_IFTYPE_POINTOPOINT)
48
0
    key->u.prefix4 = nbr->router_id;
49
1
  else
50
1
    key->u.prefix4 = nbr->src;
51
1
  return;
52
1
}
53
54
struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi)
55
246
{
56
246
  struct ospf_neighbor *nbr;
57
58
  /* Allcate new neighbor. */
59
246
  nbr = XCALLOC(MTYPE_OSPF_NEIGHBOR, sizeof(struct ospf_neighbor));
60
61
  /* Relate neighbor to the interface. */
62
246
  nbr->oi = oi;
63
64
  /* Set default values. */
65
246
  nbr->state = NSM_Down;
66
67
  /* Set inheritance values. */
68
246
  nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
69
246
  nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
70
246
  nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
71
246
  nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
72
246
  nbr->priority = -1;
73
74
  /* DD flags. */
75
246
  nbr->dd_flags = OSPF_DD_FLAG_MS | OSPF_DD_FLAG_M | OSPF_DD_FLAG_I;
76
77
  /* Last received and sent DD. */
78
246
  nbr->last_send = NULL;
79
80
246
  nbr->nbr_nbma = NULL;
81
82
246
  ospf_lsdb_init(&nbr->db_sum);
83
246
  ospf_lsdb_init(&nbr->ls_rxmt);
84
246
  ospf_lsdb_init(&nbr->ls_req);
85
86
246
  nbr->crypt_seqnum = 0;
87
88
  /* Initialize GR Helper info*/
89
246
  nbr->gr_helper_info.recvd_grace_period = 0;
90
246
  nbr->gr_helper_info.actual_grace_period = 0;
91
246
  nbr->gr_helper_info.gr_helper_status = OSPF_GR_NOT_HELPER;
92
246
  nbr->gr_helper_info.helper_exit_reason = OSPF_GR_HELPER_EXIT_NONE;
93
246
  nbr->gr_helper_info.gr_restart_reason = OSPF_GR_UNKNOWN_RESTART;
94
95
246
  return nbr;
96
246
}
97
98
void ospf_nbr_free(struct ospf_neighbor *nbr)
99
0
{
100
  /* Free DB summary list. */
101
0
  if (ospf_db_summary_count(nbr))
102
0
    ospf_db_summary_clear(nbr);
103
  /* ospf_db_summary_delete_all (nbr); */
104
105
  /* Free ls request list. */
106
0
  if (ospf_ls_request_count(nbr))
107
0
    ospf_ls_request_delete_all(nbr);
108
109
  /* Free retransmit list. */
110
0
  if (ospf_ls_retransmit_count(nbr))
111
0
    ospf_ls_retransmit_clear(nbr);
112
113
  /* Cleanup LSDBs. */
114
0
  ospf_lsdb_cleanup(&nbr->db_sum);
115
0
  ospf_lsdb_cleanup(&nbr->ls_req);
116
0
  ospf_lsdb_cleanup(&nbr->ls_rxmt);
117
118
  /* Clear last send packet. */
119
0
  if (nbr->last_send)
120
0
    ospf_packet_free(nbr->last_send);
121
122
0
  if (nbr->nbr_nbma) {
123
0
    nbr->nbr_nbma->nbr = NULL;
124
0
    nbr->nbr_nbma = NULL;
125
0
  }
126
127
  /* Cancel all timers. */
128
0
  EVENT_OFF(nbr->t_inactivity);
129
0
  EVENT_OFF(nbr->t_db_desc);
130
0
  EVENT_OFF(nbr->t_ls_req);
131
0
  EVENT_OFF(nbr->t_ls_upd);
132
133
  /* Cancel all events. */ /* Thread lookup cost would be negligible. */
134
0
  event_cancel_event(master, nbr);
135
136
0
  bfd_sess_free(&nbr->bfd_session);
137
138
0
  EVENT_OFF(nbr->gr_helper_info.t_grace_timer);
139
140
0
  nbr->oi = NULL;
141
0
  XFREE(MTYPE_OSPF_NEIGHBOR, nbr);
142
0
}
143
144
/* Delete specified OSPF neighbor from interface. */
145
void ospf_nbr_delete(struct ospf_neighbor *nbr)
146
0
{
147
0
  struct ospf_interface *oi;
148
0
  struct route_node *rn;
149
0
  struct prefix p;
150
151
0
  oi = nbr->oi;
152
153
  /* get appropriate prefix 'key' */
154
0
  ospf_nbr_key(oi, nbr, &p);
155
156
0
  rn = route_node_lookup(oi->nbrs, &p);
157
0
  if (rn) {
158
    /* If lookup for a NBR succeeds, the leaf route_node could
159
     * only exist because there is (or was) a nbr there.
160
     * If the nbr was deleted, the leaf route_node should have
161
     * lost its last refcount too, and be deleted.
162
     * Therefore a looked-up leaf route_node in nbrs table
163
     * should never have NULL info.
164
     */
165
0
    assert(rn->info);
166
167
0
    if (rn->info) {
168
0
      rn->info = NULL;
169
0
      route_unlock_node(rn);
170
0
    } else
171
0
      zlog_info("Can't find neighbor %pI4 in the interface %s",
172
0
          &nbr->src, IF_NAME(oi));
173
174
0
    route_unlock_node(rn);
175
0
  } else {
176
    /*
177
     * This neighbor was not found, but before we move on and
178
     * free the neighbor structre, make sure that it was not
179
     * indexed incorrectly and ended up in the "worng" place
180
     */
181
182
    /* Reverse the lookup rules */
183
0
    if (oi->type == OSPF_IFTYPE_VIRTUALLINK
184
0
        || oi->type == OSPF_IFTYPE_POINTOPOINT)
185
0
      p.u.prefix4 = nbr->src;
186
0
    else
187
0
      p.u.prefix4 = nbr->router_id;
188
189
0
    rn = route_node_lookup(oi->nbrs, &p);
190
0
    if (rn) {
191
      /* We found the neighbor!
192
       * Now make sure it is not the exact same neighbor
193
       * structure that we are about to free
194
       */
195
0
      if (nbr == rn->info) {
196
        /* Same neighbor, drop the reference to it */
197
0
        rn->info = NULL;
198
0
        route_unlock_node(rn);
199
0
      }
200
0
      route_unlock_node(rn);
201
0
    }
202
0
  }
203
204
  /* Free ospf_neighbor structure. */
205
0
  ospf_nbr_free(nbr);
206
0
}
207
208
/* Check myself is in the neighbor list. */
209
int ospf_nbr_bidirectional(struct in_addr *router_id, struct in_addr *neighbors,
210
         int size)
211
73
{
212
73
  int i;
213
73
  int max;
214
215
73
  max = size / sizeof(struct in_addr);
216
217
552
  for (i = 0; i < max; i++)
218
482
    if (IPV4_ADDR_SAME(router_id, &neighbors[i]))
219
3
      return 1;
220
221
70
  return 0;
222
73
}
223
224
/* reset nbr_self */
225
void ospf_nbr_self_reset(struct ospf_interface *oi, struct in_addr router_id)
226
1
{
227
1
  if (oi->nbr_self)
228
0
    ospf_nbr_delete(oi->nbr_self);
229
230
1
  oi->nbr_self = ospf_nbr_new(oi);
231
1
  ospf_nbr_add_self(oi, router_id);
232
1
}
233
234
/* Add self to nbr list. */
235
void ospf_nbr_add_self(struct ospf_interface *oi, struct in_addr router_id)
236
1
{
237
1
  struct prefix p;
238
1
  struct route_node *rn;
239
240
1
  if (!oi->nbr_self)
241
0
    oi->nbr_self = ospf_nbr_new(oi);
242
243
  /* Initial state */
244
1
  oi->nbr_self->address = *oi->address;
245
1
  oi->nbr_self->priority = OSPF_IF_PARAM(oi, priority);
246
1
  oi->nbr_self->router_id = router_id;
247
1
  oi->nbr_self->src = oi->address->u.prefix4;
248
1
  oi->nbr_self->state = NSM_TwoWay;
249
250
1
  switch (oi->area->external_routing) {
251
1
  case OSPF_AREA_DEFAULT:
252
1
    SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
253
1
    break;
254
0
  case OSPF_AREA_STUB:
255
0
    UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
256
0
    break;
257
0
  case OSPF_AREA_NSSA:
258
0
    UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
259
0
    SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP);
260
0
    break;
261
1
  }
262
263
  /* Add nbr_self to nbrs table */
264
1
  ospf_nbr_key(oi, oi->nbr_self, &p);
265
266
1
  rn = route_node_get(oi->nbrs, &p);
267
1
  if (rn->info) {
268
    /* There is already pseudo neighbor. */
269
0
    if (IS_DEBUG_OSPF_EVENT)
270
0
      zlog_debug(
271
0
        "router_id %pI4 already present in neighbor table. node refcount %u",
272
0
        &router_id, route_node_get_lock_count(rn));
273
0
    route_unlock_node(rn);
274
0
  } else
275
1
    rn->info = oi->nbr_self;
276
1
}
277
278
/* Get neighbor count by status.
279
   Specify status = 0, get all neighbor other than myself. */
280
int ospf_nbr_count(struct ospf_interface *oi, int state)
281
0
{
282
0
  struct ospf_neighbor *nbr;
283
0
  struct route_node *rn;
284
0
  int count = 0;
285
286
0
  for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
287
0
    if ((nbr = rn->info))
288
0
      if (!IPV4_ADDR_SAME(&nbr->router_id,
289
0
              &oi->ospf->router_id))
290
0
        if (state == 0 || nbr->state == state)
291
0
          count++;
292
293
0
  return count;
294
0
}
295
296
int ospf_nbr_count_opaque_capable(struct ospf_interface *oi)
297
0
{
298
0
  struct ospf_neighbor *nbr;
299
0
  struct route_node *rn;
300
0
  int count = 0;
301
302
0
  for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
303
0
    if ((nbr = rn->info))
304
0
      if (!IPV4_ADDR_SAME(&nbr->router_id,
305
0
              &oi->ospf->router_id))
306
0
        if (nbr->state == NSM_Full)
307
0
          if (CHECK_FLAG(nbr->options,
308
0
                   OSPF_OPTION_O))
309
0
            count++;
310
311
0
  return count;
312
0
}
313
314
/* lookup nbr by address - use this only if you know you must
315
 * otherwise use the ospf_nbr_lookup() wrapper, which deals
316
 * with virtual link and PointToPoint neighbours
317
 */
318
struct ospf_neighbor *ospf_nbr_lookup_by_addr(struct route_table *nbrs,
319
                struct in_addr *addr)
320
2.40k
{
321
2.40k
  struct prefix p;
322
2.40k
  struct route_node *rn;
323
2.40k
  struct ospf_neighbor *nbr;
324
325
2.40k
  p.family = AF_INET;
326
2.40k
  p.prefixlen = IPV4_MAX_BITLEN;
327
2.40k
  p.u.prefix4 = *addr;
328
329
2.40k
  rn = route_node_lookup(nbrs, &p);
330
2.40k
  if (!rn)
331
5
    return NULL;
332
333
  /* See comment in ospf_nbr_delete */
334
2.39k
  assert(rn->info);
335
336
2.39k
  if (rn->info == NULL) {
337
0
    route_unlock_node(rn);
338
0
    return NULL;
339
0
  }
340
341
2.39k
  nbr = (struct ospf_neighbor *)rn->info;
342
2.39k
  route_unlock_node(rn);
343
344
2.39k
  return nbr;
345
2.39k
}
346
347
struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *nbrs,
348
              struct in_addr *id)
349
0
{
350
0
  struct route_node *rn;
351
0
  struct ospf_neighbor *nbr;
352
353
0
  for (rn = route_top(nbrs); rn; rn = route_next(rn))
354
0
    if ((nbr = rn->info) != NULL)
355
0
      if (IPV4_ADDR_SAME(&nbr->router_id, id)) {
356
0
        route_unlock_node(rn);
357
0
        return nbr;
358
0
      }
359
360
0
  return NULL;
361
0
}
362
363
void ospf_renegotiate_optional_capabilities(struct ospf *top)
364
0
{
365
0
  struct listnode *node;
366
0
  struct ospf_interface *oi;
367
0
  struct route_table *nbrs;
368
0
  struct route_node *rn;
369
0
  struct ospf_neighbor *nbr;
370
0
  uint8_t shutdown_save = top->inst_shutdown;
371
372
  /* At first, flush self-originated LSAs from routing domain. */
373
0
  ospf_flush_self_originated_lsas_now(top);
374
375
  /* ospf_flush_self_originated_lsas_now is primarily intended for shut
376
   * down scenarios. Reset the inst_shutdown flag that it sets. We are
377
   * just changing configuration, and the flag can change the scheduling
378
   * of when maxage LSAs are sent. */
379
0
  top->inst_shutdown = shutdown_save;
380
381
  /* Revert all neighbor status to ExStart. */
382
0
  for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi)) {
383
0
    if ((nbrs = oi->nbrs) == NULL)
384
0
      continue;
385
386
0
    for (rn = route_top(nbrs); rn; rn = route_next(rn)) {
387
0
      if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
388
0
        continue;
389
390
0
      if (nbr->state < NSM_ExStart)
391
0
        continue;
392
393
0
      if (IS_DEBUG_OSPF_EVENT)
394
0
        zlog_debug(
395
0
          "Renegotiate optional capabilities with neighbor(%pI4)",
396
0
          &nbr->router_id);
397
398
0
      OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch);
399
0
    }
400
0
  }
401
402
  /* Refresh/Re-originate external LSAs (Type-7 and Type-5).*/
403
0
  ospf_external_lsa_rid_change(top);
404
405
0
  return;
406
0
}
407
408
409
struct ospf_neighbor *ospf_nbr_lookup(struct ospf_interface *oi, struct ip *iph,
410
              struct ospf_header *ospfh)
411
2.39k
{
412
2.39k
  struct in_addr srcaddr = iph->ip_src;
413
414
2.39k
  if (oi->type == OSPF_IFTYPE_VIRTUALLINK
415
2.39k
      || oi->type == OSPF_IFTYPE_POINTOPOINT)
416
0
    return (ospf_nbr_lookup_by_routerid(oi->nbrs,
417
0
                &ospfh->router_id));
418
2.39k
  else
419
2.39k
    return (ospf_nbr_lookup_by_addr(oi->nbrs, &srcaddr));
420
2.39k
}
421
422
static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi,
423
            struct ospf_header *ospfh,
424
            struct prefix *p)
425
245
{
426
245
  struct ospf_neighbor *nbr;
427
428
245
  nbr = ospf_nbr_new(oi);
429
245
  nbr->state = NSM_Down;
430
245
  nbr->src = p->u.prefix4;
431
245
  memcpy(&nbr->address, p, sizeof(struct prefix));
432
433
245
  nbr->nbr_nbma = NULL;
434
245
  if (oi->type == OSPF_IFTYPE_NBMA) {
435
0
    struct ospf_nbr_nbma *nbr_nbma;
436
0
    struct listnode *node;
437
438
0
    for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, node, nbr_nbma)) {
439
0
      if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src)) {
440
0
        nbr_nbma->nbr = nbr;
441
0
        nbr->nbr_nbma = nbr_nbma;
442
#ifndef FUZZING
443
        if (nbr_nbma->t_poll)
444
          EVENT_OFF(nbr_nbma->t_poll);
445
#endif
446
0
        nbr->state_change = nbr_nbma->state_change + 1;
447
0
      }
448
0
    }
449
0
  }
450
451
  /* New nbr, save the crypto sequence number if necessary */
452
#ifndef FUZZING
453
  if (ntohs(ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
454
    nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
455
#endif
456
  /* Configure BFD if interface has it. */
457
0
  ospf_neighbor_bfd_apply(nbr);
458
459
245
  if (IS_DEBUG_OSPF_EVENT)
460
0
    zlog_debug("NSM[%s:%pI4]: start", IF_NAME(oi),
461
245
         &nbr->router_id);
462
463
245
  return nbr;
464
245
}
465
466
struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
467
           struct ospf_header *ospfh, struct ip *iph,
468
           struct prefix *p)
469
2.71k
{
470
2.71k
  struct route_node *rn;
471
2.71k
  struct prefix key;
472
2.71k
  struct ospf_neighbor *nbr;
473
474
2.71k
  key.family = AF_INET;
475
2.71k
  key.prefixlen = IPV4_MAX_BITLEN;
476
477
2.71k
  if (oi->type == OSPF_IFTYPE_VIRTUALLINK
478
2.71k
      || oi->type == OSPF_IFTYPE_POINTOPOINT)
479
0
    key.u.prefix4 = ospfh->router_id; /* index vlink and ptp nbrs by
480
                 router-id */
481
2.71k
  else
482
2.71k
    key.u.prefix4 = iph->ip_src;
483
484
2.71k
  rn = route_node_get(oi->nbrs, &key);
485
2.71k
  if (rn->info) {
486
2.47k
    route_unlock_node(rn);
487
2.47k
    nbr = rn->info;
488
489
2.47k
    if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) {
490
0
      nbr->src = iph->ip_src;
491
0
      memcpy(&nbr->address, p, sizeof(struct prefix));
492
0
    }
493
2.47k
  } else {
494
245
    rn->info = nbr = ospf_nbr_add(oi, ospfh, p);
495
245
  }
496
497
2.71k
  nbr->router_id = ospfh->router_id;
498
499
2.71k
  return nbr;
500
2.71k
}