GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ospfd/neighbor.c Lines: 0 284 0.0 %
Date: 2017-11-07 Branches: 0 152 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: neighbor.c,v 1.47 2015/11/22 13:09:10 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5
 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/ioctl.h>
22
#include <sys/time.h>
23
#include <sys/socket.h>
24
#include <netinet/in.h>
25
#include <arpa/inet.h>
26
#include <net/if.h>
27
28
#include <ctype.h>
29
#include <err.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <event.h>
34
35
#include "ospfd.h"
36
#include "ospf.h"
37
#include "ospfe.h"
38
#include "log.h"
39
#include "rde.h"
40
41
int	 nbr_adj_ok(struct nbr *);
42
43
LIST_HEAD(nbr_head, nbr);
44
45
struct nbr_table {
46
	struct nbr_head		*hashtbl;
47
	u_int32_t		 hashmask;
48
} nbrtable;
49
50
#define NBR_HASH(x)		\
51
	&nbrtable.hashtbl[(x) & nbrtable.hashmask]
52
53
u_int32_t	peercnt = NBR_CNTSTART;
54
55
struct {
56
	int		state;
57
	enum nbr_event	event;
58
	enum nbr_action	action;
59
	int		new_state; /* 0 means action decides or unchanged */
60
} nbr_fsm_tbl[] = {
61
    /* current state	event that happened	action to take		resulting state */
62
    {NBR_STA_ACTIVE,	NBR_EVT_HELLO_RCVD,	NBR_ACT_RST_ITIMER,	0},
63
    {NBR_STA_BIDIR,	NBR_EVT_2_WAY_RCVD,	NBR_ACT_NOTHING,	0},
64
    {NBR_STA_INIT,	NBR_EVT_1_WAY_RCVD,	NBR_ACT_NOTHING,	0},
65
    {NBR_STA_DOWN,	NBR_EVT_HELLO_RCVD,	NBR_ACT_STRT_ITIMER,	NBR_STA_INIT},
66
    {NBR_STA_ATTEMPT,	NBR_EVT_HELLO_RCVD,	NBR_ACT_RST_ITIMER,	NBR_STA_INIT},
67
    {NBR_STA_INIT,	NBR_EVT_2_WAY_RCVD,	NBR_ACT_EVAL,		0},
68
    {NBR_STA_XSTRT,	NBR_EVT_NEG_DONE,	NBR_ACT_SNAP,		0},
69
    {NBR_STA_SNAP,	NBR_EVT_SNAP_DONE,	NBR_ACT_SNAP_DONE,	NBR_STA_XCHNG},
70
    {NBR_STA_XCHNG,	NBR_EVT_XCHNG_DONE,	NBR_ACT_XCHNG_DONE,	0},
71
    {NBR_STA_LOAD,	NBR_EVT_LOAD_DONE,	NBR_ACT_NOTHING,	NBR_STA_FULL},
72
    {NBR_STA_2_WAY,	NBR_EVT_ADJ_OK,		NBR_ACT_EVAL,		0},
73
    {NBR_STA_ADJFORM,	NBR_EVT_ADJ_OK,		NBR_ACT_ADJ_OK,		0},
74
    {NBR_STA_PRELIM,	NBR_EVT_ADJ_OK,		NBR_ACT_HELLO_CHK,	0},
75
    {NBR_STA_ADJFORM,	NBR_EVT_ADJTMOUT,	NBR_ACT_RESTRT_DD,	0},
76
    {NBR_STA_FLOOD,	NBR_EVT_SEQ_NUM_MIS,	NBR_ACT_RESTRT_DD,	0},
77
    {NBR_STA_FLOOD,	NBR_EVT_BAD_LS_REQ,	NBR_ACT_RESTRT_DD,	0},
78
    {NBR_STA_ANY,	NBR_EVT_KILL_NBR,	NBR_ACT_DEL,		NBR_STA_DOWN},
79
    {NBR_STA_ANY,	NBR_EVT_LL_DOWN,	NBR_ACT_DEL,		NBR_STA_DOWN},
80
    {NBR_STA_ANY,	NBR_EVT_ITIMER,		NBR_ACT_DEL,		NBR_STA_DOWN},
81
    {NBR_STA_BIDIR,	NBR_EVT_1_WAY_RCVD,	NBR_ACT_CLR_LST,	NBR_STA_INIT},
82
    {-1,		NBR_EVT_NOTHING,	NBR_ACT_NOTHING,	0},
83
};
84
85
const char * const nbr_event_names[] = {
86
	"NOTHING",
87
	"HELLO_RECEIVED",
88
	"2_WAY_RECEIVED",
89
	"NEGOTIATION_DONE",
90
	"SNAPSHOT_DONE",
91
	"EXCHANGE_DONE",
92
	"BAD_LS_REQ",
93
	"LOADING_DONE",
94
	"ADJ_OK",
95
	"SEQ_NUM_MISMATCH",
96
	"1_WAY_RECEIVED",
97
	"KILL_NBR",
98
	"INACTIVITY_TIMER",
99
	"LL_DOWN",
100
	"ADJ_TIMEOUT"
101
};
102
103
const char * const nbr_action_names[] = {
104
	"NOTHING",
105
	"RESET_INACTIVITY_TIMER",
106
	"START_INACTIVITY_TIMER",
107
	"EVAL",
108
	"SNAPSHOT",
109
	"SNAPSHOT_DONE",
110
	"EXCHANGE_DONE",
111
	"ADJ_OK",
112
	"RESET_DD",
113
	"DELETE",
114
	"CLEAR_LISTS",
115
	"HELLO_CHK"
116
};
117
118
int
119
nbr_fsm(struct nbr *nbr, enum nbr_event event)
120
{
121
	struct timeval	now;
122
	int		old_state;
123
	int		new_state = 0;
124
	int		i, ret = 0;
125
126
	if (nbr == nbr->iface->self)
127
		return (0);
128
129
	old_state = nbr->state;
130
	for (i = 0; nbr_fsm_tbl[i].state != -1; i++)
131
		if ((nbr_fsm_tbl[i].state & old_state) &&
132
		    (nbr_fsm_tbl[i].event == event)) {
133
			new_state = nbr_fsm_tbl[i].new_state;
134
			break;
135
		}
136
137
	if (nbr_fsm_tbl[i].state == -1) {
138
		/* event outside of the defined fsm, ignore it. */
139
		log_warnx("nbr_fsm: neighbor ID %s, "
140
		    "event %s not expected in state %s",
141
		    inet_ntoa(nbr->id), nbr_event_names[event],
142
		    nbr_state_name(old_state));
143
		return (0);
144
	}
145
146
	switch (nbr_fsm_tbl[i].action) {
147
	case NBR_ACT_RST_ITIMER:
148
		ret = nbr_act_reset_itimer(nbr);
149
		break;
150
	case NBR_ACT_STRT_ITIMER:
151
		ret = nbr_act_start_itimer(nbr);
152
		break;
153
	case NBR_ACT_EVAL:
154
		ret = nbr_act_eval(nbr);
155
		break;
156
	case NBR_ACT_SNAP:
157
		ret = nbr_act_snapshot(nbr);
158
		break;
159
	case NBR_ACT_SNAP_DONE:
160
		/* start db exchange */
161
		start_db_tx_timer(nbr);
162
		break;
163
	case NBR_ACT_XCHNG_DONE:
164
		ret = nbr_act_exchange_done(nbr);
165
		break;
166
	case NBR_ACT_ADJ_OK:
167
		ret = nbr_act_adj_ok(nbr);
168
		break;
169
	case NBR_ACT_RESTRT_DD:
170
		ret = nbr_act_restart_dd(nbr);
171
		break;
172
	case NBR_ACT_DEL:
173
		ret = nbr_act_delete(nbr);
174
		break;
175
	case NBR_ACT_CLR_LST:
176
		ret = nbr_act_clear_lists(nbr);
177
		break;
178
	case NBR_ACT_HELLO_CHK:
179
		ret = nbr_act_hello_check(nbr);
180
		break;
181
	case NBR_ACT_NOTHING:
182
		/* do nothing */
183
		break;
184
	}
185
186
	if (ret) {
187
		log_warnx("nbr_fsm: error changing state for neighbor ID %s, "
188
		    "event %s, state %s", inet_ntoa(nbr->id),
189
		    nbr_event_names[event], nbr_state_name(old_state));
190
		return (-1);
191
	}
192
193
	if (new_state != 0)
194
		nbr->state = new_state;
195
196
	if (old_state != nbr->state) {
197
		nbr->stats.sta_chng++;
198
		/* state change inform RDE */
199
		ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CHANGE,
200
		    nbr->peerid, 0, &nbr->state, sizeof(nbr->state));
201
202
		if (old_state & NBR_STA_FULL || nbr->state & NBR_STA_FULL) {
203
			/*
204
			 * neighbor changed from/to FULL
205
			 * originate new rtr and net LSA
206
			 */
207
			orig_rtr_lsa(nbr->iface->area);
208
			if (nbr->iface->state & IF_STA_DR)
209
				orig_net_lsa(nbr->iface);
210
211
			gettimeofday(&now, NULL);
212
			nbr->uptime = now.tv_sec;
213
		}
214
215
		/* bidirectional communication lost */
216
		if (old_state & ~NBR_STA_PRELIM && nbr->state & NBR_STA_PRELIM)
217
			if_fsm(nbr->iface, IF_EVT_NBR_CHNG);
218
219
		log_debug("nbr_fsm: event %s resulted in action %s and "
220
		    "changing state for neighbor ID %s from %s to %s",
221
		    nbr_event_names[event],
222
		    nbr_action_names[nbr_fsm_tbl[i].action],
223
		    inet_ntoa(nbr->id), nbr_state_name(old_state),
224
		    nbr_state_name(nbr->state));
225
226
		if (nbr->iface->type == IF_TYPE_VIRTUALLINK) {
227
			orig_rtr_lsa(nbr->iface->area);
228
		}
229
	}
