]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/neighbor.c
OSPF: Fix reading from freed memory
[thirdparty/bird.git] / proto / ospf / neighbor.c
1 /*
2 * BIRD -- OSPF
3 *
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.
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11 #include "ospf.h"
12
13
14 const char *ospf_ns_names[] = {
15 "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
16 };
17
18 const char *ospf_inm_names[] = {
19 "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
20 "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
21 "KillNbr", "InactivityTimer", "LLDown"
22 };
23
24
25 static int can_do_adj(struct ospf_neighbor *n);
26 static void inactivity_timer_hook(timer * timer);
27 static void dbdes_timer_hook(timer *t);
28 static void lsrq_timer_hook(timer *t);
29 static void lsrt_timer_hook(timer *t);
30 static void ackd_timer_hook(timer *t);
31
32
33 static void
34 init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
35 {
36 s_init_list(&(n->lsrql));
37 n->lsrqi = SHEAD(n->lsrql);
38 n->lsrqh = ospf_top_new(p, n->pool);
39
40 s_init_list(&(n->lsrtl));
41 n->lsrth = ospf_top_new(p, n->pool);
42 }
43
44 static void
45 release_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 }
55 }
56
57 /* Resets LSA request and retransmit lists.
58 * We do not reset DB summary list iterator here,
59 * it is reset during entering EXCHANGE state.
60 */
61 static void
62 reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
63 {
64 release_lsrtl(p, n);
65 ospf_top_free(n->lsrqh);
66 ospf_top_free(n->lsrth);
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
74 init_lists(p, n);
75 }
76
77 struct ospf_neighbor *
78 ospf_neighbor_new(struct ospf_iface *ifa)
79 {
80 struct ospf_proto *p = ifa->oa->po;
81 struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
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;
88 n->csn = 0;
89 n->state = NEIGHBOR_DOWN;
90
91 init_lists(p, n);
92 s_init(&(n->dbsi), &(p->lsal));
93
94 init_list(&n->ackl[ACKL_DIRECT]);
95 init_list(&n->ackl[ACKL_DELAY]);
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);
102
103 return (n);
104 }
105
106 static void
107 ospf_neigh_down(struct ospf_neighbor *n)
108 {
109 struct ospf_iface *ifa = n->ifa;
110 struct ospf_proto *p = ifa->oa->po;
111 u32 rid = n->rid;
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
125 OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
126 }
127
128 /**
129 * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
130 * @n: OSPF neighbor
131 * @state: new state
132 *
133 * Many actions have to be taken acording to a change of state of a neighbor. It
134 * starts rxmt timers, call interface state machine etc.
135 */
136 static void
137 ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
138 {
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;
143
144 if (state == old_state)
145 return;
146
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]);
149
150 n->state = state;
151
152 /* Increase number of partial adjacencies */
153 if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
154 p->padj++;
155
156 /* Decrease number of partial adjacencies */
157 if ((old_state == NEIGHBOR_EXCHANGE) || (old_state == NEIGHBOR_LOADING))
158 p->padj--;
159
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;
187
188 tm_start(n->dbdes_timer, 0);
189 tm_start(n->ackd_timer, ifa->rxmtint / 2);
190 }
191
192 if (state > NEIGHBOR_EXSTART)
193 n->myimms &= ~DBDES_I;
194
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);
200 }
201
202 /**
203 * ospf_neigh_sm - ospf neighbor state machine
204 * @n: neighor
205 * @event: actual event
206 *
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
212 * @ospf_iface->nbma_list .
213 */
214 void
215 ospf_neigh_sm(struct ospf_neighbor *n, int event)
216 {
217 struct ospf_proto *p = n->ifa->oa->po;
218
219 DBG("Neighbor state machine for %R on %s, event %s\n",
220 n->rid, n->ifa->ifname, ospf_inm_names[event]);
221
222 switch (event)
223 {
224 case INM_START:
225 ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
226 /* NBMA are used different way */
227 break;
228
229 case INM_HELLOREC:
230 if (n->state < NEIGHBOR_INIT)
231 ospf_neigh_chstate(n, NEIGHBOR_INIT);
232
233 /* Restart inactivity timer */
234 tm_start(n->inactim, n->ifa->deadint);
235 break;
236
237 case INM_2WAYREC:
238 if (n->state < NEIGHBOR_2WAY)
239 ospf_neigh_chstate(n, NEIGHBOR_2WAY);
240 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
241 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
242 break;
243
244 case INM_NEGDONE:
245 if (n->state == NEIGHBOR_EXSTART)
246 {
247 ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
248
249 /* Reset DB summary list iterator */
250 s_get(&(n->dbsi));
251 s_init(&(n->dbsi), &p->lsal);
252
253 /* Add MaxAge LSA entries to retransmission list */
254 ospf_add_flushed_to_lsrt(p, n);
255 }
256 else
257 bug("NEGDONE and I'm not in EXSTART?");
258 break;
259
260 case INM_EXDONE:
261 if (!EMPTY_SLIST(n->lsrql))
262 ospf_neigh_chstate(n, NEIGHBOR_LOADING);
263 else
264 ospf_neigh_chstate(n, NEIGHBOR_FULL);
265 break;
266
267 case INM_LOADDONE:
268 ospf_neigh_chstate(n, NEIGHBOR_FULL);
269 break;
270
271 case INM_ADJOK:
272 /* Can In build adjacency? */
273 if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
274 {
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);
281 }
282 break;
283
284 case INM_SEQMIS:
285 case INM_BADLSREQ:
286 if (n->state >= NEIGHBOR_EXCHANGE)
287 {
288 reset_lists(p, n);
289 ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
290 }
291 break;
292
293 case INM_KILLNBR:
294 case INM_LLDOWN:
295 case INM_INACTTIM:
296 /* No need for reset_lists() */
297 ospf_neigh_chstate(n, NEIGHBOR_DOWN);
298 ospf_neigh_down(n);
299 break;
300
301 case INM_1WAYREC:
302 reset_lists(p, n);
303 ospf_neigh_chstate(n, NEIGHBOR_INIT);
304 break;
305
306 default:
307 bug("%s: INM - Unknown event?", p->p.name);
308 break;
309 }
310 }
311
312 static int
313 can_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
362 static 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
365 static struct ospf_neighbor *
366 elect_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
419 static struct ospf_neighbor *
420 elect_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
452 /**
453 * ospf_dr_election - (Backup) Designed Router election
454 * @ifa: actual interface
455 *
456 * When the wait timer fires, it is time to elect (Backup) Designated Router.
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.
462 */
463 void
464 ospf_dr_election(struct ospf_iface *ifa)
465 {
466 struct ospf_proto *p = ifa->oa->po;
467 struct ospf_neighbor *neigh, *ndr, *nbdr, me;
468 u32 myid = p->router_id;
469
470 DBG("(B)DR election.\n");
471
472 me.state = NEIGHBOR_2WAY;
473 me.rid = myid;
474 me.priority = ifa->priority;
475 me.ip = ifa->addr->ip;
476
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;
479 me.iface_id = ifa->iface_id;
480
481 add_tail(&ifa->neigh_list, NODE & me);
482
483 nbdr = elect_bdr(p, ifa->neigh_list);
484 ndr = elect_dr(p, ifa->neigh_list);
485
486 if (ndr == NULL)
487 ndr = nbdr;
488
489 /* 9.4. (4) */
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)))
494 {
495 me.dr = ndr ? neigh_get_id(p, ndr) : 0;
496 me.bdr = nbdr ? neigh_get_id(p, nbdr) : 0;
497
498 nbdr = elect_bdr(p, ifa->neigh_list);
499 ndr = elect_dr(p, ifa->neigh_list);
500
501 if (ndr == NULL)
502 ndr = nbdr;
503 }
504
505 rem_node(NODE & me);
506
507
508 u32 old_drid = ifa->drid;
509 u32 old_bdrid = ifa->bdrid;
510
511 ifa->drid = ndr ? ndr->rid : 0;
512 ifa->drip = ndr ? ndr->ip : IPA_NONE;
513 ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
514
515 ifa->bdrid = nbdr ? nbdr->rid : 0;
516 ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE;
517
518 DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
519
520 /* We are part of the interface state machine */
521 if (ifa->drid == myid)
522 ospf_iface_chstate(ifa, OSPF_IS_DR);
523 else if (ifa->bdrid == myid)
524 ospf_iface_chstate(ifa, OSPF_IS_BACKUP);
525 else
526 ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
527
528 /* Review neighbor adjacencies if DR or BDR changed */
529 if ((ifa->drid != old_drid) || (ifa->bdrid != old_bdrid))
530 WALK_LIST(neigh, ifa->neigh_list)
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);
537 }
538
539 struct ospf_neighbor *
540 find_neigh(struct ospf_iface *ifa, u32 rid)
541 {
542 struct ospf_neighbor *n;
543 WALK_LIST(n, ifa->neigh_list)
544 if (n->rid == rid)
545 return n;
546 return NULL;
547 }
548
549 struct ospf_neighbor *
550 find_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;
556 return NULL;
557 }
558
559 static void
560 inactivity_timer_hook(timer * timer)
561 {
562 struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
563 struct ospf_proto *p = n->ifa->oa->po;
564
565 OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
566 n->rid, n->ifa->ifname);
567 ospf_neigh_sm(n, INM_INACTTIM);
568 }
569
570 static void
571 ospf_neigh_bfd_hook(struct bfd_request *req)
572 {
573 struct ospf_neighbor *n = req->data;
574 struct ospf_proto *p = n->ifa->oa->po;
575
576 if (req->down)
577 {
578 OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
579 n->rid, n->ifa->ifname);
580 ospf_neigh_sm(n, INM_INACTTIM);
581 }
582 }
583
584 void
585 ospf_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
599 static void
600 dbdes_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
614 static void
615 lsrq_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
626 static void
627 lsrt_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
638 static void
639 ackd_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
648 void
649 ospf_sh_neigh_info(struct ospf_neighbor *n)
650 {
651 struct ospf_iface *ifa = n->ifa;
652 char *pos = "PtP ";
653 char etime[6];
654 int exp, sec, min;
655
656 exp = n->inactim->expires - now;
657 sec = exp % 60;
658 min = exp / 60;
659 if (min > 59)
660 {
661 bsprintf(etime, "-Inf-");
662 }
663 else
664 {
665 bsprintf(etime, "%02u:%02u", min, sec);
666 }
667
668 if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
669 {
670 if (n->rid == ifa->drid)
671 pos = "DR ";
672 else if (n->rid == ifa->bdrid)
673 pos = "BDR ";
674 else
675 pos = "Other";
676 }
677
678 cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
679 ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
680 }