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