230
231
	return (ret);
232
}
233
234
void
235
nbr_init(u_int32_t hashsize)
236
{
237
	struct nbr_head	*head;
238
	struct nbr	*nbr;
239
	u_int32_t        hs, i;
240
241
	for (hs = 1; hs < hashsize; hs <<= 1)
242
		;
243
	nbrtable.hashtbl = calloc(hs, sizeof(struct nbr_head));
244
	if (nbrtable.hashtbl == NULL)
245
		fatal("nbr_init");
246
247
	for (i = 0; i < hs; i++)
248
		LIST_INIT(&nbrtable.hashtbl[i]);
249
250
	nbrtable.hashmask = hs - 1;
251
252
	/* allocate a dummy neighbor used for self originated AS ext routes */
253
	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
254
		fatal("nbr_init");
255
256
	nbr->id.s_addr = ospfe_router_id();
257
	nbr->state = NBR_STA_DOWN;
258
	nbr->peerid = NBR_IDSELF;
259
	head = NBR_HASH(nbr->peerid);
260
	LIST_INSERT_HEAD(head, nbr, hash);
261
262
	TAILQ_INIT(&nbr->ls_retrans_list);
263
	TAILQ_INIT(&nbr->db_sum_list);
264
	TAILQ_INIT(&nbr->ls_req_list);
265
}
266
267
struct nbr *
268
nbr_new(u_int32_t nbr_id, struct iface *iface, int self)
269
{
270
	struct nbr_head	*head;
271
	struct nbr	*nbr;
272
	struct rde_nbr	 rn;
273
274
	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
275
		fatal("nbr_new");
276
277
	nbr->state = NBR_STA_DOWN;
278
	nbr->dd_master = 1;
279
	nbr->dd_seq_num = arc4random();	/* RFC: some unique value */
280
	nbr->id.s_addr = nbr_id;
281
282
	/* get next unused peerid */
283
	while (nbr_find_peerid(++peercnt))
284
		;
285
	nbr->peerid = peercnt;
286
	head = NBR_HASH(nbr->peerid);
287
	LIST_INSERT_HEAD(head, nbr, hash);
288
289
	/* add to peer list */
290
	nbr->iface = iface;
291
	LIST_INSERT_HEAD(&iface->nbr_list, nbr, entry);
292
293
	TAILQ_INIT(&nbr->ls_retrans_list);
294
	TAILQ_INIT(&nbr->db_sum_list);
295
	TAILQ_INIT(&nbr->ls_req_list);
296
297
	nbr->ls_req = NULL;
298
299
	if (self) {
300
		nbr->state = NBR_STA_FULL;
301
		nbr->addr.s_addr = iface->addr.s_addr;
302
		nbr->priority = iface->priority;
303
	}
304
305
	/* set event structures */
306
	evtimer_set(&nbr->inactivity_timer, nbr_itimer, nbr);
307
	evtimer_set(&nbr->db_tx_timer, db_tx_timer, nbr);
308
	evtimer_set(&nbr->lsreq_tx_timer, ls_req_tx_timer, nbr);
309
	evtimer_set(&nbr->ls_retrans_timer, ls_retrans_timer, nbr);
310
	evtimer_set(&nbr->adj_timer, nbr_adj_timer, nbr);
311
312
	bzero(&rn, sizeof(rn));
313
	rn.id.s_addr = nbr->id.s_addr;
314
	rn.area_id.s_addr = nbr->iface->area->id.s_addr;
315
	rn.ifindex = nbr->iface->ifindex;
316
	rn.state = nbr->state;
317
	rn.self = self;
318
	ospfe_imsg_compose_rde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn,
319
	    sizeof(rn));
