xref: /openbsd/usr.sbin/bgpd/bgpd.c (revision 17df1aa7)
1 /*	$OpenBSD: bgpd.c,v 1.161 2010/05/03 13:09: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 <unistd.h>
34 
35 #include "bgpd.h"
36 #include "mrt.h"
37 #include "session.h"
38 
39 void		sighdlr(int);
40 __dead void	usage(void);
41 int		main(int, char *[]);
42 int		check_child(pid_t, const char *);
43 int		send_filterset(struct imsgbuf *, struct filter_set_head *);
44 int		reconfigure(char *, struct bgpd_config *, struct mrt_head *,
45 		    struct peer **);
46 int		dispatch_imsg(struct imsgbuf *, int);
47 
48 int			 rfd = -1;
49 int			 cflags = 0;
50 struct filter_set_head	*connectset;
51 struct filter_set_head	*connectset6;
52 struct filter_set_head	*staticset;
53 struct filter_set_head	*staticset6;
54 volatile sig_atomic_t	 mrtdump = 0;
55 volatile sig_atomic_t	 quit = 0;
56 volatile sig_atomic_t	 sigchld = 0;
57 volatile sig_atomic_t	 reconfig = 0;
58 pid_t			 reconfpid = 0;
59 struct imsgbuf		*ibuf_se;
60 struct imsgbuf		*ibuf_rde;
61 struct rib_names	 ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames);
62 
63 void
64 sighdlr(int sig)
65 {
66 	switch (sig) {
67 	case SIGTERM:
68 	case SIGINT:
69 		quit = 1;
70 		break;
71 	case SIGCHLD:
72 		sigchld = 1;
73 		break;
74 	case SIGHUP:
75 		reconfig = 1;
76 		break;
77 	case SIGALRM:
78 	case SIGUSR1:
79 		mrtdump = 1;
80 		break;
81 	}
82 }
83 
84 __dead void
85 usage(void)
86 {
87 	extern char *__progname;
88 
89 	fprintf(stderr, "usage: %s [-cdnv] ", __progname);
90 	fprintf(stderr, "[-D macro=value] [-f file] [-r path] [-s path]\n");
91 	exit(1);
92 }
93 
94 #define PFD_PIPE_SESSION	0
95 #define PFD_PIPE_ROUTE		1
96 #define PFD_SOCK_ROUTE		2
97 #define POLL_MAX		3
98 #define MAX_TIMEOUT		3600
99 
100 int
101 main(int argc, char *argv[])
102 {
103 	struct bgpd_config	 conf;
104 	struct mrt_head		 mrt_l;
105 	struct peer		*peer_l, *p;
106 	struct mrt		*m;
107 	struct listen_addr	*la;
108 	struct pollfd		 pfd[POLL_MAX];
109 	pid_t			 io_pid = 0, rde_pid = 0, pid;
110 	char			*conffile;
111 	int			 debug = 0;
112 	int			 ch, timeout, nfds;
113 	int			 pipe_m2s[2];
114 	int			 pipe_m2r[2];
115 	int			 pipe_s2r[2];
116 	int			 pipe_s2r_c[2];
117 
118 	conffile = CONFFILE;
119 	bgpd_process = PROC_MAIN;
120 
121 	log_init(1);		/* log to stderr until daemonized */
122 
123 	bzero(&conf, sizeof(conf));
124 	LIST_INIT(&mrt_l);
125 	peer_l = NULL;
126 	conf.csock = SOCKET_NAME;
127 
128 	while ((ch = getopt(argc, argv, "cdD:f:nr:s:v")) != -1) {
129 		switch (ch) {
130 		case 'c':
131 			conf.opts |= BGPD_OPT_FORCE_DEMOTE;
132 			break;
133 		case 'd':
134 			debug = 1;
135 			break;
136 		case 'D':
137 			if (cmdline_symset(optarg) < 0)
138 				log_warnx("could not parse macro definition %s",
139 				    optarg);
140 			break;
141 		case 'f':
142 			conffile = optarg;
143 			break;
144 		case 'n':
145 			conf.opts |= BGPD_OPT_NOACTION;
146 			break;
147 		case 'v':
148 			if (conf.opts & BGPD_OPT_VERBOSE)
149 				conf.opts |= BGPD_OPT_VERBOSE2;
150 			conf.opts |= BGPD_OPT_VERBOSE;
151 			log_verbose(1);
152 			break;
153 		case 'r':
154 			conf.rcsock = optarg;
155 			break;
156 		case 's':
157 			conf.csock = optarg;
158 			break;
159 		default:
160 			usage();
161 			/* NOTREACHED */
162 		}
163 	}
164 
165 	argc -= optind;
166 	argv += optind;
167 	if (argc > 0)
168 		usage();
169 
170 	if (conf.opts & BGPD_OPT_NOACTION) {
171 		struct network_head	net_l;
172 		struct filter_head	rules_l;
173 
174 		if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l,
175 		    &rules_l))
176 			exit(1);
177 
178 		if (conf.opts & BGPD_OPT_VERBOSE)
179 			print_config(&conf, &ribnames, &net_l, peer_l, &rules_l,
180 			    &mrt_l);
181 		else
182 			fprintf(stderr, "configuration OK\n");
183 		exit(0);
184 	}
185 	cflags = conf.flags;
186 	connectset = &conf.connectset;
187 	staticset = &conf.staticset;
188 	connectset6 = &conf.connectset6;
189 	staticset6 = &conf.staticset6;
190 
191 	if (geteuid())
192 		errx(1, "need root privileges");
193 
194 	if (getpwnam(BGPD_USER) == NULL)
195 		errx(1, "unknown user %s", BGPD_USER);
196 
197 	log_init(debug);
198 
199 	if (!debug)
200 		daemon(1, 0);
201 
202 	log_info("startup");
203 
204 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2s) == -1)
205 		fatal("socketpair");
206 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2r) == -1)
207 		fatal("socketpair");
208 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_s2r) == -1)
209 		fatal("socketpair");
210 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_s2r_c) == -1)
211 		fatal("socketpair");
212 	session_socket_blockmode(pipe_m2s[0], BM_NONBLOCK);
213 	session_socket_blockmode(pipe_m2s[1], BM_NONBLOCK);
214 	session_socket_blockmode(pipe_m2r[0], BM_NONBLOCK);
215 	session_socket_blockmode(pipe_m2r[1], BM_NONBLOCK);
216 	session_socket_blockmode(pipe_s2r[0], BM_NONBLOCK);
217 	session_socket_blockmode(pipe_s2r[1], BM_NONBLOCK);
218 	session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK);
219 	session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK);
220 
221 	/* fork children */
222 	rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug);
223 	io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c,
224 	    conf.csock, conf.rcsock);
225 
226 	setproctitle("parent");
227 
228 	signal(SIGTERM, sighdlr);
229 	signal(SIGINT, sighdlr);
230 	signal(SIGCHLD, sighdlr);
231 	signal(SIGHUP, sighdlr);
232 	signal(SIGALRM, sighdlr);
233 	signal(SIGUSR1, sighdlr);
234 	signal(SIGPIPE, SIG_IGN);
235 
236 	close(pipe_m2s[1]);
237 	close(pipe_m2r[1]);
238 	close(pipe_s2r[0]);
239 	close(pipe_s2r[1]);
240 
241 	if ((ibuf_se = malloc(sizeof(struct imsgbuf))) == NULL ||
242 	    (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL)
243 		fatal(NULL);
244 	imsg_init(ibuf_se, pipe_m2s[0]);
245 	imsg_init(ibuf_rde, pipe_m2r[0]);
246 	mrt_init(ibuf_rde, ibuf_se);
247 	if ((rfd = kr_init()) == -1)
248 		quit = 1;
249 	quit = reconfigure(conffile, &conf, &mrt_l, &peer_l);
250 	if (pftable_clear_all() != 0)
251 		quit = 1;
252 
253 	while (quit == 0) {
254 		bzero(pfd, sizeof(pfd));
255 		pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd;
256 		pfd[PFD_PIPE_SESSION].events = POLLIN;
257 		if (ibuf_se->w.queued)
258 			pfd[PFD_PIPE_SESSION].events |= POLLOUT;
259 		pfd[PFD_PIPE_ROUTE].fd = ibuf_rde->fd;
260 		pfd[PFD_PIPE_ROUTE].events = POLLIN;
261 		if (ibuf_rde->w.queued)
262 			pfd[PFD_PIPE_ROUTE].events |= POLLOUT;
263 		pfd[PFD_SOCK_ROUTE].fd = rfd;
264 		pfd[PFD_SOCK_ROUTE].events = POLLIN;
265 
266 		timeout = mrt_timeout(&mrt_l);
267 		if (timeout > MAX_TIMEOUT)
268 			timeout = MAX_TIMEOUT;
269 
270 		if ((nfds = poll(pfd, POLL_MAX, timeout * 1000)) == -1)
271 			if (errno != EINTR) {
272 				log_warn("poll error");
273 				quit = 1;
274 			}
275 
276 		if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLOUT)
277 			if (msgbuf_write(&ibuf_se->w) < 0) {
278 				log_warn("pipe write error (to SE)");
279 				quit = 1;
280 			}
281 
282 		if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLOUT)
283 			if (msgbuf_write(&ibuf_rde->w) < 0) {
284 				log_warn("pipe write error (to RDE)");
285 				quit = 1;
286 			}
287 
288 		if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLIN) {
289 			if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION) == -1)
290 				quit = 1;
291 		}
292 
293 		if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) {
294 			if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE) == -1)
295 				quit = 1;
296 		}
297 
298 		if (nfds > 0 && pfd[PFD_SOCK_ROUTE].revents & POLLIN) {
299 			if (kr_dispatch_msg() == -1)
300 				quit = 1;
301 		}
302 
303 		if (reconfig) {
304 			u_int	error;
305 
306 			reconfig = 0;
307 			log_info("rereading config");
308 			switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) {
309 			case -1:	/* fatal error */
310 				quit = 1;
311 				break;
312 			case 0:		/* all OK */
313 				error = 0;
314 				break;
315 			default:	/* parse error */
316 				error = CTL_RES_PARSE_ERROR;
317 				break;
318 			}
319 			if (reconfpid != 0) {
320 				send_imsg_session(IMSG_CTL_RESULT, reconfpid,
321 				    &error, sizeof(error));
322 				reconfpid = 0;
323 			}
324 		}
325 
326 		if (sigchld) {
327 			sigchld = 0;
328 			if (check_child(io_pid, "session engine")) {
329 				quit = 1;
330 				io_pid = 0;
331 			}
332 			if (check_child(rde_pid, "route decision engine")) {
333 				quit = 1;
334 				rde_pid = 0;
335 			}
336 		}
337 
338 		if (mrtdump) {
339 			mrtdump = 0;
340 			mrt_handler(&mrt_l);
341 		}
342 	}
343 
344 	signal(SIGCHLD, SIG_IGN);
345 
346 	if (io_pid)
347 		kill(io_pid, SIGTERM);
348 
349 	if (rde_pid)
350 		kill(rde_pid, SIGTERM);
351 
352 	while ((p = peer_l) != NULL) {
353 		peer_l = p->next;
354 		free(p);
355 	}
356 	while ((m = LIST_FIRST(&mrt_l)) != NULL) {
357 		LIST_REMOVE(m, entry);
358 		free(m);
359 	}
360 	if (conf.listen_addrs)
361 		while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) {
362 			TAILQ_REMOVE(conf.listen_addrs, la, entry);
363 			close(la->fd);
364 			free(la);
365 		}
366 
367 	control_cleanup(conf.csock);
368 	control_cleanup(conf.rcsock);
369 	carp_demote_shutdown();
370 	kr_shutdown();
371 	pftable_clear_all();
372 	free(conf.listen_addrs);
373 
374 	do {
375 		if ((pid = wait(NULL)) == -1 &&
376 		    errno != EINTR && errno != ECHILD)
377 			fatal("wait");
378 	} while (pid != -1 || (pid == -1 && errno == EINTR));
379 
380 	msgbuf_clear(&ibuf_se->w);
381 	free(ibuf_se);
382 	msgbuf_clear(&ibuf_rde->w);
383 	free(ibuf_rde);
384 
385 	log_info("Terminating");
386 	return (0);
387 }
388 
389 int
390 check_child(pid_t pid, const char *pname)
391 {
392 	int	status;
393 
394 	if (waitpid(pid, &status, WNOHANG) > 0) {
395 		if (WIFEXITED(status)) {
396 			log_warnx("Lost child: %s exited", pname);
397 			return (1);
398 		}
399 		if (WIFSIGNALED(status)) {
400 			log_warnx("Lost child: %s terminated; signal %d",
401 			    pname, WTERMSIG(status));
402 			return (1);
403 		}
404 	}
405 
406 	return (0);
407 }
408 
409 int
410 send_filterset(struct imsgbuf *i, struct filter_set_head *set)
411 {
412 	struct filter_set	*s;
413 
414 	TAILQ_FOREACH(s, set, entry)
415 		if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
416 		    sizeof(struct filter_set)) == -1)
417 			return (-1);
418 	return (0);
419 }
420 
421 int
422 reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
423     struct peer **peer_l)
424 {
425 	struct network_head	 net_l;
426 	struct filter_head	 rules_l;
427 	struct network		*n;
428 	struct peer		*p;
429 	struct filter_rule	*r;
430 	struct listen_addr	*la;
431 	struct rde_rib		*rr;
432 
433 	if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l)) {
434 		log_warnx("config file %s has errors, not reloading",
435 		    conffile);
436 		return (1);
437 	}
438 
439 	cflags = conf->flags;
440 	connectset = &conf->connectset;
441 	staticset = &conf->staticset;
442 	connectset6 = &conf->connectset6;
443 	staticset6 = &conf->staticset6;
444 
445 	prepare_listeners(conf);
446 
447 	/* start reconfiguration */
448 	if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1,
449 	    conf, sizeof(struct bgpd_config)) == -1)
450 		return (-1);
451 	if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1,
452 	    conf, sizeof(struct bgpd_config)) == -1)
453 		return (-1);
454 
455 	/* send peer list and listeners to the SE */
456 	for (p = *peer_l; p != NULL; p = p->next) {
457 		if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
458 		    &p->conf, sizeof(struct peer_config)) == -1)
459 			return (-1);
460 	}
461 
462 	TAILQ_FOREACH(la, conf->listen_addrs, entry) {
463 		if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
464 		    la, sizeof(struct listen_addr)) == -1)
465 			return (-1);
466 		la->fd = -1;
467 	}
468 
469 	/* adjust fib syncing on reload */
470 	ktable_preload();
471 
472 	/* RIBs for the RDE */
473 	while ((rr = SIMPLEQ_FIRST(&ribnames))) {
474 		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
475 		if (ktable_update(rr) == -1) {
476 			log_warnx("failed to load rdomain %d",
477 			    rr->rtableid);
478 			return (-1);
479 		}
480 		if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1,
481 		    rr, sizeof(struct rde_rib)) == -1)
482 			return (-1);
483 		free(rr);
484 	}
485 
486 	/* networks for the RDE */
487 	while ((n = TAILQ_FIRST(&net_l)) != NULL) {
488 		if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1,
489 		    &n->net, sizeof(struct network_config)) == -1)
490 			return (-1);
491 		if (send_filterset(ibuf_rde, &n->net.attrset) == -1)
492 			return (-1);
493 		if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1,
494 		    NULL, 0) == -1)
495 			return (-1);
496 		TAILQ_REMOVE(&net_l, n, entry);
497 		filterset_free(&n->net.attrset);
498 		free(n);
499 	}
500 
501 	/* filters for the RDE */
502 	while ((r = TAILQ_FIRST(&rules_l)) != NULL) {
503 		if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
504 		    r, sizeof(struct filter_rule)) == -1)
505 			return (-1);
506 		if (send_filterset(ibuf_rde, &r->set) == -1)
507 			return (-1);
508 		TAILQ_REMOVE(&rules_l, r, entry);
509 		filterset_free(&r->set);
510 		free(r);
511 	}
512 
513 	/* signal both childs to replace their config */
514 	if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1 ||
515 	    imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1)
516 		return (-1);
517 
518 	/* fix kroute information */
519 	ktable_postload();
520 
521 	/* redistribute list needs to be reloaded too */
522 	if (kr_reload() == -1)
523 		return (-1);
524 
525 	/* mrt changes can be sent out of bound */
526 	mrt_reconfigure(mrt_l);
527 	return (0);
528 }
529 
530 int
531 dispatch_imsg(struct imsgbuf *ibuf, int idx)
532 {
533 	struct imsg		 imsg;
534 	ssize_t			 n;
535 	int			 rv, verbose;
536 
537 	if ((n = imsg_read(ibuf)) == -1)
538 		return (-1);
539 
540 	if (n == 0) {	/* connection closed */
541 		log_warnx("dispatch_imsg in main: pipe closed");
542 		return (-1);
543 	}
544 
545 	rv = 0;
546 	for (;;) {
547 		if ((n = imsg_get(ibuf, &imsg)) == -1)
548 			return (-1);
549 
550 		if (n == 0)
551 			break;
552 
553 		switch (imsg.hdr.type) {
554 		case IMSG_KROUTE_CHANGE:
555 			if (idx != PFD_PIPE_ROUTE)
556 				log_warnx("route request not from RDE");
557 			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
558 			    sizeof(struct kroute_full))
559 				log_warnx("wrong imsg len");
560 			else if (kr_change(imsg.hdr.peerid, imsg.data))
561 				rv = -1;
562 			break;
563 		case IMSG_KROUTE_DELETE:
564 			if (idx != PFD_PIPE_ROUTE)
565 				log_warnx("route request not from RDE");
566 			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
567 			    sizeof(struct kroute_full))
568 				log_warnx("wrong imsg len");
569 			else if (kr_delete(imsg.hdr.peerid, imsg.data))
570 				rv = -1;
571 			break;
572 		case IMSG_NEXTHOP_ADD:
573 			if (idx != PFD_PIPE_ROUTE)
574 				log_warnx("nexthop request not from RDE");
575 			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
576 			    sizeof(struct bgpd_addr))
577 				log_warnx("wrong imsg len");
578 			else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data) ==
579 			    -1)
580 				rv = -1;
581 			break;
582 		case IMSG_NEXTHOP_REMOVE:
583 			if (idx != PFD_PIPE_ROUTE)
584 				log_warnx("nexthop request not from RDE");
585 			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
586 			    sizeof(struct bgpd_addr))
587 				log_warnx("wrong imsg len");
588 			else
589 				kr_nexthop_delete(imsg.hdr.peerid, imsg.data);
590 			break;
591 		case IMSG_PFTABLE_ADD:
592 			if (idx != PFD_PIPE_ROUTE)
593 				log_warnx("pftable request not from RDE");
594 			else
595 				if (imsg.hdr.len != IMSG_HEADER_SIZE +
596 				    sizeof(struct pftable_msg))
597 					log_warnx("wrong imsg len");
598 				else if (pftable_addr_add(imsg.data) != 0)
599 					rv = -1;
600 			break;
601 		case IMSG_PFTABLE_REMOVE:
602 			if (idx != PFD_PIPE_ROUTE)
603 				log_warnx("pftable request not from RDE");
604 			else
605 				if (imsg.hdr.len != IMSG_HEADER_SIZE +
606 				    sizeof(struct pftable_msg))
607 					log_warnx("wrong imsg len");
608 				else if (pftable_addr_remove(imsg.data) != 0)
609 					rv = -1;
610 			break;
611 		case IMSG_PFTABLE_COMMIT:
612 			if (idx != PFD_PIPE_ROUTE)
613 				log_warnx("pftable request not from RDE");
614 			else
615 				if (imsg.hdr.len != IMSG_HEADER_SIZE)
616 					log_warnx("wrong imsg len");
617 				else if (pftable_commit() != 0)
618 					rv = -1;
619 			break;
620 		case IMSG_CTL_RELOAD:
621 			if (idx != PFD_PIPE_SESSION)
622 				log_warnx("reload request not from SE");
623 			else
624 				reconfig = 1;
625 				reconfpid = imsg.hdr.pid;
626 			break;
627 		case IMSG_CTL_FIB_COUPLE:
628 			if (idx != PFD_PIPE_SESSION)
629 				log_warnx("couple request not from SE");
630 			else
631 				kr_fib_couple(imsg.hdr.peerid);
632 			break;
633 		case IMSG_CTL_FIB_DECOUPLE:
634 			if (idx != PFD_PIPE_SESSION)
635 				log_warnx("decouple request not from SE");
636 			else
637 				kr_fib_decouple(imsg.hdr.peerid);
638 			break;
639 		case IMSG_CTL_KROUTE:
640 		case IMSG_CTL_KROUTE_ADDR:
641 		case IMSG_CTL_SHOW_NEXTHOP:
642 		case IMSG_CTL_SHOW_INTERFACE:
643 		case IMSG_CTL_SHOW_FIB_TABLES:
644 			if (idx != PFD_PIPE_SESSION)
645 				log_warnx("kroute request not from SE");
646 			else
647 				kr_show_route(&imsg);
648 			break;
649 		case IMSG_IFINFO:
650 			if (idx != PFD_PIPE_SESSION)
651 				log_warnx("IFINFO request not from SE");
652 			else if (imsg.hdr.len != IMSG_HEADER_SIZE + IFNAMSIZ)
653 				log_warnx("IFINFO request with wrong len");
654 			else
655 				kr_ifinfo(imsg.data);
656 			break;
657 		case IMSG_DEMOTE:
658 			if (idx != PFD_PIPE_SESSION)
659 				log_warnx("demote request not from SE");
660 			else if (imsg.hdr.len != IMSG_HEADER_SIZE +
661 			    sizeof(struct demote_msg))
662 				log_warnx("DEMOTE request with wrong len");
663 			else {
664 				struct demote_msg	*msg;
665 
666 				msg = imsg.data;
667 				carp_demote_set(msg->demote_group, msg->level);
668 			}
669 			break;
670 		case IMSG_CTL_LOG_VERBOSE:
671 			/* already checked by SE */
672 			memcpy(&verbose, imsg.data, sizeof(verbose));
673 			log_verbose(verbose);
674 			break;
675 		default:
676 			break;
677 		}
678 		imsg_free(&imsg);
679 		if (rv != 0)
680 			return (rv);
681 	}
682 	return (0);
683 }
684 
685 void
686 send_nexthop_update(struct kroute_nexthop *msg)
687 {
688 	char	*gw = NULL;
689 
690 	if (msg->gateway.aid)
691 		if (asprintf(&gw, ": via %s",
692 		    log_addr(&msg->gateway)) == -1) {
693 			log_warn("send_nexthop_update");
694 			quit = 1;
695 		}
696 
697 	log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop),
698 	    msg->valid ? "valid" : "invalid",
699 	    msg->connected ? ": directly connected" : "",
700 	    msg->gateway.aid ? gw : "");
701 
702 	free(gw);
703 
704 	if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1,
705 	    msg, sizeof(struct kroute_nexthop)) == -1)
706 		quit = 1;
707 }
708 
709 void
710 send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen)
711 {
712 	imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen);
713 }
714 
715 int
716 bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6)
717 {
718 	struct network_config	 net;
719 	struct filter_set_head	*h;
720 
721 	if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && kr &&
722 	    (kr->flags & F_CONNECTED))
723 		h = connectset;
724 	else if ((cflags & BGPD_FLAG_REDIST_STATIC) && kr &&
725 	    (kr->flags & F_STATIC))
726 		h = staticset;
727 	else if ((cflags & BGPD_FLAG_REDIST6_CONNECTED) && kr6 &&
728 	    (kr6->flags & F_CONNECTED))
729 		h = connectset6;
730 	else if ((cflags & BGPD_FLAG_REDIST6_STATIC) && kr6 &&
731 	    (kr6->flags & F_STATIC))
732 		h = staticset6;
733 	else
734 		return (0);
735 
736 	bzero(&net, sizeof(net));
737 	if (kr && kr6)
738 		fatalx("bgpd_redistribute: unable to redistribute v4 and v6"
739 		    "together");
740 	if (kr != NULL) {
741 		net.prefix.aid = AID_INET;
742 		net.prefix.v4.s_addr = kr->prefix.s_addr;
743 		net.prefixlen = kr->prefixlen;
744 	}
745 	if (kr6 != NULL) {
746 		net.prefix.aid = AID_INET6;
747 		memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
748 		net.prefixlen = kr6->prefixlen;
749 	}
750 
751 	if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net,
752 	    sizeof(struct network_config)) == -1)
753 		return (-1);
754 
755 	/* networks that get deleted don't need to send the filter set */
756 	if (type == IMSG_NETWORK_REMOVE)
757 		return (1);
758 
759 	if (send_filterset(ibuf_rde, h) == -1)
760 		return (-1);
761 	if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1)
762 		return (-1);
763 
764 	return (1);
765 }
766 
767 int
768 bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6)
769 {
770 	/* kernel routes are never filtered */
771 	if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0)
772 		return (0);
773 	if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0)
774 		return (0);
775 
776 	if (cflags & BGPD_FLAG_NEXTHOP_BGP) {
777 		if (kr && kr->flags & F_BGPD_INSERTED)
778 			return (0);
779 		if (kr6 && kr6->flags & F_BGPD_INSERTED)
780 			return (0);
781 	}
782 
783 	if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) {
784 		if (kr && kr->prefixlen == 0)
785 			return (0);
786 		if (kr6 && kr6->prefixlen == 0)
787 			return (0);
788 	}
789 
790 	return (1);
791 }
792