1 /* $OpenBSD: bgpd.c,v 1.270 2024/10/08 12:28:09 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 imsg_init(ibuf_se, pipe_m2s[0]);
280 imsg_init(ibuf_rde, pipe_m2r[0]);
281 imsg_init(ibuf_rtr, pipe_m2roa[0]);
282 mrt_init(ibuf_rde, ibuf_se);
283 if (kr_init(&rfd, conf->fib_priority) == -1)
284 quit = 1;
285 keyfd = pfkey_init();
286
287 /*
288 * rpath, read config file
289 * cpath, unlink control socket
290 * fattr, chmod on control socket
291 * wpath, needed if we are doing mrt dumps
292 *
293 * pledge placed here because kr_init() does a setsockopt on the
294 * routing socket thats not allowed at all.
295 */
296 #if 0
297 /*
298 * disabled because we do ioctls on /dev/pf and SIOCSIFGATTR
299 * this needs some redesign of bgpd to be fixed.
300 */
301 BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
302 NULL) == -1)
303 fatal("pledge");
304 #endif
305
306 if (imsg_send_sockets(ibuf_se, ibuf_rde, ibuf_rtr))
307 fatal("could not establish imsg links");
308 /* control setup needs to happen late since it sends imsgs */
309 if (control_setup(conf) == -1)
310 quit = 1;
311 if (send_config(conf) != 0)
312 quit = 1;
313 if (pftable_clear_all() != 0)
314 quit = 1;
315
316 while (quit == 0) {
317 if (pfd_elms < PFD_CONNECT_START + connect_cnt) {
318 struct pollfd *newp;
319
320 if ((newp = reallocarray(pfd,
321 PFD_CONNECT_START + connect_cnt,
322 sizeof(struct pollfd))) == NULL) {
323 log_warn("could not resize pfd from %u -> %u"
324 " entries", pfd_elms, PFD_CONNECT_START +
325 connect_cnt);
326 fatalx("exiting");
327 }
328 pfd = newp;
329 pfd_elms = PFD_CONNECT_START + connect_cnt;
330 }
331 memset(pfd, 0, sizeof(struct pollfd) * pfd_elms);
332
333 timeout = mrt_timeout(conf->mrt);
334
335 pfd[PFD_SOCK_ROUTE].fd = rfd;
336 pfd[PFD_SOCK_ROUTE].events = POLLIN;
337
338 pfd[PFD_SOCK_PFKEY].fd = keyfd;
339 pfd[PFD_SOCK_PFKEY].events = POLLIN;
340
341 set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se);
342 set_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde);
343 set_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr);
344
345 npfd = PFD_CONNECT_START;
346 TAILQ_FOREACH(ce, &connect_queue, entry) {
347 pfd[npfd].fd = ce->fd;
348 pfd[npfd++].events = POLLOUT;
349 if (npfd > pfd_elms)
350 fatalx("polli pfd overflow");
351 }
352
353 if (timeout < 0 || timeout > MAX_TIMEOUT)
354 timeout = MAX_TIMEOUT;
355 if (poll(pfd, npfd, timeout * 1000) == -1) {
356 if (errno != EINTR) {
357 log_warn("poll error");
358 quit = 1;
359 }
360 goto next_loop;
361 }
362
363 if (handle_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se) == -1) {
364 log_warnx("main: Lost connection to SE");
365 msgbuf_clear(&ibuf_se->w);
366 free(ibuf_se);
367 ibuf_se = NULL;
368 quit = 1;
369 } else {
370 if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, conf) ==
371 -1)
372 quit = 1;
373 }
374
375 if (handle_pollfd(&pfd[PFD_PIPE_RDE], ibuf_rde) == -1) {
376 log_warnx("main: Lost connection to RDE");
377 msgbuf_clear(&ibuf_rde->w);
378 free(ibuf_rde);
379 ibuf_rde = NULL;
380 quit = 1;
381 } else {
382 if (dispatch_imsg(ibuf_rde, PFD_PIPE_RDE, conf) == -1)
383 quit = 1;
384 }
385
386 if (handle_pollfd(&pfd[PFD_PIPE_RTR], ibuf_rtr) == -1) {
387 log_warnx("main: Lost connection to RTR");
388 msgbuf_clear(&ibuf_rtr->w);
389 free(ibuf_rtr);
390 ibuf_rtr = NULL;
391 quit = 1;
392 } else {
393 if (dispatch_imsg(ibuf_rtr, PFD_PIPE_RTR, conf) == -1)
394 quit = 1;
395 }
396
397 if (pfd[PFD_SOCK_ROUTE].revents & POLLIN) {
398 if (kr_dispatch_msg() == -1)
399 quit = 1;
400 }
401
402 if (pfd[PFD_SOCK_PFKEY].revents & POLLIN) {
403 if (pfkey_read(keyfd, NULL) == -1) {
404 log_warnx("pfkey_read failed, exiting...");
405 quit = 1;
406 }
407 }
408
409 for (i = PFD_CONNECT_START; i < npfd; i++)
410 if (pfd[i].revents != 0)
411 bgpd_rtr_conn_setup_done(pfd[i].fd, conf);
412
413 next_loop:
414 if (reconfig) {
415 u_int error;
416
417 reconfig = 0;
418 switch (reconfigure(conffile, conf)) {
419 case -1: /* fatal error */
420 quit = 1;
421 break;
422 case 0: /* all OK */
423 error = 0;
424 break;
425 case 2:
426 log_info("previous reload still running");
427 error = CTL_RES_PENDING;
428 break;
429 default: /* parse error */
430 log_warnx("config file %s has errors, "
431 "not reloading", conffile);
432 error = CTL_RES_PARSE_ERROR;
433 break;
434 }
435 if (reconfpid != 0) {
436 send_imsg_session(IMSG_CTL_RESULT, reconfpid,
437 &error, sizeof(error));
438 reconfpid = 0;
439 }
440 }
441
442 if (mrtdump) {
443 mrtdump = 0;
444 mrt_handler(conf->mrt);
445 }
446 }
447
448 /* close pipes */
449 if (ibuf_se) {
450 msgbuf_clear(&ibuf_se->w);
451 close(ibuf_se->fd);
452 free(ibuf_se);
453 ibuf_se = NULL;
454 }
455 if (ibuf_rde) {
456 msgbuf_clear(&ibuf_rde->w);
457 close(ibuf_rde->fd);
458 free(ibuf_rde);
459 ibuf_rde = NULL;
460 }
461 if (ibuf_rtr) {
462 msgbuf_clear(&ibuf_rtr->w);
463 close(ibuf_rtr->fd);
464 free(ibuf_rtr);
465 ibuf_rtr = NULL;
466 }
467
468 /* cleanup kernel data structures */
469 carp_demote_shutdown();
470 kr_shutdown();
471 pftable_clear_all();
472
473 RB_FOREACH(p, peer_head, &conf->peers)
474 pfkey_remove(&p->auth_state);
475
476 while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
477 SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
478 free(rr);
479 }
480 free_config(conf);
481
482 log_debug("waiting for children to terminate");
483 do {
484 pid = wait(&status);
485 if (pid == -1) {
486 if (errno != EINTR && errno != ECHILD)
487 fatal("wait");
488 } else if (WIFSIGNALED(status)) {
489 char *name = "unknown process";
490 if (pid == rde_pid)
491 name = "route decision engine";
492 else if (pid == se_pid)
493 name = "session engine";
494 else if (pid == rtr_pid)
495 name = "rtr engine";
496 log_warnx("%s terminated; signal %d", name,
497 WTERMSIG(status));
498 }
499 } while (pid != -1 || (pid == -1 && errno == EINTR));
500
501 free(rcname);
502 free(cname);
503
504 log_info("terminating");
505 return (0);
506 }
507
508 pid_t
start_child(enum bgpd_process p,char * argv0,int fd,int debug,int verbose)509 start_child(enum bgpd_process p, char *argv0, int fd, int debug, int verbose)
510 {
511 char *argv[5];
512 int argc = 0;
513 pid_t pid;
514
515 switch (pid = fork()) {
516 case -1:
517 fatal("cannot fork");
518 case 0:
519 break;
520 default:
521 close(fd);
522 return (pid);
523 }
524
525 if (fd != 3) {
526 if (dup2(fd, 3) == -1)
527 fatal("cannot setup imsg fd");
528 } else if (fcntl(fd, F_SETFD, 0) == -1)
529 fatal("cannot setup imsg fd");
530
531 argv[argc++] = argv0;
532 switch (p) {
533 case PROC_MAIN:
534 fatalx("Can not start main process");
535 case PROC_RDE:
536 argv[argc++] = "-R";
537 break;
538 case PROC_SE:
539 argv[argc++] = "-S";
540 break;
541 case PROC_RTR:
542 argv[argc++] = "-T";
543 break;
544 }
545 if (debug)
546 argv[argc++] = "-d";
547 if (verbose)
548 argv[argc++] = "-v";
549 argv[argc++] = NULL;
550
551 execvp(argv0, argv);
552 fatal("execvp");
553 }
554
555 int
send_filterset(struct imsgbuf * i,struct filter_set_head * set)556 send_filterset(struct imsgbuf *i, struct filter_set_head *set)
557 {
558 struct filter_set *s;
559
560 TAILQ_FOREACH(s, set, entry)
561 if (imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
562 sizeof(struct filter_set)) == -1)
563 return (-1);
564 return (0);
565 }
566
567 int
reconfigure(char * conffile,struct bgpd_config * conf)568 reconfigure(char *conffile, struct bgpd_config *conf)
569 {
570 struct bgpd_config *new_conf;
571
572 if (reconfpending)
573 return (2);
574
575 log_info("rereading config");
576 if ((new_conf = parse_config(conffile, &conf->peers,
577 &conf->rtrs)) == NULL)
578 return (1);
579
580 merge_config(conf, new_conf);
581
582 if (prepare_listeners(conf) == -1)
583 return (1);
584
585 if (control_setup(conf) == -1)
586 return (1);
587
588 return send_config(conf);
589 }
590
591 int
send_config(struct bgpd_config * conf)592 send_config(struct bgpd_config *conf)
593 {
594 struct peer *p;
595 struct filter_rule *r;
596 struct listen_addr *la;
597 struct rde_rib *rr;
598 struct l3vpn *vpn;
599 struct as_set *aset;
600 struct prefixset *ps;
601 struct prefixset_item *psi, *npsi;
602 struct roa *roa;
603 struct aspa_set *aspa;
604 struct rtr_config *rtr;
605 struct flowspec_config *f, *nf;
606
607 reconfpending = 3; /* one per child */
608
609 expand_networks(conf, &conf->networks);
610 SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry)
611 expand_networks(conf, &vpn->net_l);
612
613 cflags = conf->flags;
614
615 /* start reconfiguration */
616 if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1,
617 conf, sizeof(*conf)) == -1)
618 return (-1);
619 if (imsg_compose(ibuf_rde, IMSG_RECONF_CONF, 0, 0, -1,
620 conf, sizeof(*conf)) == -1)
621 return (-1);
622 if (imsg_compose(ibuf_rtr, IMSG_RECONF_CONF, 0, 0, -1,
623 conf, sizeof(*conf)) == -1)
624 return (-1);
625
626 TAILQ_FOREACH(la, conf->listen_addrs, entry) {
627 if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
628 la, sizeof(*la)) == -1)
629 return (-1);
630 la->fd = -1;
631 }
632
633 /* adjust fib syncing on reload */
634 ktable_preload();
635
636 /* RIBs for the RDE */
637 while ((rr = SIMPLEQ_FIRST(&ribnames))) {
638 SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
639 if (ktable_update(rr->rtableid, rr->name, rr->flags) == -1) {
640 log_warnx("failed to load routing table %d",
641 rr->rtableid);
642 return (-1);
643 }
644 if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1,
645 rr, sizeof(*rr)) == -1)
646 return (-1);
647 free(rr);
648 }
649
650 /* send peer list to the SE */
651 RB_FOREACH(p, peer_head, &conf->peers) {
652 if (p->reconf_action == RECONF_DELETE)
653 continue;
654
655 if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
656 &p->conf, sizeof(p->conf)) == -1)
657 return (-1);
658 if (pfkey_send_conf(ibuf_se, p->conf.id, &p->auth_conf) == -1)
659 return (-1);
660
661 if (p->reconf_action == RECONF_REINIT)
662 if (pfkey_establish(&p->auth_state, &p->auth_conf,
663 session_localaddr(p), &p->conf.remote_addr) == -1)
664 log_peer_warnx(&p->conf, "auth setup failed");
665 }
666
667 /* networks go via kroute to the RDE */
668 kr_net_reload(conf->default_tableid, 0, &conf->networks);
669
670 /* flowspec goes directly to the RDE, also remove old objects */
671 RB_FOREACH_SAFE(f, flowspec_tree, &conf->flowspecs, nf) {
672 if (f->reconf_action != RECONF_DELETE) {
673 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_ADD, 0, 0, -1,
674 f->flow, FLOWSPEC_SIZE + f->flow->len) == -1)
675 return (-1);
676 if (send_filterset(ibuf_rde, &f->attrset) == -1)
677 return (-1);
678 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_DONE, 0, 0, -1,
679 NULL, 0) == -1)
680 return (-1);
681 } else {
682 if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_REMOVE, 0, 0,
683 -1, f->flow, FLOWSPEC_SIZE + f->flow->len) == -1)
684 return (-1);
685 RB_REMOVE(flowspec_tree, &conf->flowspecs, f);
686 flowspec_free(f);
687 }
688 }
689
690 /* prefixsets for filters in the RDE */
691 while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) {
692 SIMPLEQ_REMOVE_HEAD(&conf->prefixsets, entry);
693 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET, 0, 0, -1,
694 ps->name, sizeof(ps->name)) == -1)
695 return (-1);
696 RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
697 RB_REMOVE(prefixset_tree, &ps->psitems, psi);
698 if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
699 0, 0, -1, psi, sizeof(*psi)) == -1)
700 return (-1);
701 free(psi);
702 }
703 free(ps);
704 }
705
706 /* originsets for filters in the RDE */
707 while ((ps = SIMPLEQ_FIRST(&conf->originsets)) != NULL) {
708 SIMPLEQ_REMOVE_HEAD(&conf->originsets, entry);
709 if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1,
710 ps->name, sizeof(ps->name)) == -1)
711 return (-1);
712 RB_FOREACH(roa, roa_tree, &ps->roaitems) {
713 if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0,
714 -1, roa, sizeof(*roa)) == -1)
715 return (-1);
716 }
717 free_roatree(&ps->roaitems);
718 free(ps);
719 }
720
721 /* roa table, aspa table and rtr config are sent to the RTR engine */
722 RB_FOREACH(roa, roa_tree, &conf->roa) {
723 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ROA_ITEM, 0, 0,
724 -1, roa, sizeof(*roa)) == -1)
725 return (-1);
726 }
727 free_roatree(&conf->roa);
728 RB_FOREACH(aspa, aspa_tree, &conf->aspa) {
729 /* XXX prevent oversized IMSG for now */
730 if (aspa->num * sizeof(*aspa->tas) >
731 MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
732 log_warnx("oversized ASPA set for customer-as %s, %s",
733 log_as(aspa->as), "dropped");
734 continue;
735 }
736
737 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA, 0, 0,
738 -1, aspa, offsetof(struct aspa_set, tas)) == -1)
739 return (-1);
740 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_TAS, 0, 0,
741 -1, aspa->tas, aspa->num * sizeof(*aspa->tas)) == -1)
742 return (-1);
743 if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_DONE, 0, 0, -1,
744 NULL, 0) == -1)
745 return -1;
746 }
747 free_aspatree(&conf->aspa);
748 SIMPLEQ_FOREACH(rtr, &conf->rtrs, entry) {
749 struct rtr_config_msg rtrconf = { 0 };
750
751 strlcpy(rtrconf.descr, rtr->descr, sizeof(rtrconf.descr));
752 rtrconf.min_version = rtr->min_version;
753 if (imsg_compose(ibuf_rtr, IMSG_RECONF_RTR_CONFIG, rtr->id,
754 0, -1, &rtrconf, sizeof(rtrconf)) == -1)
755 return (-1);
756 }
757
758 /* as-sets for filters in the RDE */
759 while ((aset = SIMPLEQ_FIRST(&conf->as_sets)) != NULL) {
760 struct ibuf *wbuf;
761 uint32_t *as;
762 size_t i, l, n;
763
764 SIMPLEQ_REMOVE_HEAD(&conf->as_sets, entry);
765
766 as = set_get(aset->set, &n);
767 if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0,
768 sizeof(n) + sizeof(aset->name))) == NULL)
769 return -1;
770 if (imsg_add(wbuf, &n, sizeof(n)) == -1 ||
771 imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1)
772 return -1;
773 imsg_close(ibuf_rde, wbuf);
774
775 for (i = 0; i < n; i += l) {
776 l = (n - i > 1024 ? 1024 : n - i);
777 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS,
778 0, 0, -1, as + i, l * sizeof(*as)) == -1)
779 return -1;
780 }
781
782 if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1,
783 NULL, 0) == -1)
784 return -1;
785
786 set_free(aset->set);
787 free(aset);
788 }
789
790 /* filters for the RDE */
791 while ((r = TAILQ_FIRST(conf->filters)) != NULL) {
792 TAILQ_REMOVE(conf->filters, r, entry);
793 if (send_filterset(ibuf_rde, &r->set) == -1)
794 return (-1);
795 if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
796 r, sizeof(struct filter_rule)) == -1)
797 return (-1);
798 filterset_free(&r->set);
799 free(r);
800 }
801
802 while ((vpn = SIMPLEQ_FIRST(&conf->l3vpns)) != NULL) {
803 SIMPLEQ_REMOVE_HEAD(&conf->l3vpns, entry);
804 if (ktable_update(vpn->rtableid, vpn->descr, vpn->flags) ==
805 -1) {
806 log_warnx("failed to load routing table %d",
807 vpn->rtableid);
808 return (-1);
809 }
810 /* networks go via kroute to the RDE */
811 kr_net_reload(vpn->rtableid, vpn->rd, &vpn->net_l);
812
813 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN, 0, 0, -1,
814 vpn, sizeof(*vpn)) == -1)
815 return (-1);
816
817 /* export targets */
818 if (send_filterset(ibuf_rde, &vpn->export) == -1)
819 return (-1);
820 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0,
821 -1, NULL, 0) == -1)
822 return (-1);
823 filterset_free(&vpn->export);
824
825 /* import targets */
826 if (send_filterset(ibuf_rde, &vpn->import) == -1)
827 return (-1);
828 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0,
829 -1, NULL, 0) == -1)
830 return (-1);
831 filterset_free(&vpn->import);
832
833 if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_DONE, 0, 0,
834 -1, NULL, 0) == -1)
835 return (-1);
836
837 free(vpn);
838 }
839
840 /* send a drain message to know when all messages where processed */
841 if (imsg_compose(ibuf_se, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
842 return (-1);
843 if (imsg_compose(ibuf_rde, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
844 return (-1);
845 if (imsg_compose(ibuf_rtr, IMSG_RECONF_DRAIN, 0, 0, -1, NULL, 0) == -1)
846 return (-1);
847
848 /* mrt changes can be sent out of bound */
849 mrt_reconfigure(conf->mrt);
850 return (0);
851 }
852
853 int
dispatch_imsg(struct imsgbuf * imsgbuf,int idx,struct bgpd_config * conf)854 dispatch_imsg(struct imsgbuf *imsgbuf, int idx, struct bgpd_config *conf)
855 {
856 struct imsg imsg;
857 struct peer *p;
858 struct rtr_config *r;
859 struct kroute_full kf;
860 struct bgpd_addr addr;
861 struct pftable_msg pfmsg;
862 struct demote_msg demote;
863 char reason[REASON_LEN], ifname[IFNAMSIZ];
864 ssize_t n;
865 u_int rtableid;
866 int rv, verbose;
867
868 rv = 0;
869 while (imsgbuf) {
870 if ((n = imsg_get(imsgbuf, &imsg)) == -1)
871 return (-1);
872
873 if (n == 0)
874 break;
875
876 switch (imsg_get_type(&imsg)) {
877 case IMSG_KROUTE_CHANGE:
878 if (idx != PFD_PIPE_RDE)
879 log_warnx("route request not from RDE");
880 else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1)
881 log_warn("wrong imsg len");
882 else if (kr_change(imsg_get_id(&imsg), &kf))
883 rv = -1;
884 break;
885 case IMSG_KROUTE_DELETE:
886 if (idx != PFD_PIPE_RDE)
887 log_warnx("route request not from RDE");
888 else if (imsg_get_data(&imsg, &kf, sizeof(kf)) == -1)
889 log_warn("wrong imsg len");
890 else if (kr_delete(imsg_get_id(&imsg), &kf))
891 rv = -1;
892 break;
893 case IMSG_KROUTE_FLUSH:
894 if (idx != PFD_PIPE_RDE)
895 log_warnx("route request not from RDE");
896 else if (kr_flush(imsg_get_id(&imsg)))
897 rv = -1;
898 break;
899 case IMSG_NEXTHOP_ADD:
900 if (idx != PFD_PIPE_RDE)
901 log_warnx("nexthop request not from RDE");
902 else if (imsg_get_data(&imsg, &addr, sizeof(addr)) ==
903 -1)
904 log_warn("wrong imsg len");
905 else {
906 rtableid = conf->default_tableid;
907 if (kr_nexthop_add(rtableid, &addr) == -1)
908 rv = -1;
909 }
910 break;
911 case IMSG_NEXTHOP_REMOVE:
912 if (idx != PFD_PIPE_RDE)
913 log_warnx("nexthop request not from RDE");
914 else if (imsg_get_data(&imsg, &addr, sizeof(addr)) ==
915 -1)
916 log_warn("wrong imsg len");
917 else {
918 rtableid = conf->default_tableid;
919 kr_nexthop_delete(rtableid, &addr);
920 }
921 break;
922 case IMSG_PFTABLE_ADD:
923 if (idx != PFD_PIPE_RDE)
924 log_warnx("pftable request not from RDE");
925 else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) ==
926 -1)
927 log_warn("wrong imsg len");
928 else if (pftable_addr_add(&pfmsg) != 0)
929 rv = -1;
930 break;
931 case IMSG_PFTABLE_REMOVE:
932 if (idx != PFD_PIPE_RDE)
933 log_warnx("pftable request not from RDE");
934 else if (imsg_get_data(&imsg, &pfmsg, sizeof(pfmsg)) ==
935 -1)
936 log_warn("wrong imsg len");
937 else if (pftable_addr_remove(&pfmsg) != 0)
938 rv = -1;
939 break;
940 case IMSG_PFTABLE_COMMIT:
941 if (idx != PFD_PIPE_RDE)
942 log_warnx("pftable request not from RDE");
943 else if (pftable_commit() != 0)
944 rv = -1;
945 break;
946 case IMSG_PFKEY_RELOAD:
947 if (idx != PFD_PIPE_SESSION) {
948 log_warnx("pfkey reload request not from SE");
949 break;
950 }
951 p = getpeerbyid(conf, imsg_get_id(&imsg));
952 if (p != NULL) {
953 if (pfkey_establish(&p->auth_state,
954 &p->auth_conf, session_localaddr(p),
955 &p->conf.remote_addr) == -1)
956 log_peer_warnx(&p->conf,
957 "pfkey setup failed");
958 }
959 break;
960 case IMSG_CTL_RELOAD:
961 if (idx != PFD_PIPE_SESSION)
962 log_warnx("reload request not from SE");
963 else {
964 reconfig = 1;
965 reconfpid = imsg_get_pid(&imsg);
966 if (imsg_get_data(&imsg, reason,
967 sizeof(reason)) == 0 && reason[0] != '\0')
968 log_info("reload due to: %s",
969 log_reason(reason));
970 }
971 break;
972 case IMSG_CTL_FIB_COUPLE:
973 if (idx != PFD_PIPE_SESSION)
974 log_warnx("couple request not from SE");
975 else
976 kr_fib_couple(imsg_get_id(&imsg));
977 break;
978 case IMSG_CTL_FIB_DECOUPLE:
979 if (idx != PFD_PIPE_SESSION)
980 log_warnx("decouple request not from SE");
981 else
982 kr_fib_decouple(imsg_get_id(&imsg));
983 break;
984 case IMSG_CTL_KROUTE:
985 case IMSG_CTL_KROUTE_ADDR:
986 case IMSG_CTL_SHOW_NEXTHOP:
987 case IMSG_CTL_SHOW_INTERFACE:
988 case IMSG_CTL_SHOW_FIB_TABLES:
989 if (idx != PFD_PIPE_SESSION)
990 log_warnx("kroute request not from SE");
991 else
992 kr_show_route(&imsg);
993 break;
994 case IMSG_SESSION_DEPENDON:
995 if (idx != PFD_PIPE_SESSION)
996 log_warnx("DEPENDON request not from SE");
997 else if (imsg_get_data(&imsg, ifname, sizeof(ifname)) ==
998 -1)
999 log_warn("wrong imsg len");
1000 else
1001 kr_ifinfo(ifname);
1002 break;
1003 case IMSG_DEMOTE:
1004 if (idx != PFD_PIPE_SESSION)
1005 log_warnx("demote request not from SE");
1006 else if (imsg_get_data(&imsg, &demote, sizeof(demote))
1007 == -1)
1008 log_warn("wrong imsg len");
1009 else
1010 carp_demote_set(demote.demote_group,
1011 demote.level);
1012 break;
1013 case IMSG_CTL_LOG_VERBOSE:
1014 /* already checked by SE */
1015 if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
1016 -1)
1017 log_warn("wrong imsg len");
1018 else
1019 log_setverbose(verbose);
1020 break;
1021 case IMSG_RECONF_DONE:
1022 if (reconfpending == 0) {
1023 log_warnx("unexpected RECONF_DONE received");
1024 break;
1025 }
1026 if (idx == PFD_PIPE_SESSION) {
1027 /* RDE and RTR engine can reload concurrently */
1028 imsg_compose(ibuf_rtr, IMSG_RECONF_DONE, 0,
1029 0, -1, NULL, 0);
1030 imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0,
1031 0, -1, NULL, 0);
1032
1033 /* finally fix kroute information */
1034 ktable_postload();
1035
1036 /* redistribute list needs to be reloaded too */
1037 kr_reload();
1038
1039 /* also remove old peers */
1040 free_deleted_peers(conf);
1041 }
1042 reconfpending--;
1043 break;
1044 case IMSG_RECONF_DRAIN:
1045 if (reconfpending == 0) {
1046 log_warnx("unexpected RECONF_DRAIN received");
1047 break;
1048 }
1049 reconfpending--;
1050 if (reconfpending == 0) {
1051 /*
1052 * SE goes first to bring templated neighbors
1053 * in sync.
1054 */
1055 imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0,
1056 0, -1, NULL, 0);
1057 reconfpending = 3; /* expecting 2 DONE msg */
1058 }
1059 break;
1060 case IMSG_SOCKET_SETUP:
1061 if (idx != PFD_PIPE_RTR) {
1062 log_warnx("connect request not from RTR");
1063 } else {
1064 uint32_t rtrid = imsg_get_id(&imsg);
1065 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1066 if (rtrid == r->id)
1067 break;
1068 }
1069 if (r == NULL)
1070 log_warnx("unknown rtr id %d", rtrid);
1071 else
1072 bgpd_rtr_conn_setup(r);
1073 }
1074 break;
1075 case IMSG_SOCKET_TEARDOWN:
1076 if (idx != PFD_PIPE_RTR) {
1077 log_warnx("connect request not from RTR");
1078 } else {
1079 uint32_t rtrid = imsg_get_id(&imsg);
1080 bgpd_rtr_conn_teardown(rtrid);
1081 }
1082 break;
1083 case IMSG_CTL_SHOW_RTR:
1084 if (idx == PFD_PIPE_SESSION) {
1085 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1086 imsg_compose(ibuf_rtr,
1087 IMSG_CTL_SHOW_RTR, r->id,
1088 imsg_get_pid(&imsg), -1, NULL, 0);
1089 }
1090 imsg_compose(ibuf_rtr, IMSG_CTL_END,
1091 0, imsg_get_pid(&imsg), -1, NULL, 0);
1092 } else if (idx == PFD_PIPE_RTR) {
1093 struct ctl_show_rtr rtr;
1094 if (imsg_get_data(&imsg, &rtr, sizeof(rtr)) ==
1095 -1) {
1096 log_warn("wrong imsg len");
1097 break;
1098 }
1099
1100 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1101 if (imsg_get_id(&imsg) == r->id)
1102 break;
1103 }
1104 if (r != NULL) {
1105 strlcpy(rtr.descr, r->descr,
1106 sizeof(rtr.descr));
1107 rtr.local_addr = r->local_addr;
1108 rtr.remote_addr = r->remote_addr;
1109 rtr.remote_port = r->remote_port;
1110
1111 imsg_compose(ibuf_se, IMSG_CTL_SHOW_RTR,
1112 imsg_get_id(&imsg),
1113 imsg_get_pid(&imsg), -1,
1114 &rtr, sizeof(rtr));
1115 }
1116 }
1117 break;
1118 case IMSG_CTL_END:
1119 case IMSG_CTL_SHOW_TIMER:
1120 if (idx != PFD_PIPE_RTR) {
1121 log_warnx("connect request not from RTR");
1122 break;
1123 }
1124 imsg_forward(ibuf_se, &imsg);
1125 break;
1126 default:
1127 break;
1128 }
1129 imsg_free(&imsg);
1130 if (rv != 0)
1131 return (rv);
1132 }
1133 return (0);
1134 }
1135
1136 void
send_nexthop_update(struct kroute_nexthop * msg)1137 send_nexthop_update(struct kroute_nexthop *msg)
1138 {
1139 char *gw = NULL;
1140
1141 if (msg->gateway.aid)
1142 if (asprintf(&gw, ": via %s",
1143 log_addr(&msg->gateway)) == -1) {
1144 log_warn("send_nexthop_update");
1145 quit = 1;
1146 }
1147
1148 log_debug("nexthop %s now %s%s%s", log_addr(&msg->nexthop),
1149 msg->valid ? "valid" : "invalid",
1150 msg->connected ? ": directly connected" : "",
1151 msg->gateway.aid ? gw : "");
1152
1153 free(gw);
1154
1155 if (imsg_compose(ibuf_rde, IMSG_NEXTHOP_UPDATE, 0, 0, -1,
1156 msg, sizeof(struct kroute_nexthop)) == -1)
1157 quit = 1;
1158 }
1159
1160 void
send_imsg_session(int type,pid_t pid,void * data,uint16_t datalen)1161 send_imsg_session(int type, pid_t pid, void *data, uint16_t datalen)
1162 {
1163 imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen);
1164 }
1165
1166 int
send_network(int type,struct network_config * net,struct filter_set_head * h)1167 send_network(int type, struct network_config *net, struct filter_set_head *h)
1168 {
1169 if (quit)
1170 return (0);
1171 if (imsg_compose(ibuf_rde, type, 0, 0, -1, net,
1172 sizeof(struct network_config)) == -1)
1173 return (-1);
1174 /* networks that get deleted don't need to send the filter set */
1175 if (type == IMSG_NETWORK_REMOVE)
1176 return (0);
1177 if (send_filterset(ibuf_rde, h) == -1)
1178 return (-1);
1179 if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1)
1180 return (-1);
1181
1182 return (0);
1183 }
1184
1185 /*
1186 * Return true if a route can be used for nexthop resolution.
1187 */
1188 int
bgpd_oknexthop(struct kroute_full * kf)1189 bgpd_oknexthop(struct kroute_full *kf)
1190 {
1191 if (kf->flags & F_BGPD)
1192 return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0);
1193
1194 if (kf->prefixlen == 0)
1195 return ((cflags & BGPD_FLAG_NEXTHOP_DEFAULT) != 0);
1196
1197 /* any other route is fine */
1198 return (1);
1199 }
1200
1201 int
bgpd_has_bgpnh(void)1202 bgpd_has_bgpnh(void)
1203 {
1204 return ((cflags & BGPD_FLAG_NEXTHOP_BGP) != 0);
1205 }
1206
1207 int
control_setup(struct bgpd_config * conf)1208 control_setup(struct bgpd_config *conf)
1209 {
1210 int fd, restricted;
1211
1212 /* control socket is outside chroot */
1213 if (!cname || strcmp(cname, conf->csock)) {
1214 if (cname) {
1215 free(cname);
1216 }
1217 if ((cname = strdup(conf->csock)) == NULL)
1218 fatal("strdup");
1219 if (control_check(cname) == -1)
1220 return (-1);
1221 if ((fd = control_init(0, cname)) == -1)
1222 fatalx("control socket setup failed");
1223 if (control_listen(fd) == -1)
1224 fatalx("control socket setup failed");
1225 restricted = 0;
1226 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
1227 &restricted, sizeof(restricted)) == -1)
1228 return (-1);
1229 }
1230 if (!conf->rcsock) {
1231 /* remove restricted socket */
1232 free(rcname);
1233 rcname = NULL;
1234 } else if (!rcname || strcmp(rcname, conf->rcsock)) {
1235 if (rcname) {
1236 free(rcname);
1237 }
1238 if ((rcname = strdup(conf->rcsock)) == NULL)
1239 fatal("strdup");
1240 if (control_check(rcname) == -1)
1241 return (-1);
1242 if ((fd = control_init(1, rcname)) == -1)
1243 fatalx("control socket setup failed");
1244 if (control_listen(fd) == -1)
1245 fatalx("control socket setup failed");
1246 restricted = 1;
1247 if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
1248 &restricted, sizeof(restricted)) == -1)
1249 return (-1);
1250 }
1251 return (0);
1252 }
1253
1254 void
set_pollfd(struct pollfd * pfd,struct imsgbuf * i)1255 set_pollfd(struct pollfd *pfd, struct imsgbuf *i)
1256 {
1257 if (i == NULL || i->fd == -1) {
1258 pfd->fd = -1;
1259 return;
1260 }
1261 pfd->fd = i->fd;
1262 pfd->events = POLLIN;
1263 if (i->w.queued > 0)
1264 pfd->events |= POLLOUT;
1265 }
1266
1267 int
handle_pollfd(struct pollfd * pfd,struct imsgbuf * i)1268 handle_pollfd(struct pollfd *pfd, struct imsgbuf *i)
1269 {
1270 ssize_t n;
1271
1272 if (i == NULL)
1273 return (0);
1274
1275 if (pfd->revents & POLLOUT)
1276 if (msgbuf_write(&i->w) <= 0 && errno != EAGAIN) {
1277 log_warn("imsg write error");
1278 close(i->fd);
1279 i->fd = -1;
1280 return (-1);
1281 }
1282
1283 if (pfd->revents & POLLIN) {
1284 if ((n = imsg_read(i)) == -1 && errno != EAGAIN) {
1285 log_warn("imsg read error");
1286 close(i->fd);
1287 i->fd = -1;
1288 return (-1);
1289 }
1290 if (n == 0) {
1291 log_warnx("peer closed imsg connection");
1292 close(i->fd);
1293 i->fd = -1;
1294 return (-1);
1295 }
1296 }
1297 return (0);
1298 }
1299
1300 static void
getsockpair(int pipe[2])1301 getsockpair(int pipe[2])
1302 {
1303 int bsize, i;
1304
1305 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1306 PF_UNSPEC, pipe) == -1)
1307 fatal("socketpair");
1308
1309 for (i = 0; i < 2; i++) {
1310 for (bsize = MAX_SOCK_BUF; bsize >= 16 * 1024; bsize /= 2) {
1311 if (setsockopt(pipe[i], SOL_SOCKET, SO_RCVBUF,
1312 &bsize, sizeof(bsize)) == -1) {
1313 if (errno != ENOBUFS)
1314 fatal("setsockopt(SO_RCVBUF, %d)",
1315 bsize);
1316 log_warn("setsockopt(SO_RCVBUF, %d)", bsize);
1317 continue;
1318 }
1319 break;
1320 }
1321 }
1322 for (i = 0; i < 2; i++) {
1323 for (bsize = MAX_SOCK_BUF; bsize >= 16 * 1024; bsize /= 2) {
1324 if (setsockopt(pipe[i], SOL_SOCKET, SO_SNDBUF,
1325 &bsize, sizeof(bsize)) == -1) {
1326 if (errno != ENOBUFS)
1327 fatal("setsockopt(SO_SNDBUF, %d)",
1328 bsize);
1329 log_warn("setsockopt(SO_SNDBUF, %d)", bsize);
1330 continue;
1331 }
1332 break;
1333 }
1334 }
1335 }
1336
1337 int
imsg_send_sockets(struct imsgbuf * se,struct imsgbuf * rde,struct imsgbuf * rtr)1338 imsg_send_sockets(struct imsgbuf *se, struct imsgbuf *rde, struct imsgbuf *rtr)
1339 {
1340 int pipe_s2r[2];
1341 int pipe_s2r_ctl[2];
1342 int pipe_r2r[2];
1343
1344 getsockpair(pipe_s2r);
1345 getsockpair(pipe_s2r_ctl);
1346 getsockpair(pipe_r2r);
1347
1348 if (imsg_compose(se, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[0],
1349 NULL, 0) == -1)
1350 return (-1);
1351 if (imsg_compose(rde, IMSG_SOCKET_CONN, 0, 0, pipe_s2r[1],
1352 NULL, 0) == -1)
1353 return (-1);
1354
1355 if (imsg_compose(se, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[0],
1356 NULL, 0) == -1)
1357 return (-1);
1358 if (imsg_compose(rde, IMSG_SOCKET_CONN_CTL, 0, 0, pipe_s2r_ctl[1],
1359 NULL, 0) == -1)
1360 return (-1);
1361
1362 if (imsg_compose(rtr, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[0],
1363 NULL, 0) == -1)
1364 return (-1);
1365 if (imsg_compose(rde, IMSG_SOCKET_CONN_RTR, 0, 0, pipe_r2r[1],
1366 NULL, 0) == -1)
1367 return (-1);
1368
1369 return (0);
1370 }
1371
1372 void
bgpd_rtr_conn_setup(struct rtr_config * r)1373 bgpd_rtr_conn_setup(struct rtr_config *r)
1374 {
1375 struct connect_elm *ce;
1376 struct sockaddr *sa;
1377 socklen_t len;
1378 int nodelay = 1;
1379 int pre = IPTOS_PREC_INTERNETCONTROL;
1380
1381 if (connect_cnt >= MAX_CONNECT_CNT) {
1382 log_warnx("rtr %s: too many concurrent connection requests",
1383 r->descr);
1384 return;
1385 }
1386
1387 if ((ce = calloc(1, sizeof(*ce))) == NULL) {
1388 log_warn("rtr %s", r->descr);
1389 return;
1390 }
1391
1392 if (pfkey_establish(&ce->auth_state, &r->auth,
1393 &r->local_addr, &r->remote_addr) == -1)
1394 log_warnx("rtr %s: pfkey setup failed", r->descr);
1395
1396 ce->id = r->id;
1397 ce->fd = socket(aid2af(r->remote_addr.aid),
1398 SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_TCP);
1399 if (ce->fd == -1) {
1400 log_warn("rtr %s", r->descr);
1401 goto fail;
1402 }
1403
1404 switch (r->remote_addr.aid) {
1405 case AID_INET:
1406 if (setsockopt(ce->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) ==
1407 -1) {
1408 log_warn("rtr %s: setsockopt IP_TOS", r->descr);
1409 return;
1410 }
1411 break;
1412 case AID_INET6:
1413 if (setsockopt(ce->fd, IPPROTO_IPV6, IPV6_TCLASS, &pre,
1414 sizeof(pre)) == -1) {
1415 log_warn("rtr %s: setsockopt IP_TOS", r->descr);
1416 return;
1417 }
1418 break;
1419 }
1420
1421 if (setsockopt(ce->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
1422 sizeof(nodelay)) == -1) {
1423 log_warn("rtr %s: setsockopt TCP_NODELAY", r->descr);
1424 return;
1425 }
1426
1427 if (tcp_md5_set(ce->fd, &r->auth, &r->remote_addr) == -1)
1428 log_warn("rtr %s: setting md5sig", r->descr);
1429
1430 if ((sa = addr2sa(&r->local_addr, 0, &len)) != NULL) {
1431 if (bind(ce->fd, sa, len) == -1) {
1432 log_warn("rtr %s: bind to %s", r->descr,
1433 log_addr(&r->local_addr));
1434 goto fail;
1435 }
1436 }
1437
1438 sa = addr2sa(&r->remote_addr, r->remote_port, &len);
1439 if (connect(ce->fd, sa, len) == -1) {
1440 if (errno != EINPROGRESS) {
1441 log_warn("rtr %s: connect to %s:%u", r->descr,
1442 log_addr(&r->remote_addr), r->remote_port);
1443 goto fail;
1444 }
1445 TAILQ_INSERT_TAIL(&connect_queue, ce, entry);
1446 connect_cnt++;
1447 return;
1448 }
1449
1450 imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0);
1451 TAILQ_INSERT_TAIL(&socket_queue, ce, entry);
1452 return;
1453
1454 fail:
1455 if (ce->fd != -1)
1456 close(ce->fd);
1457 free(ce);
1458 }
1459
1460 void
bgpd_rtr_conn_setup_done(int fd,struct bgpd_config * conf)1461 bgpd_rtr_conn_setup_done(int fd, struct bgpd_config *conf)
1462 {
1463 struct rtr_config *r;
1464 struct connect_elm *ce;
1465 int error = 0;
1466 socklen_t len;
1467
1468 TAILQ_FOREACH(ce, &connect_queue, entry) {
1469 if (ce->fd == fd)
1470 break;
1471 }
1472 if (ce == NULL)
1473 fatalx("connect entry not found");
1474
1475 TAILQ_REMOVE(&connect_queue, ce, entry);
1476 connect_cnt--;
1477
1478 SIMPLEQ_FOREACH(r, &conf->rtrs, entry) {
1479 if (ce->id == r->id)
1480 break;
1481 }
1482 if (r == NULL) {
1483 log_warnx("rtr id %d no longer exists", ce->id);
1484 goto fail;
1485 }
1486
1487 len = sizeof(error);
1488 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
1489 log_warn("rtr %s: getsockopt SO_ERROR", r->descr);
1490 goto fail;
1491 }
1492
1493 if (error != 0) {
1494 errno = error;
1495 log_warn("rtr %s: connect to %s:%u", r->descr,
1496 log_addr(&r->remote_addr), r->remote_port);
1497 goto fail;
1498 }
1499
1500 imsg_compose(ibuf_rtr, IMSG_SOCKET_SETUP, ce->id, 0, ce->fd, NULL, 0);
1501 TAILQ_INSERT_TAIL(&socket_queue, ce, entry);
1502 return;
1503
1504 fail:
1505 close(fd);
1506 free(ce);
1507 }
1508
1509 void
bgpd_rtr_conn_teardown(uint32_t id)1510 bgpd_rtr_conn_teardown(uint32_t id)
1511 {
1512 struct connect_elm *ce;
1513
1514 TAILQ_FOREACH(ce, &socket_queue, entry) {
1515 if (ce->id == id) {
1516 pfkey_remove(&ce->auth_state);
1517 TAILQ_REMOVE(&socket_queue, ce, entry);
1518 free(ce);
1519 return;
1520 }
1521 }
1522 }
1523