320
321
	return (nbr);
322
}
323
324
void
325
nbr_del(struct nbr *nbr)
326
{
327
	ospfe_imsg_compose_rde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, NULL, 0);
328
329
	if (evtimer_pending(&nbr->inactivity_timer, NULL))
330
		evtimer_del(&nbr->inactivity_timer);
331
	if (evtimer_pending(&nbr->db_tx_timer, NULL))
332
		evtimer_del(&nbr->db_tx_timer);
333
	if (evtimer_pending(&nbr->lsreq_tx_timer, NULL))
334
		evtimer_del(&nbr->lsreq_tx_timer);
335
	if (evtimer_pending(&nbr->ls_retrans_timer, NULL))
336
		evtimer_del(&nbr->ls_retrans_timer);
337
	if (evtimer_pending(&nbr->adj_timer, NULL))
338
		evtimer_del(&nbr->adj_timer);
339
340
	/* clear lists */
341
	ls_retrans_list_clr(nbr);
342
	db_sum_list_clr(nbr);
343
	ls_req_list_clr(nbr);
344
345
	if (nbr->peerid != NBR_IDSELF)
346
		LIST_REMOVE(nbr, entry);
347
	LIST_REMOVE(nbr, hash);
348
349
	free(nbr);
350
}
351
352
struct nbr *
353
nbr_find_peerid(u_int32_t peerid)
354
{
355
	struct nbr_head	*head;
356
	struct nbr	*nbr;
357
358
	head = NBR_HASH(peerid);
359
360
	LIST_FOREACH(nbr, head, hash) {
361
		if (nbr->peerid == peerid)
362
			return (nbr);
363
	}
364
365
	return (NULL);
366
}
367
368
struct nbr *
369
nbr_find_id(struct iface *iface, u_int32_t rtr_id)
370
{
371
	struct nbr	*nbr = NULL;
372
373
	LIST_FOREACH(nbr, &iface->nbr_list, entry) {
374
		if (nbr->id.s_addr == rtr_id)
375
			return (nbr);
376
	}
377
378
	return (NULL);
379
}
380
381
/* timers */
382
/* ARGSUSED */
383
void
384
nbr_itimer(int fd, short event, void *arg)
385
{
386
	struct nbr *nbr = arg;
387
388
	if (nbr->state == NBR_STA_DOWN)
389
		nbr_del(nbr);
390
	else
391
		nbr_fsm(nbr, NBR_EVT_ITIMER);
392
}
393
394
void
395
nbr_start_itimer(struct nbr *nbr)
396
{
397
	struct timeval	tv;
398
399
	timerclear(&tv);
400
	tv.tv_sec = nbr->iface->dead_interval;
401
402
	if (evtimer_add(&nbr->inactivity_timer, &tv) == -1)
403
		fatal("nbr_start_itimer");
404
}
405
406
void
407
nbr_stop_itimer(struct nbr *nbr)
408
{
409
	if (evtimer_del(&nbr->inactivity_timer) == -1)
410
		fatal("nbr_stop_itimer");
411
}
412
413
void
414
nbr_reset_itimer(struct nbr *nbr)
415
{
416
	struct timeval	tv;
417
418
	timerclear(&tv);
419
	tv.tv_sec = nbr->iface->dead_interval;
420
421
	if (evtimer_add(&nbr->inactivity_timer, &tv) == -1)
422
		fatal("nbr_reset_itimer");
423
}
424
425
/* ARGSUSED */
426
void
427
nbr_adj_timer(int fd, short event, void *arg)
428
{
429
	struct nbr *nbr = arg;
430
431
	if (!(nbr->state & NBR_STA_ADJFORM))
432
		return;
433
434
	if (nbr->state & NBR_STA_ACTIVE && nbr->state != NBR_STA_FULL) {
435
		log_warnx("nbr_adj_timer: failed to form adjacency with %s "
436
		    "on interface %s", inet_ntoa(nbr->id), nbr->iface->name);
437
		nbr_fsm(nbr, NBR_EVT_ADJTMOUT);
438
	}
439
}
440
441
void
442
nbr_start_adj_timer(struct nbr *nbr)
443
{
444
	struct timeval	tv;
445
446
	timerclear(&tv);
447
	tv.tv_sec = DEFAULT_ADJ_TMOUT;
448
449
	if (evtimer_add(&nbr->adj_timer, &tv) == -1)
450
		fatal("nbr_start_adj_timer");
451
}
452
453
/* actions */
454
int
455
nbr_act_reset_itimer(struct nbr *nbr)
456
{
457
	nbr_reset_itimer(nbr);
458
459
	return (0);
460
}
461
462
int
463
nbr_act_start_itimer(struct nbr *nbr)
464
{
465
	nbr_start_itimer(nbr);
466
467
	return (0);
468
}
469
470
int
471
nbr_adj_ok(struct nbr *nbr)
472
{
473
	struct iface	*iface = nbr->iface;
474
475
	switch (iface->type) {
476
	case IF_TYPE_POINTOPOINT:
477
	case IF_TYPE_VIRTUALLINK:
478
	case IF_TYPE_POINTOMULTIPOINT:
479
		/* always ok */
480
		break;
481
	case IF_TYPE_BROADCAST:
482
	case IF_TYPE_NBMA:
483
		/*
484
		 * if neighbor is dr, bdr or router self is dr or bdr
485
		 * start forming adjacency
486
		 */
487
		if (iface->dr == nbr || iface->bdr == nbr ||
488
		    iface->state & IF_STA_DRORBDR)
489
			break;
490
		return (0);
491
	default:
492
		fatalx("nbr_adj_ok: unknown interface type");
493
	}
494
	return (1);
495
}
496
497
int
498
nbr_act_eval(struct nbr *nbr)
499
{
500
	if (!nbr_adj_ok(nbr)) {
501
		nbr->state = NBR_STA_2_WAY;
502
		return (0);
503
	}
504
505
	nbr->state = NBR_STA_XSTRT;
506
	nbr->dd_master = 1;
507
	nbr->dd_seq_num++;	/* as per RFC */
508
	nbr->dd_pending = 0;
509
	/* initial db negotiation */
510
	start_db_tx_timer(nbr);
511
512
	nbr_start_adj_timer(nbr);
513
514
	return (0);
515
}
516
517
int
518
nbr_act_snapshot(struct nbr *nbr)
519
{
520
	stop_db_tx_timer(nbr);
521
522
	/* we need to wait for the old snapshot to finish */
523
	if (nbr->dd_snapshot) {
524
		log_debug("nbr_act_snapshot: giving up, old snapshot running "
525
		    "for neigbor ID %s", inet_ntoa(nbr->id));
526
		return (nbr_act_restart_dd(nbr));
527
	}
528
	ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CAPA, nbr->peerid, 0,
529
	    &nbr->capa_options, sizeof(nbr->capa_options));
