xref: /openbsd-src/usr.sbin/ldpd/ldpe.c (revision f1b790a5738b7375271fee81f99119b1f82f2cfd)
1*f1b790a5Sclaudio /*	$OpenBSD: ldpe.c,v 1.88 2024/11/21 13:38:14 claudio Exp $ */
2ab0c2486Smichele 
3ab0c2486Smichele /*
45dc9330aSrenato  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5ab0c2486Smichele  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6ab0c2486Smichele  * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
7ab0c2486Smichele  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8ab0c2486Smichele  *
9ab0c2486Smichele  * Permission to use, copy, modify, and distribute this software for any
10ab0c2486Smichele  * purpose with or without fee is hereby granted, provided that the above
11ab0c2486Smichele  * copyright notice and this permission notice appear in all copies.
12ab0c2486Smichele  *
13ab0c2486Smichele  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14ab0c2486Smichele  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15ab0c2486Smichele  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16ab0c2486Smichele  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17ab0c2486Smichele  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18ab0c2486Smichele  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19ab0c2486Smichele  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20ab0c2486Smichele  */
21ab0c2486Smichele 
22ab0c2486Smichele #include <sys/types.h>
23ab0c2486Smichele #include <stdlib.h>
24ab0c2486Smichele #include <signal.h>
25ab0c2486Smichele #include <string.h>
26ab0c2486Smichele #include <pwd.h>
27ab0c2486Smichele #include <unistd.h>
28a8c39dc0Srenato #include <arpa/inet.h>
29ab0c2486Smichele #include <errno.h>
30ab0c2486Smichele 
31ab0c2486Smichele #include "ldpd.h"
32ab0c2486Smichele #include "ldpe.h"
33ab0c2486Smichele #include "lde.h"
34ab0c2486Smichele #include "control.h"
35ab0c2486Smichele #include "log.h"
36ab0c2486Smichele 
37c28a25a1Srenato static void	 ldpe_sig_handler(int, short, void *);
38d5e026a8Srenato static __dead void ldpe_shutdown(void);
39c28a25a1Srenato static void	 ldpe_dispatch_main(int, short, void *);
40c28a25a1Srenato static void	 ldpe_dispatch_lde(int, short, void *);
41c28a25a1Srenato static void	 ldpe_dispatch_pfkey(int, short, void *);
42c28a25a1Srenato static void	 ldpe_setup_sockets(int, int, int, int);
43c28a25a1Srenato static void	 ldpe_close_sockets(int);
44c28a25a1Srenato static void	 ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45ab0c2486Smichele 
46c28a25a1Srenato struct ldpd_conf	*leconf;
47627846caSrenato struct ldpd_sysdep	 sysdep;
48ab0c2486Smichele 
49c28a25a1Srenato static struct imsgev	*iev_main;
50c28a25a1Srenato static struct imsgev	*iev_lde;
51c28a25a1Srenato static struct event	 pfkey_ev;
52c28a25a1Srenato 
53c28a25a1Srenato static void
54ab0c2486Smichele ldpe_sig_handler(int sig, short event, void *bula)
55ab0c2486Smichele {
56ab0c2486Smichele 	switch (sig) {
57ab0c2486Smichele 	case SIGINT:
58ab0c2486Smichele 	case SIGTERM:
59ab0c2486Smichele 		ldpe_shutdown();
60ab0c2486Smichele 		/* NOTREACHED */
61ab0c2486Smichele 	default:
62ab0c2486Smichele 		fatalx("unexpected signal");
63ab0c2486Smichele 	}
64ab0c2486Smichele }
65ab0c2486Smichele 
66ab0c2486Smichele /* label distribution protocol engine */
67e21b401eSrenato void
68dcaf1165Srenato ldpe(int debug, int verbose, char *sockname)
69ab0c2486Smichele {
70ab0c2486Smichele 	struct passwd		*pw;
71ab0c2486Smichele 	struct event		 ev_sigint, ev_sigterm;
72ab0c2486Smichele 
7316040b47Srenato 	leconf = config_new_empty();
74ab0c2486Smichele 
7516040b47Srenato 	log_init(debug);
7616040b47Srenato 	log_verbose(verbose);
771b8ec09cSclaudio 
781b8ec09cSclaudio 	setproctitle("ldp engine");
791b8ec09cSclaudio 	ldpd_process = PROC_LDP_ENGINE;
802b80d179Sclaudio 	log_procname = "ldpe";
811b8ec09cSclaudio 
82ab0c2486Smichele 	/* create ldpd control socket outside chroot */
83dcaf1165Srenato 	global.csock = sockname;
84dcaf1165Srenato 	if (control_init(global.csock) == -1)
85ab0c2486Smichele 		fatalx("control socket setup failed");
86ab0c2486Smichele 
873de94509Srenato 	LIST_INIT(&global.addr_list);
88a8c39dc0Srenato 	LIST_INIT(&global.adj_list);
893de94509Srenato 	TAILQ_INIT(&global.pending_conns);
90a8c39dc0Srenato 	if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
91a8c39dc0Srenato 		fatal("inet_pton");
92a8c39dc0Srenato 	if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
93a8c39dc0Srenato 		fatal("inet_pton");
94c28a25a1Srenato 	global.pfkeysock = pfkey_init();
957416d201Srenato 
96ab0c2486Smichele 	if ((pw = getpwnam(LDPD_USER)) == NULL)
97ab0c2486Smichele 		fatal("getpwnam");
98ab0c2486Smichele 
99ab0c2486Smichele 	if (chroot(pw->pw_dir) == -1)
100ab0c2486Smichele 		fatal("chroot");
101ab0c2486Smichele 	if (chdir("/") == -1)
102ab0c2486Smichele 		fatal("chdir(\"/\")");
103ab0c2486Smichele 
104ab0c2486Smichele 	if (setgroups(1, &pw->pw_gid) ||
105ab0c2486Smichele 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
106ab0c2486Smichele 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
107ab0c2486Smichele 		fatal("can't drop privileges");
108ab0c2486Smichele 
10944e5c375Smestre 	if (pledge("stdio inet mcast recvfd", NULL) == -1)
11076c6280cSrenato 		fatal("pledge");
11176c6280cSrenato 
112ab0c2486Smichele 	event_init();
1134dda87d0Sclaudio 	accept_init();
114ab0c2486Smichele 
115ab0c2486Smichele 	/* setup signal handler */
116ab0c2486Smichele 	signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
117ab0c2486Smichele 	signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
118ab0c2486Smichele 	signal_add(&ev_sigint, NULL);
119ab0c2486Smichele 	signal_add(&ev_sigterm, NULL);
120ab0c2486Smichele 	signal(SIGPIPE, SIG_IGN);
121ab0c2486Smichele 	signal(SIGHUP, SIG_IGN);
122ab0c2486Smichele 
12316040b47Srenato 	/* setup pipe and event handler to the parent process */
12416040b47Srenato 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
125ab0c2486Smichele 		fatal(NULL);
126*f1b790a5Sclaudio 	if (imsgbuf_init(&iev_main->ibuf, 3) == -1)
127*f1b790a5Sclaudio 		fatal(NULL);
128*f1b790a5Sclaudio 	imsgbuf_allow_fdpass(&iev_main->ibuf);
129cb77742aSpyr 	iev_main->handler = ldpe_dispatch_main;
130cb77742aSpyr 	iev_main->events = EV_READ;
131cb77742aSpyr 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
132cb77742aSpyr 	    iev_main->handler, iev_main);
133cb77742aSpyr 	event_add(&iev_main->ev, NULL);
134ab0c2486Smichele 
135d810d05aSrenato 	if (sysdep.no_pfkey == 0) {
1363de94509Srenato 		event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST,
137627846caSrenato 		    ldpe_dispatch_pfkey, NULL);
138627846caSrenato 		event_add(&pfkey_ev, NULL);
139d810d05aSrenato 	}
140627846caSrenato 
141b5921293Srenato 	/* mark sockets as closed */
142a8c39dc0Srenato 	global.ipv4.ldp_disc_socket = -1;
143a8c39dc0Srenato 	global.ipv4.ldp_edisc_socket = -1;
144a8c39dc0Srenato 	global.ipv4.ldp_session_socket = -1;
145a8c39dc0Srenato 	global.ipv6.ldp_disc_socket = -1;
146a8c39dc0Srenato 	global.ipv6.ldp_edisc_socket = -1;
147a8c39dc0Srenato 	global.ipv6.ldp_session_socket = -1;
148ab0c2486Smichele 
149ab0c2486Smichele 	/* listen on ldpd control socket */
150ab0c2486Smichele 	control_listen();
151ab0c2486Smichele 
152ab0c2486Smichele 	event_dispatch();
153ab0c2486Smichele 
154ab0c2486Smichele 	ldpe_shutdown();
155ab0c2486Smichele }
156ab0c2486Smichele 
157d5e026a8Srenato static __dead void
158ab0c2486Smichele ldpe_shutdown(void)
159ab0c2486Smichele {
160b9b5a6c8Srenato 	struct if_addr		*if_addr;
161a8c39dc0Srenato 	struct adj		*adj;
16217cc0810Srenato 
163d5e026a8Srenato 	/* close pipes */
164dd7efffeSclaudio 	imsgbuf_write(&iev_lde->ibuf);
1659cbf9e90Sclaudio 	imsgbuf_clear(&iev_lde->ibuf);
166d5e026a8Srenato 	close(iev_lde->ibuf.fd);
167dd7efffeSclaudio 	imsgbuf_write(&iev_main->ibuf);
1689cbf9e90Sclaudio 	imsgbuf_clear(&iev_main->ibuf);
169d5e026a8Srenato 	close(iev_main->ibuf.fd);
170d5e026a8Srenato 
171b0e92afdSmestre 	control_cleanup();
1723df4d07bSrenato 	config_clear(leconf);
173dbbaa7d2Srenato 
174d810d05aSrenato 	if (sysdep.no_pfkey == 0) {
1757416d201Srenato 		event_del(&pfkey_ev);
1763de94509Srenato 		close(global.pfkeysock);
177d810d05aSrenato 	}
178a8c39dc0Srenato 	ldpe_close_sockets(AF_INET);
179a8c39dc0Srenato 	ldpe_close_sockets(AF_INET6);
180ab0c2486Smichele 
181b9b5a6c8Srenato 	/* remove addresses from global list */
1823de94509Srenato 	while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
183b9b5a6c8Srenato 		LIST_REMOVE(if_addr, entry);
184b9b5a6c8Srenato 		free(if_addr);
185b9b5a6c8Srenato 	}
186a8c39dc0Srenato 	while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
187e373a269Srenato 		adj_del(adj, S_SHUTDOWN);
188b9b5a6c8Srenato 
189ab0c2486Smichele 	/* clean up */
190cb77742aSpyr 	free(iev_lde);
191cb77742aSpyr 	free(iev_main);
192ab0c2486Smichele 
193ab0c2486Smichele 	log_info("ldp engine exiting");
194220e0715Srenato 	exit(0);
195ab0c2486Smichele }
196ab0c2486Smichele 
197ab0c2486Smichele /* imesg */
198ab0c2486Smichele int
1993de94509Srenato ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
200ab0c2486Smichele {
201cb77742aSpyr 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
202ab0c2486Smichele }
203ab0c2486Smichele 
204ab0c2486Smichele int
2053de94509Srenato ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
2063de94509Srenato     uint16_t datalen)
207ab0c2486Smichele {
208cb77742aSpyr 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
209cb77742aSpyr 	    data, datalen));
210ab0c2486Smichele }
211ab0c2486Smichele 
212c28a25a1Srenato static void
213ab0c2486Smichele ldpe_dispatch_main(int fd, short event, void *bula)
214ab0c2486Smichele {
215c28a25a1Srenato 	static struct ldpd_conf	*nconf;
216be87e4d3Srenato 	struct iface		*niface;
217be87e4d3Srenato 	struct tnbr		*ntnbr;
218be87e4d3Srenato 	struct nbr_params	*nnbrp;
21938e65088Srenato 	static struct l2vpn	*l2vpn, *nl2vpn;
22038e65088Srenato 	struct l2vpn_if		*lif = NULL, *nlif;
2216399cec1Srenato 	struct l2vpn_pw		*npw;
222ab0c2486Smichele 	struct imsg		 imsg;
223cb77742aSpyr 	struct imsgev		*iev = bula;
224cb77742aSpyr 	struct imsgbuf		*ibuf = &iev->ibuf;
225ab0c2486Smichele 	struct iface		*iface = NULL;
226ab0c2486Smichele 	struct kif		*kif;
227a8c39dc0Srenato 	int			 af;
228b5921293Srenato 	enum socket_type	*socket_type;
229b5921293Srenato 	static int		 disc_socket = -1;
230b5921293Srenato 	static int		 edisc_socket = -1;
231b5921293Srenato 	static int		 session_socket = -1;
2325a7df819Srenato 	struct nbr		*nbr;
233814e607dSclaudio 	int			 n, shut = 0;
234ab0c2486Smichele 
235ab0c2486Smichele 	if (event & EV_READ) {
236668e5ba9Sclaudio 		if ((n = imsgbuf_read(ibuf)) == -1)
237dd7efffeSclaudio 			fatal("imsgbuf_read error");
238ab0c2486Smichele 		if (n == 0)	/* connection closed */
239ab0c2486Smichele 			shut = 1;
240ab0c2486Smichele 	}
241ab0c2486Smichele 	if (event & EV_WRITE) {
242dd7efffeSclaudio 		if (imsgbuf_write(ibuf) == -1) {
243c1aa9554Sclaudio 			if (errno == EPIPE)	/* connection closed */
2441203692fSkrw 				shut = 1;
245c1aa9554Sclaudio 			else
246dd7efffeSclaudio 				fatal("imsgbuf_write");
247c1aa9554Sclaudio 		}
248ab0c2486Smichele 	}
249ab0c2486Smichele 
250ab0c2486Smichele 	for (;;) {
251ab0c2486Smichele 		if ((n = imsg_get(ibuf, &imsg)) == -1)
252ae7f1740Sclaudio 			fatal("ldpe_dispatch_main: imsg_get error");
253ab0c2486Smichele 		if (n == 0)
254ab0c2486Smichele 			break;
255ab0c2486Smichele 
256ab0c2486Smichele 		switch (imsg.hdr.type) {
257814e607dSclaudio 		case IMSG_IFSTATUS:
258ab0c2486Smichele 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
259ab0c2486Smichele 			    sizeof(struct kif))
260b9b5a6c8Srenato 				fatalx("IFSTATUS imsg with wrong len");
261814e607dSclaudio 			kif = imsg.data;
26219fce358Srenato 
263be87e4d3Srenato 			iface = if_lookup(leconf, kif->ifindex);
26438e65088Srenato 			if (iface) {
265ab0c2486Smichele 				iface->flags = kif->flags;
266ab0c2486Smichele 				iface->linkstate = kif->link_state;
267a8c39dc0Srenato 				if_update(iface, AF_UNSPEC);
268814e607dSclaudio 				break;
26938e65088Srenato 			}
27038e65088Srenato 
27138e65088Srenato 			LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) {
27238e65088Srenato 				lif = l2vpn_if_find(l2vpn, kif->ifindex);
27338e65088Srenato 				if (lif) {
27438e65088Srenato 					lif->flags = kif->flags;
27538e65088Srenato 					lif->linkstate = kif->link_state;
27638e65088Srenato 					memcpy(lif->mac, kif->mac,
27738e65088Srenato 					    sizeof(lif->mac));
27838e65088Srenato 					l2vpn_if_update(lif);
27938e65088Srenato 					break;
28038e65088Srenato 				}
28138e65088Srenato 			}
28238e65088Srenato 			break;
283814e607dSclaudio 		case IMSG_NEWADDR:
284814e607dSclaudio 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
285814e607dSclaudio 			    sizeof(struct kaddr))
286814e607dSclaudio 				fatalx("NEWADDR imsg with wrong len");
287814e607dSclaudio 
2883de94509Srenato 			if_addr_add(imsg.data);
289ab0c2486Smichele 			break;
290814e607dSclaudio 		case IMSG_DELADDR:
291814e607dSclaudio 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
292814e607dSclaudio 			    sizeof(struct kaddr))
293814e607dSclaudio 				fatalx("DELADDR imsg with wrong len");
294814e607dSclaudio 
2953de94509Srenato 			if_addr_del(imsg.data);
296814e607dSclaudio 			break;
29716040b47Srenato 		case IMSG_SOCKET_IPC:
29816040b47Srenato 			if (iev_lde) {
29916040b47Srenato 				log_warnx("%s: received unexpected imsg fd "
30016040b47Srenato 				    "to lde", __func__);
30116040b47Srenato 				break;
30216040b47Srenato 			}
3034bba3f27Sclaudio 			if ((fd = imsg_get_fd(&imsg)) == -1) {
30416040b47Srenato 				log_warnx("%s: expected to receive imsg fd to "
30516040b47Srenato 				    "lde but didn't receive any", __func__);
30616040b47Srenato 				break;
30716040b47Srenato 			}
30816040b47Srenato 
30916040b47Srenato 			if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
31016040b47Srenato 				fatal(NULL);
311*f1b790a5Sclaudio 			if (imsgbuf_init(&iev_lde->ibuf, fd) == -1)
312*f1b790a5Sclaudio 				fatal(NULL);
31316040b47Srenato 			iev_lde->handler = ldpe_dispatch_lde;
31416040b47Srenato 			iev_lde->events = EV_READ;
31516040b47Srenato 			event_set(&iev_lde->ev, iev_lde->ibuf.fd,
31616040b47Srenato 			    iev_lde->events, iev_lde->handler, iev_lde);
31716040b47Srenato 			event_add(&iev_lde->ev, NULL);
31816040b47Srenato 			break;
319b5921293Srenato 		case IMSG_CLOSE_SOCKETS:
320a8c39dc0Srenato 			af = imsg.hdr.peerid;
321a8c39dc0Srenato 
3225a7df819Srenato 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
3235a7df819Srenato 				if (nbr->af != af)
3245a7df819Srenato 					continue;
3255a7df819Srenato 				session_shutdown(nbr, S_SHUTDOWN, 0, 0);
3265a7df819Srenato 				pfkey_remove(nbr);
3275a7df819Srenato 			}
328a8c39dc0Srenato 			ldpe_close_sockets(af);
329a8c39dc0Srenato 			if_update_all(af);
330a8c39dc0Srenato 			tnbr_update_all(af);
331b5921293Srenato 
332b5921293Srenato 			disc_socket = -1;
333b5921293Srenato 			edisc_socket = -1;
334b5921293Srenato 			session_socket = -1;
33572b2a41bSrenato 			if ((ldp_af_conf_get(leconf, af))->flags &
33672b2a41bSrenato 			    F_LDPD_AF_ENABLED)
33772b2a41bSrenato 				ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
33872b2a41bSrenato 				    af, NULL, 0);
339b5921293Srenato 			break;
340b5921293Srenato 		case IMSG_SOCKET_NET:
341b5921293Srenato 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
342b5921293Srenato 			    sizeof(enum socket_type))
343b5921293Srenato 				fatalx("SOCKET_NET imsg with wrong len");
344b5921293Srenato 			socket_type = imsg.data;
345b5921293Srenato 
346b5921293Srenato 			switch (*socket_type) {
347b5921293Srenato 			case LDP_SOCKET_DISC:
3484bba3f27Sclaudio 				disc_socket = imsg_get_fd(&imsg);
349b5921293Srenato 				break;
350b5921293Srenato 			case LDP_SOCKET_EDISC:
3514bba3f27Sclaudio 				edisc_socket = imsg_get_fd(&imsg);
352b5921293Srenato 				break;
353b5921293Srenato 			case LDP_SOCKET_SESSION:
3544bba3f27Sclaudio 				session_socket = imsg_get_fd(&imsg);
355b5921293Srenato 				break;
356b5921293Srenato 			}
357b5921293Srenato 			break;
358b5921293Srenato 		case IMSG_SETUP_SOCKETS:
359a8c39dc0Srenato 			af = imsg.hdr.peerid;
360b5921293Srenato 			if (disc_socket == -1 || edisc_socket == -1 ||
361b5921293Srenato 			    session_socket == -1) {
362b5921293Srenato 				if (disc_socket != -1)
363b5921293Srenato 					close(disc_socket);
364b5921293Srenato 				if (edisc_socket != -1)
365b5921293Srenato 					close(edisc_socket);
366b5921293Srenato 				if (session_socket != -1)
367b5921293Srenato 					close(session_socket);
368b5921293Srenato 				break;
369b5921293Srenato 			}
370b5921293Srenato 
371a8c39dc0Srenato 			ldpe_setup_sockets(af, disc_socket, edisc_socket,
372b5921293Srenato 			    session_socket);
373a8c39dc0Srenato 			if_update_all(af);
374a8c39dc0Srenato 			tnbr_update_all(af);
3755a7df819Srenato 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
3765a7df819Srenato 				if (nbr->af != af)
3775a7df819Srenato 					continue;
3785a7df819Srenato 				nbr->laddr = (ldp_af_conf_get(leconf,
3795a7df819Srenato 				    af))->trans_addr;
3807ee91690Sdlg 				if (pfkey_establish(nconf, nbr) == -1)
3815a7df819Srenato 					fatalx("pfkey setup failed");
3825a7df819Srenato 				if (nbr_session_active_role(nbr))
3835a7df819Srenato 					nbr_establish_connection(nbr);
3845a7df819Srenato 			}
385b5921293Srenato 			break;
386ab0c2486Smichele 		case IMSG_RECONF_CONF:
387be87e4d3Srenato 			if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
388be87e4d3Srenato 			    NULL)
389be87e4d3Srenato 				fatal(NULL);
390be87e4d3Srenato 			memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
391be87e4d3Srenato 
392be87e4d3Srenato 			LIST_INIT(&nconf->iface_list);
393be87e4d3Srenato 			LIST_INIT(&nconf->tnbr_list);
394be87e4d3Srenato 			LIST_INIT(&nconf->nbrp_list);
3956399cec1Srenato 			LIST_INIT(&nconf->l2vpn_list);
3967ee91690Sdlg 			LIST_INIT(&nconf->auth_list);
397ab0c2486Smichele 			break;
398ab0c2486Smichele 		case IMSG_RECONF_IFACE:
399be87e4d3Srenato 			if ((niface = malloc(sizeof(struct iface))) == NULL)
400be87e4d3Srenato 				fatal(NULL);
401be87e4d3Srenato 			memcpy(niface, imsg.data, sizeof(struct iface));
402be87e4d3Srenato 
403be87e4d3Srenato 			LIST_INIT(&niface->addr_list);
404a8c39dc0Srenato 			LIST_INIT(&niface->ipv4.adj_list);
405a8c39dc0Srenato 			LIST_INIT(&niface->ipv6.adj_list);
406a8c39dc0Srenato 			niface->ipv4.iface = niface;
407a8c39dc0Srenato 			niface->ipv6.iface = niface;
408be87e4d3Srenato 
409be87e4d3Srenato 			LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
410be87e4d3Srenato 			break;
411be87e4d3Srenato 		case IMSG_RECONF_TNBR:
412be87e4d3Srenato 			if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
413be87e4d3Srenato 				fatal(NULL);
414be87e4d3Srenato 			memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
415be87e4d3Srenato 
416be87e4d3Srenato 			LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
417be87e4d3Srenato 			break;
418be87e4d3Srenato 		case IMSG_RECONF_NBRP:
419be87e4d3Srenato 			if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
420be87e4d3Srenato 				fatal(NULL);
421be87e4d3Srenato 			memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
422be87e4d3Srenato 
423be87e4d3Srenato 			LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
424ab0c2486Smichele 			break;
4256399cec1Srenato 		case IMSG_RECONF_L2VPN:
4266399cec1Srenato 			if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
4276399cec1Srenato 				fatal(NULL);
4286399cec1Srenato 			memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
4296399cec1Srenato 
4306399cec1Srenato 			LIST_INIT(&nl2vpn->if_list);
4316399cec1Srenato 			LIST_INIT(&nl2vpn->pw_list);
4326399cec1Srenato 
4336399cec1Srenato 			LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
4346399cec1Srenato 			break;
4356399cec1Srenato 		case IMSG_RECONF_L2VPN_IF:
4366399cec1Srenato 			if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
4376399cec1Srenato 				fatal(NULL);
4386399cec1Srenato 			memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
4396399cec1Srenato 
4406399cec1Srenato 			nlif->l2vpn = nl2vpn;
4416399cec1Srenato 			LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
4426399cec1Srenato 			break;
4436399cec1Srenato 		case IMSG_RECONF_L2VPN_PW:
4446399cec1Srenato 			if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
4456399cec1Srenato 				fatal(NULL);
4466399cec1Srenato 			memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
4476399cec1Srenato 
4486399cec1Srenato 			npw->l2vpn = nl2vpn;
4496399cec1Srenato 			LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
4506399cec1Srenato 			break;
4517ee91690Sdlg 		case IMSG_RECONF_CONF_AUTH: {
4527ee91690Sdlg 			struct ldp_auth *auth;
4537ee91690Sdlg 
4547ee91690Sdlg 			auth = malloc(sizeof(*auth));
4557ee91690Sdlg 			if (auth == NULL)
4567ee91690Sdlg 				fatal(NULL);
4577ee91690Sdlg 
4587ee91690Sdlg 			memcpy(auth, imsg.data, sizeof(*auth));
4597ee91690Sdlg 
4607ee91690Sdlg 			LIST_INSERT_HEAD(&nconf->auth_list, auth, entry);
4617ee91690Sdlg 			break;
4627ee91690Sdlg 		}
4637ee91690Sdlg 
464ab0c2486Smichele 		case IMSG_RECONF_END:
465be87e4d3Srenato 			merge_config(leconf, nconf);
466be87e4d3Srenato 			nconf = NULL;
4670e35860dSrenato 			global.conf_seqnum++;
468ab0c2486Smichele 			break;
469ab0c2486Smichele 		case IMSG_CTL_KROUTE:
470ab0c2486Smichele 		case IMSG_CTL_KROUTE_ADDR:
471ab0c2486Smichele 		case IMSG_CTL_IFINFO:
472ab0c2486Smichele 		case IMSG_CTL_END:
473ab0c2486Smichele 			control_imsg_relay(&imsg);
474ab0c2486Smichele 			break;
475ab0c2486Smichele 		default:
476ab0c2486Smichele 			log_debug("ldpe_dispatch_main: error handling imsg %d",
477ab0c2486Smichele 			    imsg.hdr.type);
478ab0c2486Smichele 			break;
479ab0c2486Smichele 		}
480ab0c2486Smichele 		imsg_free(&imsg);
481ab0c2486Smichele 	}
482ab0c2486Smichele 	if (!shut)
483cb77742aSpyr 		imsg_event_add(iev);
484ab0c2486Smichele 	else {
485ab0c2486Smichele 		/* this pipe is dead, so remove the event handler */
486cb77742aSpyr 		event_del(&iev->ev);
487ab0c2486Smichele 		event_loopexit(NULL);
488ab0c2486Smichele 	}
489ab0c2486Smichele }
490ab0c2486Smichele 
491c28a25a1Srenato static void
492ab0c2486Smichele ldpe_dispatch_lde(int fd, short event, void *bula)
493ab0c2486Smichele {
494cb77742aSpyr 	struct imsgev		*iev = bula;
495cb77742aSpyr 	struct imsgbuf		*ibuf = &iev->ibuf;
496ab0c2486Smichele 	struct imsg		 imsg;
497ab0c2486Smichele 	struct map		 map;
4987d508fe8Smichele 	struct notify_msg	 nm;
499ab0c2486Smichele 	int			 n, shut = 0;
500ab0c2486Smichele 	struct nbr		*nbr = NULL;
501ab0c2486Smichele 
502ab0c2486Smichele 	if (event & EV_READ) {
503668e5ba9Sclaudio 		if ((n = imsgbuf_read(ibuf)) == -1)
504dd7efffeSclaudio 			fatal("imsgbuf_read error");
505ab0c2486Smichele 		if (n == 0)	/* connection closed */
506ab0c2486Smichele 			shut = 1;
507ab0c2486Smichele 	}
508ab0c2486Smichele 	if (event & EV_WRITE) {
509dd7efffeSclaudio 		if (imsgbuf_write(ibuf) == -1) {
510c1aa9554Sclaudio 			if (errno == EPIPE)	/* connection closed */
5111203692fSkrw 				shut = 1;
512c1aa9554Sclaudio 			else
513dd7efffeSclaudio 				fatal("imsgbuf_write");
514c1aa9554Sclaudio 		}
515ab0c2486Smichele 	}
516ab0c2486Smichele 
517ab0c2486Smichele 	for (;;) {
518ab0c2486Smichele 		if ((n = imsg_get(ibuf, &imsg)) == -1)
519ae7f1740Sclaudio 			fatal("ldpe_dispatch_lde: imsg_get error");
520ab0c2486Smichele 		if (n == 0)
521ab0c2486Smichele 			break;
522ab0c2486Smichele 
523ab0c2486Smichele 		switch (imsg.hdr.type) {
524ab0c2486Smichele 		case IMSG_MAPPING_ADD:
52532415746Sclaudio 		case IMSG_RELEASE_ADD:
52632415746Sclaudio 		case IMSG_REQUEST_ADD:
527cf483f25Srenato 		case IMSG_WITHDRAW_ADD:
528ab0c2486Smichele 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
52932415746Sclaudio 				fatalx("invalid size of map request");
530ab0c2486Smichele 			memcpy(&map, imsg.data, sizeof(map));
531ab0c2486Smichele 
532ab0c2486Smichele 			nbr = nbr_find_peerid(imsg.hdr.peerid);
533ab0c2486Smichele 			if (nbr == NULL) {
534ab0c2486Smichele 				log_debug("ldpe_dispatch_lde: cannot find "
535ab0c2486Smichele 				    "neighbor");
53612da3e3bSrenato 				break;
537ab0c2486Smichele 			}
53853e24948Sclaudio 			if (nbr->state != NBR_STA_OPER)
53912da3e3bSrenato 				break;
540ab0c2486Smichele 
54132415746Sclaudio 			switch (imsg.hdr.type) {
54232415746Sclaudio 			case IMSG_MAPPING_ADD:
5438d99d653Srenato 				mapping_list_add(&nbr->mapping_list, &map);
544ab0c2486Smichele 				break;
545ab0c2486Smichele 			case IMSG_RELEASE_ADD:
5468d99d653Srenato 				mapping_list_add(&nbr->release_list, &map);
547ab0c2486Smichele 				break;
54832415746Sclaudio 			case IMSG_REQUEST_ADD:
5498d99d653Srenato 				mapping_list_add(&nbr->request_list, &map);
55032415746Sclaudio 				break;
551cf483f25Srenato 			case IMSG_WITHDRAW_ADD:
5528d99d653Srenato 				mapping_list_add(&nbr->withdraw_list, &map);
553cf483f25Srenato 				break;
55432415746Sclaudio 			}
55532415746Sclaudio 			break;
55632415746Sclaudio 		case IMSG_MAPPING_ADD_END:
557ab0c2486Smichele 		case IMSG_RELEASE_ADD_END:
55832415746Sclaudio 		case IMSG_REQUEST_ADD_END:
559cf483f25Srenato 		case IMSG_WITHDRAW_ADD_END:
560ab0c2486Smichele 			nbr = nbr_find_peerid(imsg.hdr.peerid);
561ab0c2486Smichele 			if (nbr == NULL) {
562ab0c2486Smichele 				log_debug("ldpe_dispatch_lde: cannot find "
563ab0c2486Smichele 				    "neighbor");
56412da3e3bSrenato 				break;
565ab0c2486Smichele 			}
56653e24948Sclaudio 			if (nbr->state != NBR_STA_OPER)
56712da3e3bSrenato 				break;
56832415746Sclaudio 
56932415746Sclaudio 			switch (imsg.hdr.type) {
57032415746Sclaudio 			case IMSG_MAPPING_ADD_END:
571bb21b33cSrenato 				send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
572bb21b33cSrenato 				    &nbr->mapping_list);
57332415746Sclaudio 				break;
57432415746Sclaudio 			case IMSG_RELEASE_ADD_END:
575bb21b33cSrenato 				send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
576bb21b33cSrenato 				    &nbr->release_list);
577ab0c2486Smichele 				break;
57832415746Sclaudio 			case IMSG_REQUEST_ADD_END:
579bb21b33cSrenato 				send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
580bb21b33cSrenato 				    &nbr->request_list);
58132415746Sclaudio 				break;
582cf483f25Srenato 			case IMSG_WITHDRAW_ADD_END:
583cf483f25Srenato 				send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
584cf483f25Srenato 				    &nbr->withdraw_list);
585cf483f25Srenato 				break;
58632415746Sclaudio 			}
58732415746Sclaudio 			break;
588ab0c2486Smichele 		case IMSG_NOTIFICATION_SEND:
5897d508fe8Smichele 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
590ab0c2486Smichele 				fatalx("invalid size of OE request");
5917d508fe8Smichele 			memcpy(&nm, imsg.data, sizeof(nm));
592ab0c2486Smichele 
593ab0c2486Smichele 			nbr = nbr_find_peerid(imsg.hdr.peerid);
594ab0c2486Smichele 			if (nbr == NULL) {
595ab0c2486Smichele 				log_debug("ldpe_dispatch_lde: cannot find "
596ab0c2486Smichele 				    "neighbor");
59712da3e3bSrenato 				break;
598ab0c2486Smichele 			}
59953e24948Sclaudio 			if (nbr->state != NBR_STA_OPER)
60012da3e3bSrenato 				break;
601ab0c2486Smichele 
6026399cec1Srenato 			send_notification_full(nbr->tcp, &nm);
603ab0c2486Smichele 			break;
604ab0c2486Smichele 		case IMSG_CTL_END:
605ab0c2486Smichele 		case IMSG_CTL_SHOW_LIB:
6066399cec1Srenato 		case IMSG_CTL_SHOW_L2VPN_PW:
6076399cec1Srenato 		case IMSG_CTL_SHOW_L2VPN_BINDING:
608ab0c2486Smichele 			control_imsg_relay(&imsg);
609ab0c2486Smichele 			break;
610ab0c2486Smichele 		default:
611ab0c2486Smichele 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
612ab0c2486Smichele 			    imsg.hdr.type);
613ab0c2486Smichele 			break;
614ab0c2486Smichele 		}
615ab0c2486Smichele 		imsg_free(&imsg);
616ab0c2486Smichele 	}
617ab0c2486Smichele 	if (!shut)
618cb77742aSpyr 		imsg_event_add(iev);
619ab0c2486Smichele 	else {
620ab0c2486Smichele 		/* this pipe is dead, so remove the event handler */
621cb77742aSpyr 		event_del(&iev->ev);
622ab0c2486Smichele 		event_loopexit(NULL);
623ab0c2486Smichele 	}
624ab0c2486Smichele }
625ab0c2486Smichele 
626c28a25a1Srenato static void
627627846caSrenato ldpe_dispatch_pfkey(int fd, short event, void *bula)
628627846caSrenato {
629627846caSrenato 	if (event & EV_READ) {
630627846caSrenato 		if (pfkey_read(fd, NULL) == -1) {
631627846caSrenato 			fatal("pfkey_read failed, exiting...");
632627846caSrenato 		}
633627846caSrenato 	}
634627846caSrenato }
635627846caSrenato 
636c28a25a1Srenato static void
637c28a25a1Srenato ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
638c28a25a1Srenato     int session_socket)
639b5921293Srenato {
640a8c39dc0Srenato 	struct ldpd_af_global	*af_global;
641a8c39dc0Srenato 
642a8c39dc0Srenato 	af_global = ldp_af_global_get(&global, af);
643a8c39dc0Srenato 
644b5921293Srenato 	/* discovery socket */
645a8c39dc0Srenato 	af_global->ldp_disc_socket = disc_socket;
646a8c39dc0Srenato 	event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
647b5921293Srenato 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
648a8c39dc0Srenato 	event_add(&af_global->disc_ev, NULL);
649b5921293Srenato 
650b5921293Srenato 	/* extended discovery socket */
651a8c39dc0Srenato 	af_global->ldp_edisc_socket = edisc_socket;
652a8c39dc0Srenato 	event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
653b5921293Srenato 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
654a8c39dc0Srenato 	event_add(&af_global->edisc_ev, NULL);
655b5921293Srenato 
656b5921293Srenato 	/* session socket */
657a8c39dc0Srenato 	af_global->ldp_session_socket = session_socket;
658a8c39dc0Srenato 	accept_add(af_global->ldp_session_socket, session_accept, NULL);
659b5921293Srenato }
660b5921293Srenato 
661c28a25a1Srenato static void
662a8c39dc0Srenato ldpe_close_sockets(int af)
663b5921293Srenato {
664a8c39dc0Srenato 	struct ldpd_af_global	*af_global;
665a8c39dc0Srenato 
666a8c39dc0Srenato 	af_global = ldp_af_global_get(&global, af);
667a8c39dc0Srenato 
668b5921293Srenato 	/* discovery socket */
669a8c39dc0Srenato 	if (event_initialized(&af_global->disc_ev))
670a8c39dc0Srenato 		event_del(&af_global->disc_ev);
671a8c39dc0Srenato 	if (af_global->ldp_disc_socket != -1) {
672a8c39dc0Srenato 		close(af_global->ldp_disc_socket);
673a8c39dc0Srenato 		af_global->ldp_disc_socket = -1;
674b5921293Srenato 	}
675b5921293Srenato 
676b5921293Srenato 	/* extended discovery socket */
677a8c39dc0Srenato 	if (event_initialized(&af_global->edisc_ev))
678a8c39dc0Srenato 		event_del(&af_global->edisc_ev);
679a8c39dc0Srenato 	if (af_global->ldp_edisc_socket != -1) {
680a8c39dc0Srenato 		close(af_global->ldp_edisc_socket);
681a8c39dc0Srenato 		af_global->ldp_edisc_socket = -1;
682b5921293Srenato 	}
683b5921293Srenato 
684b5921293Srenato 	/* session socket */
685a8c39dc0Srenato 	if (af_global->ldp_session_socket != -1) {
686a8c39dc0Srenato 		accept_del(af_global->ldp_session_socket);
687a8c39dc0Srenato 		close(af_global->ldp_session_socket);
688a8c39dc0Srenato 		af_global->ldp_session_socket = -1;
689b5921293Srenato 	}
690b5921293Srenato }
691b5921293Srenato 
692b5921293Srenato void
693a8c39dc0Srenato ldpe_reset_nbrs(int af)
69408964f31Srenato {
69508964f31Srenato 	struct nbr		*nbr;
69608964f31Srenato 
697a8c39dc0Srenato 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
698a8c39dc0Srenato 		if (nbr->af == af)
69908964f31Srenato 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
70008964f31Srenato 	}
701a8c39dc0Srenato }
70208964f31Srenato 
70308964f31Srenato void
704a8c39dc0Srenato ldpe_reset_ds_nbrs(void)
705a8c39dc0Srenato {
706a8c39dc0Srenato 	struct nbr		*nbr;
707a8c39dc0Srenato 
708a8c39dc0Srenato 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
709a8c39dc0Srenato 		if (nbr->ds_tlv)
710a8c39dc0Srenato 			session_shutdown(nbr, S_SHUTDOWN, 0, 0);
711a8c39dc0Srenato 	}
712a8c39dc0Srenato }
713a8c39dc0Srenato 
714a8c39dc0Srenato void
715a8c39dc0Srenato ldpe_remove_dynamic_tnbrs(int af)
7162cba3533Srenato {
7172cba3533Srenato 	struct tnbr		*tnbr, *safe;
7182cba3533Srenato 
7192cba3533Srenato 	LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
720a8c39dc0Srenato 		if (tnbr->af != af)
721a8c39dc0Srenato 			continue;
722a8c39dc0Srenato 
7232cba3533Srenato 		tnbr->flags &= ~F_TNBR_DYNAMIC;
7242cba3533Srenato 		tnbr_check(tnbr);
7252cba3533Srenato 	}
7262cba3533Srenato }
7272cba3533Srenato 
7282cba3533Srenato void
729a8c39dc0Srenato ldpe_stop_init_backoff(int af)
7302cba3533Srenato {
7312cba3533Srenato 	struct nbr		*nbr;
7322cba3533Srenato 
7332cba3533Srenato 	RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
734a8c39dc0Srenato 		if (nbr->af == af && nbr_pending_idtimer(nbr)) {
7352cba3533Srenato 			nbr_stop_idtimer(nbr);
7362cba3533Srenato 			nbr_establish_connection(nbr);
7372cba3533Srenato 		}
7382cba3533Srenato 	}
7392cba3533Srenato }
7402cba3533Srenato 
741c28a25a1Srenato static void
742a8c39dc0Srenato ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
74333f6ccfeSrenato {
74433f6ccfeSrenato 	struct iface		*iface;
745a8c39dc0Srenato 	struct iface_af		*ia;
74633f6ccfeSrenato 	struct ctl_iface	*ictl;
74733f6ccfeSrenato 
74833f6ccfeSrenato 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
74933f6ccfeSrenato 		if (idx == 0 || idx == iface->ifindex) {
750a8c39dc0Srenato 			ia = iface_af_get(iface, af);
751a8c39dc0Srenato 			if (!ia->enabled)
752a8c39dc0Srenato 				continue;
753a8c39dc0Srenato 
754a8c39dc0Srenato 			ictl = if_to_ctl(ia);
75502a212eeSrenato 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
75633f6ccfeSrenato 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
75733f6ccfeSrenato 		}
75833f6ccfeSrenato 	}
75933f6ccfeSrenato }
76033f6ccfeSrenato 
76133f6ccfeSrenato void
762a8c39dc0Srenato ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
763a8c39dc0Srenato {
764a8c39dc0Srenato 	ldpe_iface_af_ctl(c, AF_INET, idx);
765a8c39dc0Srenato 	ldpe_iface_af_ctl(c, AF_INET6, idx);
766a8c39dc0Srenato }
767a8c39dc0Srenato 
768a8c39dc0Srenato void
76933f6ccfeSrenato ldpe_adj_ctl(struct ctl_conn *c)
77033f6ccfeSrenato {
771a8c39dc0Srenato 	struct nbr	*nbr;
77233f6ccfeSrenato 	struct adj	*adj;
77333f6ccfeSrenato 	struct ctl_adj	*actl;
77433f6ccfeSrenato 
775a8c39dc0Srenato 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
776a8c39dc0Srenato 		LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) {
77733f6ccfeSrenato 			actl = adj_to_ctl(adj);
77833f6ccfeSrenato 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
77933f6ccfeSrenato 			    0, 0, -1, actl, sizeof(struct ctl_adj));
78033f6ccfeSrenato 		}
781a8c39dc0Srenato 	}
782a8c39dc0Srenato 	/* show adjacencies not associated with any neighbor */
783a8c39dc0Srenato 	LIST_FOREACH(adj, &global.adj_list, global_entry) {
784a8c39dc0Srenato 		if (adj->nbr != NULL)
785a8c39dc0Srenato 			continue;
78633f6ccfeSrenato 
787a8c39dc0Srenato 		actl = adj_to_ctl(adj);
788a8c39dc0Srenato 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
789a8c39dc0Srenato 		    -1, actl, sizeof(struct ctl_adj));
79033f6ccfeSrenato 	}
79133f6ccfeSrenato 
79233f6ccfeSrenato 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
79333f6ccfeSrenato }
79433f6ccfeSrenato 
79533f6ccfeSrenato void
79633f6ccfeSrenato ldpe_nbr_ctl(struct ctl_conn *c)
79733f6ccfeSrenato {
79833f6ccfeSrenato 	struct nbr	*nbr;
79933f6ccfeSrenato 	struct ctl_nbr	*nctl;
80033f6ccfeSrenato 
801a8c39dc0Srenato 	RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
80233f6ccfeSrenato 		nctl = nbr_to_ctl(nbr);
80333f6ccfeSrenato 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
80433f6ccfeSrenato 		    sizeof(struct ctl_nbr));
80533f6ccfeSrenato 	}
80633f6ccfeSrenato 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
80733f6ccfeSrenato }
80833f6ccfeSrenato 
80933f6ccfeSrenato void
8108d99d653Srenato mapping_list_add(struct mapping_head *mh, struct map *map)
8118d99d653Srenato {
8128d99d653Srenato 	struct mapping_entry	*me;
8138d99d653Srenato 
8148d99d653Srenato 	me = calloc(1, sizeof(*me));
8158d99d653Srenato 	if (me == NULL)
816b7b4db73Srenato 		fatal(__func__);
8178d99d653Srenato 	me->map = *map;
8188d99d653Srenato 
8198d99d653Srenato 	TAILQ_INSERT_TAIL(mh, me, entry);
8208d99d653Srenato }
8218d99d653Srenato 
8228d99d653Srenato void
8238d99d653Srenato mapping_list_clr(struct mapping_head *mh)
8248d99d653Srenato {
8258d99d653Srenato 	struct mapping_entry	*me;
8268d99d653Srenato 
8278d99d653Srenato 	while ((me = TAILQ_FIRST(mh)) != NULL) {
8288d99d653Srenato 		TAILQ_REMOVE(mh, me, entry);
8298d99d653Srenato 		free(me);
8308d99d653Srenato 	}
8318d99d653Srenato }
832