xref: /openbsd/usr.sbin/ldpd/ldpe.c (revision 73471bf0)
1 /*	$OpenBSD: ldpe.c,v 1.80 2021/01/19 15:59:25 claudio 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 = "ldpe";
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 	control_listen();
150 
151 	event_dispatch();
152 
153 	ldpe_shutdown();
154 }
155 
156 static __dead void
157 ldpe_shutdown(void)
158 {
159 	struct if_addr		*if_addr;
160 	struct adj		*adj;
161 
162 	/* close pipes */
163 	msgbuf_write(&iev_lde->ibuf.w);
164 	msgbuf_clear(&iev_lde->ibuf.w);
165 	close(iev_lde->ibuf.fd);
166 	msgbuf_write(&iev_main->ibuf.w);
167 	msgbuf_clear(&iev_main->ibuf.w);
168 	close(iev_main->ibuf.fd);
169 
170 	control_cleanup();
171 	config_clear(leconf);
172 
173 	if (sysdep.no_pfkey == 0) {
174 		event_del(&pfkey_ev);
175 		close(global.pfkeysock);
176 	}
177 	ldpe_close_sockets(AF_INET);
178 	ldpe_close_sockets(AF_INET6);
179 
180 	/* remove addresses from global list */
181 	while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
182 		LIST_REMOVE(if_addr, entry);
183 		free(if_addr);
184 	}
185 	while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
186 		adj_del(adj, S_SHUTDOWN);
187 
188 	/* clean up */
189 	free(iev_lde);
190 	free(iev_main);
191 
192 	log_info("ldp engine exiting");
193 	exit(0);
194 }
195 
196 /* imesg */
197 int
198 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
199 {
200 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
201 }
202 
203 int
204 ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
205     uint16_t datalen)
206 {
207 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
208 	    data, datalen));
209 }
210 
211 /* ARGSUSED */
212 static void
213 ldpe_dispatch_main(int fd, short event, void *bula)
214 {
215 	static struct ldpd_conf	*nconf;
216 	struct iface		*niface;
217 	struct tnbr		*ntnbr;
218 	struct nbr_params	*nnbrp;
219 	static struct l2vpn	*l2vpn, *nl2vpn;
220 	struct l2vpn_if		*lif = NULL, *nlif;
221 	struct l2vpn_pw		*npw;
222 	struct imsg		 imsg;
223 	struct imsgev		*iev = bula;
224 	struct imsgbuf		*ibuf = &iev->ibuf;
225 	struct iface		*iface = NULL;
226 	struct kif		*kif;
227 	int			 af;
228 	enum socket_type	*socket_type;
229 	static int		 disc_socket = -1;
230 	static int		 edisc_socket = -1;
231 	static int		 session_socket = -1;
232 	struct nbr		*nbr;
233 	int			 n, shut = 0;
234 
235 	if (event & EV_READ) {
236 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
237 			fatal("imsg_read error");
238 		if (n == 0)	/* connection closed */
239 			shut = 1;
240 	}
241 	if (event & EV_WRITE) {
242 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
243 			fatal("ldpe_dispatch_main: msgbuf_write");
244 		if (n == 0)
245 			shut = 1;
246 	}
247 
248 	for (;;) {
249 		if ((n = imsg_get(ibuf, &imsg)) == -1)
250 			fatal("ldpe_dispatch_main: imsg_get error");
251 		if (n == 0)
252 			break;
253 
254 		switch (imsg.hdr.type) {
255 		case IMSG_IFSTATUS:
256 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
257 			    sizeof(struct kif))
258 				fatalx("IFSTATUS imsg with wrong len");
259 			kif = imsg.data;
260 
261 			iface = if_lookup(leconf, kif->ifindex);
262 			if (iface) {
263 				iface->flags = kif->flags;
264 				iface->linkstate = kif->link_state;
265 				if_update(iface, AF_UNSPEC);
266 				break;
267 			}
268 
269 			LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) {
270 				lif = l2vpn_if_find(l2vpn, kif->ifindex);
271 				if (lif) {
272 					lif->flags = kif->flags;
273 					lif->linkstate = kif->link_state;
274 					memcpy(lif->mac, kif->mac,
275 					    sizeof(lif->mac));
276 					l2vpn_if_update(lif);
277 					break;
278 				}
279 			}
280 			break;
281 		case IMSG_NEWADDR:
282 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
283 			    sizeof(struct kaddr))
284 				fatalx("NEWADDR imsg with wrong len");
285 
286 			if_addr_add(imsg.data);
287 			break;
288 		case IMSG_DELADDR:
289 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
290 			    sizeof(struct kaddr))
291 				fatalx("DELADDR imsg with wrong len");
292 
293 			if_addr_del(imsg.data);
294 			break;
295 		case IMSG_SOCKET_IPC:
296 			if (iev_lde) {
297 				log_warnx("%s: received unexpected imsg fd "
298 				    "to lde", __func__);
299 				break;
300 			}
301 			if ((fd = imsg.fd) == -1) {
302 				log_warnx("%s: expected to receive imsg fd to "
303 				    "lde but didn't receive any", __func__);
304 				break;
305 			}
306 
307 			if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
308 				fatal(NULL);
309 			imsg_init(&iev_lde->ibuf, fd);
310 			iev_lde->handler = ldpe_dispatch_lde;
311 			iev_lde->events = EV_READ;
312 			event_set(&iev_lde->ev, iev_lde->ibuf.fd,
313 			    iev_lde->events, iev_lde->handler, iev_lde);
314 			event_add(&iev_lde->ev, NULL);
315 			break;
316 		case IMSG_CLOSE_SOCKETS:
317 			af = imsg.hdr.peerid;
318 
319 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
320 				if (nbr->af != af)
321 					continue;
322 				session_shutdown(nbr, S_SHUTDOWN, 0, 0);
323 				pfkey_remove(nbr);
324 			}
325 			ldpe_close_sockets(af);
326 			if_update_all(af);
327 			tnbr_update_all(af);
328 
329 			disc_socket = -1;
330 			edisc_socket = -1;
331 			session_socket = -1;
332 			if ((ldp_af_conf_get(leconf, af))->flags &
333 			    F_LDPD_AF_ENABLED)
334 				ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
335 				    af, NULL, 0);
336 			break;
337 		case IMSG_SOCKET_NET:
338 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
339 			    sizeof(enum socket_type))
340 				fatalx("SOCKET_NET imsg with wrong len");
341 			socket_type = imsg.data;
342 
343 			switch (*socket_type) {
344 			case LDP_SOCKET_DISC:
345 				disc_socket = imsg.fd;
346 				break;
347 			case LDP_SOCKET_EDISC:
348 				edisc_socket = imsg.fd;
349 				break;
350 			case LDP_SOCKET_SESSION:
351 				session_socket = imsg.fd;
352 				break;
353 			}
354 			break;
355 		case IMSG_SETUP_SOCKETS:
356 			af = imsg.hdr.peerid;
357 			if (disc_socket == -1 || edisc_socket == -1 ||
358 			    session_socket == -1) {
359 				if (disc_socket != -1)
360 					close(disc_socket);
361 				if (edisc_socket != -1)
362 					close(edisc_socket);
363 				if (session_socket != -1)
364 					close(session_socket);
365 				break;
366 			}
367 
368 			ldpe_setup_sockets(af, disc_socket, edisc_socket,
369 			    session_socket);
370 			if_update_all(af);
371 			tnbr_update_all(af);
372 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
373 				if (nbr->af != af)
374 					continue;
375 				nbr->laddr = (ldp_af_conf_get(leconf,
376 				    af))->trans_addr;
377 				if (pfkey_establish(nconf, nbr) == -1)
378 					fatalx("pfkey setup failed");
379 				if (nbr_session_active_role(nbr))
380 					nbr_establish_connection(nbr);
381 			}
382 			break;
383 		case IMSG_RECONF_CONF:
384 			if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
385 			    NULL)
386 				fatal(NULL);
387 			memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
388 
389 			LIST_INIT(&nconf->iface_list);
390 			LIST_INIT(&nconf->tnbr_list);
391 			LIST_INIT(&nconf->nbrp_list);
392 			LIST_INIT(&nconf->l2vpn_list);
393 			LIST_INIT(&nconf->auth_list);
394 			break;
395 		case IMSG_RECONF_IFACE:
396 			if ((niface = malloc(sizeof(struct iface))) == NULL)
397 				fatal(NULL);
398 			memcpy(niface, imsg.data, sizeof(struct iface));
399 
400 			LIST_INIT(&niface->addr_list);
401 			LIST_INIT(&niface->ipv4.adj_list);
402 			LIST_INIT(&niface->ipv6.adj_list);
403 			niface->ipv4.iface = niface;
404 			niface->ipv6.iface = niface;
405 
406 			LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
407 			break;
408 		case IMSG_RECONF_TNBR:
409 			if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
410 				fatal(NULL);
411 			memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
412 
413 			LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
414 			break;
415 		case IMSG_RECONF_NBRP:
416 			if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
417 				fatal(NULL);
418 			memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
419 
420 			LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
421 			break;
422 		case IMSG_RECONF_L2VPN:
423 			if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
424 				fatal(NULL);
425 			memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
426 
427 			LIST_INIT(&nl2vpn->if_list);
428 			LIST_INIT(&nl2vpn->pw_list);
429 
430 			LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
431 			break;
432 		case IMSG_RECONF_L2VPN_IF:
433 			if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
434 				fatal(NULL);
435 			memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
436 
437 			nlif->l2vpn = nl2vpn;
438 			LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
439 			break;
440 		case IMSG_RECONF_L2VPN_PW:
441 			if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
442 				fatal(NULL);
443 			memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
444 
445 			npw->l2vpn = nl2vpn;
446 			LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
447 			break;
448 		case IMSG_RECONF_CONF_AUTH: {
449 			struct ldp_auth *auth;
450 
451 			auth = malloc(sizeof(*auth));
452 			if (auth == NULL)
453 				fatal(NULL);
454 
455 			memcpy(auth, imsg.data, sizeof(*auth));
456 
457 			LIST_INSERT_HEAD(&nconf->auth_list, auth, entry);
458 			break;
459 		}
460 
461 		case IMSG_RECONF_END:
462 			merge_config(leconf, nconf);
463 			nconf = NULL;
464 			global.conf_seqnum++;
465 			break;
466 		case IMSG_CTL_KROUTE:
467 		case IMSG_CTL_KROUTE_ADDR:
468 		case IMSG_CTL_IFINFO:
469 		case IMSG_CTL_END:
470 			control_imsg_relay(&imsg);
471 			break;
472 		default:
473 			log_debug("ldpe_dispatch_main: error handling imsg %d",
474 			    imsg.hdr.type);
475 			break;
476 		}
477 		imsg_free(&imsg);
478 	}
479 	if (!shut)
480 		imsg_event_add(iev);
481 	else {
482 		/* this pipe is dead, so remove the event handler */
483 		event_del(&iev->ev);
484 		event_loopexit(NULL);
485 	}
486 }
487 
488 /* ARGSUSED */
489 static void
490 ldpe_dispatch_lde(int fd, short event, void *bula)
491 {
492 	struct imsgev		*iev = bula;
493 	struct imsgbuf		*ibuf = &iev->ibuf;
494 	struct imsg		 imsg;
495 	struct map		 map;
496 	struct notify_msg	 nm;
497 	int			 n, shut = 0;
498 	struct nbr		*nbr = NULL;
499 
500 	if (event & EV_READ) {
501 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
502 			fatal("imsg_read error");
503 		if (n == 0)	/* connection closed */
504 			shut = 1;
505 	}
506 	if (event & EV_WRITE) {
507 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
508 			fatal("ldpe_dispatch_lde: msgbuf_write");
509 		if (n == 0)
510 			shut = 1;
511 	}
512 
513 	for (;;) {
514 		if ((n = imsg_get(ibuf, &imsg)) == -1)
515 			fatal("ldpe_dispatch_lde: imsg_get error");
516 		if (n == 0)
517 			break;
518 
519 		switch (imsg.hdr.type) {
520 		case IMSG_MAPPING_ADD:
521 		case IMSG_RELEASE_ADD:
522 		case IMSG_REQUEST_ADD:
523 		case IMSG_WITHDRAW_ADD:
524 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
525 				fatalx("invalid size of map request");
526 			memcpy(&map, imsg.data, sizeof(map));
527 
528 			nbr = nbr_find_peerid(imsg.hdr.peerid);
529 			if (nbr == NULL) {
530 				log_debug("ldpe_dispatch_lde: cannot find "
531 				    "neighbor");
532 				break;
533 			}
534 			if (nbr->state != NBR_STA_OPER)
535 				break;
536 
537 			switch (imsg.hdr.type) {
538 			case IMSG_MAPPING_ADD:
539 				mapping_list_add(&nbr->mapping_list, &map);
540 				break;
541 			case IMSG_RELEASE_ADD:
542 				mapping_list_add(&nbr->release_list, &map);
543 				break;
544 			case IMSG_REQUEST_ADD:
545 				mapping_list_add(&nbr->request_list, &map);
546 				break;
547 			case IMSG_WITHDRAW_ADD:
548 				mapping_list_add(&nbr->withdraw_list, &map);
549 				break;
550 			}
551 			break;
552 		case IMSG_MAPPING_ADD_END:
553 		case IMSG_RELEASE_ADD_END:
554 		case IMSG_REQUEST_ADD_END:
555 		case IMSG_WITHDRAW_ADD_END:
556 			nbr = nbr_find_peerid(imsg.hdr.peerid);
557 			if (nbr == NULL) {
558 				log_debug("ldpe_dispatch_lde: cannot find "
559 				    "neighbor");
560 				break;
561 			}
562 			if (nbr->state != NBR_STA_OPER)
563 				break;
564 
565 			switch (imsg.hdr.type) {
566 			case IMSG_MAPPING_ADD_END:
567 				send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
568 				    &nbr->mapping_list);
569 				break;
570 			case IMSG_RELEASE_ADD_END:
571 				send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
572 				    &nbr->release_list);
573 				break;
574 			case IMSG_REQUEST_ADD_END:
575 				send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
576 				    &nbr->request_list);
577 				break;
578 			case IMSG_WITHDRAW_ADD_END:
579 				send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
580 				    &nbr->withdraw_list);
581 				break;
582 			}
583 			break;
584 		case IMSG_NOTIFICATION_SEND:
585 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
586 				fatalx("invalid size of OE request");
587 			memcpy(&nm, imsg.data, sizeof(nm));
588 
589 			nbr = nbr_find_peerid(imsg.hdr.peerid);
590 			if (nbr == NULL) {
591 				log_debug("ldpe_dispatch_lde: cannot find "
592 				    "neighbor");
593 				break;
594 			}
595 			if (nbr->state != NBR_STA_OPER)
596 				break;
597 
598 			send_notification_full(nbr->tcp, &nm);
599 			break;
600 		case IMSG_CTL_END:
601 		case IMSG_CTL_SHOW_LIB:
602 		case IMSG_CTL_SHOW_L2VPN_PW:
603 		case IMSG_CTL_SHOW_L2VPN_BINDING:
604 			control_imsg_relay(&imsg);
605 			break;
606 		default:
607 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
608 			    imsg.hdr.type);
609 			break;
610 		}
611 		imsg_free(&imsg);
612 	}
613 	if (!shut)
614 		imsg_event_add(iev);
615 	else {
616 		/* this pipe is dead, so remove the event handler */
617 		event_del(&iev->ev);
618 		event_loopexit(NULL);
619 	}
620 }
621 
622 /* ARGSUSED */
623 static void
624 ldpe_dispatch_pfkey(int fd, short event, void *bula)
625 {
626 	if (event & EV_READ) {
627 		if (pfkey_read(fd, NULL) == -1) {
628 			fatal("pfkey_read failed, exiting...");
629 		}
630 	}
631 }
632 
633 static void
634 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
635     int session_socket)
636 {
637 	struct ldpd_af_global	*af_global;
638 
639 	af_global = ldp_af_global_get(&global, af);
640 
641 	/* discovery socket */
642 	af_global->ldp_disc_socket = disc_socket;
643 	event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
644 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
645 	event_add(&af_global->disc_ev, NULL);
646 
647 	/* extended discovery socket */
648 	af_global->ldp_edisc_socket = edisc_socket;
649 	event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
650 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
651 	event_add(&af_global->edisc_ev, NULL);
652 
653 	/* session socket */
654 	af_global->ldp_session_socket = session_socket;
655 	accept_add(af_global->ldp_session_socket, session_accept, NULL);
656 }
657 
658 static void
659 ldpe_close_sockets(int af)
660 {
661 	struct ldpd_af_global	*af_global;
662 
663 	af_global = ldp_af_global_get(&global, af);
664 
665 	/* discovery socket */
666 	if (event_initialized(&af_global->disc_ev))
667 		event_del(&af_global->disc_ev);
668 	if (af_global->ldp_disc_socket != -1) {
669 		close(af_global->ldp_disc_socket);
670 		af_global->ldp_disc_socket = -1;
671 	}
672 
673 	/* extended discovery socket */
674 	if (event_initialized(&af_global->edisc_ev))
675 		event_del(&af_global->edisc_ev);
676 	if (af_global->ldp_edisc_socket != -1) {
677 		close(af_global->ldp_edisc_socket);
678 		af_global->ldp_edisc_socket = -1;
679 	}
680 
681 	/* session socket */
682 	if (af_global->ldp_session_socket != -1) {
683 		accept_del(af_global->ldp_session_socket);
684 		close(af_global->ldp_session_socket);
685 		af_global->ldp_session_socket = -1;
686 	}
687 }
688 
689 void
690 ldpe_reset_nbrs(int af)
691 {
692 	struct nbr		*nbr;
693 
694 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
695 		if (nbr->af == af)
696 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
697 	}
698 }
699 
700 void
701 ldpe_reset_ds_nbrs(void)
702 {
703 	struct nbr		*nbr;
704 
705 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
706 		if (nbr->ds_tlv)
707 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
708 	}
709 }
710 
711 void
712 ldpe_remove_dynamic_tnbrs(int af)
713 {
714 	struct tnbr		*tnbr, *safe;
715 
716 	LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
717 		if (tnbr->af != af)
718 			continue;
719 
720 		tnbr->flags &= ~F_TNBR_DYNAMIC;
721 		tnbr_check(tnbr);
722 	}
723 }
724 
725 void
726 ldpe_stop_init_backoff(int af)
727 {
728 	struct nbr		*nbr;
729 
730 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
731 		if (nbr->af == af && nbr_pending_idtimer(nbr)) {
732 			nbr_stop_idtimer(nbr);
733 			nbr_establish_connection(nbr);
734 		}
735 	}
736 }
737 
738 static void
739 ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
740 {
741 	struct iface		*iface;
742 	struct iface_af		*ia;
743 	struct ctl_iface	*ictl;
744 
745 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
746 		if (idx == 0 || idx == iface->ifindex) {
747 			ia = iface_af_get(iface, af);
748 			if (!ia->enabled)
749 				continue;
750 
751 			ictl = if_to_ctl(ia);
752 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
753 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
754 		}
755 	}
756 }
757 
758 void
759 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
760 {
761 	ldpe_iface_af_ctl(c, AF_INET, idx);
762 	ldpe_iface_af_ctl(c, AF_INET6, idx);
763 }
764 
765 void
766 ldpe_adj_ctl(struct ctl_conn *c)
767 {
768 	struct nbr	*nbr;
769 	struct adj	*adj;
770 	struct ctl_adj	*actl;
771 
772 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
773 		LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) {
774 			actl = adj_to_ctl(adj);
775 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
776 			    0, 0, -1, actl, sizeof(struct ctl_adj));
777 		}
778 	}
779 	/* show adjacencies not associated with any neighbor */
780 	LIST_FOREACH(adj, &global.adj_list, global_entry) {
781 		if (adj->nbr != NULL)
782 			continue;
783 
784 		actl = adj_to_ctl(adj);
785 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
786 		    -1, actl, sizeof(struct ctl_adj));
787 	}
788 
789 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
790 }
791 
792 void
793 ldpe_nbr_ctl(struct ctl_conn *c)
794 {
795 	struct nbr	*nbr;
796 	struct ctl_nbr	*nctl;
797 
798 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
799 		nctl = nbr_to_ctl(nbr);
800 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
801 		    sizeof(struct ctl_nbr));
802 	}
803 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
804 }
805 
806 void
807 mapping_list_add(struct mapping_head *mh, struct map *map)
808 {
809 	struct mapping_entry	*me;
810 
811 	me = calloc(1, sizeof(*me));
812 	if (me == NULL)
813 		fatal(__func__);
814 	me->map = *map;
815 
816 	TAILQ_INSERT_TAIL(mh, me, entry);
817 }
818 
819 void
820 mapping_list_clr(struct mapping_head *mh)
821 {
822 	struct mapping_entry	*me;
823 
824 	while ((me = TAILQ_FIRST(mh)) != NULL) {
825 		TAILQ_REMOVE(mh, me, entry);
826 		free(me);
827 	}
828 }
829