530
	ospfe_imsg_compose_rde(IMSG_DB_SNAPSHOT, nbr->peerid, 0, NULL, 0);
531
532
	nbr->dd_snapshot = 1;	/* wait for IMSG_DB_END */
533
	nbr->state = NBR_STA_SNAP;
534
535
	return (0);
536
}
537
538
int
539
nbr_act_exchange_done(struct nbr *nbr)
540
{
541
	if (nbr->dd_master)
542
		stop_db_tx_timer(nbr);
543
544
	if (ls_req_list_empty(nbr) && nbr->state == NBR_STA_XCHNG &&
545
	    nbr->dd_pending == 0) {
546
		nbr->state = NBR_STA_FULL;
547
		return (0);
548
	}
549
550
	nbr->state = NBR_STA_LOAD;
551
552
	if (!ls_req_list_empty(nbr))
553
		start_ls_req_tx_timer(nbr);
554
555
	return (0);
556
}
557
558
int
559
nbr_act_adj_ok(struct nbr *nbr)
560
{
561
	if (nbr_adj_ok(nbr)) {
562
		if (nbr->state == NBR_STA_2_WAY)
563
			return (nbr_act_eval(nbr));
564
	} else {
565
		nbr->state = NBR_STA_2_WAY;
566
		return (nbr_act_clear_lists(nbr));
567
	}
568
569
	return (0);
570
}
571
572
int
573
nbr_act_restart_dd(struct nbr *nbr)
574
{
575
	nbr_act_clear_lists(nbr);
576
577
	if (!nbr_adj_ok(nbr)) {
578
		nbr->state = NBR_STA_2_WAY;
579
		return (0);
580
	}
581
582
	nbr->state = NBR_STA_XSTRT;
583
	nbr->dd_master = 1;
584
	nbr->dd_seq_num += arc4random() & 0xffff;
585
	nbr->dd_pending = 0;
586
587
	/* initial db negotiation */
588
	start_db_tx_timer(nbr);
589
590
	nbr_start_adj_timer(nbr);
591
592
	return (0);
593
}
594
595
int
596
nbr_act_delete(struct nbr *nbr)
597
{
598
	struct timeval	tv;
599
600
	if (nbr == nbr->iface->self) {
601
		nbr->dr.s_addr = 0;
602
		nbr->bdr.s_addr = 0;
603
		return (0);
604
	}
605
606
	/* stop timers */
607
	nbr_stop_itimer(nbr);
608
609
	/* clear dr and bdr */
610
	nbr->dr.s_addr = 0;
611
	nbr->bdr.s_addr = 0;
612
	/* XXX reset crypt_seq_num will allow replay attacks. */
613
	nbr->crypt_seq_num = 0;
614
615
	/* schedule kill timer */
616
	timerclear(&tv);
617
	tv.tv_sec = DEFAULT_NBR_TMOUT;
618
619
	if (evtimer_add(&nbr->inactivity_timer, &tv)) {
620
		log_warnx("nbr_act_delete: error scheduling neighbor ID %s "
621
		    "for removal", inet_ntoa(nbr->id));
622
	}
623
624
	return (nbr_act_clear_lists(nbr));
625
}
626
627
int
628
nbr_act_clear_lists(struct nbr *nbr)
629
{
630
	/* stop timers */
631
	stop_db_tx_timer(nbr);
632
	stop_ls_req_tx_timer(nbr);
633
634
	/* clear lists */
635
	ls_retrans_list_clr(nbr);
636
	db_sum_list_clr(nbr);
637
	ls_req_list_clr(nbr);
638
639
	return (0);
640
}
641
642
int
643
nbr_act_hello_check(struct nbr *nbr)
644
{
645
	log_debug("nbr_act_hello_check: neighbor ID %s", inet_ntoa(nbr->id));
646
647
	return (-1);
648
}
649
650
struct ctl_nbr *
651
nbr_to_ctl(struct nbr *nbr)
652
{
653
	static struct ctl_nbr	 nctl;
654
	struct timeval		 tv, now, res;
655
	struct lsa_entry	*le;
656
657
	memcpy(nctl.name, nbr->iface->name, sizeof(nctl.name));
658
	memcpy(&nctl.id, &nbr->id, sizeof(nctl.id));
659
	memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr));
