xref: /openbsd-src/usr.sbin/ldpd/lde.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: lde.c,v 1.22 2010/10/26 12:08:14 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
5  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6  * Copyright (c) 2003, 2004 Henning Brauer <henning@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/socket.h>
23 #include <sys/queue.h>
24 #include <netinet/in.h>
25 #include <netmpls/mpls.h>
26 #include <arpa/inet.h>
27 #include <err.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <pwd.h>
33 #include <unistd.h>
34 #include <event.h>
35 
36 #include "ldp.h"
37 #include "ldpd.h"
38 #include "ldpe.h"
39 #include "log.h"
40 #include "lde.h"
41 
42 void		 lde_sig_handler(int sig, short, void *);
43 void		 lde_shutdown(void);
44 void		 lde_dispatch_imsg(int, short, void *);
45 void		 lde_dispatch_parent(int, short, void *);
46 
47 struct lde_nbr	*lde_nbr_find(u_int32_t);
48 struct lde_nbr	*lde_nbr_new(u_int32_t, struct lde_nbr *);
49 void		 lde_nbr_del(struct lde_nbr *);
50 void		 lde_nbr_clear(void);
51 
52 void		 lde_map_free(void *);
53 void		 lde_address_list_free(struct lde_nbr *);
54 
55 struct ldpd_conf	*ldeconf = NULL, *nconf = NULL;
56 struct imsgev		*iev_ldpe;
57 struct imsgev		*iev_main;
58 
59 /* ARGSUSED */
60 void
61 lde_sig_handler(int sig, short event, void *arg)
62 {
63 	/*
64 	 * signal handler rules don't apply, libevent decouples for us
65 	 */
66 
67 	switch (sig) {
68 	case SIGINT:
69 	case SIGTERM:
70 		lde_shutdown();
71 		/* NOTREACHED */
72 	default:
73 		fatalx("unexpected signal");
74 	}
75 }
76 
77 /* label decision engine */
78 pid_t
79 lde(struct ldpd_conf *xconf, int pipe_parent2lde[2], int pipe_ldpe2lde[2],
80     int pipe_parent2ldpe[2])
81 {
82 	struct event		 ev_sigint, ev_sigterm;
83 	struct timeval		 now;
84 	struct passwd		*pw;
85 	pid_t			 pid;
86 
87 	switch (pid = fork()) {
88 	case -1:
89 		fatal("cannot fork");
90 		/* NOTREACHED */
91 	case 0:
92 		break;
93 	default:
94 		return (pid);
95 	}
96 
97 	ldeconf = xconf;
98 
99 	if ((pw = getpwnam(LDPD_USER)) == NULL)
100 		fatal("getpwnam");
101 
102 	if (chroot(pw->pw_dir) == -1)
103 		fatal("chroot");
104 	if (chdir("/") == -1)
105 		fatal("chdir(\"/\")");
106 
107 	setproctitle("label decision engine");
108 	ldpd_process = PROC_LDE_ENGINE;
109 
110 	if (setgroups(1, &pw->pw_gid) ||
111 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
112 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
113 		fatal("can't drop privileges");
114 
115 	event_init();
116 
117 	/* setup signal handler */
118 	signal_set(&ev_sigint, SIGINT, lde_sig_handler, NULL);
119 	signal_set(&ev_sigterm, SIGTERM, lde_sig_handler, NULL);
120 	signal_add(&ev_sigint, NULL);
121 	signal_add(&ev_sigterm, NULL);
122 	signal(SIGPIPE, SIG_IGN);
123 	signal(SIGHUP, SIG_IGN);
124 
125 	/* setup pipes */
126 	close(pipe_ldpe2lde[0]);
127 	close(pipe_parent2lde[0]);
128 	close(pipe_parent2ldpe[0]);
129 	close(pipe_parent2ldpe[1]);
130 
131 	if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL ||
132 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
133 		fatal(NULL);
134 	imsg_init(&iev_ldpe->ibuf, pipe_ldpe2lde[1]);
135 	iev_ldpe->handler = lde_dispatch_imsg;
136 	imsg_init(&iev_main->ibuf, pipe_parent2lde[1]);
137 	iev_main->handler = lde_dispatch_parent;
138 
139 	/* setup event handler */
140 	iev_ldpe->events = EV_READ;
141 	event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events,
142 	    iev_ldpe->handler, iev_ldpe);
143 	event_add(&iev_ldpe->ev, NULL);
144 
145 	iev_main->events = EV_READ;
146 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
147 	    iev_main->handler, iev_main);
148 	event_add(&iev_main->ev, NULL);
149 
150 	gettimeofday(&now, NULL);
151 	ldeconf->uptime = now.tv_sec;
152 
153 	event_dispatch();
154 
155 	lde_shutdown();
156 	/* NOTREACHED */
157 
158 	return (0);
159 }
160 
161 void
162 lde_shutdown(void)
163 {
164 	lde_nbr_clear();
165 	rt_clear();
166 
167 	msgbuf_clear(&iev_ldpe->ibuf.w);
168 	free(iev_ldpe);
169 	msgbuf_clear(&iev_main->ibuf.w);
170 	free(iev_main);
171 	free(ldeconf);
172 
173 	log_info("label decision engine exiting");
174 	_exit(0);
175 }
176 
177 int
178 lde_imsg_compose_ldpe(int type, u_int32_t peerid, pid_t pid, void *data,
179     u_int16_t datalen)
180 {
181 	return (imsg_compose_event(iev_ldpe, type, peerid, pid,
182 	     -1, data, datalen));
183 }
184 
185 /* ARGSUSED */
186 void
187 lde_dispatch_imsg(int fd, short event, void *bula)
188 {
189 	struct imsgev		*iev = bula;
190 	struct imsgbuf		*ibuf = &iev->ibuf;
191 	struct imsg		 imsg;
192 	struct lde_nbr		 rn, *nbr;
193 	struct map		 map;
194 	struct timespec		 tp;
195 	struct in_addr		 addr;
196 	ssize_t			 n;
197 	time_t			 now;
198 	int			 state, shut = 0, verbose;
199 
200 	if (event & EV_READ) {
201 		if ((n = imsg_read(ibuf)) == -1)
202 			fatal("imsg_read error");
203 		if (n == 0)	/* connection closed */
204 			shut = 1;
205 	}
206 	if (event & EV_WRITE) {
207 		if (msgbuf_write(&ibuf->w) == -1)
208 			fatal("msgbuf_write");
209 	}
210 
211 	clock_gettime(CLOCK_MONOTONIC, &tp);
212 	now = tp.tv_sec;
213 
214 	for (;;) {
215 		if ((n = imsg_get(ibuf, &imsg)) == -1)
216 			fatal("lde_dispatch_imsg: imsg_read error");
217 		if (n == 0)
218 			break;
219 
220 		switch (imsg.hdr.type) {
221 		case IMSG_LABEL_MAPPING_FULL:
222 			nbr = lde_nbr_find(imsg.hdr.peerid);
223 			if (nbr == NULL) {
224 				log_debug("lde_dispatch_imsg: cannot find "
225 				    "lde neighbor");
226 				return;
227 			}
228 
229 			rt_snap(nbr);
230 			lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END,
231 			    imsg.hdr.peerid, 0, NULL, 0);
232 			break;
233 		case IMSG_LABEL_MAPPING:
234 		case IMSG_LABEL_REQUEST:
235 		case IMSG_LABEL_RELEASE:
236 		case IMSG_LABEL_WITHDRAW:
237 		case IMSG_LABEL_ABORT:
238 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
239 				fatalx("invalid size of OE request");
240 			memcpy(&map, imsg.data, sizeof(map));
241 
242 			nbr = lde_nbr_find(imsg.hdr.peerid);
243 			if (nbr == NULL) {
244 				log_debug("lde_dispatch_imsg: cannot find "
245 				    "lde neighbor");
246 				return;
247 			}
248 
249 			switch (imsg.hdr.type) {
250 			case IMSG_LABEL_MAPPING:
251 				lde_check_mapping(&map, nbr);
252 				break;
253 			case IMSG_LABEL_REQUEST:
254 				lde_check_request(&map, nbr);
255 				break;
256 			case IMSG_LABEL_RELEASE:
257 				lde_check_release(&map, nbr);
258 				break;
259 			case IMSG_LABEL_WITHDRAW:
260 				lde_check_withdraw(&map, nbr);
261 				break;
262 			default:
263 				log_warnx("type %d not yet handled. nbr %s",
264 				    imsg.hdr.type, inet_ntoa(nbr->id));
265 			}
266 			break;
267 		case IMSG_ADDRESS_ADD:
268 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr))
269 				fatalx("invalid size of OE request");
270 			memcpy(&addr, imsg.data, sizeof(addr));
271 
272 			nbr = lde_nbr_find(imsg.hdr.peerid);
273 			if (nbr == NULL) {
274 				log_debug("lde_dispatch_imsg: cannot find "
275 				    "lde neighbor");
276 				return;
277 			}
278 
279 			if (lde_address_add(nbr, &addr) < 0) {
280 				log_debug("lde_dispatch_imsg: cannot add "
281 				    "address %s, it already exists",
282 				    inet_ntoa(addr));
283 			}
284 
285 			break;
286 		case IMSG_ADDRESS_DEL:
287 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr))
288 				fatalx("invalid size of OE request");
289 			memcpy(&addr, imsg.data, sizeof(addr));
290 
291 			nbr = lde_nbr_find(imsg.hdr.peerid);
292 			if (nbr == NULL) {
293 				log_debug("lde_dispatch_imsg: cannot find "
294 				    "lde neighbor");
295 				return;
296 			}
297 
298 			if (lde_address_del(nbr, &addr) < 0) {
299 				log_debug("lde_dispatch_imsg: cannot delete "
300 				    "address %s, it does not exists",
301 				    inet_ntoa(addr));
302 			}
303 
304 			break;
305 		case IMSG_NEIGHBOR_UP:
306 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn))
307 				fatalx("invalid size of OE request");
308 			memcpy(&rn, imsg.data, sizeof(rn));
309 
310 			if (lde_nbr_find(imsg.hdr.peerid))
311 				fatalx("lde_dispatch_imsg: "
312 				    "neighbor already exists");
313 			lde_nbr_new(imsg.hdr.peerid, &rn);
314 			break;
315 		case IMSG_NEIGHBOR_DOWN:
316 			lde_nbr_del(lde_nbr_find(imsg.hdr.peerid));
317 			break;
318 		case IMSG_NEIGHBOR_CHANGE:
319 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
320 				fatalx("invalid size of OE request");
321 			memcpy(&state, imsg.data, sizeof(state));
322 
323 			nbr = lde_nbr_find(imsg.hdr.peerid);
324 			if (nbr == NULL)
325 				break;
326 
327 			nbr->state = state;
328 			break;
329 		case IMSG_CTL_SHOW_LIB:
330 			rt_dump(imsg.hdr.pid);
331 
332 			imsg_compose_event(iev_ldpe, IMSG_CTL_END, 0,
333 			    imsg.hdr.pid, -1, NULL, 0);
334 			break;
335 		case IMSG_CTL_LOG_VERBOSE:
336 			/* already checked by ldpe */
337 			memcpy(&verbose, imsg.data, sizeof(verbose));
338 			log_verbose(verbose);
339 			break;
340 		default:
341 			log_debug("lde_dispatch_imsg: unexpected imsg %d",
342 			    imsg.hdr.type);
343 			break;
344 		}
345 		imsg_free(&imsg);
346 	}
347 	if (!shut)
348 		imsg_event_add(iev);
349 	else {
350 		/* this pipe is dead, so remove the event handler */
351 		event_del(&iev->ev);
352 		event_loopexit(NULL);
353 	}
354 }
355 
356 /* ARGSUSED */
357 void
358 lde_dispatch_parent(int fd, short event, void *bula)
359 {
360 	struct imsg		 imsg;
361 	struct kroute		 kr;
362 	struct imsgev		*iev = bula;
363 	struct imsgbuf		*ibuf = &iev->ibuf;
364 	ssize_t			 n;
365 	int			 shut = 0;
366 
367 	if (event & EV_READ) {
368 		if ((n = imsg_read(ibuf)) == -1)
369 			fatal("imsg_read error");
370 		if (n == 0)	/* connection closed */
371 			shut = 1;
372 	}
373 	if (event & EV_WRITE) {
374 		if (msgbuf_write(&ibuf->w) == -1)
375 			fatal("msgbuf_write");
376 	}
377 
378 	for (;;) {
379 		if ((n = imsg_get(ibuf, &imsg)) == -1)
380 			fatal("lde_dispatch_parent: imsg_read error");
381 		if (n == 0)
382 			break;
383 
384 		switch (imsg.hdr.type) {
385 		case IMSG_NETWORK_ADD:
386 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
387 				log_warnx("lde_dispatch_parent: "
388 				    "wrong imsg len");
389 				break;
390 			}
391 			memcpy(&kr, imsg.data, sizeof(kr));
392 
393 			lde_kernel_insert(&kr);
394 			break;
395 		case IMSG_NETWORK_DEL:
396 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
397 				log_warnx("lde_dispatch_parent: "
398 				    "wrong imsg len");
399 				break;
400 			}
401 			memcpy(&kr, imsg.data, sizeof(kr));
402 
403 			lde_kernel_remove(&kr);
404 			break;
405 		case IMSG_RECONF_CONF:
406 			if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
407 			    NULL)
408 				fatal(NULL);
409 			memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
410 
411 			break;
412 		case IMSG_RECONF_IFACE:
413 			break;
414 		case IMSG_RECONF_END:
415 			break;
416 		default:
417 			log_debug("lde_dispatch_parent: unexpected imsg %d",
418 			    imsg.hdr.type);
419 			break;
420 		}
421 		imsg_free(&imsg);
422 	}
423 	if (!shut)
424 		imsg_event_add(iev);
425 	else {
426 		/* this pipe is dead, so remove the event handler */
427 		event_del(&iev->ev);
428 		event_loopexit(NULL);
429 	}
430 }
431 
432 u_int32_t
433 lde_assign_label(void)
434 {
435 	static u_int32_t label = MPLS_LABEL_RESERVED_MAX;
436 
437 	/* XXX some checks needed */
438 	label++;
439 	return label;
440 }
441 
442 void
443 lde_send_change_klabel(struct rt_node *rr, struct rt_lsp *rl)
444 {
445 	struct kroute	kr;
446 
447 	bzero(&kr, sizeof(kr));
448 	kr.prefix.s_addr = rr->fec.prefix.s_addr;
449 	kr.prefixlen = rr->fec.prefixlen;
450 	kr.local_label = rr->local_label;
451 
452 	kr.nexthop.s_addr = rl->nexthop.s_addr;
453 	kr.remote_label = rl->remote_label;
454 
455 	imsg_compose_event(iev_main, IMSG_KLABEL_CHANGE, 0, 0, -1,
456 	     &kr, sizeof(kr));
457 }
458 
459 void
460 lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl)
461 {
462 	struct kroute	 kr;
463 
464 	bzero(&kr, sizeof(kr));
465 	kr.prefix.s_addr = rr->fec.prefix.s_addr;
466 	kr.prefixlen = rr->fec.prefixlen;
467 	kr.local_label = rr->local_label;
468 
469 	kr.nexthop.s_addr = rl->nexthop.s_addr;
470 	kr.remote_label = rl->remote_label;
471 
472 	imsg_compose_event(iev_main, IMSG_KLABEL_DELETE, 0, 0, -1,
473 	     &kr, sizeof(kr));
474 }
475 
476 void
477 lde_send_labelrequest(struct lde_nbr *ln, struct rt_node *rn)
478 {
479 	struct map	 map;
480 
481 	/* TODO check if status of peer is OK to send requests (SLRq.2 & 6)
482 	 * For now assume no peer will send no-label-resource notifications */
483 
484 	/* check if request is already pending */
485 	if (fec_find(&ln->sent_req, &rn->fec) != NULL)
486 		return;
487 	/* and try to add request to pending list */
488 	lde_req_add(ln, &rn->fec, 1);
489 	/* msgid does not matter since only one req can be pending */
490 
491 	bzero(&map, sizeof(map));
492 	map.prefix = rn->fec.prefix;
493 	map.prefixlen = rn->fec.prefixlen;
494 
495 	imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD, ln->peerid, 0,
496 	     -1, &map, sizeof(map));
497 	imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD_END, ln->peerid, 0,
498 	     -1, NULL, 0);
499 }
500 
501 void
502 lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn)
503 {
504 	struct lde_req	*lre;
505 	struct lde_map	*me;
506 	struct map	 map;
507 
508 	/*
509 	 * This function skips SL.1 - 3 and SL.9 - 14 because the lable
510 	 * allocation is done way earlier (because of the merging nature of
511 	 * ldpd).
512 	 */
513 
514 	bzero(&map, sizeof(map));
515 	map.label = rn->local_label;
516 	map.prefix = rn->fec.prefix;
517 	map.prefixlen = rn->fec.prefixlen;
518 
519 	/* is there a pending request for this mapping? */
520 	lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
521 	if (lre) {
522 		/* set label request msg id in the mapping response. */
523 		map.requestid = lre->msgid;
524 		map.flags = F_MAP_REQ_ID;
525 		lde_req_del(ln, lre, 0);
526 	}
527 
528 	me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
529 	if (me == NULL)
530 		me = lde_map_add(ln, rn, 1);
531 	me->label = map.label;
532 
533 	imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD, ln->peerid, 0,
534 	     -1, &map, sizeof(map));
535 	imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD_END, ln->peerid, 0,
536 	     -1, NULL, 0);
537 }
538 
539 void
540 lde_send_labelrelease(struct lde_nbr *ln, struct rt_node *rn, u_int32_t label)
541 {
542 	struct map	 map;
543 
544 	bzero(&map, sizeof(map));
545 	map.prefix = rn->fec.prefix;
546 	map.prefixlen = rn->fec.prefixlen;
547 	if (label != NO_LABEL) {
548 		map.flags = F_MAP_OPTLABEL;
549 		map.label = label;
550 	}
551 
552 	imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD, ln->peerid, 0,
553 	    -1, &map, sizeof(map));
554 	imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD_END, ln->peerid, 0,
555 	    -1, NULL, 0);
556 }
557 
558 void
559 lde_send_notification(u_int32_t peerid, u_int32_t code, u_int32_t msgid,
560     u_int32_t type)
561 {
562 	struct notify_msg nm;
563 
564 	bzero(&nm, sizeof(nm));
565 
566 	/* Every field is in host byte order, to keep things clear */
567 	nm.status = code;
568 	nm.messageid = ntohl(msgid);
569 	nm.type = type;
570 
571 	imsg_compose_event(iev_ldpe, IMSG_NOTIFICATION_SEND, peerid, 0,
572 	    -1, &nm, sizeof(nm));
573 }
574 
575 static __inline int lde_nbr_compare(struct lde_nbr *, struct lde_nbr *);
576 
577 RB_HEAD(nbr_tree, lde_nbr);
578 RB_PROTOTYPE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
579 RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
580 
581 struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
582 
583 static __inline int
584 lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b)
585 {
586 	return (a->peerid - b->peerid);
587 }
588 
589 struct lde_nbr *
590 lde_nbr_find(u_int32_t peerid)
591 {
592 	struct lde_nbr	n;
593 
594 	n.peerid = peerid;
595 
596 	return (RB_FIND(nbr_tree, &lde_nbrs, &n));
597 }
598 
599 struct lde_nbr *
600 lde_nbr_new(u_int32_t peerid, struct lde_nbr *new)
601 {
602 	struct lde_nbr	*nbr;
603 
604 	if (lde_nbr_find(peerid))
605 		return (NULL);
606 
607 	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
608 		fatal("lde_nbr_new");
609 
610 	memcpy(nbr, new, sizeof(*nbr));
611 	nbr->peerid = peerid;
612 	fec_init(&nbr->recv_map);
613 	fec_init(&nbr->sent_map);
614 	fec_init(&nbr->recv_req);
615 	fec_init(&nbr->sent_req);
616 	fec_init(&nbr->sent_wdraw);
617 
618 	TAILQ_INIT(&nbr->addr_list);
619 
620 	if (RB_INSERT(nbr_tree, &lde_nbrs, nbr) != NULL)
621 		fatalx("lde_nbr_new: RB_INSERT failed");
622 
623 	return (nbr);
624 }
625 
626 void
627 lde_nbr_del(struct lde_nbr *nbr)
628 {
629 	if (nbr == NULL)
630 		return;
631 
632 	lde_address_list_free(nbr);
633 
634 	fec_clear(&nbr->recv_map, lde_map_free);
635 	fec_clear(&nbr->sent_map, lde_map_free);
636 	fec_clear(&nbr->recv_req, free);
637 	fec_clear(&nbr->sent_req, free);
638 	fec_clear(&nbr->sent_wdraw, free);
639 
640 	RB_REMOVE(nbr_tree, &lde_nbrs, nbr);
641 
642 	free(nbr);
643 }
644 
645 void
646 lde_nbr_clear(void)
647 {
648 	struct lde_nbr	*nbr;
649 
650 	 while ((nbr = RB_ROOT(&lde_nbrs)) != NULL)
651 		lde_nbr_del(nbr);
652 }
653 
654 void
655 lde_nbr_do_mappings(struct rt_node *rn)
656 {
657 	struct lde_nbr	*ln;
658 	struct lde_map	*me;
659 	struct lde_req	*lre;
660 
661 	/* This handles LMp.17-31 for lde_check_mapping() */
662 
663 	RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
664 		/* LMp.18 Did we already send a mapping to this peer? */
665 		me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
666 		if (me && me->label == rn->local_label)
667 			/* same mapping already sent, skip */
668 			/* TODO LMp.22-27 Loop detection check */
669 			continue;
670 
671 		/* LMp.28 Is this from a pending request? */
672 		lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
673 
674 		/* Check for the only case where no mapping should be sent.
675 		 * This is the On Demand case of LMp.29  */
676 		if (ldeconf->mode & MODE_ADV_ONDEMAND && lre == NULL)
677 			/* adv. on demand but no req pending, skip */
678 			continue;
679 
680 		lde_send_labelmapping(ln, rn);
681 		/* LMp.30 & 31 are not needed because labels are always added */
682 	}
683 }
684 
685 struct lde_map *
686 lde_map_add(struct lde_nbr *ln, struct rt_node *rn, int sent)
687 {
688 	struct lde_map  *me;
689 
690 	me = calloc(1, sizeof(*me));
691 	if (me == NULL)
692 		fatal("lde_map_add");
693 
694 	me->fec = rn->fec;
695 	me->nexthop = ln;
696 
697 	if (sent) {
698 		LIST_INSERT_HEAD(&rn->upstream, me, entry);
699 		if (fec_insert(&ln->sent_map, &me->fec))
700 			log_warnx("failed to add %s/%u to sent map",
701 			    inet_ntoa(me->fec.prefix), me->fec.prefixlen);
702 			/* XXX on failure more cleanup is needed */
703 	} else {
704 		LIST_INSERT_HEAD(&rn->downstream, me, entry);
705 		if (fec_insert(&ln->recv_map, &me->fec))
706 			log_warnx("failed to add %s/%u to recv map",
707 			    inet_ntoa(me->fec.prefix), me->fec.prefixlen);
708 	}
709 
710 	return (me);
711 }
712 
713 void
714 lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent)
715 {
716 	if (sent)
717 		fec_remove(&ln->sent_map, &me->fec);
718 	else
719 		fec_remove(&ln->recv_map, &me->fec);
720 
721 	lde_map_free(me);
722 }
723 
724 void
725 lde_map_free(void *ptr)
726 {
727 	struct lde_map	*map = ptr;
728 
729 	LIST_REMOVE(map, entry);
730 	free(map);
731 }
732 
733 struct lde_req *
734 lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent)
735 {
736 	struct fec_tree	*ft;
737 	struct lde_req	*lre;
738 
739 	ft = sent ? &ln->sent_req : &ln->recv_req;
740 
741 	lre = calloc(1, sizeof(*lre));
742 	if (lre != NULL) {
743 		lre->fec = *fec;
744 
745 		if (fec_insert(ft, &lre->fec)) {
746 			log_warnx("failed to add %s/%u to %s req",
747 			    inet_ntoa(lre->fec.prefix), lre->fec.prefixlen,
748 			    sent ? "sent" : "recv");
749 			free(lre);
750 			return (NULL);
751 		}
752 	}
753 
754 	return (lre);
755 }
756 
757 void
758 lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent)
759 {
760 	if (sent)
761 		fec_remove(&ln->sent_req, &lre->fec);
762 	else
763 		fec_remove(&ln->recv_req, &lre->fec);
764 
765 	free(lre);
766 }
767 
768 int
769 lde_address_add(struct lde_nbr *lr, struct in_addr *addr)
770 {
771 	struct lde_nbr_address	*address;
772 
773 	if (lde_address_find(lr, addr) != NULL)
774 		return (-1);
775 
776 	if ((address = calloc(1, sizeof(*address))) == NULL)
777 		fatal("lde_address_add");
778 
779 	address->addr.s_addr = addr->s_addr;
780 
781 	TAILQ_INSERT_TAIL(&lr->addr_list, address, entry);
782 
783 	log_debug("lde_address_add: added %s", inet_ntoa(*addr));
784 
785 	return (0);
786 }
787 
788 struct lde_nbr_address *
789 lde_address_find(struct lde_nbr *lr, struct in_addr *addr)
790 {
791 	struct lde_nbr_address	*address = NULL;
792 
793 	TAILQ_FOREACH(address, &lr->addr_list, entry) {
794 		if (address->addr.s_addr == addr->s_addr)
795 			return (address);
796 	}
797 
798 	return (NULL);
799 }
800 
801 int
802 lde_address_del(struct lde_nbr *lr, struct in_addr *addr)
803 {
804 	struct lde_nbr_address	*address;
805 
806 	address = lde_address_find(lr, addr);
807 	if (address == NULL)
808 		return (-1);
809 
810 	TAILQ_REMOVE(&lr->addr_list, address, entry);
811 
812 	free(address);
813 
814 	log_debug("lde_address_del: deleted %s", inet_ntoa(*addr));
815 
816 	return (0);
817 }
818 
819 void
820 lde_address_list_free(struct lde_nbr *nbr)
821 {
822 	struct lde_nbr_address	*addr;
823 
824 	while ((addr = TAILQ_FIRST(&nbr->addr_list)) != NULL) {
825 		TAILQ_REMOVE(&nbr->addr_list, addr, entry);
826 		free(addr);
827 	}
828 }
829 
830 struct lde_nbr *
831 lde_find_address(struct in_addr address)
832 {
833 	struct lde_nbr	*ln;
834 
835 	RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
836 		if (lde_address_find(ln, &address) != NULL)
837 			return (ln);
838 	}
839 
840 	return (NULL);
841 }
842