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