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