xref: /openbsd/usr.sbin/ldpd/neighbor.c (revision 404b540a)
1 /*	$OpenBSD: neighbor.c,v 1.3 2009/08/01 12:47:02 michele Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/ioctl.h>
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <net/if.h>
28 
29 #include <ctype.h>
30 #include <err.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <event.h>
35 #include <unistd.h>
36 
37 #include "ldpd.h"
38 #include "ldp.h"
39 #include "ldpe.h"
40 #include "log.h"
41 #include "lde.h"
42 
43 int	nbr_establish_connection(struct nbr *);
44 void	nbr_send_labelmappings(struct nbr *);
45 
46 LIST_HEAD(nbr_head, nbr);
47 
48 struct nbr_table {
49 	struct nbr_head		*hashtbl;
50 	u_int32_t		 hashmask;
51 } nbrtable;
52 
53 #define NBR_HASH(x)		\
54 	&nbrtable.hashtbl[(x) & nbrtable.hashmask]
55 
56 u_int32_t	peercnt = NBR_CNTSTART;
57 
58 extern struct ldpd_conf	*leconf;
59 
60 struct {
61 	int		state;
62 	enum nbr_event	event;
63 	enum nbr_action	action;
64 	int		new_state;
65 } nbr_fsm_tbl[] = {
66     /* current state	event that happened	action to take		resulting state */
67 /* Discovery States */
68     {NBR_STA_DOWN,	NBR_EVT_HELLO_RCVD,	NBR_ACT_STRT_ITIMER,	NBR_STA_PRESENT},
69     {NBR_STA_UP,	NBR_EVT_HELLO_RCVD,	NBR_ACT_RST_ITIMER,	0},
70 /* Passive Role */
71     {NBR_STA_PRESENT,	NBR_EVT_SESSION_UP,	NBR_ACT_SESSION_EST,	NBR_STA_INITIAL},
72     {NBR_STA_INITIAL,	NBR_EVT_INIT_RCVD,	NBR_ACT_INIT_SEND,	NBR_STA_OPENREC},
73     {NBR_STA_OPENREC,	NBR_EVT_KEEPALIVE_RCVD,	NBR_ACT_STRT_KTIMER,	NBR_STA_OPER},
74 /* Active Role */
75     {NBR_STA_PRESENT,	NBR_EVT_INIT_SENT,	NBR_ACT_NOTHING,	NBR_STA_OPENSENT},
76     {NBR_STA_OPENSENT,	NBR_EVT_INIT_RCVD,	NBR_ACT_KEEPALIVE_SEND,	NBR_STA_OPER},
77 /* Session Maintenance */
78     {NBR_STA_OPER,	NBR_EVT_PDU_RCVD,	NBR_ACT_RST_KTIMEOUT,	0},
79 /* Session Close */
80     {NBR_STA_SESSION,	NBR_EVT_CLOSE_SESSION,	NBR_ACT_CLOSE_SESSION,	NBR_STA_PRESENT},
81     {NBR_STA_UP,	NBR_EVT_DOWN,		NBR_ACT_CLOSE_SESSION,	},
82     {-1,		NBR_EVT_NOTHING,	NBR_ACT_NOTHING,	0},
83 };
84 
85 const char * const nbr_event_names[] = {
86 	"NOTHING",
87 	"HELLO RECEIVED",
88 	"SESSION UP",
89 	"SESSION CLOSE",
90 	"INIT RECEIVED",
91 	"KEEPALIVE RECEIVED",
92 	"PDU RECEIVED",
93 	"INIT SENT",
94 	"DOWN"
95 };
96 
97 const char * const nbr_action_names[] = {
98 	"NOTHING",
99 	"START INACTIVITY TIMER",
100 	"RESET INACTIVITY TIMER",
101 	"RESET KEEPALIVE TIMEOUT",
102 	"START KEEPALIVE TIMER",
103 	"RESET KEEPALIVE TIMER",
104 	"START NEIGHBOR SESSION",
105 	"SEND INIT",
106 	"SEND KEEPALIVE",
107 	"CLOSE SESSION"
108 };
109 
110 int
111 nbr_fsm(struct nbr *nbr, enum nbr_event event)
112 {
113 	struct timeval	now;
114 	int		old_state;
115 	int		new_state = 0;
116 	int		i, ret = 0;
117 
118 	if (nbr == nbr->iface->self)
119 		return (0);
120 
121 	old_state = nbr->state;
122 	for (i = 0; nbr_fsm_tbl[i].state != -1; i++)
123 		if ((nbr_fsm_tbl[i].state & old_state) &&
124 		    (nbr_fsm_tbl[i].event == event)) {
125 			new_state = nbr_fsm_tbl[i].new_state;
126 			break;
127 		}
128 
129 	if (nbr_fsm_tbl[i].state == -1) {
130 		/* event outside of the defined fsm, ignore it. */
131 		log_warnx("nbr_fsm: neighbor ID %s, "
132 		    "event %s not expected in state %s",
133 		    inet_ntoa(nbr->id), nbr_event_names[event],
134 		    nbr_state_name(old_state));
135 		return (0);
136 	}
137 
138 	switch (nbr_fsm_tbl[i].action) {
139 	case NBR_ACT_RST_ITIMER:
140 		ret = nbr_act_reset_itimer(nbr);
141 		break;
142 	case NBR_ACT_STRT_ITIMER:
143 		ret = nbr_act_start_itimer(nbr);
144 		break;
145 	case NBR_ACT_RST_KTIMEOUT:
146 		ret = nbr_act_reset_ktimeout(nbr);
147 		break;
148 	case NBR_ACT_RST_KTIMER:
149 		ret = nbr_act_reset_ktimer(nbr);
150 		break;
151 	case NBR_ACT_STRT_KTIMER:
152 		/* XXX */
153 		ret = nbr_act_start_ktimer(nbr);
154 		nbr_act_start_ktimeout(nbr);
155 		send_address(nbr, NULL);
156 		nbr_send_labelmappings(nbr);
157 		break;
158 	case NBR_ACT_SESSION_EST:
159 		ret = nbr_act_session_establish(nbr, 0);
160 		break;
161 	case NBR_ACT_INIT_SEND:
162 		/* XXX */
163 		send_keepalive(nbr);
164 		ret = send_init(nbr);
165 		break;
166 	case NBR_ACT_KEEPALIVE_SEND:
167 		/* XXX */
168 		ret = nbr_act_start_ktimer(nbr);
169 		nbr_act_start_ktimeout(nbr);
170 		send_keepalive(nbr);
171 		send_address(nbr, NULL);
172 		nbr_send_labelmappings(nbr);
173 		break;
174 	case NBR_ACT_CLOSE_SESSION:
175 		session_close(nbr);
176 		ret = nbr_act_start_idtimer(nbr);
177 		break;
178 	case NBR_ACT_NOTHING:
179 		/* do nothing */
180 		break;
181 	}
182 
183 	if (ret) {
184 		log_warnx("nbr_fsm: error changing state for neighbor ID %s, "
185 		    "event %s, state %s", inet_ntoa(nbr->id),
186 		    nbr_event_names[event], nbr_state_name(old_state));
187 		return (-1);
188 	}
189 
190 	if (new_state != 0)
191 		nbr->state = new_state;
192 
193 	if (old_state != nbr->state) {
194 		log_debug("nbr_fsm: event %s resulted in action %s and "
195 		    "changing state for neighbor ID %s from %s to %s",
196 		    nbr_event_names[event],
197 		    nbr_action_names[nbr_fsm_tbl[i].action],
198 		    inet_ntoa(nbr->id), nbr_state_name(old_state),
199 		    nbr_state_name(nbr->state));
200 
201 		if (nbr->state == NBR_STA_OPER) {
202 			gettimeofday(&now, NULL);
203 			nbr->uptime = now.tv_sec;
204 		}
205 	}
206 
207 	return (ret);
208 }
209 
210 void
211 nbr_init(u_int32_t hashsize)
212 {
213 	struct nbr_head	*head;
214 	struct nbr	*nbr;
215 	u_int32_t        hs, i;
216 
217 	for (hs = 1; hs < hashsize; hs <<= 1)
218 		;
219 	nbrtable.hashtbl = calloc(hs, sizeof(struct nbr_head));
220 	if (nbrtable.hashtbl == NULL)
221 		fatal("nbr_init");
222 
223 	for (i = 0; i < hs; i++)
224 		LIST_INIT(&nbrtable.hashtbl[i]);
225 
226 	nbrtable.hashmask = hs - 1;
227 
228 	/* allocate a dummy neighbor used for self originated AS ext routes */
229 	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
230 		fatal("nbr_init");
231 
232 	nbr->id.s_addr = ldpe_router_id();
233 	nbr->state = NBR_STA_DOWN;
234 	nbr->peerid = NBR_IDSELF;
235 	head = NBR_HASH(nbr->peerid);
236 	LIST_INSERT_HEAD(head, nbr, hash);
237 
238 	TAILQ_INIT(&nbr->mapping_list);
239 	TAILQ_INIT(&nbr->withdraw_list);
240 	TAILQ_INIT(&nbr->request_list);
241 	TAILQ_INIT(&nbr->release_list);
242 	TAILQ_INIT(&nbr->abortreq_list);
243 }
244 
245 struct nbr *
246 nbr_new(u_int32_t nbr_id, u_int16_t lspace, struct iface *iface, int self)
247 {
248 	struct nbr_head	*head;
249 	struct nbr	*nbr;
250 	struct lde_nbr	 rn;
251 
252 	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
253 		fatal("nbr_new");
254 
255 	nbr->state = NBR_STA_DOWN;
256 	nbr->id.s_addr = nbr_id;
257 	nbr->lspace = lspace;
258 
259 	/* get next unused peerid */
260 	while (nbr_find_peerid(++peercnt))
261 		;
262 	nbr->peerid = peercnt;
263 	head = NBR_HASH(nbr->peerid);
264 	LIST_INSERT_HEAD(head, nbr, hash);
265 
266 	/* add to peer list */
267 	nbr->iface = iface;
268 	LIST_INSERT_HEAD(&iface->nbr_list, nbr, entry);
269 
270 	if (self) {
271 		nbr->addr.s_addr = iface->addr.s_addr;
272 		nbr->priority = iface->priority;
273 	}
274 
275 	/* set event structures */
276 	evtimer_set(&nbr->inactivity_timer, nbr_itimer, nbr);
277 	evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr);
278 	evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr);
279 	evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr);
280 
281 	bzero(&rn, sizeof(rn));
282 	rn.id.s_addr = nbr->id.s_addr;
283 	rn.lspace = nbr->lspace;
284 	rn.ifindex = nbr->iface->ifindex;
285 	rn.self = self;
286 	ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn,
287 	    sizeof(rn));
288 
289 	return (nbr);
290 }
291 
292 void
293 nbr_del(struct nbr *nbr)
294 {
295 	ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, NULL, 0);
296 
297 	if (evtimer_pending(&nbr->inactivity_timer, NULL))
298 		evtimer_del(&nbr->inactivity_timer);
299 	if (evtimer_pending(&nbr->keepalive_timer, NULL))
300 		evtimer_del(&nbr->keepalive_timer);
301 	if (evtimer_pending(&nbr->keepalive_timeout, NULL))
302 		evtimer_del(&nbr->keepalive_timeout);
303 	if (evtimer_pending(&nbr->initdelay_timer, NULL))
304 		evtimer_del(&nbr->initdelay_timer);
305 
306 	nbr_mapping_list_clr(nbr, &nbr->mapping_list);
307 
308 	LIST_REMOVE(nbr, entry);
309 	LIST_REMOVE(nbr, hash);
310 
311 	free(nbr);
312 }
313 
314 struct nbr *
315 nbr_find_peerid(u_int32_t peerid)
316 {
317 	struct nbr_head	*head;
318 	struct nbr	*nbr;
319 
320 	head = NBR_HASH(peerid);
321 
322 	LIST_FOREACH(nbr, head, hash) {
323 		if (nbr->peerid == peerid)
324 			return (nbr);
325 	}
326 
327 	return (NULL);
328 }
329 
330 struct nbr *
331 nbr_find_ip(struct iface *iface, u_int32_t rtr_id)
332 {
333 	struct nbr	*nbr = NULL;
334 
335 	LIST_FOREACH(nbr, &iface->nbr_list, entry) {
336 		if (nbr->addr.s_addr == rtr_id)
337 			return (nbr);
338 	}
339 
340 	return (NULL);
341 }
342 
343 struct nbr *
344 nbr_find_ldpid(struct iface *iface, u_int32_t rtr_id, u_int16_t lspace)
345 {
346 	struct nbr	*nbr = NULL;
347 
348 	LIST_FOREACH(nbr, &iface->nbr_list, entry) {
349 		if (nbr->id.s_addr == rtr_id && nbr->lspace == lspace)
350 			return (nbr);
351 	}
352 
353 	return (NULL);
354 }
355 
356 /* timers */
357 
358 /* Inactivity timer: timeout based on hellos */
359 /* ARGSUSED */
360 void
361 nbr_itimer(int fd, short event, void *arg)
362 {
363 	struct nbr *nbr = arg;
364 
365 	log_debug("nbr_itimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
366 	    nbr->peerid);
367 
368 	nbr_del(nbr);
369 }
370 
371 void
372 nbr_start_itimer(struct nbr *nbr)
373 {
374 	struct timeval	tv;
375 
376 	timerclear(&tv);
377 	tv.tv_sec = nbr->holdtime;
378 
379 	if (evtimer_add(&nbr->inactivity_timer, &tv) == -1)
380 		fatal("nbr_start_itimer");
381 }
382 
383 void
384 nbr_stop_itimer(struct nbr *nbr)
385 {
386 	if (evtimer_del(&nbr->inactivity_timer) == -1)
387 		fatal("nbr_stop_itimer");
388 }
389 
390 void
391 nbr_reset_itimer(struct nbr *nbr)
392 {
393 	struct timeval	tv;
394 
395 	timerclear(&tv);
396 	tv.tv_sec = nbr->holdtime;
397 
398 	if (evtimer_add(&nbr->inactivity_timer, &tv) == -1)
399 		fatal("nbr_reset_itimer");
400 }
401 
402 /* Keepalive timer: timer to send keepalive message to neighbors */
403 
404 void
405 nbr_ktimer(int fd, short event, void *arg)
406 {
407 	struct nbr	*nbr = arg;
408 	struct timeval	 tv;
409 
410 	log_debug("nbr_ktimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
411 	    nbr->peerid);
412 
413 	send_keepalive(nbr);
414 
415 	timerclear(&tv);
416 	tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
417 	if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
418 		fatal("nbr_ktimer");
419 }
420 
421 void
422 nbr_start_ktimer(struct nbr *nbr)
423 {
424 	struct timeval	tv;
425 
426 	timerclear(&tv);
427 
428 	/* XXX: just to be sure it will send three keepalives per period */
429 	tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
430 
431 	if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
432 		fatal("nbr_start_ktimer");
433 }
434 
435 void
436 nbr_stop_ktimer(struct nbr *nbr)
437 {
438 	if (evtimer_del(&nbr->keepalive_timer) == -1)
439 		fatal("nbr_stop_ktimer");
440 }
441 
442 void
443 nbr_reset_ktimer(struct nbr *nbr)
444 {
445 	struct timeval	tv;
446 
447 	timerclear(&tv);
448 
449 	/* XXX: just to be sure it will send three keepalives per period */
450 	tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
451 
452 	if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
453 		fatal("nbr_reset_ktimer");
454 }
455 
456 /* Keepalive timeout: if the nbr hasn't sent keepalive */
457 
458 void
459 nbr_ktimeout(int fd, short event, void *arg)
460 {
461 	struct nbr *nbr = arg;
462 
463 	log_debug("nbr_ktimeout: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
464 	    nbr->peerid);
465 
466 	send_notification_nbr(nbr, S_KEEPALIVE_TMR, 0, 0);
467 	close(nbr->fd);
468 }
469 
470 void
471 nbr_start_ktimeout(struct nbr *nbr)
472 {
473 	struct timeval	tv;
474 
475 	timerclear(&tv);
476 	tv.tv_sec = nbr->keepalive;
477 
478 	if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1)
479 		fatal("nbr_start_ktimeout");
480 }
481 
482 void
483 nbr_stop_ktimeout(struct nbr *nbr)
484 {
485 	if (evtimer_del(&nbr->keepalive_timeout) == -1)
486 		fatal("nbr_stop_ktimeout");
487 }
488 
489 void
490 nbr_reset_ktimeout(struct nbr *nbr)
491 {
492 	struct timeval	tv;
493 
494 	timerclear(&tv);
495 	tv.tv_sec = nbr->keepalive;
496 
497 	if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1)
498 		fatal("nbr_reset_ktimeout");
499 }
500 
501 /* Init delay timer: timer to retry to iniziatize session */
502 
503 void
504 nbr_idtimer(int fd, short event, void *arg)
505 {
506 	struct nbr *nbr = arg;
507 
508 	log_debug("nbr_idtimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
509 	    nbr->peerid);
510 
511 	nbr_act_session_establish(nbr, 1);
512 }
513 
514 void
515 nbr_start_idtimer(struct nbr *nbr)
516 {
517 	struct timeval	tv;
518 
519 	timerclear(&tv);
520 	tv.tv_sec = INIT_DELAY_TMR;
521 
522 	if (evtimer_add(&nbr->initdelay_timer, &tv) == -1)
523 		fatal("nbr_start_idtimer");
524 }
525 
526 void
527 nbr_stop_idtimer(struct nbr *nbr)
528 {
529 	if (evtimer_del(&nbr->initdelay_timer) == -1)
530 		fatal("nbr_stop_idtimer");
531 }
532 
533 int
534 nbr_pending_idtimer(struct nbr *nbr)
535 {
536 	if (evtimer_pending(&nbr->initdelay_timer, NULL))
537 		return (1);
538 
539 	return (0);
540 }
541 
542 
543 void
544 nbr_reset_idtimer(struct nbr *nbr)
545 {
546 	struct timeval	tv;
547 
548 	timerclear(&tv);
549 	tv.tv_sec = INIT_DELAY_TMR;
550 
551 	if (evtimer_add(&nbr->initdelay_timer, &tv) == -1)
552 		fatal("nbr_reset_idtimer");
553 }
554 /* actions */
555 int
556 nbr_act_reset_itimer(struct nbr *nbr)
557 {
558 	nbr_reset_itimer(nbr);
559 
560 	return (0);
561 }
562 
563 int
564 nbr_act_start_itimer(struct nbr *nbr)
565 {
566 	nbr_start_itimer(nbr);
567 
568 	return (0);
569 }
570 
571 int
572 nbr_act_reset_ktimer(struct nbr *nbr)
573 {
574 	nbr_reset_ktimer(nbr);
575 
576 	return (0);
577 }
578 
579 int
580 nbr_act_start_ktimer(struct nbr *nbr)
581 {
582 	nbr_start_ktimer(nbr);
583 
584 	return (0);
585 }
586 
587 int
588 nbr_act_reset_ktimeout(struct nbr *nbr)
589 {
590 	nbr_reset_ktimeout(nbr);
591 
592 	return (0);
593 }
594 
595 int
596 nbr_act_start_ktimeout(struct nbr *nbr)
597 {
598 	nbr_start_ktimeout(nbr);
599 
600 	return (0);
601 }
602 
603 int
604 nbr_act_reset_idtimer(struct nbr *nbr)
605 {
606 	nbr_reset_idtimer(nbr);
607 
608 	return (0);
609 }
610 
611 int
612 nbr_act_start_idtimer(struct nbr *nbr)
613 {
614 	if (nbr->addr.s_addr < nbr->iface->addr.s_addr)
615 		nbr_start_idtimer(nbr);
616 
617 	return (0);
618 }
619 
620 int
621 nbr_establish_connection(struct nbr *nbr)
622 {
623 	struct sockaddr_in	in;
624 	int			st;
625 
626 	in.sin_family = AF_INET;
627 	in.sin_port = htons(LDP_PORT);
628 	in.sin_addr.s_addr = nbr->addr.s_addr;
629 
630 	nbr->fd = socket(AF_INET, SOCK_STREAM, 0);
631 	if (nbr->fd < 0) {
632 		log_debug("nbr_establish_connection: error while "
633 		    "creating socket");
634 		return (-1);
635 	}
636 
637 	st = connect(nbr->fd, (struct sockaddr *)&in, sizeof(in));
638 	if (st < 0 ) {
639 		log_debug("nbr_establish_connection: error while "
640 		    "connecting to %s", inet_ntoa(nbr->addr));
641 		nbr_act_start_idtimer(nbr);
642 		return (-1);
643 	}
644 
645 	return (0);
646 }
647 
648 int
649 nbr_close_connection(struct nbr *nbr)
650 {
651 	bufferevent_disable(nbr->bev, EV_READ|EV_WRITE);
652 	bufferevent_free(nbr->bev);
653 	close(nbr->fd);
654 
655 	return (0);
656 }
657 
658 int
659 nbr_act_session_establish(struct nbr *nbr, int active)
660 {
661 	evbuffercb	readfn = session_read;
662 	everrorcb	errorfn = session_error;
663 
664 	if (active) {
665 		if (nbr_establish_connection(nbr) < 0)
666 			return (-1);
667 	}
668 
669 	nbr->bev = bufferevent_new(nbr->fd, readfn, NULL, errorfn, nbr);
670 	bufferevent_settimeout(nbr->bev, 0, 0);
671 	bufferevent_enable(nbr->bev, EV_READ|EV_WRITE);
672 
673 	if (active) {
674 		send_init(nbr);
675 		nbr_fsm(nbr, NBR_EVT_INIT_SENT);
676 	}
677 
678 
679 	return (0);
680 }
681 
682 void
683 nbr_send_labelmappings(struct nbr *nbr)
684 {
685 	if (leconf->mode & MODE_ADV_UNSOLICITED) {
686 		ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0,
687 		    0, 0);
688 	}
689 }
690 
691 void
692 nbr_mapping_add(struct nbr *nbr, struct mapping_head *mh, struct map *map)
693 {
694 	struct mapping_entry	*me;
695 
696 	me = calloc(1, sizeof(*me));
697 	if (me == NULL)
698 		fatal("nbr_mapping_add");
699 
700 	me->prefix = map->prefix;
701 	me->prefixlen = map->prefixlen;
702 	me->label = map->label;
703 
704 	TAILQ_INSERT_HEAD(mh, me, entry);
705 }
706 
707 struct mapping_entry *
708 nbr_mapping_find(struct nbr *nbr, struct mapping_head *mh, struct map *map)
709 {
710 	struct mapping_entry	*me = NULL;
711 
712 	TAILQ_FOREACH(me, mh, entry) {
713 		if (me->prefix == map->prefix &&
714 		    me->prefixlen == map->prefixlen)
715 			return (me);
716 	}
717 
718 	return (NULL);
719 }
720 
721 void
722 nbr_mapping_del(struct nbr *nbr, struct mapping_head *mh, struct map *map)
723 {
724 	struct mapping_entry	*me;
725 
726 	me = nbr_mapping_find(nbr, mh, map);
727 	if (me == NULL)
728 		return;
729 
730 	TAILQ_REMOVE(mh, me, entry);
731 	free(me);
732 }
733 
734 void
735 nbr_mapping_list_clr(struct nbr *nbr, struct mapping_head *mh)
736 {
737 	struct mapping_entry	*me;
738 
739 	while ((me = TAILQ_FIRST(mh)) != NULL) {
740 		TAILQ_REMOVE(mh, me, entry);
741 		free(me);
742 	}
743 }
744 
745 struct ctl_nbr *
746 nbr_to_ctl(struct nbr *nbr)
747 {
748 	static struct ctl_nbr	 nctl;
749 	struct timeval		 tv, now, res;
750 
751 	memcpy(nctl.name, nbr->iface->name, sizeof(nctl.name));
752 	memcpy(&nctl.id, &nbr->id, sizeof(nctl.id));
753 	memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr));
754 
755 	nctl.nbr_state = nbr->state;
756 	nctl.iface_state = nbr->iface->state;
757 
758 	gettimeofday(&now, NULL);
759 	if (evtimer_pending(&nbr->inactivity_timer, &tv)) {
760 		timersub(&tv, &now, &res);
761 		if (nbr->state & NBR_STA_DOWN)
762 			nctl.dead_timer = DEFAULT_NBR_TMOUT - res.tv_sec;
763 		else
764 			nctl.dead_timer = res.tv_sec;
765 	} else
766 		nctl.dead_timer = 0;
767 
768 	if (nbr->state == NBR_STA_OPER) {
769 		nctl.uptime = now.tv_sec - nbr->uptime;
770 	} else
771 		nctl.uptime = 0;
772 
773 	return (&nctl);
774 }
775