xref: /openbsd/usr.sbin/bgpd/bgpd.c (revision 3a99c822)
1 /*	$OpenBSD: bgpd.c,v 1.280 2024/12/03 13:46:53 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <netinet/in.h>
23 #include <netinet/ip.h>
24 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <poll.h>
30 #include <pwd.h>
31 #include <signal.h>
32 #include <stddef.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <syslog.h>
37 #include <unistd.h>
38 
39 #include "bgpd.h"
40 #include "session.h"
41 #include "log.h"
42 #include "version.h"
43 
44 void		sighdlr(int);
45 __dead void	usage(void);
46 int		main(int, char *[]);
47 pid_t		start_child(enum bgpd_process, char *, int, int, int);
48 int		send_filterset(struct imsgbuf *, struct filter_set_head *);
49 int		reconfigure(char *, struct bgpd_config *);
50 int		send_config(struct bgpd_config *);
51 int		dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *);
52 int		control_setup(struct bgpd_config *);
53 static void	getsockpair(int [2]);
54 int		imsg_send_sockets(struct imsgbuf *, struct imsgbuf *,
55 		    struct imsgbuf *);
56 void		bgpd_rtr_conn_setup(struct rtr_config *);
57 void		bgpd_rtr_conn_setup_done(int, struct bgpd_config *);
58 void		bgpd_rtr_conn_teardown(uint32_t);
59 
60 int			 cflags;
61 volatile sig_atomic_t	 mrtdump;
62 volatile sig_atomic_t	 quit;
63 volatile sig_atomic_t	 reconfig;
64 pid_t			 reconfpid;
65 int			 reconfpending;
66 struct imsgbuf		*ibuf_se;
67 struct imsgbuf		*ibuf_rde;
68 struct imsgbuf		*ibuf_rtr;
69 struct rib_names	 ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames);
70 char			*cname;
71 char			*rcname;
72 
73 struct connect_elm {
74 	TAILQ_ENTRY(connect_elm)	entry;
75 	struct auth_state		auth_state;
76 	uint32_t			id;
77 	int				fd;
78 };
79 
80 TAILQ_HEAD(, connect_elm)	connect_queue = \
81 				    TAILQ_HEAD_INITIALIZER(connect_queue),
82 				socket_queue = \
83 				    TAILQ_HEAD_INITIALIZER(socket_queue);
84 u_int				connect_cnt;
85 #define MAX_CONNECT_CNT		32
86 
87 void
sighdlr(int sig)88 sighdlr(int sig)
89 {
90 	switch (sig) {
91 	case SIGTERM:
92 	case SIGINT:
93 		quit = 1;
94 		break;
95 	case SIGHUP:
96 		reconfig = 1;
97 		break;
98 	case SIGALRM:
99 	case SIGUSR1:
100 		mrtdump = 1;
101 		break;
102 	}
103 }
104 
105 __dead void
usage(void)106 usage(void)
107 {
108 	extern char *__progname;
109 
110 	fprintf(stderr, "usage: %s [-cdnvV] [-D macro=value] [-f file]\n",
111 	    __progname);
112 	exit(1);
113 }
114 
115 #define PFD_PIPE_SESSION	0
116 #define PFD_PIPE_RDE		1
117 #define PFD_PIPE_RTR		2
118 #define PFD_SOCK_ROUTE		3
119 #define PFD_SOCK_PFKEY		4
120 #define PFD_CONNECT_START	5
121 #define MAX_TIMEOUT		3600
122 
123 int	 cmd_opts;
124 
125 int
main(int argc,char * argv[])126 main(int argc, char *argv[])
127 {
128 	struct bgpd_config	*conf;
129 	enum bgpd_process	 proc = PROC_MAIN;
130 	struct rde_rib		*rr;
131 	struct peer		*p;
132 	struct pollfd		*pfd = NULL;
133 	struct connect_elm	*ce;
134 	time_t			 timeout;
135 	pid_t			 se_pid = 0, rde_pid = 0, rtr_pid = 0, pid;
136 	char			*conffile;
137 	char			*saved_argv0;
138 	u_int			 pfd_elms = 0, npfd, i;
139 	int			 debug = 0;
140 	int			 rfd, keyfd;
141 	int			 ch, status;
142 	int			 pipe_m2s[2];
143 	int			 pipe_m2r[2];
144 	int			 pipe_m2roa[2];
145 
146 	conffile = CONFFILE;
147 
148 	log_init(1, LOG_DAEMON);	/* log to stderr until daemonized */
149 	log_procinit(log_procnames[PROC_MAIN]);
150 	log_setverbose(1);
151 
152 	saved_argv0 = argv[0];
153 	if (saved_argv0 == NULL)
154 		saved_argv0 = "bgpd";
155 
156 	while ((ch = getopt(argc, argv, "cdD:f:nRSTvV")) != -1) {
157 		switch (ch) {
158 		case 'c':
159 			cmd_opts |= BGPD_OPT_FORCE_DEMOTE;
160 			break;
161 		case 'd':
162 			debug = 1;
163 			break;
164 		case 'D':
165 			if (cmdline_symset(optarg) < 0)
166 				log_warnx("could not parse macro definition %s",
167 				    optarg);
168 			break;
169 		case 'f':
170 			conffile = optarg;
171 			break;
172 		case 'n':
173 			cmd_opts |= BGPD_OPT_NOACTION;
174 			break;
175 		case 'v':
176 			if (cmd_opts & BGPD_OPT_VERBOSE)
177 				cmd_opts |= BGPD_OPT_VERBOSE2;
178 			cmd_opts |= BGPD_OPT_VERBOSE;
179 			break;
180 		case 'R':
181 			proc = PROC_RDE;
182 			break;
183 		case 'S':
184 			proc = PROC_SE;
185 			break;
186 		case 'T':
187 			proc = PROC_RTR;
188 			break;
189 		case 'V':
190 			fprintf(stderr, "OpenBGPD %s\n", BGPD_VERSION);
191 			return 0;
192 		default:
193 			usage();
194 			/* NOTREACHED */
195 		}
196 	}
197 
198 	argc -= optind;
199 	argv += optind;
200 	if (argc > 0)
201 		usage();
202 
203 	if (cmd_opts & BGPD_OPT_NOACTION) {
204 		if ((conf = parse_config(conffile, NULL, NULL)) == NULL)
205 			exit(1);
206 
207 		if (cmd_opts & BGPD_OPT_VERBOSE)
208 			print_config(conf, &ribnames);
209 		else
210 			fprintf(stderr, "configuration OK\n");
211 
212 		while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
213 			SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
214 			free(rr);
215 		}
216 		free_config(conf);
217 		exit(0);
218 	}
219 
220 	switch (proc) {
221 	case PROC_MAIN:
222 		break;
223 	case PROC_RDE:
224 		rde_main(debug, cmd_opts & BGPD_OPT_VERBOSE);
225 		/* NOTREACHED */
226 	case PROC_SE:
227 		session_main(debug, cmd_opts & BGPD_OPT_VERBOSE);
228 		/* NOTREACHED */
229 	case PROC_RTR:
230 		rtr_main(debug, cmd_opts & BGPD_OPT_VERBOSE);
231 		/* NOTREACHED */
232 	}
233 
234 	if (geteuid())
235 		errx(1, "need root privileges");
236 
237 	if (getpwnam(BGPD_USER) == NULL)
238 		errx(1, "unknown user %s", BGPD_USER);
239 
240 	if ((conf = parse_config(conffile, NULL, NULL)) == NULL) {
241 		log_warnx("config file %s has errors", conffile);
242 		exit(1);
243 	}
244 
245 	if (prepare_listeners(conf) == -1)
246 		exit(1);
247 
248 	log_init(debug, LOG_DAEMON);
249 	log_setverbose(cmd_opts & BGPD_OPT_VERBOSE);
250 
251 	if (!debug)
252 		daemon(1, 0);
253 
254 	log_info("startup");
255 
256 	getsockpair(pipe_m2s);
257 	getsockpair(pipe_m2r);
258 	getsockpair(pipe_m2roa);
259 
260 	/* fork children */
261 	rde_pid = start_child(PROC_RDE, saved_argv0, pipe_m2r[1], debug,
262 	    cmd_opts & BGPD_OPT_VERBOSE);
263 	se_pid = start_child(PROC_SE, saved_argv0, pipe_m2s[1], debug,
264 	    cmd_opts & BGPD_OPT_VERBOSE);
265 	rtr_pid = start_child(PROC_RTR, saved_argv0, pipe_m2roa[1], debug,
266 	    cmd_opts & BGPD_OPT_VERBOSE);
267 
268 	signal(SIGTERM, sighdlr);
269 	signal(SIGINT, sighdlr);
270 	signal(SIGHUP, sighdlr);
271 	signal(SIGALRM, sighdlr);
272 	signal(SIGUSR1, sighdlr);
273 	signal(SIGPIPE, SIG_IGN);
274 
275 	if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL ||
276 	    (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL ||
277 	    (ibuf_rtr = malloc(sizeof(struct imsgbuf))) == NULL)
278 		fatal(NULL);
279 	if (imsgbuf_init(ibuf_se, pipe_m2s[0]) == -1 ||
280 	    imsgbuf_set_maxsize(ibuf_se, MAX_BGPD_IMSGSIZE) == -1 ||
281 	    imsgbuf_init(ibuf_rde, pipe_m2r[0]) == -1 ||
282 	    imsgbuf_set_maxsize(ibuf_rde, MAX_BGPD_IMSGSIZE) == -1 ||
283 	    imsgbuf_init(ibuf_rtr, pipe_m2roa[0]) == -1 ||
284 	    imsgbuf_set_maxsize(ibuf_rtr, MAX_BGPD_IMSGSIZE) == -1)
285 		fatal(NULL);
286 	imsgbuf_allow_fdpass(ibuf_se);
287 	imsgbuf_allow_fdpass(ibuf_rde);
288 	imsgbuf_allow_fdpass(ibuf_rtr);
289 	mrt_init(ibuf_rde, ibuf_se);
290 	if (kr_init(&rfd, conf->fib_priority) == -1)
291 		quit = 1;
292 	keyfd = pfkey_init();
293 
294 	/*
295 	 * rpath, read config file
296 	 * cpath, unlink control socket
297 	 * fattr, chmod on control socket
298 	 * wpath, needed if we are doing mrt dumps
299 	 *
300 	 * pledge placed here because kr_init() does a setsockopt on the
301 	 * routing socket thats not allowed at all.
302 	 */
303 #if 0
304 	/*
305 	 * disabled because we do ioctls on /dev/pf and SIOCSIFGATTR
306 	 * this needs some redesign of bgpd to be fixed.
307 	 */
308 BROKEN	if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
309 	    NULL) == -1)
310 		fatal("pledge");
311 #endif
312 
313 	if (imsg_send_sockets(ibuf_se, ibuf_rde, ibuf_rtr))
314 		fatal("could not establish imsg links");
315 	/* control setup needs to happen late since it sends imsgs */
316 	if (control_setup(conf) == -1)
317 		quit = 1;
318 	if (send_config(conf) != 0)
319 		quit = 1;
320 	if (pftable_clear_all() != 0)
321 		quit = 1;
322 
323 	while (quit == 0) {
324 		if (pfd_elms < PFD_CONNECT_START + connect_cnt) {
325 			struct pollfd *newp;
326 
327 			if ((newp = reallocarray(pfd,
328 			    PFD_CONNECT_START + connect_cnt,
329 			    sizeof(struct pollfd))) == NULL) {
330 				log_warn("could not resize pfd from %u -> %u"
331 				    " entries", pfd_elms, PFD_CONNECT_START +
332 				    connect_cnt);
333 				fatalx("exiting");
334 			}
335 			pfd = newp;
336 			pfd_elms = PFD_CONNECT_START + connect_cnt;
337 		}
338 		memset(pfd, 0, sizeof(struct pollfd) * pfd_elms);
339 
340 		timeout = mrt_timeout(conf->mrt);
341 
342 		pfd[PFD_SOCK_ROUTE].fd = rfd;
343 		pfd[PFD_SOCK_ROUTE].events = POLLIN;
344 
345 		pfd[PFD_SOCK_PFKEY].fd = keyfd;
346 		pfd[PFD_SOCK_PFKEY].events = POLLIN;
347 
348 		set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se);
349 		set_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde);
350 		set_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr);
351 
352 		npfd = PFD_CONNECT_START;
353 		TAILQ_FOREACH(ce, &connect_queue, entry) {
354 			pfd[npfd].fd = ce->fd;
355 			pfd[npfd++].events = POLLOUT;
356 			if (npfd > pfd_elms)
357 				fatalx("polli pfd overflow");
358 		}
359 
360 		if (timeout < 0 || timeout > MAX_TIMEOUT)
361 			timeout = MAX_TIMEOUT;
362 		if (poll(pfd, npfd, timeout * 1000) == -1) {
363 			if (errno != EINTR) {
364 				log_warn("poll error");
365 				quit = 1;
366 			}
367 			goto next_loop;
368 		}
369 
370 		if (handle_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se) == -1) {
371 			log_warnx("main: Lost connection to SE");
372 			imsgbuf_clear(ibuf_se);
373 			free(ibuf_se);
374 			ibuf_se = NULL;
375 			quit = 1;
376 		} else {
377 			if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, conf) ==
378 			    -1)
379 				quit = 1;
380 		}
381 
382 		if (handle_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde) == -1) {
383 			log_warnx("main: Lost connection to RDE");
384 			imsgbuf_clear(ibuf_rde);
385 			free(ibuf_rde);
386 			ibuf_rde = NULL;
387 			quit = 1;
388 		} else {
389 			if (dispatch_imsg(ibuf_rde, PFD_PIPE_RDE, conf) == -1)
390 				quit = 1;
391 		}
392 
393 		if (handle_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr) == -1) {
394 			log_warnx("main: Lost connection to RTR");
395 			imsgbuf_clear(ibuf_rtr);
396 			free(ibuf_rtr);
397 			ibuf_rtr = NULL;
398 			quit = 1;
399 		} else {
400 			if (dispatch_imsg(ibuf_rtr, PFD_PIPE_RTR, conf) == -1)
401 				quit = 1;
402 		}
403 
404 		if (pfd[PFD_SOCK_ROUTE].revents & POLLIN) {
405 			if (kr_dispatch_msg() == -1)
406 				quit = 1;
407 		}
408 
409 		if (pfd[PFD_SOCK_PFKEY].revents & POLLIN) {
410 			if (pfkey_read(keyfd, NULL) == -1) {
411 				log_warnx("pfkey_read failed, exiting...");
412 				quit = 1;
413 			}
414 		}
415 
416 		for (i = PFD_CONNECT_START; i < npfd; i++)
417 			if (pfd[i].revents != 0)
418 				bgpd_rtr_conn_setup_done(pfd[i].fd, conf);
419 
420  next_loop:
421 		if (reconfig) {
422 			u_int	error;
423 
424 			reconfig = 0;
425 			switch (reconfigure(conffile, conf)) {
426 			case -1:	/* fatal error */
427 				quit = 1;
428 				break;
429 			case 0:		/* all OK */
430 				error = 0;
431 				break;
432 			case 2:
433 				log_info("previous reload still running");
434 				error = CTL_RES_PENDING;
435 				break;
436 			default:	/* parse error */
437 				log_warnx("config file %s has errors, "
438 				    "not reloading", conffile);
439 				error = CTL_RES_PARSE_ERROR;
440 				break;
441 			}
442 			if (reconfpid != 0) {
443 				send_imsg_session(IMSG_CTL_RESULT, reconfpid,
444 				    &error, sizeof(error));
445 				reconfpid = 0;
446 			}
447 		}
448 
449 		if (mrtdump) {
450 			mrtdump = 0;
451 			mrt_handler(conf->mrt);
452 		}
453 	}
454 
455 	/* close pipes */
456 	if (ibuf_se) {
457 		imsgbuf_clear(ibuf_se);
458 		close(ibuf_se->fd);
459 		free(ibuf_se);
460 		ibuf_se = NULL;
461 	}
462 	if (ibuf_rde) {
463 		imsgbuf_clear(ibuf_rde);
464 		close(ibuf_rde->fd);
465 		free(ibuf_rde);
466 		ibuf_rde = NULL;
467 	}
468 	if (ibuf_rtr) {
469 		imsgbuf_clear(ibuf_rtr);
470 		close(ibuf_rtr->fd);
471 		free(ibuf_rtr);
472 		ibuf_rtr = NULL;
473 	}
474 
475 	/* cleanup kernel data structures */
476 	carp_demote_shutdown();
477 	kr_shutdown();
478 	pftable_clear_all();
479 
480 	RB_FOREACH(p, peer_head, &conf->peers)
481 		pfkey_remove(&p->auth_state);
482 
483 	while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
484 		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
485 		free(rr);
486 	}
487 	free_config(conf);
488 
489 	log_debug("waiting for children to terminate");
490 	do {
491 		pid = wait(&status);
492 		if (pid == -1) {
493 			if (errno != EINTR && errno != ECHILD)
494 				fatal("wait");
495 		} else if (WIFSIGNALED(status)) {
496 			char *name = "unknown process";
497 			if (pid == rde_pid)
498 				name = "route decision engine";
499 			else if (pid == se_pid)
500 				name = "session engine";
501 			else if (pid == rtr_pid)
502 				name = "rtr engine";
503 			log_warnx("%s terminated; signal %d", name,
504 				WTERMSIG(status));
505 		}
506 	} while (pid != -1 || (pid == -1 && errno == EINTR));
507 
508 	free(rcname);
509 	free(cname);
510 
511 	log_info("terminating");
512 	return (0);
513 }
514 
515 pid_t
start_child(enum bgpd_process p,char * argv0,int fd,int debug,int verbose)516 start_child(enum bgpd_process p, char *argv0, int fd, int debug, int verbose)
517 {
518 	char *argv[5];
519 	int argc = 0;
520 	pid_t pid;
521 
522 	switch (pid = fork()) {
523 	case -1:
524 		fatal("cannot fork");
525 	case 0:
526 		break;
527 	default:
528 		close(fd);
529 		return (pid);
530 	}
531 
532 	if (fd != 3) {
533 		if (dup2(fd, 3) == -1)
534 			fatal("cannot setup imsg fd");
535 	} else if (fcntl(fd, F_SETFD, 0) == -1)
536 		fatal("cannot setup imsg fd");
537 
538 	argv[argc++] = argv0;
539 	switch (p) {
540 	case PROC_MAIN:
541 		fatalx("Can not start main process");
542 	case PROC_RDE:
543 		argv[argc++] = "-R";
544 		break;
545 	case PROC_SE:
546 		argv[argc++] = "-S";
547 		break;
548 	case PROC_RTR:
549 		argv[argc++] = "-T";
550 		break;
551 	}
552 	if (debug)
553 		argv[argc++] = "-d";
554 	if (verbose)
555 		argv[argc++] = "-v";
556 	argv[argc++] = NULL;
557 
558 	execvp(argv0, argv);
559 	fatal("execvp");
560 }
561 
562 int
send_filterset(struct imsgbuf * i,struct filter_set_head * set)563 send_filterset(struct imsgbuf *i, struct filter_set_head *set)
564 {
565 	struct filter_set	*s;
566 
567 	TAILQ_FOREACH(s, set, entry)
568 		if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
569 		    sizeof(struct filter_set)) == -1)
570 			return (-1);
571 	return (0);
572 }
573 
574 int
reconfigure(char * conffile,struct bgpd_config * conf)575 reconfigure(char *conffile, struct bgpd_config *conf)
576 {
577 	struct bgpd_config	*new_conf;
578 
579 	if (reconfpending)
580 		return (2);
581 
582 	log_info("rereading config");
583 	if ((new_conf = parse_config(conffile, &conf->peers,
584 	    &conf->rtrs)) == NULL)
585 		return (1);
586 
587 	merge_config(conf, new_conf);
588 
589 	if (prepare_listeners(conf) == -1)
590 		return (1);
591 
592 	if (control_setup(conf) == -1)
593 		return (1);
594 
595 	return send_config(conf);
596 }
597 
598 int
send_config(struct bgpd_config * conf)599 send_config(struct bgpd_config *conf)
600 {
601 	struct peer		*p;
602 	struct filter_rule	*r;
603 	struct listen_addr	*la;
604 	struct rde_rib		*rr;
605 	struct l3vpn		*vpn;
606 	struct as_set		*aset;
607 	struct prefixset	*ps;
608 	struct prefixset_item	*psi, *npsi;
609 	struct roa		*roa;
610 	struct aspa_set		*aspa;
611 	struct rtr_config	*rtr;
612 	struct flowspec_config	*f, *nf;
613 
614 	reconfpending = 3;	/* one per child */
615 
616 	expand_networks(conf, &conf->networks);
617 	SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry)
618 		expand_networks(conf, &vpn->net_l);
619 
620 	cflags = conf->flags;
621 
622 	/* start reconfiguration */
623 	if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1,
624 	    conf, sizeof(*conf)) == -1)
625 		return (-1);
626 	if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1,
627 	    conf, sizeof(*conf)) == -1)
628 		return (-1);
629 	if (imsg_compose(ibuf_rtr, IMSG_RECONF_CONF, 0, 0, -1,
630 	    conf, sizeof(*conf)) == -1)
631 		return (-1);
632 
633 	TAILQ_FOREACH(la, conf->listen_addrs, entry) {
634 		if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
635 		    la, sizeof(*la)) == -1)
636 			return (-1);
637 		la->fd = -1;
638 	}
639 
640 	/* adjust fib syncing on reload */
641 	ktable_preload();
642 
643 	/* RIBs for the RDE */
644 	while ((rr = SIMPLEQ_FIRST(&ribnames))) {
645 		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
646 		if (ktable_update(rr->rtableid, rr->name, rr->flags) == -1) {
647 			log_warnx("failed to load routing table %d",
648 			    rr->rtableid);
649 			return (-1);
650 		}
651 		if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1,
652 		    rr, sizeof(*rr)) == -1)
653 			return (-1);
654 		free(rr);
655 	}
656 
657 	/* send peer list to the SE */
658 	RB_FOREACH(p, peer_head, &conf->peers) {
659 		if (p->reconf_action == RECONF_DELETE)
660 			continue;
661 
662 		if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
663 		    &p->conf, sizeof(p->conf)) == -1)
664 			return (-1);
665 		if (pfkey_send_conf(ibuf_se, p->conf.id, &p->auth_conf) == -1)
666 			return (-1);
667 
668 		if (p->reconf_action == RECONF_REINIT)
669 			if (pfkey_establish(&p->auth_state, &p->auth_conf,
670 			    session_localaddr(p), &p->conf.remote_addr) == -1)
671 				log_peer_warnx(&p->conf, "auth setup failed");
672 	}
673 
674 	/* networks go via kroute to the RDE */
675 	kr_net_reload(conf->default_tableid, 0, &conf->networks);
676 
677 	/* flowspec goes directly to the RDE, also remove old objects */
678 	RB_FOREACH_SAFE(f, flowspec_tree, &conf->flowspecs, nf) {
679 		if (f->reconf_action != RECONF_DELETE) {
680 			if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_ADD, 0, 0, -1,
681 			    f->flow, FLOWSPEC_SIZE + f->flow->len) == -1)
682 				return (-1);
683 			if (send_filterset(ibuf_rde, &f->attrset) == -1)
684 				return (-1);
685 			if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_DONE, 0, 0, -1,
686 			    NULL, 0) == -1)
687 				return (-1);
688 		} else {
689 			if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_REMOVE, 0, 0,
690 			    -1, f->flow, FLOWSPEC_SIZE + f->flow->len) == -1)
691 				return (-1);
692 			RB_REMOVE(flowspec_tree, &conf->flowspecs, f);
693 			flowspec_free(f);
694 		}
695 	}
696 
697 	/* prefixsets for filters in the RDE */
698 	while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) {
699 		SIMPLEQ_REMOVE_HEAD(&conf->prefixsets, entry);
700 		if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET, 0, 0, -1,
701 		    ps->name, sizeof(ps->name)) == -1)
702 			return (-1);
703 		RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
704 			RB_REMOVE(prefixset_tree, &ps->psitems, psi);
705 			if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
706 			    0, 0, -1, psi, sizeof(*psi)) == -1)
707 				return (-1);
708 			free(psi);
709 		}
710 		free(ps);
711 	}
712 
713 	/* originsets for filters in the RDE */
714 	while ((ps = SIMPLEQ_FIRST(&conf->originsets)) != NULL) {
715 		SIMPLEQ_REMOVE_HEAD(&conf->originsets, entry);
716 		if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1,
717 		    ps->name, sizeof(ps->name)) == -1)
718 			return (-1);
719 		RB_FOREACH(roa, roa_tree, &ps->roaitems) {
720 			if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0,
721 			    -1, roa, sizeof(*roa)) == -1)
722 				return (-1);
723 		}
724 		free_roatree(&ps->roaitems);
725 		free(ps);
726 	}
727 
728 	/* roa table, aspa table and rtr config are sent to the RTR engine */
729 	RB_FOREACH(roa, roa_tree, &conf->roa) {
730 		if (imsg_compose(ibuf_rtr, IMSG_RECONF_ROA_ITEM, 0, 0,
731 		    -1, roa, sizeof(*roa)) == -1)
732 			return (-1);
733 	}
734 	free_roatree(&conf->roa);
735 	RB_FOREACH(aspa, aspa_tree, &conf->aspa) {
736 		if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA, 0, 0,
737 		    -1, aspa, offsetof(struct aspa_set, tas)) == -1)
738 			return (-1);
739 		if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_TAS, 0, 0,
740 		    -1, aspa->tas, aspa->num * sizeof(*aspa->tas)) == -1)
741 			return (-1);
742 		if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_DONE, 0, 0, -1,
743 		    NULL, 0) == -1)
744 			return -1;
745 	}
746 	free_aspatree(&conf->aspa);
747 	SIMPLEQ_FOREACH(rtr, &conf->rtrs, entry) {
748 		struct rtr_config_msg rtrconf = { 0 };
749 
750 		strlcpy(rtrconf.descr, rtr->descr, sizeof(rtrconf.descr));
751 		rtrconf.min_version = rtr->min_version;
752 		if (imsg_compose(ibuf_rtr, IMSG_RECONF_RTR_CONFIG, rtr->id,
753 		    0, -1, &rtrconf, sizeof(rtrconf)) == -1)
754 			return (-1);
755 	}
756 
757 	/* as-sets for filters in the RDE */
758 	while ((aset = SIMPLEQ_FIRST(&conf->as_sets)) != NULL) {
759 		struct ibuf *wbuf;
760 		uint32_t *as;
761 		size_t i, l, n;
762 
763 		SIMPLEQ_REMOVE_HEAD(&conf->as_sets, entry);
764 
765 		as = set_get(aset->set, &n);
766 		if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0,
767 		    sizeof(n) + sizeof(aset->name))) == NULL)
768 			return -1;
769 		if (imsg_add(wbuf, &n, sizeof(n)) == -1 ||
770 		    imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1)
771 			return -1;
772 		imsg_close(ibuf_rde, wbuf);
773 
774 		for (i = 0; i < n; i += l) {
775 			l = (n - i > 1024 ? 1024 : n - i);
776 			if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS,
777 			    0, 0, -1, as + i, l * sizeof(*as)) == -1)
778 				return -1;
779 		}
780 
781 		if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1,
782 		    NULL, 0) == -1)
783 			return -1;
784 
785 		set_free(aset->set);
786 		free(aset);
787 	}
788 
789 	/* filters for the RDE */
790 	while ((r = TAILQ_FIRST(conf->filters)) != NULL) {
791 		TAILQ_REMOVE(conf->filters, r, entry);
792 		if (send_filterset(ibuf_rde, &r->set) == -1)
793 			return (-1);
794 		if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
795 		    r, sizeof(struct filter_rule)) == -1)
796 			return (-1);
797 		filterset_free(&r->set);
798 		free(r);
799 	}
800 
801 	while ((vpn = SIMPLEQ_FIRST(&conf->l3vpns)) != NULL) {
802 		SIMPLEQ_REMOVE_HEAD(&conf->l3vpns, entry);
803 		if (ktable_update(vpn->rtableid, vpn->descr, vpn->flags) ==
804 		    -1) {
805 			log_warnx("failed to load routing table %d",
806 			    vpn->rtableid);
807 			return (-1);
808 		}
809 		/* networks go via kroute to the RDE */
810 		kr_net_reload(vpn->rtableid, vpn->rd, &vpn->net_l);
811 
812 		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN, 0, 0, -1,
813 		    vpn, sizeof(*vpn)) == -1)
814 			return (-1);
815 
816 		/* export targets */
817 		if (send_filterset(ibuf_rde, &vpn->export) == -1)
818 			return (-1);
819 		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0,
820 		    -1, NULL, 0) == -1)
821 			return (-1);
822 		filterset_free(&vpn->export);
823 
824 		/* import targets */
825 		if (send_filterset(ibuf_rde, &vpn->import) == -1)
826 			return (-1);
827 		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0,
828 		    -1, NULL, 0) == -1)
829 			return (-1);
830 		filterset_free(&vpn->import);
831 
832 		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_DONE, 0, 0,
833 		    -1, NULL, 0) == -1)
834 			return (-1);
835 
836 		free(vpn);
837 	}
838 
839 	/* send a drain message to know when all messages where processed */
840 	if (imsg_compose(ibuf_se, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
841 		return (-1);
842 	if (imsg_compose(ibuf_rde, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
843 		return (-1);
844 	if (imsg_compose(ibuf_rtr, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
845 		return (-1);
846 
847 	/* mrt changes can be sent out of bound */
848 	mrt_reconfigure(conf->mrt);
849 	return (0);
850 }
851 
852 int
dispatch_imsg(struct imsgbuf * imsgbuf,int idx,struct bgpd_config * conf)853 dispatch_imsg(struct imsgbuf *imsgbuf, int idx, struct bgpd_config *conf)
854 {
855 	struct imsg		 imsg;
856 	struct peer		*p;
857 	struct rtr_config	*r;
858 	struct kroute_full	 kf;
859 	struct bgpd_addr	 addr;
860 	struct pftable_msg	 pfmsg;
861 	struct demote_msg	 demote;
862 	char			 reason[REASON_LEN], ifname[IFNAMSIZ];
863 	ssize_t			 n;
864 	u_int			 rtableid;
865 	int			 rv, verbose;
866 
867 	rv = 0;
868 	while (imsgbuf) {
869 		if ((n = imsg_get(imsgbuf, &imsg)) == -1)
870 			return (-1);
871 
872 		if (n == 0)
873 			break;
874 
875 		switch (imsg_get_type(&imsg)) {
876 		case IMSG_KROUTE_CHANGE:
877 			if (idx != PFD_PIPE_RDE)
878 				log_warnx("route request not from RDE");
879 			else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1)
880 				log_warn("wrong imsg len");
881 			else if (kr_change(imsg_get_id(&imsg), &kf))
882 				rv = -1;
883 			break;
884 		case IMSG_KROUTE_DELETE:
885 			if (idx != PFD_PIPE_RDE)
886 				log_warnx("route request not from RDE");
887 			else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1)
888 				log_warn("wrong imsg len");
889 			else if (kr_delete(imsg_get_id(&imsg), &kf))
890 				rv = -1;
891 			break;
892 		case IMSG_KROUTE_FLUSH:
893 			if (idx != PFD_PIPE_RDE)
894 				log_warnx("route request not from RDE");
895 			else if (kr_flush(imsg_get_id(&imsg)))
896 				rv = -1;
897 			break;
898 		case IMSG_NEXTHOP_ADD:
899 			if (idx != PFD_PIPE_RDE)
900 				log_warnx("nexthop request not from RDE");
901 			else if (imsg_get_data(&imsg, &addr, sizeof(addr)) ==
902 			    -1)
903 				log_warn("wrong imsg len");
904 			else {
905 				rtableid = conf->default_tableid;
906 				if (kr_nexthop_add(rtableid, &addr) == -1)
907 					rv = -1;
908 			}
909 			break;
910 		case IMSG_NEXTHOP_REMOVE:
911 			if (idx != PFD_PIPE_RDE)
912 				log_warnx("nexthop request not from RDE");
913 			else if (imsg_get_data(&imsg, &addr, sizeof(addr)) ==
914 			    -1)
915 				log_warn("wrong imsg len");
916 			else {
917 				rtableid = conf->default_tableid;
918 				kr_nexthop_delete(rtableid, &addr);
919 			}
920 			break;
921 		case IMSG_PFTABLE_ADD:
922 			if (idx != PFD_PIPE_RDE)
923 				log_warnx("pftable request not from RDE");
924 			else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) ==
925 			    -1)
926 				log_warn("wrong imsg len");
927 			else if (pftable_addr_add(&pfmsg) != 0)
928 				rv = -1;
929 			break;
930 		case IMSG_PFTABLE_REMOVE:
931 			if (idx != PFD_PIPE_RDE)
932 				log_warnx("pftable request not from RDE");
933 			else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) ==
934 			    -1)
935 				log_warn("wrong imsg len");
936 			else if (pftable_addr_remove(&pfmsg) != 0)
937 				rv = -1;
938 			break;
939 		case IMSG_PFTABLE_COMMIT:
940 			if (idx != PFD_PIPE_RDE)
941 				log_warnx("pftable request not from RDE");
942 			else if (pftable_commit() != 0)
943 				rv = -1;
944 			break;
945 		case IMSG_PFKEY_RELOAD:
946 			if (idx != PFD_PIPE_SESSION) {
947 				log_warnx("pfkey reload request not from SE");
948 				break;
949 			}
950 			p = getpeerbyid(conf, imsg_get_id(&imsg));
951 			if (p != NULL) {
952 				if (pfkey_establish(&p->auth_state,
953 				    &p->auth_conf, session_localaddr(p),
954 				    &p->conf.remote_addr) == -1)
955 					log_peer_warnx(&p->conf,
956 					    "pfkey setup failed");
957 			}
958 			break;
959 		case IMSG_CTL_RELOAD:
960 			if (idx != PFD_PIPE_SESSION)
961 				log_warnx("reload request not from SE");
962 			else {
963 				reconfig = 1;
964 				reconfpid = imsg_get_pid(&imsg);
965 				if (imsg_get_data(&imsg, reason,
966 				    sizeof(reason)) == 0 && reason[0] != '\0')
967 					log_info("reload due to: %s",
968 					    log_reason(reason));
969 			}
970 			break;
971 		case IMSG_CTL_FIB_COUPLE:
972 			if (idx != PFD_PIPE_SESSION)
973 				log_warnx("couple request not from SE");
974 			else
975 				kr_fib_couple(imsg_get_id(&imsg));
976 			break;
977 		case IMSG_CTL_FIB_DECOUPLE:
978 			if (idx != PFD_PIPE_SESSION)
979 				log_warnx("decouple request not from SE");
980 			else
981 				kr_fib_decouple(imsg_get_id(&imsg));
982 			break;
983 		case IMSG_CTL_KROUTE:
984 		case IMSG_CTL_KROUTE_ADDR:
985 		case IMSG_CTL_SHOW_NEXTHOP:
986 		case IMSG_CTL_SHOW_INTERFACE:
987 		case IMSG_CTL_SHOW_FIB_TABLES:
988 			if (idx != PFD_PIPE_SESSION)
989 				log_warnx("kroute request not from SE");
990 			else
991 				kr_show_route(&imsg);
992 			break;
993 		case IMSG_SESSION_DEPENDON:
994 			if (idx != PFD_PIPE_SESSION)
995 				log_warnx("DEPENDON request not from SE");
996 			else if (imsg_get_data(&imsg, ifname, sizeof(ifname)) ==
997 			    -1)
998 				log_warn("wrong imsg len");
999 			else
1000 				kr_ifinfo(ifname);
1001 			break;
1002 		case IMSG_DEMOTE:
1003 			if (idx != PFD_PIPE_SESSION)
1004 				log_warnx("demote request not from SE");
1005 			else if (imsg_get_data(&imsg, &demote, sizeof(demote))
1006 			    == -1)
1007 				log_warn("wrong imsg len");
1008 			else
1009 				carp_demote_set(demote.demote_group,
1010 				    demote.level);
1011 			break;
1012 		case IMSG_CTL_LOG_VERBOSE:
1013 			/* already checked by SE */
1014 			if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
1015 			    -1)
1016 				log_warn("wrong imsg len");
1017 			else
1018 				log_setverbose(verbose);
1019 			break;
1020 		case IMSG_RECONF_DONE:
1021 			if (reconfpending == 0) {
1022 				log_warnx("unexpected RECONF_DONE received");
1023 				break;
1024 			}
1025 			if (idx == PFD_PIPE_SESSION) {
1026 				/* RDE and RTR engine can reload concurrently */
1027 				imsg_compose(ibuf_rtr, IMSG_RECONF_DONE, 0,
1028 				    0, -1, NULL, 0);
1029 				imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0,
1030 				    0, -1, NULL, 0);
1031 
1032 				/* finally fix kroute information */
1033 				ktable_postload();
1034 
1035 				/* redistribute list needs to be reloaded too */
1036 				kr_reload();
1037 
1038 				/* also remove old peers */
1039 				free_deleted_peers(conf);
1040 			}
1041 			reconfpending--;
1042 			break;
1043 		case IMSG_RECONF_DRAIN:
1044 			if (reconfpending == 0) {
1045 				log_warnx("unexpected RECONF_DRAIN received");
1046 				break;
1047 			}
1048 			reconfpending--;
1049 			if (reconfpending == 0) {
1050 				/*
1051 				 * SE goes first to bring templated neighbors
1052 				 * in sync.
1053 				 */
1054 				imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0,
1055 				    0, -1, NULL, 0);
1056 				reconfpending = 3; /* expecting 2 DONE msg */
1057 			}
1058 			break;
1059 		case IMSG_SOCKET_SETUP:
1060 			if (idx != PFD_PIPE_RTR) {
1061 				log_warnx("connect request not from RTR");
1062 			} else {
1063 				uint32_t rtrid = imsg_get_id(&imsg);
1064 				SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1065 					if (rtrid == r->id)
1066 						break;
1067 				}
1068 				if (r == NULL)
1069 					log_warnx("unknown rtr id %d", rtrid);
1070 				else
1071 					bgpd_rtr_conn_setup(r);
1072 			}
1073 			break;
1074 		case IMSG_SOCKET_TEARDOWN:
1075 			if (idx != PFD_PIPE_RTR) {
1076 				log_warnx("connect request not from RTR");
1077 			} else {
1078 				uint32_t rtrid = imsg_get_id(&imsg);
1079 				bgpd_rtr_conn_teardown(rtrid);
1080 			}
1081 			break;
1082 		case IMSG_CTL_SHOW_RTR:
1083 			if (idx == PFD_PIPE_SESSION) {
1084 				SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1085 					imsg_compose(ibuf_rtr,
1086 					    IMSG_CTL_SHOW_RTR, r->id,
1087 					    imsg_get_pid(&imsg), -1, NULL, 0);
1088 				}
1089 				imsg_compose(ibuf_rtr, IMSG_CTL_END,
1090 				    0, imsg_get_pid(&imsg), -1, NULL, 0);
1091 			} else if (idx == PFD_PIPE_RTR) {
1092 				struct ctl_show_rtr rtr;
1093 				if (imsg_get_data(&imsg, &rtr, sizeof(rtr)) ==
1094 				    -1) {
1095 					log_warn("wrong imsg len");
1096 					break;
1097 				}
1098 
1099 				SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1100 					if (imsg_get_id(&imsg) == r->id)
1101 						break;
1102 				}
1103 				if (r != NULL) {
1104 					strlcpy(rtr.descr, r->descr,
1105 					    sizeof(rtr.descr));
1106 					rtr.local_addr = r->local_addr;
1107 					rtr.remote_addr = r->remote_addr;
1108 					rtr.remote_port = r->remote_port;
1109 
1110 					imsg_compose(ibuf_se, IMSG_CTL_SHOW_RTR,
1111 					    imsg_get_id(&imsg),
1112 					    imsg_get_pid(&imsg), -1,
1113 					    &rtr, sizeof(rtr));
1114 				}
1115 			}
1116 			break;
1117 		case IMSG_CTL_END:
1118 		case IMSG_CTL_SHOW_TIMER:
1119 			if (idx != PFD_PIPE_RTR) {
1120 				log_warnx("connect request not from RTR");
1121 				break;
1122 			}
1123 			imsg_forward(ibuf_se, &imsg);
1124 			break;
1125 		default:
1126 			break;
1127 		}
1128 		imsg_free(&imsg);
1129 		if (rv != 0)
1130 			return (rv);
1131 	}
1132 	return (0);
1133 }
1134 
1135 void
send_nexthop_update(struct kroute_nexthop * msg)1136 send_nexthop_update(struct kroute_nexthop *msg)
1137 {
1138 	char	*gw = NULL;
1139 
1140 	if (msg->gateway.aid)
1141 		if (asprintf(&gw, ": via %s",
1142 		    log_addr(&msg->gateway)) == -1) {
1143 			log_warn("send_nexthop_update");
1144 			quit = 1;
1145 		}
1146 
1147 	log_debug("nexthop %s now %s%s%s", log_addr(&msg->nexthop),
1148 	    msg->valid ? "valid" : "invalid",
1149 	    msg->connected ? ": directly connected" : "",
1150 	    msg->gateway.aid ? gw : "");
1151 
1152 	free(gw);
1153 
1154 	if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1,
1155 	    msg, sizeof(struct kroute_nexthop)) == -1)
1156 		quit = 1;
1157 }
1158 
1159 void
send_imsg_session(int type,pid_t pid,void * data,uint16_t datalen)1160 send_imsg_session(int type, pid_t pid, void *data, uint16_t datalen)
1161 {
1162 	imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen);
1163 }
1164 
1165 int
send_network(int type,struct network_config * net,struct filter_set_head * h)1166 send_network(int type, struct network_config *net, struct filter_set_head *h)
1167 {
1168 	if (quit)
1169 		return (0);
1170 	if (imsg_compose(ibuf_rde, type, 0, 0, -1, net,
1171 	    sizeof(struct network_config)) == -1)
1172 		return (-1);
1173 	/* networks that get deleted don't need to send the filter set */
1174 	if (type == IMSG_NETWORK_REMOVE)
1175 		return (0);
1176 	if (send_filterset(ibuf_rde, h) == -1)
1177 		return (-1);
1178 	if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1)
1179 		return (-1);
1180 
1181 	return (0);
1182 }
1183 
1184 /*
1185  * Return true if a route can be used for nexthop resolution.
1186  */
1187 int
bgpd_oknexthop(struct kroute_full * kf)1188 bgpd_oknexthop(struct kroute_full *kf)
1189 {
1190 	if (kf->flags & F_BGPD)
1191 		return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0);
1192 
1193 	if (kf->prefixlen == 0)
1194 		return ((cflags & BGPD_FLAG_NEXTHOP_DEFAULT) != 0);
1195 
1196 	/* any other route is fine */
1197 	return (1);
1198 }
1199 
1200 int
bgpd_has_bgpnh(void)1201 bgpd_has_bgpnh(void)
1202 {
1203 	return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0);
1204 }
1205 
1206 int
control_setup(struct bgpd_config * conf)1207 control_setup(struct bgpd_config *conf)
1208 {
1209 	int fd, restricted;
1210 
1211 	/* control socket is outside chroot */
1212 	if (!cname || strcmp(cname, conf->csock)) {
1213 		if (cname) {
1214 			free(cname);
1215 		}
1216 		if ((cname = strdup(conf->csock)) == NULL)
1217 			fatal("strdup");
1218 		if (control_check(cname) == -1)
1219 			return (-1);
1220 		if ((fd = control_init(0, cname)) == -1)
1221 			fatalx("control socket setup failed");
1222 		if (control_listen(fd) == -1)
1223 			fatalx("control socket setup failed");
1224 		restricted = 0;
1225 		if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
1226 		    &restricted, sizeof(restricted)) == -1)
1227 			return (-1);
1228 	}
1229 	if (!conf->rcsock) {
1230 		/* remove restricted socket */
1231 		free(rcname);
1232 		rcname = NULL;
1233 	} else if (!rcname || strcmp(rcname, conf->rcsock)) {
1234 		if (rcname) {
1235 			free(rcname);
1236 		}
1237 		if ((rcname = strdup(conf->rcsock)) == NULL)
1238 			fatal("strdup");
1239 		if (control_check(rcname) == -1)
1240 			return (-1);
1241 		if ((fd = control_init(1, rcname)) == -1)
1242 			fatalx("control socket setup failed");
1243 		if (control_listen(fd) == -1)
1244 			fatalx("control socket setup failed");
1245 		restricted = 1;
1246 		if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
1247 		    &restricted, sizeof(restricted)) == -1)
1248 			return (-1);
1249 	}
1250 	return (0);
1251 }
1252 
1253 void
set_pollfd(struct pollfd * pfd,struct imsgbuf * i)1254 set_pollfd(struct pollfd *pfd, struct imsgbuf *i)
1255 {
1256 	if (i == NULL || i->fd == -1) {
1257 		pfd->fd = -1;
1258 		return;
1259 	}
1260 	pfd->fd = i->fd;
1261 	pfd->events = POLLIN;
1262 	if (imsgbuf_queuelen(i) > 0)
1263 		pfd->events |= POLLOUT;
1264 }
1265 
1266 int
handle_pollfd(struct pollfd * pfd,struct imsgbuf * i)1267 handle_pollfd(struct pollfd *pfd, struct imsgbuf *i)
1268 {
1269 	ssize_t n;
1270 
1271 	if (i == NULL)
1272 		return (0);
1273 
1274 	if (pfd->revents & POLLOUT)
1275 		if (imsgbuf_write(i) == -1) {
1276 			log_warn("imsg write error");
1277 			close(i->fd);
1278 			i->fd = -1;
1279 			return (-1);
1280 		}
1281 
1282 	if (pfd->revents & POLLIN) {
1283 		if ((n = imsgbuf_read(i)) == -1) {
1284 			log_warn("imsg read error");
1285 			close(i->fd);
1286 			i->fd = -1;
1287 			return (-1);
1288 		}
1289 		if (n == 0) {
1290 			log_warnx("peer closed imsg connection");
1291 			close(i->fd);
1292 			i->fd = -1;
1293 			return (-1);
1294 		}
1295 	}
1296 	return (0);
1297 }
1298 
1299 static void
getsockpair(int pipe[2])1300 getsockpair(int pipe[2])
1301 {
1302 	int bsize, i;
1303 
1304 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1305 	    PF_UNSPEC, pipe) == -1)
1306 		fatal("socketpair");
1307 
1308 	for (i = 0; i < 2; i++) {
1309 		bsize = MAX_SOCK_BUF;
1310 		if (setsockopt(pipe[i], SOL_SOCKET, SO_RCVBUF,
1311 		    &bsize, sizeof(bsize)) == -1) {
1312 			if (errno != ENOBUFS)
1313 				fatal("setsockopt(SO_RCVBUF, %d)",
1314 				    bsize);
1315 			log_warn("setsockopt(SO_RCVBUF, %d)", bsize);
1316 		}
1317 	}
1318 	for (i = 0; i < 2; i++) {
1319 		bsize = MAX_SOCK_BUF;
1320 		if (setsockopt(pipe[i], SOL_SOCKET, SO_SNDBUF,
1321 		    &bsize, sizeof(bsize)) == -1) {
1322 			if (errno != ENOBUFS)
1323 				fatal("setsockopt(SO_SNDBUF, %d)",
1324 				    bsize);
1325 			log_warn("setsockopt(SO_SNDBUF, %d)", bsize);
1326 		}
1327 	}
1328 }
1329 
1330 int
imsg_send_sockets(struct imsgbuf * se,struct imsgbuf * rde,struct imsgbuf * rtr)1331 imsg_send_sockets(struct imsgbuf *se, struct imsgbuf *rde, struct imsgbuf *rtr)
1332 {
1333 	int pipe_s2r[2];
1334 	int pipe_s2r_ctl[2];
1335 	int pipe_r2r[2];
1336 
1337 	getsockpair(pipe_s2r);
1338 	getsockpair(pipe_s2r_ctl);
1339 	getsockpair(pipe_r2r);
1340 
1341 	if (imsg_compose(se, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[0],
1342 	    NULL, 0) == -1)
1343 		return (-1);
1344 	if (imsg_compose(rde, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[1],
1345 	    NULL, 0) == -1)
1346 		return (-1);
1347 
1348 	if (imsg_compose(se, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[0],
1349 	    NULL, 0) == -1)
1350 		return (-1);
1351 	if (imsg_compose(rde, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[1],
1352 	    NULL, 0) == -1)
1353 		return (-1);
1354 
1355 	if (imsg_compose(rtr, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[0],
1356 	    NULL, 0) == -1)
1357 		return (-1);
1358 	if (imsg_compose(rde, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[1],
1359 	    NULL, 0) == -1)
1360 		return (-1);
1361 
1362 	return (0);
1363 }
1364 
1365 void
bgpd_rtr_conn_setup(struct rtr_config * r)1366 bgpd_rtr_conn_setup(struct rtr_config *r)
1367 {
1368 	struct connect_elm *ce;
1369 	struct sockaddr *sa;
1370 	socklen_t len;
1371 	int nodelay = 1;
1372 	int pre = IPTOS_PREC_INTERNETCONTROL;
1373 
1374 	if (connect_cnt >= MAX_CONNECT_CNT) {
1375 		log_warnx("rtr %s: too many concurrent connection requests",
1376 		    r->descr);
1377 		return;
1378 	}
1379 
1380 	if ((ce = calloc(1, sizeof(*ce))) == NULL) {
1381 		log_warn("rtr %s", r->descr);
1382 		return;
1383 	}
1384 
1385 	if (pfkey_establish(&ce->auth_state, &r->auth,
1386 	    &r->local_addr, &r->remote_addr) == -1)
1387 		log_warnx("rtr %s: pfkey setup failed", r->descr);
1388 
1389 	ce->id = r->id;
1390 	ce->fd = socket(aid2af(r->remote_addr.aid),
1391 	    SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_TCP);
1392 	if (ce->fd == -1) {
1393 		log_warn("rtr %s", r->descr);
1394 		goto fail;
1395 	}
1396 
1397 	switch (r->remote_addr.aid) {
1398 	case AID_INET:
1399 		if (setsockopt(ce->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) ==
1400 		    -1) {
1401 			log_warn("rtr %s: setsockopt IP_TOS", r->descr);
1402 			return;
1403 		}
1404 		break;
1405 	case AID_INET6:
1406 		if (setsockopt(ce->fd, IPPROTO_IPV6, IPV6_TCLASS, &pre,
1407 		    sizeof(pre)) == -1) {
1408 			log_warn("rtr %s: setsockopt IP_TOS", r->descr);
1409 			return;
1410 		}
1411 		break;
1412 	}
1413 
1414 	if (setsockopt(ce->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
1415 	    sizeof(nodelay)) == -1) {
1416 		log_warn("rtr %s: setsockopt TCP_NODELAY", r->descr);
1417 		return;
1418 	}
1419 
1420 	if (tcp_md5_set(ce->fd, &r->auth, &r->remote_addr) == -1)
1421 		log_warn("rtr %s: setting md5sig", r->descr);
1422 
1423 	if ((sa = addr2sa(&r->local_addr, 0, &len)) != NULL) {
1424 		if (bind(ce->fd, sa, len) == -1) {
1425 			log_warn("rtr %s: bind to %s", r->descr,
1426 			    log_addr(&r->local_addr));
1427 			goto fail;
1428 		}
1429 	}
1430 
1431 	sa = addr2sa(&r->remote_addr, r->remote_port, &len);
1432 	if (connect(ce->fd, sa, len) == -1) {
1433 		if (errno != EINPROGRESS) {
1434 			log_warn("rtr %s: connect to %s:%u", r->descr,
1435 			    log_addr(&r->remote_addr), r->remote_port);
1436 			goto fail;
1437 		}
1438 		TAILQ_INSERT_TAIL(&connect_queue, ce, entry);
1439 		connect_cnt++;
1440 		return;
1441 	}
1442 
1443 	imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0);
1444 	TAILQ_INSERT_TAIL(&socket_queue, ce, entry);
1445 	return;
1446 
1447  fail:
1448 	if (ce->fd != -1)
1449 		close(ce->fd);
1450 	free(ce);
1451 }
1452 
1453 void
bgpd_rtr_conn_setup_done(int fd,struct bgpd_config * conf)1454 bgpd_rtr_conn_setup_done(int fd, struct bgpd_config *conf)
1455 {
1456 	struct rtr_config *r;
1457 	struct connect_elm *ce;
1458 	int error = 0;
1459 	socklen_t len;
1460 
1461 	TAILQ_FOREACH(ce, &connect_queue, entry) {
1462 		if (ce->fd == fd)
1463 			break;
1464 	}
1465 	if (ce == NULL)
1466 		fatalx("connect entry not found");
1467 
1468 	TAILQ_REMOVE(&connect_queue, ce, entry);
1469 	connect_cnt--;
1470 
1471 	SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1472 		if (ce->id == r->id)
1473 			break;
1474 	}
1475 	if (r == NULL) {
1476 		log_warnx("rtr id %d no longer exists", ce->id);
1477 		goto fail;
1478 	}
1479 
1480 	len = sizeof(error);
1481 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
1482 		log_warn("rtr %s: getsockopt SO_ERROR", r->descr);
1483 		goto fail;
1484 	}
1485 
1486 	if (error != 0) {
1487 		errno = error;
1488 		log_warn("rtr %s: connect to %s:%u", r->descr,
1489 		    log_addr(&r->remote_addr), r->remote_port);
1490 		goto fail;
1491 	}
1492 
1493 	imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0);
1494 	TAILQ_INSERT_TAIL(&socket_queue, ce, entry);
1495 	return;
1496 
1497 fail:
1498 	close(fd);
1499 	free(ce);
1500 }
1501 
1502 void
bgpd_rtr_conn_teardown(uint32_t id)1503 bgpd_rtr_conn_teardown(uint32_t id)
1504 {
1505 	struct connect_elm *ce;
1506 
1507 	TAILQ_FOREACH(ce, &socket_queue, entry) {
1508 		if (ce->id == id) {
1509 			pfkey_remove(&ce->auth_state);
1510 			TAILQ_REMOVE(&socket_queue, ce, entry);
1511 			free(ce);
1512 			return;
1513 		}
1514 	}
1515 }
1516