660
	memcpy(&nctl.dr, &nbr->dr, sizeof(nctl.dr));
661
	memcpy(&nctl.bdr, &nbr->bdr, sizeof(nctl.bdr));
662
	memcpy(&nctl.area, &nbr->iface->area->id, sizeof(nctl.area));
663
664
	/* this list is 99% of the time empty so that's OK for now */
665
	nctl.db_sum_lst_cnt = 0;
666
	TAILQ_FOREACH(le, &nbr->db_sum_list, entry)
667
		nctl.db_sum_lst_cnt++;
668
669
	nctl.ls_req_lst_cnt = nbr->ls_req_cnt;
670
	nctl.ls_retrans_lst_cnt = nbr->ls_ret_cnt;
671
672
	nctl.nbr_state = nbr->state;
673
674
	/*
675
	 * We need to trick a bit to show the remote iface state.
676
	 * The idea is to print DR, BDR or DROther dependent on
677
	 * the type of the neighbor.
678
	 */
679
	if (nbr->iface->dr == nbr)
680
		nctl.iface_state = IF_STA_DR;
681
	else if (nbr->iface->bdr == nbr)
682
		nctl.iface_state = IF_STA_BACKUP;
683
	else if (nbr->iface->state & IF_STA_MULTI)
684
		nctl.iface_state = IF_STA_DROTHER;
