bgpd.c revision 1.215
1/*	$OpenBSD: bgpd.c,v 1.215 2019/03/31 16:57:38 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 <arpa/inet.h>
24#include <err.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <poll.h>
28#include <pwd.h>
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <syslog.h>
34#include <unistd.h>
35
36#include "bgpd.h"
37#include "mrt.h"
38#include "session.h"
39#include "log.h"
40
41void		sighdlr(int);
42__dead void	usage(void);
43int		main(int, char *[]);
44pid_t		start_child(enum bgpd_process, char *, int, int, int);
45int		send_filterset(struct imsgbuf *, struct filter_set_head *);
46int		reconfigure(char *, struct bgpd_config *);
47int		dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *);
48int		control_setup(struct bgpd_config *);
49int		imsg_send_sockets(struct imsgbuf *, struct imsgbuf *);
50
51int			 cflags;
52volatile sig_atomic_t	 mrtdump;
53volatile sig_atomic_t	 quit;
54volatile sig_atomic_t	 reconfig;
55pid_t			 reconfpid;
56int			 reconfpending;
57struct imsgbuf		*ibuf_se;
58struct imsgbuf		*ibuf_rde;
59struct rib_names	 ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames);
60char			*cname;
61char			*rcname;
62
63void
64sighdlr(int sig)
65{
66	switch (sig) {
67	case SIGTERM:
68	case SIGINT:
69		quit = 1;
70		break;
71	case SIGHUP:
72		reconfig = 1;
73		break;
74	case SIGALRM:
75	case SIGUSR1:
76		mrtdump = 1;
77		break;
78	}
79}
80
81__dead void
82usage(void)
83{
84	extern char *__progname;
85
86	fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n",
87	    __progname);
88	exit(1);
89}
90
91#define PFD_PIPE_SESSION	0
92#define PFD_PIPE_ROUTE		1
93#define PFD_SOCK_ROUTE		2
94#define POLL_MAX		3
95#define MAX_TIMEOUT		3600
96
97int	 cmd_opts;
98
99int
100main(int argc, char *argv[])
101{
102	struct bgpd_config	*conf;
103	struct rde_rib		*rr;
104	struct pollfd		 pfd[POLL_MAX];
105	time_t			 timeout;
106	pid_t			 se_pid = 0, rde_pid = 0, pid;
107	char			*conffile;
108	char			*saved_argv0;
109	int			 debug = 0;
110	int			 rflag = 0, sflag = 0;
111	int			 rfd = -1;
112	int			 ch, status;
113	int			 pipe_m2s[2];
114	int			 pipe_m2r[2];
115
116	conffile = CONFFILE;
117	bgpd_process = PROC_MAIN;
118
119	log_init(1, LOG_DAEMON);	/* log to stderr until daemonized */
120	log_procinit(log_procnames[bgpd_process]);
121	log_setverbose(1);
122
123	saved_argv0 = argv[0];
124	if (saved_argv0 == NULL)
125		saved_argv0 = "bgpd";
126
127	while ((ch = getopt(argc, argv, "cdD:f:nRSv")) != -1) {
128		switch (ch) {
129		case 'c':
130			cmd_opts |= BGPD_OPT_FORCE_DEMOTE;
131			break;
132		case 'd':
133			debug = 1;
134			break;
135		case 'D':
136			if (cmdline_symset(optarg) < 0)
137				log_warnx("could not parse macro definition %s",
138				    optarg);
139			break;
140		case 'f':
141			conffile = optarg;
142			break;
143		case 'n':
144			cmd_opts |= BGPD_OPT_NOACTION;
145			break;
146		case 'v':
147			if (cmd_opts & BGPD_OPT_VERBOSE)
148				cmd_opts |= BGPD_OPT_VERBOSE2;
149			cmd_opts |= BGPD_OPT_VERBOSE;
150			break;
151		case 'R':
152			rflag = 1;
153			break;
154		case 'S':
155			sflag = 1;
156			break;
157		default:
158			usage();
159			/* NOTREACHED */
160		}
161	}
162
163	argc -= optind;
164	argv += optind;
165	if (argc > 0 || (sflag && rflag))
166		usage();
167
168	if (cmd_opts & BGPD_OPT_NOACTION) {
169		if ((conf = parse_config(conffile, NULL)) == NULL)
170			exit(1);
171
172		if (cmd_opts & BGPD_OPT_VERBOSE)
173			print_config(conf, &ribnames);
174		else
175			fprintf(stderr, "configuration OK\n");
176
177		while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
178			SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
179			free(rr);
180		}
181		free_config(conf);
182		exit(0);
183	}
184
185	if (rflag)
186		rde_main(debug, cmd_opts & BGPD_OPT_VERBOSE);
187	else if (sflag)
188		session_main(debug, cmd_opts & BGPD_OPT_VERBOSE);
189
190	if (geteuid())
191		errx(1, "need root privileges");
192
193	if (getpwnam(BGPD_USER) == NULL)
194		errx(1, "unknown user %s", BGPD_USER);
195
196	log_init(debug, LOG_DAEMON);
197	log_setverbose(cmd_opts & BGPD_OPT_VERBOSE);
198
199	if (!debug)
200		daemon(1, 0);
201
202	log_info("startup");
203
204	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
205	    PF_UNSPEC, pipe_m2s) == -1)
206		fatal("socketpair");
207	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
208	    PF_UNSPEC, pipe_m2r) == -1)
209		fatal("socketpair");
210
211	/* fork children */
212	rde_pid = start_child(PROC_RDE, saved_argv0, pipe_m2r[1], debug,
213	    cmd_opts & BGPD_OPT_VERBOSE);
214	se_pid = start_child(PROC_SE, saved_argv0, pipe_m2s[1], debug,
215	    cmd_opts & BGPD_OPT_VERBOSE);
216
217	signal(SIGTERM, sighdlr);
218	signal(SIGINT, sighdlr);
219	signal(SIGHUP, sighdlr);
220	signal(SIGALRM, sighdlr);
221	signal(SIGUSR1, sighdlr);
222	signal(SIGPIPE, SIG_IGN);
223
224	if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL ||
225	    (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL)
226		fatal(NULL);
227	imsg_init(ibuf_se, pipe_m2s[0]);
228	imsg_init(ibuf_rde, pipe_m2r[0]);
229	mrt_init(ibuf_rde, ibuf_se);
230	if ((rfd = kr_init()) == -1)
231		quit = 1;
232
233	/*
234	 * rpath, read config file
235	 * cpath, unlink control socket
236	 * fattr, chmod on control socket
237	 * wpath, needed if we are doing mrt dumps
238	 *
239	 * pledge placed here because kr_init() does a setsockopt on the
240	 * routing socket thats not allowed at all.
241	 */
242#if 0
243	/*
244	 * disabled because we do ioctls on /dev/pf and SIOCSIFGATTR
245	 * this needs some redesign of bgpd to be fixed.
246	 */
247BROKEN	if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
248	    NULL) == -1)
249		fatal("pledge");
250#endif
251
252	if (imsg_send_sockets(ibuf_se, ibuf_rde))
253		fatal("could not establish imsg links");
254	conf = new_config();
255	quit = reconfigure(conffile, conf);
256	if (pftable_clear_all() != 0)
257		quit = 1;
258
259	while (quit == 0) {
260		bzero(pfd, sizeof(pfd));
261
262		timeout = mrt_timeout(conf->mrt);
263
264		pfd[PFD_SOCK_ROUTE].fd = rfd;
265		pfd[PFD_SOCK_ROUTE].events = POLLIN;
266
267		set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se);
268		set_pollfd(&pfd[PFD_PIPE_ROUTE], ibuf_rde);
269
270		if (timeout < 0 || timeout > MAX_TIMEOUT)
271			timeout = MAX_TIMEOUT;
272		if (poll(pfd, POLL_MAX, timeout * 1000) == -1)
273			if (errno != EINTR) {
274				log_warn("poll error");
275				quit = 1;
276			}
277
278		if (handle_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se) == -1) {
279			log_warnx("main: Lost connection to SE");
280			msgbuf_clear(&ibuf_se->w);
281			free(ibuf_se);
282			ibuf_se = NULL;
283			quit = 1;
284		} else {
285			if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, conf) ==
286			    -1)
287				quit = 1;
288		}
289
290		if (handle_pollfd(&pfd[PFD_PIPE_ROUTE], ibuf_rde) == -1) {
291			log_warnx("main: Lost connection to RDE");
292			msgbuf_clear(&ibuf_rde->w);
293			free(ibuf_rde);
294			ibuf_rde = NULL;
295			quit = 1;
296		} else {
297			if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE, conf) ==
298			    -1)
299				quit = 1;
300		}
301
302		if (pfd[PFD_SOCK_ROUTE].revents & POLLIN) {
303			if (kr_dispatch_msg(conf->default_tableid) == -1)
304				quit = 1;
305		}
306
307		if (reconfig) {
308			u_int	error;
309
310			reconfig = 0;
311			switch (reconfigure(conffile, conf)) {
312			case -1:	/* fatal error */
313				quit = 1;
314				break;
315			case 0:		/* all OK */
316				error = 0;
317				break;
318			case 2:
319				error = CTL_RES_PENDING;
320				break;
321			default:	/* parse error */
322				error = CTL_RES_PARSE_ERROR;
323				break;
324			}
325			if (reconfpid != 0) {
326				send_imsg_session(IMSG_CTL_RESULT, reconfpid,
327				    &error, sizeof(error));
328				reconfpid = 0;
329			}
330		}
331
332		if (mrtdump) {
333			mrtdump = 0;
334			mrt_handler(conf->mrt);
335		}
336	}
337
338	/* close pipes */
339	if (ibuf_se) {
340		msgbuf_clear(&ibuf_se->w);
341		close(ibuf_se->fd);
342		free(ibuf_se);
343		ibuf_se = NULL;
344	}
345	if (ibuf_rde) {
346		msgbuf_clear(&ibuf_rde->w);
347		close(ibuf_rde->fd);
348		free(ibuf_rde);
349		ibuf_rde = NULL;
350	}
351
352	while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
353		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
354		free(rr);
355	}
356
357	carp_demote_shutdown();
358	kr_shutdown(conf->fib_priority, conf->default_tableid);
359	pftable_clear_all();
360
361	free_config(conf);
362
363	log_debug("waiting for children to terminate");
364	do {
365		pid = wait(&status);
366		if (pid == -1) {
367			if (errno != EINTR && errno != ECHILD)
368				fatal("wait");
369		} else if (WIFSIGNALED(status)) {
370			char *name = "unknown process";
371			if (pid == rde_pid)
372				name = "route decision engine";
373			else if (pid == se_pid)
374				name = "session engine";
375			log_warnx("%s terminated; signal %d", name,
376				WTERMSIG(status));
377		}
378	} while (pid != -1 || (pid == -1 && errno == EINTR));
379
380	free(rcname);
381	free(cname);
382
383	log_info("terminating");
384	return (0);
385}
386
387pid_t
388start_child(enum bgpd_process p, char *argv0, int fd, int debug, int verbose)
389{
390	char *argv[5];
391	int argc = 0;
392	pid_t pid;
393
394	switch (pid = fork()) {
395	case -1:
396		fatal("cannot fork");
397	case 0:
398		break;
399	default:
400		close(fd);
401		return (pid);
402	}
403
404	if (fd != 3) {
405		if (dup2(fd, 3) == -1)
406			fatal("cannot setup imsg fd");
407	} else if (fcntl(fd, F_SETFD, 0) == -1)
408		fatal("cannot setup imsg fd");
409
410	argv[argc++] = argv0;
411	switch (p) {
412	case PROC_MAIN:
413		fatalx("Can not start main process");
414	case PROC_RDE:
415		argv[argc++] = "-R";
416		break;
417	case PROC_SE:
418		argv[argc++] = "-S";
419		break;
420	}
421	if (debug)
422		argv[argc++] = "-d";
423	if (verbose)
424		argv[argc++] = "-v";
425	argv[argc++] = NULL;
426
427	execvp(argv0, argv);
428	fatal("execvp");
429}
430
431int
432send_filterset(struct imsgbuf *i, struct filter_set_head *set)
433{
434	struct filter_set	*s;
435
436	TAILQ_FOREACH(s, set, entry)
437		if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
438		    sizeof(struct filter_set)) == -1)
439			return (-1);
440	return (0);
441}
442
443int
444reconfigure(char *conffile, struct bgpd_config *conf)
445{
446	struct bgpd_config	*new_conf;
447	struct peer		*p;
448	struct filter_rule	*r;
449	struct listen_addr	*la;
450	struct rde_rib		*rr;
451	struct l3vpn		*vpn;
452	struct as_set		*aset;
453	struct prefixset	*ps;
454	struct prefixset_item	*psi, *npsi;
455
456	if (reconfpending) {
457		log_info("previous reload still running");
458		return (2);
459	}
460	reconfpending = 2;	/* one per child */
461
462	log_info("rereading config");
463	if ((new_conf = parse_config(conffile, &conf->peers)) == NULL) {
464		log_warnx("config file %s has errors, not reloading",
465		    conffile);
466		reconfpending = 0;
467		return (1);
468	}
469	merge_config(conf, new_conf);
470
471	if (prepare_listeners(conf) == -1) {
472		reconfpending = 0;
473		return (1);
474	}
475
476	if (control_setup(conf) == -1) {
477		reconfpending = 0;
478		return (1);
479	}
480
481	expand_networks(conf);
482
483	cflags = conf->flags;
484
485	/* start reconfiguration */
486	if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1,
487	    conf, sizeof(struct bgpd_config)) == -1)
488		return (-1);
489	if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1,
490	    conf, sizeof(struct bgpd_config)) == -1)
491		return (-1);
492
493	TAILQ_FOREACH(la, conf->listen_addrs, entry) {
494		if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
495		    la, sizeof(struct listen_addr)) == -1)
496			return (-1);
497		la->fd = -1;
498	}
499
500	/* adjust fib syncing on reload */
501	ktable_preload();
502
503	/* RIBs for the RDE */
504	while ((rr = SIMPLEQ_FIRST(&ribnames))) {
505		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
506		if (ktable_update(rr->rtableid, rr->name, rr->flags,
507		    conf->fib_priority) == -1) {
508			log_warnx("failed to load rdomain %d",
509			    rr->rtableid);
510			return (-1);
511		}
512		if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1,
513		    rr, sizeof(struct rde_rib)) == -1)
514			return (-1);
515		free(rr);
516	}
517
518	/* send peer list to the SE */
519	TAILQ_FOREACH(p, &conf->peers, entry) {
520		if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
521		    &p->conf, sizeof(struct peer_config)) == -1)
522			return (-1);
523	}
524
525	/* networks go via kroute to the RDE */
526	kr_net_reload(conf->default_tableid, 0, &conf->networks);
527
528	/* prefixsets for filters in the RDE */
529	while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) {
530		SIMPLEQ_REMOVE_HEAD(&conf->prefixsets, entry);
531		if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET, 0, 0, -1,
532		    ps->name, sizeof(ps->name)) == -1)
533			return (-1);
534		RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
535			RB_REMOVE(prefixset_tree, &ps->psitems, psi);
536			if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
537			    0, 0, -1, psi, sizeof(*psi)) == -1)
538				return (-1);
539			set_free(psi->set);
540			free(psi);
541		}
542		free(ps);
543	}
544
545	/* originsets for filters in the RDE */
546	while ((ps = SIMPLEQ_FIRST(&conf->originsets)) != NULL) {
547		SIMPLEQ_REMOVE_HEAD(&conf->originsets, entry);
548		if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1,
549		    ps->name, sizeof(ps->name)) == -1)
550			return (-1);
551		RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
552			struct roa_set *rs;
553			size_t i, l, n;
554			RB_REMOVE(prefixset_tree, &ps->psitems, psi);
555			rs = set_get(psi->set, &n);
556			for (i = 0; i < n; i += l) {
557				l = (n - i > 1024 ? 1024 : n - i);
558				if (imsg_compose(ibuf_rde,
559				    IMSG_RECONF_ROA_SET_ITEMS,
560				    0, 0, -1, rs + i, l * sizeof(*rs)) == -1)
561					return -1;
562			}
563			if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
564			    0, 0, -1, psi, sizeof(*psi)) == -1)
565				return (-1);
566			set_free(psi->set);
567			free(psi);
568		}
569		free(ps);
570	}
571
572	if (!RB_EMPTY(&conf->roa)) {
573		if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_SET, 0, 0, -1,
574		    NULL, 0) == -1)
575			return (-1);
576		RB_FOREACH_SAFE(psi, prefixset_tree, &conf->roa, npsi) {
577			struct roa_set *rs;
578			size_t i, l, n;
579			RB_REMOVE(prefixset_tree, &conf->roa, psi);
580			rs = set_get(psi->set, &n);
581			for (i = 0; i < n; i += l) {
582				l = (n - i > 1024 ? 1024 : n - i);
583				if (imsg_compose(ibuf_rde,
584				    IMSG_RECONF_ROA_SET_ITEMS,
585				    0, 0, -1, rs + i, l * sizeof(*rs)) == -1)
586					return -1;
587			}
588			if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
589			    0, 0, -1, psi, sizeof(*psi)) == -1)
590				return (-1);
591			set_free(psi->set);
592			free(psi);
593		}
594	}
595
596	/* as-sets for filters in the RDE */
597	while ((aset = SIMPLEQ_FIRST(conf->as_sets)) != NULL) {
598		struct ibuf *wbuf;
599		u_int32_t *as;
600		size_t i, l, n;
601
602		SIMPLEQ_REMOVE_HEAD(conf->as_sets, entry);
603
604		as = set_get(aset->set, &n);
605		if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0,
606		    sizeof(n) + sizeof(aset->name))) == NULL)
607			return -1;
608		if (imsg_add(wbuf, &n, sizeof(n)) == -1 ||
609		    imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1)
610			return -1;
611		imsg_close(ibuf_rde, wbuf);
612
613		for (i = 0; i < n; i += l) {
614			l = (n - i > 1024 ? 1024 : n - i);
615			if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS,
616			    0, 0, -1, as + i, l * sizeof(*as)) == -1)
617				return -1;
618		}
619
620		if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1,
621		    NULL, 0) == -1)
622			return -1;
623
624		set_free(aset->set);
625		free(aset);
626	}
627
628	/* filters for the RDE */
629	while ((r = TAILQ_FIRST(conf->filters)) != NULL) {
630		TAILQ_REMOVE(conf->filters, r, entry);
631		if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
632		    r, sizeof(struct filter_rule)) == -1)
633			return (-1);
634		if (send_filterset(ibuf_rde, &r->set) == -1)
635			return (-1);
636		filterset_free(&r->set);
637		free(r);
638	}
639
640	while ((vpn = SIMPLEQ_FIRST(&conf->l3vpns)) != NULL) {
641		SIMPLEQ_REMOVE_HEAD(&conf->l3vpns, entry);
642		if (ktable_update(vpn->rtableid, vpn->descr, vpn->flags,
643		    conf->fib_priority) == -1) {
644			log_warnx("failed to load rdomain %d",
645			    vpn->rtableid);
646			return (-1);
647		}
648		/* networks go via kroute to the RDE */
649		kr_net_reload(vpn->rtableid, vpn->rd, &vpn->net_l);
650
651		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN, 0, 0, -1,
652		    vpn, sizeof(*vpn)) == -1)
653			return (-1);
654
655		/* export targets */
656		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0,
657		    -1, NULL, 0) == -1)
658			return (-1);
659		if (send_filterset(ibuf_rde, &vpn->export) == -1)
660			return (-1);
661		filterset_free(&vpn->export);
662
663		/* import targets */
664		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0,
665		    -1, NULL, 0) == -1)
666			return (-1);
667		if (send_filterset(ibuf_rde, &vpn->import) == -1)
668			return (-1);
669		filterset_free(&vpn->import);
670
671		if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_DONE, 0, 0,
672		    -1, NULL, 0) == -1)
673			return (-1);
674
675		free(vpn);
676	}
677
678	/* send a drain message to know when all messages where processed */
679	if (imsg_compose(ibuf_se, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
680		return (-1);
681	if (imsg_compose(ibuf_rde, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
682		return (-1);
683
684	/* mrt changes can be sent out of bound */
685	mrt_reconfigure(conf->mrt);
686	return (0);
687}
688
689int
690dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf)
691{
692	struct imsg		 imsg;
693	ssize_t			 n;
694	int			 rv, verbose;
695
696	rv = 0;
697	while (ibuf) {
698		if ((n = imsg_get(ibuf, &imsg)) == -1)
699			return (-1);
700
701		if (n == 0)
702			break;
703
704		switch (imsg.hdr.type) {
705		case IMSG_KROUTE_CHANGE:
706			if (idx != PFD_PIPE_ROUTE)
707				log_warnx("route request not from RDE");
708			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
709			    sizeof(struct kroute_full))
710				log_warnx("wrong imsg len");
711			else if (kr_change(imsg.hdr.peerid, imsg.data,
712			    conf->fib_priority))
713				rv = -1;
714			break;
715		case IMSG_KROUTE_DELETE:
716			if (idx != PFD_PIPE_ROUTE)
717				log_warnx("route request not from RDE");
718			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
719			    sizeof(struct kroute_full))
720				log_warnx("wrong imsg len");
721			else if (kr_delete(imsg.hdr.peerid, imsg.data,
722			    conf->fib_priority))
723				rv = -1;
724			break;
725		case IMSG_NEXTHOP_ADD:
726			if (idx != PFD_PIPE_ROUTE)
727				log_warnx("nexthop request not from RDE");
728			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
729			    sizeof(struct bgpd_addr))
730				log_warnx("wrong imsg len");
731			else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data,
732			    conf) == -1)
733				rv = -1;
734			break;
735		case IMSG_NEXTHOP_REMOVE:
736			if (idx != PFD_PIPE_ROUTE)
737				log_warnx("nexthop request not from RDE");
738			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
739			    sizeof(struct bgpd_addr))
740				log_warnx("wrong imsg len");
741			else
742				kr_nexthop_delete(imsg.hdr.peerid, imsg.data,
743				    conf);
744			break;
745		case IMSG_PFTABLE_ADD:
746			if (idx != PFD_PIPE_ROUTE)
747				log_warnx("pftable request not from RDE");
748			else
749				if (imsg.hdr.len != IMSG_HEADER_SIZE +
750				    sizeof(struct pftable_msg))
751					log_warnx("wrong imsg len");
752				else if (pftable_addr_add(imsg.data) != 0)
753					rv = -1;
754			break;
755		case IMSG_PFTABLE_REMOVE:
756			if (idx != PFD_PIPE_ROUTE)
757				log_warnx("pftable request not from RDE");
758			else
759				if (imsg.hdr.len != IMSG_HEADER_SIZE +
760				    sizeof(struct pftable_msg))
761					log_warnx("wrong imsg len");
762				else if (pftable_addr_remove(imsg.data) != 0)
763					rv = -1;
764			break;
765		case IMSG_PFTABLE_COMMIT:
766			if (idx != PFD_PIPE_ROUTE)
767				log_warnx("pftable request not from RDE");
768			else
769				if (imsg.hdr.len != IMSG_HEADER_SIZE)
770					log_warnx("wrong imsg len");
771				else if (pftable_commit() != 0)
772					rv = -1;
773			break;
774		case IMSG_CTL_RELOAD:
775			if (idx != PFD_PIPE_SESSION)
776				log_warnx("reload request not from SE");
777			else {
778				reconfig = 1;
779				reconfpid = imsg.hdr.pid;
780			}
781			break;
782		case IMSG_CTL_FIB_COUPLE:
783			if (idx != PFD_PIPE_SESSION)
784				log_warnx("couple request not from SE");
785			else
786				kr_fib_couple(imsg.hdr.peerid,
787				    conf->fib_priority);
788			break;
789		case IMSG_CTL_FIB_DECOUPLE:
790			if (idx != PFD_PIPE_SESSION)
791				log_warnx("decouple request not from SE");
792			else
793				kr_fib_decouple(imsg.hdr.peerid,
794				    conf->fib_priority);
795			break;
796		case IMSG_CTL_KROUTE:
797		case IMSG_CTL_KROUTE_ADDR:
798		case IMSG_CTL_SHOW_NEXTHOP:
799		case IMSG_CTL_SHOW_INTERFACE:
800		case IMSG_CTL_SHOW_FIB_TABLES:
801			if (idx != PFD_PIPE_SESSION)
802				log_warnx("kroute request not from SE");
803			else
804				kr_show_route(&imsg);
805			break;
806		case IMSG_IFINFO:
807			if (idx != PFD_PIPE_SESSION)
808				log_warnx("IFINFO request not from SE");
809			else if (imsg.hdr.len != IMSG_HEADER_SIZE + IFNAMSIZ)
810				log_warnx("IFINFO request with wrong len");
811			else
812				kr_ifinfo(imsg.data);
813			break;
814		case IMSG_DEMOTE:
815			if (idx != PFD_PIPE_SESSION)
816				log_warnx("demote request not from SE");
817			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
818			    sizeof(struct demote_msg))
819				log_warnx("DEMOTE request with wrong len");
820			else {
821				struct demote_msg	*msg;
822
823				msg = imsg.data;
824				carp_demote_set(msg->demote_group, msg->level);
825			}
826			break;
827		case IMSG_CTL_LOG_VERBOSE:
828			/* already checked by SE */
829			memcpy(&verbose, imsg.data, sizeof(verbose));
830			log_setverbose(verbose);
831			break;
832		case IMSG_RECONF_DONE:
833			if (reconfpending == 0) {
834				log_warnx("unexpected RECONF_DONE received");
835				break;
836			}
837			if (idx == PFD_PIPE_SESSION) {
838				imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0,
839				    0, -1, NULL, 0);
840
841				/* finally fix kroute information */
842				ktable_postload(conf->fib_priority);
843
844				/* redistribute list needs to be reloaded too */
845				kr_reload();
846			}
847			reconfpending--;
848			break;
849		case IMSG_RECONF_DRAIN:
850			if (reconfpending == 0) {
851				log_warnx("unexpected RECONF_DRAIN received");
852				break;
853			}
854			reconfpending--;
855			if (reconfpending == 0) {
856				/*
857				 * SE goes first to bring templated neighbors
858				 * in sync.
859				 */
860				imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0,
861				    0, -1, NULL, 0);
862				reconfpending = 2; /* expecting 2 DONE msg */
863			}
864			break;
865		default:
866			break;
867		}
868		imsg_free(&imsg);
869		if (rv != 0)
870			return (rv);
871	}
872	return (0);
873}
874
875void
876send_nexthop_update(struct kroute_nexthop *msg)
877{
878	char	*gw = NULL;
879
880	if (msg->gateway.aid)
881		if (asprintf(&gw, ": via %s",
882		    log_addr(&msg->gateway)) == -1) {
883			log_warn("send_nexthop_update");
884			quit = 1;
885		}
886
887	log_debug("nexthop %s now %s%s%s", log_addr(&msg->nexthop),
888	    msg->valid ? "valid" : "invalid",
889	    msg->connected ? ": directly connected" : "",
890	    msg->gateway.aid ? gw : "");
891
892	free(gw);
893
894	if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1,
895	    msg, sizeof(struct kroute_nexthop)) == -1)
896		quit = 1;
897}
898
899void
900send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen)
901{
902	imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen);
903}
904
905int
906send_network(int type, struct network_config *net, struct filter_set_head *h)
907{
908	if (quit)
909		return (0);
910	if (imsg_compose(ibuf_rde, type, 0, 0, -1, net,
911	    sizeof(struct network_config)) == -1)
912		return (-1);
913	/* networks that get deleted don't need to send the filter set */
914	if (type == IMSG_NETWORK_REMOVE)
915		return (0);
916	if (send_filterset(ibuf_rde, h) == -1)
917		return (-1);
918	if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1)
919		return (-1);
920
921	return (0);
922}
923
924int
925bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6)
926{
927	/* kernel routes are never filtered */
928	if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0)
929		return (0);
930	if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0)
931		return (0);
932
933	if (cflags & BGPD_FLAG_NEXTHOP_BGP) {
934		if (kr && kr->flags & F_BGPD_INSERTED)
935			return (0);
936		if (kr6 && kr6->flags & F_BGPD_INSERTED)
937			return (0);
938	}
939
940	if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) {
941		if (kr && kr->prefixlen == 0)
942			return (0);
943		if (kr6 && kr6->prefixlen == 0)
944			return (0);
945	}
946
947	return (1);
948}
949
950int
951control_setup(struct bgpd_config *conf)
952{
953	int fd, restricted;
954
955	/* control socket is outside chroot */
956	if (!cname || strcmp(cname, conf->csock)) {
957		if (cname) {
958			free(cname);
959		}
960		if ((cname = strdup(conf->csock)) == NULL)
961			fatal("strdup");
962		if (control_check(cname) == -1)
963			return (-1);
964		if ((fd = control_init(0, cname)) == -1)
965			fatalx("control socket setup failed");
966		if (control_listen(fd) == -1)
967			fatalx("control socket setup failed");
968		restricted = 0;
969		if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
970		    &restricted, sizeof(restricted)) == -1)
971			return (-1);
972	}
973	if (!conf->rcsock) {
974		/* remove restricted socket */
975		free(rcname);
976		rcname = NULL;
977	} else if (!rcname || strcmp(rcname, conf->rcsock)) {
978		if (rcname) {
979			free(rcname);
980		}
981		if ((rcname = strdup(conf->rcsock)) == NULL)
982			fatal("strdup");
983		if (control_check(rcname) == -1)
984			return (-1);
985		if ((fd = control_init(1, rcname)) == -1)
986			fatalx("control socket setup failed");
987		if (control_listen(fd) == -1)
988			fatalx("control socket setup failed");
989		restricted = 1;
990		if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
991		    &restricted, sizeof(restricted)) == -1)
992			return (-1);
993	}
994	return (0);
995}
996
997void
998set_pollfd(struct pollfd *pfd, struct imsgbuf *i)
999{
1000	if (i == NULL || i->fd == -1) {
1001		pfd->fd = -1;
1002		return;
1003	}
1004	pfd->fd = i->fd;
1005	pfd->events = POLLIN;
1006	if (i->w.queued > 0)
1007		pfd->events |= POLLOUT;
1008}
1009
1010int
1011handle_pollfd(struct pollfd *pfd, struct imsgbuf *i)
1012{
1013	ssize_t n;
1014
1015	if (i == NULL)
1016		return (0);
1017
1018	if (pfd->revents & POLLOUT)
1019		if (msgbuf_write(&i->w) <= 0 && errno != EAGAIN) {
1020			log_warn("imsg write error");
1021			close(i->fd);
1022			i->fd = -1;
1023			return (-1);
1024		}
1025
1026	if (pfd->revents & POLLIN) {
1027		if ((n = imsg_read(i)) == -1 && errno != EAGAIN) {
1028			log_warn("imsg read error");
1029			close(i->fd);
1030			i->fd = -1;
1031			return (-1);
1032		}
1033		if (n == 0) {
1034			log_warnx("peer closed imsg connection");
1035			close(i->fd);
1036			i->fd = -1;
1037			return (-1);
1038		}
1039	}
1040	return (0);
1041}
1042
1043int
1044imsg_send_sockets(struct imsgbuf *se, struct imsgbuf *rde)
1045{
1046	int pipe_s2r[2];
1047	int pipe_s2r_ctl[2];
1048
1049	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1050	     PF_UNSPEC, pipe_s2r) == -1)
1051		return (-1);
1052	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1053	     PF_UNSPEC, pipe_s2r_ctl) == -1)
1054		return (-1);
1055
1056	if (imsg_compose(se, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[0],
1057	    NULL, 0) == -1)
1058		return (-1);
1059	if (imsg_compose(rde, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[1],
1060	    NULL, 0) == -1)
1061		return (-1);
1062
1063	if (imsg_compose(se, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[0],
1064	    NULL, 0) == -1)
1065		return (-1);
1066	if (imsg_compose(rde, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[1],
1067	    NULL, 0) == -1)
1068		return (-1);
1069
1070	return (0);
1071}
1072