]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/neighbor.c
OSPF: Fix reading from freed memory
[thirdparty/bird.git] / proto / ospf / neighbor.c
CommitLineData
4364b47e
OF
1/*
2 * BIRD -- OSPF
3 *
70945cb6
OZ
4 * (c) 1999--2004 Ondrej Filip <feela@network.cz>
5 * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6 * (c) 2009--2014 CZ.NIC z.s.p.o.
4364b47e
OF
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11#include "ospf.h"
12
f8fefde3
OZ
13
14const char *ospf_ns_names[] = {
15 "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
2e10a170
OF
16};
17
f8fefde3
OZ
18const char *ospf_inm_names[] = {
19 "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
20 "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
21 "KillNbr", "InactivityTimer", "LLDown"
2e10a170 22};
79f036ef 23
f8fefde3
OZ
24
25static int can_do_adj(struct ospf_neighbor *n);
6f8bbaa1
OZ
26static void inactivity_timer_hook(timer * timer);
27static void dbdes_timer_hook(timer *t);
28static void lsrq_timer_hook(timer *t);
29static void lsrt_timer_hook(timer *t);
30static void ackd_timer_hook(timer *t);
31
0844b65d
OZ
32
33static void
a7a7372a 34init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
0844b65d
OZ
35{
36 s_init_list(&(n->lsrql));
6f8bbaa1 37 n->lsrqi = SHEAD(n->lsrql);
a7a7372a 38 n->lsrqh = ospf_top_new(p, n->pool);
0844b65d
OZ
39
40 s_init_list(&(n->lsrtl));
a7a7372a
OZ
41 n->lsrth = ospf_top_new(p, n->pool);
42}
43
44static void
45release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
46{
47 struct top_hash_entry *ret, *en;
48
49 WALK_SLIST(ret, n->lsrtl)
50 {
51 en = ospf_hash_find_entry(p->gr, ret);
52 if (en)
53 en->ret_count--;
54 }
0844b65d 55}
39e517d4 56
0dd7ccc7 57/* Resets LSA request and retransmit lists.
742029eb 58 * We do not reset DB summary list iterator here,
0844b65d
OZ
59 * it is reset during entering EXCHANGE state.
60 */
61static void
a7a7372a 62reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
0844b65d 63{
6f8bbaa1 64 release_lsrtl(p, n);
0844b65d
OZ
65 ospf_top_free(n->lsrqh);
66 ospf_top_free(n->lsrth);
6f8bbaa1
OZ
67 ospf_reset_lsack_queue(n);
68
69 tm_stop(n->dbdes_timer);
70 tm_stop(n->lsrq_timer);
71 tm_stop(n->lsrt_timer);
72 tm_stop(n->ackd_timer);
73
a7a7372a 74 init_lists(p, n);
0844b65d 75}
39e517d4
OF
76
77struct ospf_neighbor *
78ospf_neighbor_new(struct ospf_iface *ifa)
79{
70945cb6
OZ
80 struct ospf_proto *p = ifa->oa->po;
81 struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
39e517d4
OF
82 struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
83
84 n->pool = pool;
85 n->ifa = ifa;
86 add_tail(&ifa->neigh_list, NODE n);
87 n->adj = 0;
3e2bd0f1 88 n->csn = 0;
2e10a170 89 n->state = NEIGHBOR_DOWN;
39e517d4 90
a7a7372a 91 init_lists(p, n);
70945cb6 92 s_init(&(n->dbsi), &(p->lsal));
0844b65d 93
c76ba51a
OF
94 init_list(&n->ackl[ACKL_DIRECT]);
95 init_list(&n->ackl[ACKL_DELAY]);
6f8bbaa1
OZ
96
97 n->inactim = tm_new_set(pool, inactivity_timer_hook, n, 0, 0);
98 n->dbdes_timer = tm_new_set(pool, dbdes_timer_hook, n, 0, ifa->rxmtint);
99 n->lsrq_timer = tm_new_set(pool, lsrq_timer_hook, n, 0, ifa->rxmtint);
100 n->lsrt_timer = tm_new_set(pool, lsrt_timer_hook, n, 0, ifa->rxmtint);
101 n->ackd_timer = tm_new_set(pool, ackd_timer_hook, n, 0, ifa->rxmtint / 2);
39e517d4 102
2e10a170 103 return (n);
39e517d4
OF
104}
105
f8fefde3
OZ
106static void
107ospf_neigh_down(struct ospf_neighbor *n)
108{
109 struct ospf_iface *ifa = n->ifa;
110 struct ospf_proto *p = ifa->oa->po;
a459f4df 111 u32 rid = n->rid;
f8fefde3
OZ
112
113 if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
114 {
115 struct nbma_node *nn = find_nbma_node(ifa, n->ip);
116 if (nn)
117 nn->found = 0;
118 }
119
120 s_get(&(n->dbsi));
121 release_lsrtl(p, n);
122 rem_node(NODE n);
123 rfree(n->pool);
124
a459f4df 125 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
f8fefde3
OZ
126}
127
7ab3ff6a 128/**
f8fefde3 129 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
7ab3ff6a
OF
130 * @n: OSPF neighbor
131 * @state: new state
132 *
baa5dd6c 133 * Many actions have to be taken acording to a change of state of a neighbor. It
7ab3ff6a
OF
134 * starts rxmt timers, call interface state machine etc.
135 */
0844b65d 136static void
f8fefde3 137ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
4364b47e 138{
70945cb6
OZ
139 struct ospf_iface *ifa = n->ifa;
140 struct ospf_proto *p = ifa->oa->po;
141 u8 old_state = n->state;
142 int old_fadj = ifa->fadj;
4364b47e 143
70945cb6
OZ
144 if (state == old_state)
145 return;
eae4fcf2 146
f8fefde3
OZ
147 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
148 n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
4057093f 149
70945cb6 150 n->state = state;
4057093f 151
70945cb6
OZ
152 /* Increase number of partial adjacencies */
153 if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
154 p->padj++;
4057093f 155
70945cb6
OZ
156 /* Decrease number of partial adjacencies */
157 if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
158 p->padj--;
2e10a170 159
70945cb6
OZ
160 /* Increase number of full adjacencies */
161 if (state == NEIGHBOR_FULL)
162 ifa->fadj++;
163
164 /* Decrease number of full adjacencies */
165 if (old_state == NEIGHBOR_FULL)
166 ifa->fadj--;
167
168 if (ifa->fadj != old_fadj)
169 {
170 /* RFC 2328 12.4 Event 4 - neighbor enters/leaves Full state */
171 ospf_notify_rt_lsa(ifa->oa);
172 ospf_notify_net_lsa(ifa);
173
174 /* RFC 2328 12.4 Event 8 - vlink state change */
175 if (ifa->type == OSPF_IT_VLINK)
176 ospf_notify_rt_lsa(ifa->voa);
177 }
178
179 if (state == NEIGHBOR_EXSTART)
180 {
181 /* First time adjacency */
182 if (n->adj == 0)
183 n->dds = random_u32();
184
185 n->dds++;
186 n->myimms = DBDES_IMMS;
6f8bbaa1
OZ
187
188 tm_start(n->dbdes_timer, 0);
189 tm_start(n->ackd_timer, ifa->rxmtint / 2);
4364b47e 190 }
70945cb6
OZ
191
192 if (state > NEIGHBOR_EXSTART)
193 n->myimms &= ~DBDES_I;
4364b47e 194
f8fefde3
OZ
195 /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
196 if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
197 ospf_iface_sm(ifa, ISM_NEICH);
198 if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
199 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e
OF
200}
201
7ab3ff6a
OF
202/**
203 * ospf_neigh_sm - ospf neighbor state machine
204 * @n: neighor
205 * @event: actual event
206 *
baa5dd6c
OF
207 * This part implements the neighbor state machine as described in 10.3 of
208 * RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
209 * used. We discover neighbors on nonbroadcast networks in the
210 * same way as on broadcast networks. The only difference is in
211 * sending hello packets. These are sent to IPs listed in
7ab3ff6a
OF
212 * @ospf_iface->nbma_list .
213 */
4364b47e
OF
214void
215ospf_neigh_sm(struct ospf_neighbor *n, int event)
4364b47e 216{
70945cb6 217 struct ospf_proto *p = n->ifa->oa->po;
4364b47e 218
f8fefde3
OZ
219 DBG("Neighbor state machine for %R on %s, event %s\n",
220 n->rid, n->ifa->ifname, ospf_inm_names[event]);
79f036ef 221
2e10a170 222 switch (event)
4364b47e 223 {
2e10a170 224 case INM_START:
f8fefde3 225 ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
2e10a170
OF
226 /* NBMA are used different way */
227 break;
70945cb6 228
2e10a170 229 case INM_HELLOREC:
f8fefde3
OZ
230 if (n->state < NEIGHBOR_INIT)
231 ospf_neigh_chstate(n, NEIGHBOR_INIT);
70945cb6
OZ
232
233 /* Restart inactivity timer */
234 tm_start(n->inactim, n->ifa->deadint);
2e10a170 235 break;
70945cb6 236
2e10a170
OF
237 case INM_2WAYREC:
238 if (n->state < NEIGHBOR_2WAY)
f8fefde3 239 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
2e10a170 240 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
f8fefde3 241 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
2e10a170 242 break;
70945cb6 243
2e10a170
OF
244 case INM_NEGDONE:
245 if (n->state == NEIGHBOR_EXSTART)
246 {
f8fefde3 247 ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
0844b65d
OZ
248
249 /* Reset DB summary list iterator */
250 s_get(&(n->dbsi));
70945cb6 251 s_init(&(n->dbsi), &p->lsal);
0844b65d 252
a7a7372a
OZ
253 /* Add MaxAge LSA entries to retransmission list */
254 ospf_add_flushed_to_lsrt(p, n);
2e10a170
OF
255 }
256 else
257 bug("NEGDONE and I'm not in EXSTART?");
258 break;
70945cb6 259
2e10a170 260 case INM_EXDONE:
6f8bbaa1
OZ
261 if (!EMPTY_SLIST(n->lsrql))
262 ospf_neigh_chstate(n, NEIGHBOR_LOADING);
263 else
264 ospf_neigh_chstate(n, NEIGHBOR_FULL);
2e10a170 265 break;
70945cb6 266
2e10a170 267 case INM_LOADDONE:
f8fefde3 268 ospf_neigh_chstate(n, NEIGHBOR_FULL);
2e10a170 269 break;
70945cb6 270
2e10a170 271 case INM_ADJOK:
6f8bbaa1
OZ
272 /* Can In build adjacency? */
273 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
2e10a170 274 {
6f8bbaa1
OZ
275 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
276 }
277 else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
278 {
279 reset_lists(p, n);
280 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
2e10a170
OF
281 }
282 break;
70945cb6 283
2e10a170
OF
284 case INM_SEQMIS:
285 case INM_BADLSREQ:
286 if (n->state >= NEIGHBOR_EXCHANGE)
287 {
a7a7372a 288 reset_lists(p, n);
f8fefde3 289 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
2e10a170
OF
290 }
291 break;
70945cb6 292
2e10a170
OF
293 case INM_KILLNBR:
294 case INM_LLDOWN:
295 case INM_INACTTIM:
f8fefde3
OZ
296 /* No need for reset_lists() */
297 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
298 ospf_neigh_down(n);
2e10a170 299 break;
70945cb6 300
2e10a170 301 case INM_1WAYREC:
a7a7372a 302 reset_lists(p, n);
f8fefde3 303 ospf_neigh_chstate(n, NEIGHBOR_INIT);
2e10a170 304 break;
70945cb6 305
2e10a170 306 default:
70945cb6 307 bug("%s: INM - Unknown event?", p->p.name);
2e10a170 308 break;
4364b47e
OF
309 }
310}
311
f8fefde3
OZ
312static int
313can_do_adj(struct ospf_neighbor *n)
314{
315 struct ospf_iface *ifa = n->ifa;
316 struct ospf_proto *p = ifa->oa->po;
317 int i = 0;
318
319 switch (ifa->type)
320 {
321 case OSPF_IT_PTP:
322 case OSPF_IT_PTMP:
323 case OSPF_IT_VLINK:
324 i = 1;
325 break;
326 case OSPF_IT_BCAST:
327 case OSPF_IT_NBMA:
328 switch (ifa->state)
329 {
330 case OSPF_IS_DOWN:
331 case OSPF_IS_LOOP:
332 bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
333 break;
334 case OSPF_IS_WAITING:
335 DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
336 break;
337 case OSPF_IS_DROTHER:
338 if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
339 && (n->state >= NEIGHBOR_2WAY))
340 i = 1;
341 break;
342 case OSPF_IS_PTP:
343 case OSPF_IS_BACKUP:
344 case OSPF_IS_DR:
345 if (n->state >= NEIGHBOR_2WAY)
346 i = 1;
347 break;
348 default:
349 bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
350 break;
351 }
352 break;
353 default:
354 bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
355 break;
356 }
357 DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
358 return i;
359}
360
361
362static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
363{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
364
365static struct ospf_neighbor *
366elect_bdr(struct ospf_proto *p, list nl)
367{
368 struct ospf_neighbor *neigh, *n1, *n2;
369 u32 nid;
370
371 n1 = NULL;
372 n2 = NULL;
373 WALK_LIST(neigh, nl) /* First try those decl. themselves */
374 {
375 nid = neigh_get_id(p, neigh);
376
377 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
378 if (neigh->priority > 0) /* Eligible */
379 if (neigh->dr != nid) /* And not decl. itself DR */
380 {
381 if (neigh->bdr == nid) /* Declaring BDR */
382 {
383 if (n1 != NULL)
384 {
385 if (neigh->priority > n1->priority)
386 n1 = neigh;
387 else if (neigh->priority == n1->priority)
388 if (neigh->rid > n1->rid)
389 n1 = neigh;
390 }
391 else
392 {
393 n1 = neigh;
394 }
395 }
396 else /* And NOT declaring BDR */
397 {
398 if (n2 != NULL)
399 {
400 if (neigh->priority > n2->priority)
401 n2 = neigh;
402 else if (neigh->priority == n2->priority)
403 if (neigh->rid > n2->rid)
404 n2 = neigh;
405 }
406 else
407 {
408 n2 = neigh;
409 }
410 }
411 }
412 }
413 if (n1 == NULL)
414 n1 = n2;
415
416 return (n1);
417}
418
419static struct ospf_neighbor *
420elect_dr(struct ospf_proto *p, list nl)
421{
422 struct ospf_neighbor *neigh, *n;
423 u32 nid;
424
425 n = NULL;
426 WALK_LIST(neigh, nl) /* And now DR */
427 {
428 nid = neigh_get_id(p, neigh);
429
430 if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
431 if (neigh->priority > 0) /* Eligible */
432 if (neigh->dr == nid) /* And declaring itself DR */
433 {
434 if (n != NULL)
435 {
436 if (neigh->priority > n->priority)
437 n = neigh;
438 else if (neigh->priority == n->priority)
439 if (neigh->rid > n->rid)
440 n = neigh;
441 }
442 else
443 {
444 n = neigh;
445 }
446 }
447 }
448
449 return (n);
450}
451
7ab3ff6a 452/**
70945cb6 453 * ospf_dr_election - (Backup) Designed Router election
7ab3ff6a
OF
454 * @ifa: actual interface
455 *
baa5dd6c 456 * When the wait timer fires, it is time to elect (Backup) Designated Router.
f8fefde3
OZ
457 * Structure describing me is added to this list so every electing router has
458 * the same list. Backup Designated Router is elected before Designated
459 * Router. This process is described in 9.4 of RFC 2328. The function is
460 * supposed to be called only from ospf_iface_sm() as a part of the interface
461 * state machine.
7ab3ff6a 462 */
4364b47e 463void
70945cb6 464ospf_dr_election(struct ospf_iface *ifa)
4364b47e 465{
70945cb6 466 struct ospf_proto *p = ifa->oa->po;
2e10a170 467 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
70945cb6 468 u32 myid = p->router_id;
4364b47e 469
423230f2 470 DBG("(B)DR election.\n");
4364b47e 471
2e10a170
OF
472 me.state = NEIGHBOR_2WAY;
473 me.rid = myid;
474 me.priority = ifa->priority;
353729f5 475 me.ip = ifa->addr->ip;
4364b47e 476
70945cb6
OZ
477 me.dr = ospf_is_v2(p) ? ipa_to_u32(ifa->drip) : ifa->drid;
478 me.bdr = ospf_is_v2(p) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
dd4da6f6 479 me.iface_id = ifa->iface_id;
c3226991 480
2e10a170 481 add_tail(&ifa->neigh_list, NODE & me);
4364b47e 482
70945cb6
OZ
483 nbdr = elect_bdr(p, ifa->neigh_list);
484 ndr = elect_dr(p, ifa->neigh_list);
4364b47e 485
2e10a170
OF
486 if (ndr == NULL)
487 ndr = nbdr;
4364b47e 488
c3226991 489 /* 9.4. (4) */
2e10a170
OF
490 if (((ifa->drid == myid) && (ndr != &me))
491 || ((ifa->drid != myid) && (ndr == &me))
492 || ((ifa->bdrid == myid) && (nbdr != &me))
493 || ((ifa->bdrid != myid) && (nbdr == &me)))
4364b47e 494 {
70945cb6
OZ
495 me.dr = ndr ? neigh_get_id(p, ndr) : 0;
496 me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
2e10a170 497
70945cb6
OZ
498 nbdr = elect_bdr(p, ifa->neigh_list);
499 ndr = elect_dr(p, ifa->neigh_list);
423230f2 500
c3226991
OZ
501 if (ndr == NULL)
502 ndr = nbdr;
28950169
OF
503 }
504
70945cb6
OZ
505 rem_node(NODE & me);
506
507
508 u32 old_drid = ifa->drid;
509 u32 old_bdrid = ifa->bdrid;
742029eb 510
c3226991
OZ
511 ifa->drid = ndr ? ndr->rid : 0;
512 ifa->drip = ndr ? ndr->ip : IPA_NONE;
70945cb6
OZ
513 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
514
c3226991
OZ
515 ifa->bdrid = nbdr ? nbdr->rid : 0;
516 ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE;
517
3aab39f5 518 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
4364b47e 519
f8fefde3 520 /* We are part of the interface state machine */
70945cb6 521 if (ifa->drid == myid)
2e10a170 522 ospf_iface_chstate(ifa, OSPF_IS_DR);
70945cb6
OZ
523 else if (ifa->bdrid == myid)
524 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
4364b47e 525 else
70945cb6 526 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
4364b47e 527
70945cb6
OZ
528 /* Review neighbor adjacencies if DR or BDR changed */
529 if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
2e10a170 530 WALK_LIST(neigh, ifa->neigh_list)
70945cb6
OZ
531 if (neigh->state >= NEIGHBOR_2WAY)
532 ospf_neigh_sm(neigh, INM_ADJOK);
533
534 /* RFC 2328 12.4 Event 3 - DR change */
535 if (ifa->drid != old_drid)
536 ospf_notify_rt_lsa(ifa->oa);
4364b47e
OF
537}
538
539struct ospf_neighbor *
540find_neigh(struct ospf_iface *ifa, u32 rid)
541{
542 struct ospf_neighbor *n;
919f5411
OZ
543 WALK_LIST(n, ifa->neigh_list)
544 if (n->rid == rid)
545 return n;
546 return NULL;
547}
4364b47e 548
919f5411
OZ
549struct ospf_neighbor *
550find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
551{
552 struct ospf_neighbor *n;
553 WALK_LIST(n, ifa->neigh_list)
554 if (ipa_equal(n->ip, ip))
555 return n;
4364b47e
OF
556 return NULL;
557}
558
0844b65d 559static void
6f8bbaa1 560inactivity_timer_hook(timer * timer)
c7e46aae 561{
86c84d76 562 struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
f8fefde3 563 struct ospf_proto *p = n->ifa->oa->po;
a7a7372a 564
6f8bbaa1 565 OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
f8fefde3
OZ
566 n->rid, n->ifa->ifname);
567 ospf_neigh_sm(n, INM_INACTTIM);
18a0c0bb 568}
a783e259 569
1ec52253
OZ
570static void
571ospf_neigh_bfd_hook(struct bfd_request *req)
572{
573 struct ospf_neighbor *n = req->data;
70945cb6 574 struct ospf_proto *p = n->ifa->oa->po;
1ec52253
OZ
575
576 if (req->down)
577 {
6f8bbaa1 578 OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
f8fefde3
OZ
579 n->rid, n->ifa->ifname);
580 ospf_neigh_sm(n, INM_INACTTIM);
1ec52253
OZ
581 }
582}
583
584void
585ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
586{
587 if (use_bfd && !n->bfd_req)
588 n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface,
589 ospf_neigh_bfd_hook, n);
590
591 if (!use_bfd && n->bfd_req)
592 {
593 rfree(n->bfd_req);
594 n->bfd_req = NULL;
595 }
596}
597
598
6f8bbaa1
OZ
599static void
600dbdes_timer_hook(timer *t)
601{
602 struct ospf_neighbor *n = t->data;
603 struct ospf_proto *p = n->ifa->oa->po;
604
605 // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
606
607 if (n->state == NEIGHBOR_EXSTART)
608 ospf_send_dbdes(p, n);
609
610 if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
611 ospf_rxmt_dbdes(p, n);
612}
613
614static void
615lsrq_timer_hook(timer *t)
616{
617 struct ospf_neighbor *n = t->data;
618 struct ospf_proto *p = n->ifa->oa->po;
619
620 // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
621
622 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
623 ospf_send_lsreq(p, n);
624}
625
626static void
627lsrt_timer_hook(timer *t)
628{
629 struct ospf_neighbor *n = t->data;
630 struct ospf_proto *p = n->ifa->oa->po;
631
632 // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
633
634 if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
635 ospf_rxmt_lsupd(p, n);
636}
637
638static void
639ackd_timer_hook(timer *t)
640{
641 struct ospf_neighbor *n = t->data;
642 struct ospf_proto *p = n->ifa->oa->po;
643
644 ospf_send_lsack(p, n, ACKL_DELAY);
645}
646
647
a783e259
OF
648void
649ospf_sh_neigh_info(struct ospf_neighbor *n)
650{
2e10a170 651 struct ospf_iface *ifa = n->ifa;
6f8bbaa1 652 char *pos = "PtP ";
2e10a170
OF
653 char etime[6];
654 int exp, sec, min;
655
656 exp = n->inactim->expires - now;
6eb4b73f
OF
657 sec = exp % 60;
658 min = exp / 60;
2e10a170
OF
659 if (min > 59)
660 {
661 bsprintf(etime, "-Inf-");
662 }
663 else
664 {
665 bsprintf(etime, "%02u:%02u", min, sec);
666 }
667
f8fefde3
OZ
668 if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
669 {
670 if (n->rid == ifa->drid)
6f8bbaa1 671 pos = "DR ";
f8fefde3 672 else if (n->rid == ifa->bdrid)
6f8bbaa1 673 pos = "BDR ";
f8fefde3 674 else
6f8bbaa1 675 pos = "Other";
f8fefde3 676 }
2e10a170 677
cf31112f 678 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
f8fefde3 679 ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
a783e259 680}