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