685
	else
686
		nctl.iface_state = nbr->iface->state;
687
688
	nctl.state_chng_cnt = nbr->stats.sta_chng;
689
690
	nctl.priority = nbr->priority;
691
	nctl.options = nbr->options | nbr->capa_options;
692
693
	gettimeofday(&now, NULL);
694
	if (evtimer_pending(&nbr->inactivity_timer, &tv)) {
695
		timersub(&tv, &now, &res);
696
		if (nbr->state & NBR_STA_DOWN)
697
			nctl.dead_timer = DEFAULT_NBR_TMOUT - res.tv_sec;
698
		else
699
			nctl.dead_timer = res.tv_sec;
700
	} else
701
		nctl.dead_timer = 0;
702
703
	if (nbr->state == NBR_STA_FULL) {
704
		nctl.uptime = now.tv_sec - nbr->uptime;
705
	} else
706
		nctl.uptime = 0;
707
708
	return (&nctl);
709
}
710
711
struct lsa_hdr *
712
lsa_hdr_new(void)
713
{
714
	struct lsa_hdr	*lsa_hdr = NULL;
715
716
	if ((lsa_hdr = calloc(1, sizeof(*lsa_hdr))) == NULL)
717
		fatal("lsa_hdr_new");
718
719
	return (lsa_hdr);
720
}