xref: /openbsd/usr.sbin/ldpd/ldpe.c (revision 905646f0)
1 /*	$OpenBSD: ldpe.c,v 1.77 2020/06/22 15:09:34 mestre Exp $ */
2 
3 /*
4  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
7  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <stdlib.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <pwd.h>
27 #include <unistd.h>
28 #include <arpa/inet.h>
29 #include <errno.h>
30 
31 #include "ldpd.h"
32 #include "ldpe.h"
33 #include "lde.h"
34 #include "control.h"
35 #include "log.h"
36 
37 static void	 ldpe_sig_handler(int, short, void *);
38 static __dead void ldpe_shutdown(void);
39 static void	 ldpe_dispatch_main(int, short, void *);
40 static void	 ldpe_dispatch_lde(int, short, void *);
41 static void	 ldpe_dispatch_pfkey(int, short, void *);
42 static void	 ldpe_setup_sockets(int, int, int, int);
43 static void	 ldpe_close_sockets(int);
44 static void	 ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45 
46 struct ldpd_conf	*leconf;
47 struct ldpd_sysdep	 sysdep;
48 
49 static struct imsgev	*iev_main;
50 static struct imsgev	*iev_lde;
51 static struct event	 pfkey_ev;
52 
53 /* ARGSUSED */
54 static void
55 ldpe_sig_handler(int sig, short event, void *bula)
56 {
57 	switch (sig) {
58 	case SIGINT:
59 	case SIGTERM:
60 		ldpe_shutdown();
61 		/* NOTREACHED */
62 	default:
63 		fatalx("unexpected signal");
64 	}
65 }
66 
67 /* label distribution protocol engine */
68 void
69 ldpe(int debug, int verbose, char *sockname)
70 {
71 	struct passwd		*pw;
72 	struct event		 ev_sigint, ev_sigterm;
73 
74 	leconf = config_new_empty();
75 
76 	log_init(debug);
77 	log_verbose(verbose);
78 
79 	setproctitle("ldp engine");
80 	ldpd_process = PROC_LDP_ENGINE;
81 	log_procname = log_procnames[ldpd_process];
82 
83 	/* create ldpd control socket outside chroot */
84 	global.csock = sockname;
85 	if (control_init(global.csock) == -1)
86 		fatalx("control socket setup failed");
87 
88 	LIST_INIT(&global.addr_list);
89 	LIST_INIT(&global.adj_list);
90 	TAILQ_INIT(&global.pending_conns);
91 	if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
92 		fatal("inet_pton");
93 	if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
94 		fatal("inet_pton");
95 	global.pfkeysock = pfkey_init();
96 
97 	if ((pw = getpwnam(LDPD_USER)) == NULL)
98 		fatal("getpwnam");
99 
100 	if (chroot(pw->pw_dir) == -1)
101 		fatal("chroot");
102 	if (chdir("/") == -1)
103 		fatal("chdir(\"/\")");
104 
105 	if (setgroups(1, &pw->pw_gid) ||
106 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
107 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
108 		fatal("can't drop privileges");
109 
110 	if (pledge("stdio inet mcast recvfd", NULL) == -1)
111 		fatal("pledge");
112 
113 	event_init();
114 	accept_init();
115 
116 	/* setup signal handler */
117 	signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
118 	signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
119 	signal_add(&ev_sigint, NULL);
120 	signal_add(&ev_sigterm, NULL);
121 	signal(SIGPIPE, SIG_IGN);
122 	signal(SIGHUP, SIG_IGN);
123 
124 	/* setup pipe and event handler to the parent process */
125 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
126 		fatal(NULL);
127 	imsg_init(&iev_main->ibuf, 3);
128 	iev_main->handler = ldpe_dispatch_main;
129 	iev_main->events = EV_READ;
130 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
131 	    iev_main->handler, iev_main);
132 	event_add(&iev_main->ev, NULL);
133 
134 	if (sysdep.no_pfkey == 0) {
135 		event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST,
136 		    ldpe_dispatch_pfkey, NULL);
137 		event_add(&pfkey_ev, NULL);
138 	}
139 
140 	/* mark sockets as closed */
141 	global.ipv4.ldp_disc_socket = -1;
142 	global.ipv4.ldp_edisc_socket = -1;
143 	global.ipv4.ldp_session_socket = -1;
144 	global.ipv6.ldp_disc_socket = -1;
145 	global.ipv6.ldp_edisc_socket = -1;
146 	global.ipv6.ldp_session_socket = -1;
147 
148 	/* listen on ldpd control socket */
149 	TAILQ_INIT(&ctl_conns);
150 	control_listen();
151 
152 	if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
153 		fatal(__func__);
154 
155 	event_dispatch();
156 
157 	ldpe_shutdown();
158 }
159 
160 static __dead void
161 ldpe_shutdown(void)
162 {
163 	struct if_addr		*if_addr;
164 	struct adj		*adj;
165 
166 	/* close pipes */
167 	msgbuf_write(&iev_lde->ibuf.w);
168 	msgbuf_clear(&iev_lde->ibuf.w);
169 	close(iev_lde->ibuf.fd);
170 	msgbuf_write(&iev_main->ibuf.w);
171 	msgbuf_clear(&iev_main->ibuf.w);
172 	close(iev_main->ibuf.fd);
173 
174 	control_cleanup();
175 	config_clear(leconf);
176 
177 	if (sysdep.no_pfkey == 0) {
178 		event_del(&pfkey_ev);
179 		close(global.pfkeysock);
180 	}
181 	ldpe_close_sockets(AF_INET);
182 	ldpe_close_sockets(AF_INET6);
183 
184 	/* remove addresses from global list */
185 	while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
186 		LIST_REMOVE(if_addr, entry);
187 		free(if_addr);
188 	}
189 	while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
190 		adj_del(adj, S_SHUTDOWN);
191 
192 	/* clean up */
193 	free(iev_lde);
194 	free(iev_main);
195 	free(pkt_ptr);
196 
197 	log_info("ldp engine exiting");
198 	exit(0);
199 }
200 
201 /* imesg */
202 int
203 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
204 {
205 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
206 }
207 
208 int
209 ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
210     uint16_t datalen)
211 {
212 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
213 	    data, datalen));
214 }
215 
216 /* ARGSUSED */
217 static void
218 ldpe_dispatch_main(int fd, short event, void *bula)
219 {
220 	static struct ldpd_conf	*nconf;
221 	struct iface		*niface;
222 	struct tnbr		*ntnbr;
223 	struct nbr_params	*nnbrp;
224 	static struct l2vpn	*l2vpn, *nl2vpn;
225 	struct l2vpn_if		*lif = NULL, *nlif;
226 	struct l2vpn_pw		*npw;
227 	struct imsg		 imsg;
228 	struct imsgev		*iev = bula;
229 	struct imsgbuf		*ibuf = &iev->ibuf;
230 	struct iface		*iface = NULL;
231 	struct kif		*kif;
232 	int			 af;
233 	enum socket_type	*socket_type;
234 	static int		 disc_socket = -1;
235 	static int		 edisc_socket = -1;
236 	static int		 session_socket = -1;
237 	struct nbr		*nbr;
238 	int			 n, shut = 0;
239 
240 	if (event & EV_READ) {
241 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
242 			fatal("imsg_read error");
243 		if (n == 0)	/* connection closed */
244 			shut = 1;
245 	}
246 	if (event & EV_WRITE) {
247 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
248 			fatal("ldpe_dispatch_main: msgbuf_write");
249 		if (n == 0)
250 			shut = 1;
251 	}
252 
253 	for (;;) {
254 		if ((n = imsg_get(ibuf, &imsg)) == -1)
255 			fatal("ldpe_dispatch_main: imsg_get error");
256 		if (n == 0)
257 			break;
258 
259 		switch (imsg.hdr.type) {
260 		case IMSG_IFSTATUS:
261 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
262 			    sizeof(struct kif))
263 				fatalx("IFSTATUS imsg with wrong len");
264 			kif = imsg.data;
265 
266 			iface = if_lookup(leconf, kif->ifindex);
267 			if (iface) {
268 				iface->flags = kif->flags;
269 				iface->linkstate = kif->link_state;
270 				if_update(iface, AF_UNSPEC);
271 				break;
272 			}
273 
274 			LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) {
275 				lif = l2vpn_if_find(l2vpn, kif->ifindex);
276 				if (lif) {
277 					lif->flags = kif->flags;
278 					lif->linkstate = kif->link_state;
279 					memcpy(lif->mac, kif->mac,
280 					    sizeof(lif->mac));
281 					l2vpn_if_update(lif);
282 					break;
283 				}
284 			}
285 			break;
286 		case IMSG_NEWADDR:
287 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
288 			    sizeof(struct kaddr))
289 				fatalx("NEWADDR imsg with wrong len");
290 
291 			if_addr_add(imsg.data);
292 			break;
293 		case IMSG_DELADDR:
294 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
295 			    sizeof(struct kaddr))
296 				fatalx("DELADDR imsg with wrong len");
297 
298 			if_addr_del(imsg.data);
299 			break;
300 		case IMSG_SOCKET_IPC:
301 			if (iev_lde) {
302 				log_warnx("%s: received unexpected imsg fd "
303 				    "to lde", __func__);
304 				break;
305 			}
306 			if ((fd = imsg.fd) == -1) {
307 				log_warnx("%s: expected to receive imsg fd to "
308 				    "lde but didn't receive any", __func__);
309 				break;
310 			}
311 
312 			if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
313 				fatal(NULL);
314 			imsg_init(&iev_lde->ibuf, fd);
315 			iev_lde->handler = ldpe_dispatch_lde;
316 			iev_lde->events = EV_READ;
317 			event_set(&iev_lde->ev, iev_lde->ibuf.fd,
318 			    iev_lde->events, iev_lde->handler, iev_lde);
319 			event_add(&iev_lde->ev, NULL);
320 			break;
321 		case IMSG_CLOSE_SOCKETS:
322 			af = imsg.hdr.peerid;
323 
324 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
325 				if (nbr->af != af)
326 					continue;
327 				session_shutdown(nbr, S_SHUTDOWN, 0, 0);
328 				pfkey_remove(nbr);
329 			}
330 			ldpe_close_sockets(af);
331 			if_update_all(af);
332 			tnbr_update_all(af);
333 
334 			disc_socket = -1;
335 			edisc_socket = -1;
336 			session_socket = -1;
337 			if ((ldp_af_conf_get(leconf, af))->flags &
338 			    F_LDPD_AF_ENABLED)
339 				ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
340 				    af, NULL, 0);
341 			break;
342 		case IMSG_SOCKET_NET:
343 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
344 			    sizeof(enum socket_type))
345 				fatalx("SOCKET_NET imsg with wrong len");
346 			socket_type = imsg.data;
347 
348 			switch (*socket_type) {
349 			case LDP_SOCKET_DISC:
350 				disc_socket = imsg.fd;
351 				break;
352 			case LDP_SOCKET_EDISC:
353 				edisc_socket = imsg.fd;
354 				break;
355 			case LDP_SOCKET_SESSION:
356 				session_socket = imsg.fd;
357 				break;
358 			}
359 			break;
360 		case IMSG_SETUP_SOCKETS:
361 			af = imsg.hdr.peerid;
362 			if (disc_socket == -1 || edisc_socket == -1 ||
363 			    session_socket == -1) {
364 				if (disc_socket != -1)
365 					close(disc_socket);
366 				if (edisc_socket != -1)
367 					close(edisc_socket);
368 				if (session_socket != -1)
369 					close(session_socket);
370 				break;
371 			}
372 
373 			ldpe_setup_sockets(af, disc_socket, edisc_socket,
374 			    session_socket);
375 			if_update_all(af);
376 			tnbr_update_all(af);
377 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
378 				if (nbr->af != af)
379 					continue;
380 				nbr->laddr = (ldp_af_conf_get(leconf,
381 				    af))->trans_addr;
382 				if (pfkey_establish(nconf, nbr) == -1)
383 					fatalx("pfkey setup failed");
384 				if (nbr_session_active_role(nbr))
385 					nbr_establish_connection(nbr);
386 			}
387 			break;
388 		case IMSG_RECONF_CONF:
389 			if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
390 			    NULL)
391 				fatal(NULL);
392 			memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
393 
394 			LIST_INIT(&nconf->iface_list);
395 			LIST_INIT(&nconf->tnbr_list);
396 			LIST_INIT(&nconf->nbrp_list);
397 			LIST_INIT(&nconf->l2vpn_list);
398 			LIST_INIT(&nconf->auth_list);
399 			break;
400 		case IMSG_RECONF_IFACE:
401 			if ((niface = malloc(sizeof(struct iface))) == NULL)
402 				fatal(NULL);
403 			memcpy(niface, imsg.data, sizeof(struct iface));
404 
405 			LIST_INIT(&niface->addr_list);
406 			LIST_INIT(&niface->ipv4.adj_list);
407 			LIST_INIT(&niface->ipv6.adj_list);
408 			niface->ipv4.iface = niface;
409 			niface->ipv6.iface = niface;
410 
411 			LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
412 			break;
413 		case IMSG_RECONF_TNBR:
414 			if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
415 				fatal(NULL);
416 			memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
417 
418 			LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
419 			break;
420 		case IMSG_RECONF_NBRP:
421 			if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
422 				fatal(NULL);
423 			memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
424 
425 			LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
426 			break;
427 		case IMSG_RECONF_L2VPN:
428 			if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
429 				fatal(NULL);
430 			memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
431 
432 			LIST_INIT(&nl2vpn->if_list);
433 			LIST_INIT(&nl2vpn->pw_list);
434 
435 			LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
436 			break;
437 		case IMSG_RECONF_L2VPN_IF:
438 			if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
439 				fatal(NULL);
440 			memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
441 
442 			nlif->l2vpn = nl2vpn;
443 			LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
444 			break;
445 		case IMSG_RECONF_L2VPN_PW:
446 			if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
447 				fatal(NULL);
448 			memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
449 
450 			npw->l2vpn = nl2vpn;
451 			LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
452 			break;
453 		case IMSG_RECONF_CONF_AUTH: {
454 			struct ldp_auth *auth;
455 
456 			auth = malloc(sizeof(*auth));
457 			if (auth == NULL)
458 				fatal(NULL);
459 
460 			memcpy(auth, imsg.data, sizeof(*auth));
461 
462 			LIST_INSERT_HEAD(&nconf->auth_list, auth, entry);
463 			break;
464 		}
465 
466 		case IMSG_RECONF_END:
467 			merge_config(leconf, nconf);
468 			nconf = NULL;
469 			global.conf_seqnum++;
470 			break;
471 		case IMSG_CTL_KROUTE:
472 		case IMSG_CTL_KROUTE_ADDR:
473 		case IMSG_CTL_IFINFO:
474 		case IMSG_CTL_END:
475 			control_imsg_relay(&imsg);
476 			break;
477 		default:
478 			log_debug("ldpe_dispatch_main: error handling imsg %d",
479 			    imsg.hdr.type);
480 			break;
481 		}
482 		imsg_free(&imsg);
483 	}
484 	if (!shut)
485 		imsg_event_add(iev);
486 	else {
487 		/* this pipe is dead, so remove the event handler */
488 		event_del(&iev->ev);
489 		event_loopexit(NULL);
490 	}
491 }
492 
493 /* ARGSUSED */
494 static void
495 ldpe_dispatch_lde(int fd, short event, void *bula)
496 {
497 	struct imsgev		*iev = bula;
498 	struct imsgbuf		*ibuf = &iev->ibuf;
499 	struct imsg		 imsg;
500 	struct map		 map;
501 	struct notify_msg	 nm;
502 	int			 n, shut = 0;
503 	struct nbr		*nbr = NULL;
504 
505 	if (event & EV_READ) {
506 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
507 			fatal("imsg_read error");
508 		if (n == 0)	/* connection closed */
509 			shut = 1;
510 	}
511 	if (event & EV_WRITE) {
512 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
513 			fatal("ldpe_dispatch_lde: msgbuf_write");
514 		if (n == 0)
515 			shut = 1;
516 	}
517 
518 	for (;;) {
519 		if ((n = imsg_get(ibuf, &imsg)) == -1)
520 			fatal("ldpe_dispatch_lde: imsg_get error");
521 		if (n == 0)
522 			break;
523 
524 		switch (imsg.hdr.type) {
525 		case IMSG_MAPPING_ADD:
526 		case IMSG_RELEASE_ADD:
527 		case IMSG_REQUEST_ADD:
528 		case IMSG_WITHDRAW_ADD:
529 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
530 				fatalx("invalid size of map request");
531 			memcpy(&map, imsg.data, sizeof(map));
532 
533 			nbr = nbr_find_peerid(imsg.hdr.peerid);
534 			if (nbr == NULL) {
535 				log_debug("ldpe_dispatch_lde: cannot find "
536 				    "neighbor");
537 				break;
538 			}
539 			if (nbr->state != NBR_STA_OPER)
540 				break;
541 
542 			switch (imsg.hdr.type) {
543 			case IMSG_MAPPING_ADD:
544 				mapping_list_add(&nbr->mapping_list, &map);
545 				break;
546 			case IMSG_RELEASE_ADD:
547 				mapping_list_add(&nbr->release_list, &map);
548 				break;
549 			case IMSG_REQUEST_ADD:
550 				mapping_list_add(&nbr->request_list, &map);
551 				break;
552 			case IMSG_WITHDRAW_ADD:
553 				mapping_list_add(&nbr->withdraw_list, &map);
554 				break;
555 			}
556 			break;
557 		case IMSG_MAPPING_ADD_END:
558 		case IMSG_RELEASE_ADD_END:
559 		case IMSG_REQUEST_ADD_END:
560 		case IMSG_WITHDRAW_ADD_END:
561 			nbr = nbr_find_peerid(imsg.hdr.peerid);
562 			if (nbr == NULL) {
563 				log_debug("ldpe_dispatch_lde: cannot find "
564 				    "neighbor");
565 				break;
566 			}
567 			if (nbr->state != NBR_STA_OPER)
568 				break;
569 
570 			switch (imsg.hdr.type) {
571 			case IMSG_MAPPING_ADD_END:
572 				send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
573 				    &nbr->mapping_list);
574 				break;
575 			case IMSG_RELEASE_ADD_END:
576 				send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
577 				    &nbr->release_list);
578 				break;
579 			case IMSG_REQUEST_ADD_END:
580 				send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
581 				    &nbr->request_list);
582 				break;
583 			case IMSG_WITHDRAW_ADD_END:
584 				send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
585 				    &nbr->withdraw_list);
586 				break;
587 			}
588 			break;
589 		case IMSG_NOTIFICATION_SEND:
590 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
591 				fatalx("invalid size of OE request");
592 			memcpy(&nm, imsg.data, sizeof(nm));
593 
594 			nbr = nbr_find_peerid(imsg.hdr.peerid);
595 			if (nbr == NULL) {
596 				log_debug("ldpe_dispatch_lde: cannot find "
597 				    "neighbor");
598 				break;
599 			}
600 			if (nbr->state != NBR_STA_OPER)
601 				break;
602 
603 			send_notification_full(nbr->tcp, &nm);
604 			break;
605 		case IMSG_CTL_END:
606 		case IMSG_CTL_SHOW_LIB:
607 		case IMSG_CTL_SHOW_L2VPN_PW:
608 		case IMSG_CTL_SHOW_L2VPN_BINDING:
609 			control_imsg_relay(&imsg);
610 			break;
611 		default:
612 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
613 			    imsg.hdr.type);
614 			break;
615 		}
616 		imsg_free(&imsg);
617 	}
618 	if (!shut)
619 		imsg_event_add(iev);
620 	else {
621 		/* this pipe is dead, so remove the event handler */
622 		event_del(&iev->ev);
623 		event_loopexit(NULL);
624 	}
625 }
626 
627 /* ARGSUSED */
628 static void
629 ldpe_dispatch_pfkey(int fd, short event, void *bula)
630 {
631 	if (event & EV_READ) {
632 		if (pfkey_read(fd, NULL) == -1) {
633 			fatal("pfkey_read failed, exiting...");
634 		}
635 	}
636 }
637 
638 static void
639 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
640     int session_socket)
641 {
642 	struct ldpd_af_global	*af_global;
643 
644 	af_global = ldp_af_global_get(&global, af);
645 
646 	/* discovery socket */
647 	af_global->ldp_disc_socket = disc_socket;
648 	event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
649 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
650 	event_add(&af_global->disc_ev, NULL);
651 
652 	/* extended discovery socket */
653 	af_global->ldp_edisc_socket = edisc_socket;
654 	event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
655 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
656 	event_add(&af_global->edisc_ev, NULL);
657 
658 	/* session socket */
659 	af_global->ldp_session_socket = session_socket;
660 	accept_add(af_global->ldp_session_socket, session_accept, NULL);
661 }
662 
663 static void
664 ldpe_close_sockets(int af)
665 {
666 	struct ldpd_af_global	*af_global;
667 
668 	af_global = ldp_af_global_get(&global, af);
669 
670 	/* discovery socket */
671 	if (event_initialized(&af_global->disc_ev))
672 		event_del(&af_global->disc_ev);
673 	if (af_global->ldp_disc_socket != -1) {
674 		close(af_global->ldp_disc_socket);
675 		af_global->ldp_disc_socket = -1;
676 	}
677 
678 	/* extended discovery socket */
679 	if (event_initialized(&af_global->edisc_ev))
680 		event_del(&af_global->edisc_ev);
681 	if (af_global->ldp_edisc_socket != -1) {
682 		close(af_global->ldp_edisc_socket);
683 		af_global->ldp_edisc_socket = -1;
684 	}
685 
686 	/* session socket */
687 	if (af_global->ldp_session_socket != -1) {
688 		accept_del(af_global->ldp_session_socket);
689 		close(af_global->ldp_session_socket);
690 		af_global->ldp_session_socket = -1;
691 	}
692 }
693 
694 void
695 ldpe_reset_nbrs(int af)
696 {
697 	struct nbr		*nbr;
698 
699 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
700 		if (nbr->af == af)
701 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
702 	}
703 }
704 
705 void
706 ldpe_reset_ds_nbrs(void)
707 {
708 	struct nbr		*nbr;
709 
710 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
711 		if (nbr->ds_tlv)
712 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
713 	}
714 }
715 
716 void
717 ldpe_remove_dynamic_tnbrs(int af)
718 {
719 	struct tnbr		*tnbr, *safe;
720 
721 	LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
722 		if (tnbr->af != af)
723 			continue;
724 
725 		tnbr->flags &= ~F_TNBR_DYNAMIC;
726 		tnbr_check(tnbr);
727 	}
728 }
729 
730 void
731 ldpe_stop_init_backoff(int af)
732 {
733 	struct nbr		*nbr;
734 
735 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
736 		if (nbr->af == af && nbr_pending_idtimer(nbr)) {
737 			nbr_stop_idtimer(nbr);
738 			nbr_establish_connection(nbr);
739 		}
740 	}
741 }
742 
743 static void
744 ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
745 {
746 	struct iface		*iface;
747 	struct iface_af		*ia;
748 	struct ctl_iface	*ictl;
749 
750 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
751 		if (idx == 0 || idx == iface->ifindex) {
752 			ia = iface_af_get(iface, af);
753 			if (!ia->enabled)
754 				continue;
755 
756 			ictl = if_to_ctl(ia);
757 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
758 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
759 		}
760 	}
761 }
762 
763 void
764 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
765 {
766 	ldpe_iface_af_ctl(c, AF_INET, idx);
767 	ldpe_iface_af_ctl(c, AF_INET6, idx);
768 }
769 
770 void
771 ldpe_adj_ctl(struct ctl_conn *c)
772 {
773 	struct nbr	*nbr;
774 	struct adj	*adj;
775 	struct ctl_adj	*actl;
776 
777 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
778 		LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) {
779 			actl = adj_to_ctl(adj);
780 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
781 			    0, 0, -1, actl, sizeof(struct ctl_adj));
782 		}
783 	}
784 	/* show adjacencies not associated with any neighbor */
785 	LIST_FOREACH(adj, &global.adj_list, global_entry) {
786 		if (adj->nbr != NULL)
787 			continue;
788 
789 		actl = adj_to_ctl(adj);
790 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
791 		    -1, actl, sizeof(struct ctl_adj));
792 	}
793 
794 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
795 }
796 
797 void
798 ldpe_nbr_ctl(struct ctl_conn *c)
799 {
800 	struct nbr	*nbr;
801 	struct ctl_nbr	*nctl;
802 
803 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
804 		nctl = nbr_to_ctl(nbr);
805 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
806 		    sizeof(struct ctl_nbr));
807 	}
808 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
809 }
810 
811 void
812 mapping_list_add(struct mapping_head *mh, struct map *map)
813 {
814 	struct mapping_entry	*me;
815 
816 	me = calloc(1, sizeof(*me));
817 	if (me == NULL)
818 		fatal(__func__);
819 	me->map = *map;
820 
821 	TAILQ_INSERT_TAIL(mh, me, entry);
822 }
823 
824 void
825 mapping_list_clr(struct mapping_head *mh)
826 {
827 	struct mapping_entry	*me;
828 
829 	while ((me = TAILQ_FIRST(mh)) != NULL) {
830 		TAILQ_REMOVE(mh, me, entry);
831 		free(me);
832 	}
833 }
834