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