diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2019-05-08 12:41:56 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2019-05-08 12:41:56 +0000 |
commit | 431c95561ddc9ec98009afe5c07decbb92008e4d (patch) | |
tree | f7684cbd19e759cdd2b594a2fe63e0361db87351 /usr.sbin | |
parent | d94ed2f836cebac6cc321e51c6b339eed4120ac6 (diff) |
Rework the TCP md5sig and IKE handling. Move the pfkey socket to the parent
process in this process. The refreshing of the keys is done whenever the
session state is changes to state IDLE or ACTIVE. This should behave better
when reloading configs with auth changes.
OK benno@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 61 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/config.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/pfkey.c | 138 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 87 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 7 |
6 files changed, 183 insertions, 120 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index 6aecc7b7fd5..31c35bca2ec 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.215 2019/03/31 16:57:38 claudio Exp $ */ +/* $OpenBSD: bgpd.c,v 1.216 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -91,7 +91,8 @@ usage(void) #define PFD_PIPE_SESSION 0 #define PFD_PIPE_ROUTE 1 #define PFD_SOCK_ROUTE 2 -#define POLL_MAX 3 +#define PFD_SOCK_PFKEY 3 +#define POLL_MAX 4 #define MAX_TIMEOUT 3600 int cmd_opts; @@ -101,6 +102,7 @@ main(int argc, char *argv[]) { struct bgpd_config *conf; struct rde_rib *rr; + struct peer *p; struct pollfd pfd[POLL_MAX]; time_t timeout; pid_t se_pid = 0, rde_pid = 0, pid; @@ -108,7 +110,7 @@ main(int argc, char *argv[]) char *saved_argv0; int debug = 0; int rflag = 0, sflag = 0; - int rfd = -1; + int rfd, keyfd; int ch, status; int pipe_m2s[2]; int pipe_m2r[2]; @@ -229,6 +231,7 @@ main(int argc, char *argv[]) mrt_init(ibuf_rde, ibuf_se); if ((rfd = kr_init()) == -1) quit = 1; + keyfd = pfkey_init(); /* * rpath, read config file @@ -264,6 +267,9 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd", pfd[PFD_SOCK_ROUTE].fd = rfd; pfd[PFD_SOCK_ROUTE].events = POLLIN; + pfd[PFD_SOCK_PFKEY].fd = keyfd; + pfd[PFD_SOCK_PFKEY].events = POLLIN; + set_pollfd(&pfd[PFD_PIPE_SESSION], ibuf_se); set_pollfd(&pfd[PFD_PIPE_ROUTE], ibuf_rde); @@ -304,6 +310,13 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd", quit = 1; } + if (pfd[PFD_SOCK_PFKEY].revents & POLLIN) { + if (pfkey_read(keyfd, NULL) == -1) { + log_warnx("pfkey_read failed, exiting..."); + quit = 1; + } + } + if (reconfig) { u_int error; @@ -349,15 +362,18 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd", ibuf_rde = NULL; } - while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&ribnames, entry); - free(rr); - } - + /* cleanup kernel data structures */ carp_demote_shutdown(); kr_shutdown(conf->fib_priority, conf->default_tableid); pftable_clear_all(); + TAILQ_FOREACH(p, &conf->peers, entry) + pfkey_remove(p); + + while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&ribnames, entry); + free(rr); + } free_config(conf); log_debug("waiting for children to terminate"); @@ -520,6 +536,10 @@ reconfigure(char *conffile, struct bgpd_config *conf) if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, &p->conf, sizeof(struct peer_config)) == -1) return (-1); + + if (p->reconf_action == RECONF_REINIT) + if (pfkey_establish(p) == -1) + log_peer_warnx(&p->conf, "pfkey setup failed"); } /* networks go via kroute to the RDE */ @@ -690,6 +710,7 @@ int dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf) { struct imsg imsg; + struct peer *p; ssize_t n; int rv, verbose; @@ -765,11 +786,25 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf) case IMSG_PFTABLE_COMMIT: if (idx != PFD_PIPE_ROUTE) log_warnx("pftable request not from RDE"); - else - if (imsg.hdr.len != IMSG_HEADER_SIZE) - log_warnx("wrong imsg len"); - else if (pftable_commit() != 0) - rv = -1; + else if (imsg.hdr.len != IMSG_HEADER_SIZE) + log_warnx("wrong imsg len"); + else if (pftable_commit() != 0) + rv = -1; + break; + case IMSG_PFKEY_RELOAD: + if (idx != PFD_PIPE_SESSION) + log_warnx("pfkey reload request not from SE"); + else if ((p = getpeerbyid(conf, imsg.hdr.peerid)) == + NULL) + log_warnx("pfkey reload: no such peer: id=%u", + imsg.hdr.peerid); + else { + pfkey_remove(p); + if (pfkey_establish(p) == -1) { + log_peer_warnx(&p->conf, + "pfkey setup failed"); + } + } break; case IMSG_CTL_RELOAD: if (idx != PFD_PIPE_SESSION) diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index d8ce37d801c..4dbb6eec967 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.381 2019/05/03 15:25:47 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.382 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -492,6 +492,7 @@ enum imsg_type { IMSG_SESSION_STALE, IMSG_SESSION_FLUSH, IMSG_SESSION_RESTARTED, + IMSG_PFKEY_RELOAD, IMSG_MRT_OPEN, IMSG_MRT_REOPEN, IMSG_MRT_CLOSE, diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c index f263fa6e202..57d6aa158e4 100644 --- a/usr.sbin/bgpd/config.c +++ b/usr.sbin/bgpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.87 2019/03/31 16:57:38 claudio Exp $ */ +/* $OpenBSD: config.c,v 1.88 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -318,8 +318,11 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf) p->reconf_action = RECONF_REINIT; while ((p = TAILQ_FIRST(&xconf->peers)) != NULL) { np = getpeerbyid(conf, p->conf.id); - if (np != NULL) + if (np != NULL) { np->reconf_action = RECONF_KEEP; + /* copy the auth state since parent uses it */ + np->auth = p->auth; + } TAILQ_REMOVE(&xconf->peers, p, entry); free(p); diff --git a/usr.sbin/bgpd/pfkey.c b/usr.sbin/bgpd/pfkey.c index c1ec8164a37..964559ddd2f 100644 --- a/usr.sbin/bgpd/pfkey.c +++ b/usr.sbin/bgpd/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.54 2019/02/20 16:29:01 claudio Exp $ */ +/* $OpenBSD: pfkey.c,v 1.55 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -22,6 +22,8 @@ #include <sys/uio.h> #include <net/pfkeyv2.h> #include <netinet/ip_ipsp.h> +#include <netinet/in.h> +#include <netinet/tcp.h> #include <ctype.h> #include <errno.h> #include <limits.h> @@ -33,13 +35,15 @@ #include "session.h" #include "log.h" +extern struct bgpd_sysdep sysdep; + #define PFKEY2_CHUNK sizeof(u_int64_t) #define ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1)) #define IOV_CNT 20 static u_int32_t sadb_msg_seq = 0; static u_int32_t pid = 0; /* should pid_t but pfkey needs u_int32_t */ -static int fd; +static int pfkey_fd; int pfkey_reply(int, u_int32_t *); int pfkey_send(int, uint8_t, uint8_t, uint8_t, @@ -502,15 +506,15 @@ int pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen, char *key, u_int32_t *spi) { - if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0, + if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0, src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, spi) < 0) + if (pfkey_reply(pfkey_fd, spi) < 0) return (-1); - if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0, + if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0, src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); return (0); } @@ -518,10 +522,10 @@ pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen, int pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi) { - if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0, + if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0, src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); *spi = 0; return (0); @@ -579,7 +583,7 @@ pfkey_ipsec_establish(struct peer *p) case AUTH_IPSEC_MANUAL_AH: satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ? SADB_SATYPE_ESP : SADB_SATYPE_AH; - if (pfkey_send(fd, satype, SADB_ADD, 0, + if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0, &p->auth.local_addr, &p->conf.remote_addr, p->auth.spi_out, p->conf.auth.auth_alg_out, @@ -590,9 +594,9 @@ pfkey_ipsec_establish(struct peer *p) p->conf.auth.enc_key_out, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_send(fd, satype, SADB_ADD, 0, + if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0, &p->conf.remote_addr, &p->auth.local_addr, p->auth.spi_in, p->conf.auth.auth_alg_in, @@ -603,7 +607,7 @@ pfkey_ipsec_establish(struct peer *p) p->conf.auth.enc_key_in, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); break; default: @@ -611,28 +615,28 @@ pfkey_ipsec_establish(struct peer *p) break; } - if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT, + if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT, &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT, + if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT, &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN, + if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN, &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN, + if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN, &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); p->auth.established = 1; @@ -655,20 +659,20 @@ pfkey_ipsec_remove(struct peer *p) case AUTH_IPSEC_MANUAL_AH: satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ? SADB_SATYPE_ESP : SADB_SATYPE_AH; - if (pfkey_send(fd, satype, SADB_DELETE, 0, + if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0, &p->auth.local_addr, &p->conf.remote_addr, p->auth.spi_out, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_send(fd, satype, SADB_DELETE, 0, + if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0, &p->conf.remote_addr, &p->auth.local_addr, p->auth.spi_in, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); break; default: @@ -676,28 +680,28 @@ pfkey_ipsec_remove(struct peer *p) break; } - if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT, + if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT, &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT, + if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT, &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN, + if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN, &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); - if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN, + if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN, &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0) return (-1); - if (pfkey_reply(fd, NULL) < 0) + if (pfkey_reply(pfkey_fd, NULL) < 0) return (-1); p->auth.established = 0; @@ -740,16 +744,78 @@ pfkey_remove(struct peer *p) } int -pfkey_init(struct bgpd_sysdep *sysdep) +pfkey_init(void) { - if ((fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, + if ((pfkey_fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, PF_KEY_V2)) == -1) { if (errno == EPROTONOSUPPORT) { log_warnx("PF_KEY not available, disabling ipsec"); - sysdep->no_pfkey = 1; return (-1); } else fatal("pfkey setup failed"); } - return (fd); + return (pfkey_fd); +} + +int +tcp_md5_check(int fd, struct peer *p) +{ + socklen_t len; + int opt; + + if (p->conf.auth.method == AUTH_MD5SIG) { + if (sysdep.no_md5sig) { + log_peer_warnx(&p->conf, + "md5sig configured but not available"); + return -1; + } + len = sizeof(opt); + if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, + &opt, &len) == -1) + fatal("getsockopt TCP_MD5SIG"); + if (!opt) { /* non-md5'd connection! */ + log_peer_warnx(&p->conf, + "connection attempt without md5 signature"); + return -1; + } + } + return 0; +} + +int +tcp_md5_set(int fd, struct peer *p) +{ + int opt = 1; + + if (p->conf.auth.method == AUTH_MD5SIG) { + if (sysdep.no_md5sig) { + log_peer_warnx(&p->conf, + "md5sig configured but not available"); + return -1; + } + if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, + &opt, sizeof(opt)) == -1) { + log_peer_warn(&p->conf, "setsockopt md5sig"); + return -1; + } + } + return 0; +} + + +int +tcp_md5_listen(int fd, struct peer_head *p) +{ + int opt = 1; + + if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, + &opt, sizeof(opt)) == -1) { + if (errno == ENOPROTOOPT) { /* system w/o md5sig */ + log_warnx("md5sig not available, disabling"); + sysdep.no_md5sig = 1; + return 0; + } + return -1; + } + return 0; } diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 1d7aa83bd9f..a080c273e7d 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.379 2019/04/25 12:12:16 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.380 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -52,8 +52,7 @@ #define PFD_PIPE_ROUTE_CTL 2 #define PFD_SOCK_CTL 3 #define PFD_SOCK_RCTL 4 -#define PFD_SOCK_PFKEY 5 -#define PFD_LISTENERS_START 6 +#define PFD_LISTENERS_START 5 void session_sighdlr(int); int setup_listeners(u_int *); @@ -129,7 +128,6 @@ int setup_listeners(u_int *la_cnt) { int ttl = 255; - int opt; struct listen_addr *la; u_int cnt = 0; @@ -147,15 +145,8 @@ setup_listeners(u_int *la_cnt) continue; } - opt = 1; - if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG, - &opt, sizeof(opt)) == -1) { - if (errno == ENOPROTOOPT) { /* system w/o md5sig */ - log_warnx("md5sig not available, disabling"); - sysdep.no_md5sig = 1; - } else - fatal("setsockopt TCP_MD5SIG"); - } + if (tcp_md5_listen(la->fd, &conf->peers) == -1) + fatal("tcp_md5_listen"); /* set ttl to 255 so that ttl-security works */ if (la->sa.ss_family == AF_INET && setsockopt(la->fd, @@ -188,7 +179,7 @@ setup_listeners(u_int *la_cnt) void session_main(int debug, int verbose) { - int timeout, pfkeysock; + int timeout; unsigned int i, j, idx_peers, idx_listeners, idx_mrts; u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0; u_int listener_cnt, ctl_cnt, mrt_cnt; @@ -217,7 +208,6 @@ session_main(int debug, int verbose) fatal("chdir(\"/\")"); setproctitle("session engine"); - pfkeysock = pfkey_init(&sysdep); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || @@ -355,8 +345,6 @@ session_main(int debug, int verbose) pfd[PFD_SOCK_CTL].fd = -1; pfd[PFD_SOCK_RCTL].fd = -1; } - pfd[PFD_SOCK_PFKEY].fd = pfkeysock; - pfd[PFD_SOCK_PFKEY].events = POLLIN; i = PFD_LISTENERS_START; TAILQ_FOREACH(la, conf->listen_addrs, entry) { @@ -506,13 +494,6 @@ session_main(int debug, int verbose) if (pfd[PFD_SOCK_RCTL].revents & POLLIN) ctl_cnt += control_accept(rcsock, 1); - if (pfd[PFD_SOCK_PFKEY].revents & POLLIN) { - if (pfkey_read(pfkeysock, NULL) == -1) { - log_warnx("pfkey_read failed, exiting..."); - session_quit = 1; - } - } - for (j = PFD_LISTENERS_START; j < idx_listeners; j++) if (pfd[j].revents & POLLIN) session_accept(pfd[j].fd); @@ -540,7 +521,6 @@ session_main(int debug, int verbose) sizeof(p->conf.shutcomm)); session_stop(p, ERR_CEASE_ADMIN_DOWN); timer_remove_all(p); - pfkey_remove(p); free(p); } @@ -629,14 +609,6 @@ bgp_fsm(struct peer *peer, enum session_events event) /* init write buffer */ msgbuf_init(&peer->wbuf); - /* init pfkey - remove old if any, load new ones */ - pfkey_remove(peer); - if (pfkey_establish(peer) == -1) { - log_peer_warnx(&peer->conf, - "pfkey setup failed"); - return; - } - peer->stats.last_sent_errcode = 0; peer->stats.last_sent_suberr = 0; @@ -909,6 +881,9 @@ change_state(struct peer *peer, enum session_state state, free(peer->rbuf); peer->rbuf = NULL; bzero(&peer->capa.peer, sizeof(peer->capa.peer)); + if (!peer->template) + imsg_compose(ibuf_main, IMSG_PFKEY_RELOAD, + peer->conf.id, 0, -1, NULL, 0); if (event != EVNT_STOP) { timer_set(peer, Timer_IdleHold, peer->IdleHoldTime); @@ -953,6 +928,9 @@ change_state(struct peer *peer, enum session_state state, } break; case STATE_ACTIVE: + if (!peer->template) + imsg_compose(ibuf_main, IMSG_PFKEY_RELOAD, + peer->conf.id, 0, -1, NULL, 0); break; case STATE_OPENSENT: break; @@ -986,7 +964,6 @@ void session_accept(int listenfd) { int connfd; - int opt; socklen_t len; struct sockaddr_storage cliaddr; struct peer *p = NULL; @@ -1032,23 +1009,9 @@ open: return; } - if (p->conf.auth.method == AUTH_MD5SIG) { - if (sysdep.no_md5sig) { - log_peer_warnx(&p->conf, - "md5sig configured but not available"); - close(connfd); - return; - } - len = sizeof(opt); - if (getsockopt(connfd, IPPROTO_TCP, TCP_MD5SIG, - &opt, &len) == -1) - fatal("getsockopt TCP_MD5SIG"); - if (!opt) { /* non-md5'd connection! */ - log_peer_warnx(&p->conf, - "connection attempt without md5 signature"); - close(connfd); - return; - } + if (tcp_md5_check(connfd, p) == -1) { + close(connfd); + return; } p->fd = p->wbuf.fd = connfd; if (session_setup_socket(p)) { @@ -1072,7 +1035,6 @@ open: int session_connect(struct peer *peer) { - int opt = 1; struct sockaddr *sa; socklen_t sa_len; @@ -1098,20 +1060,7 @@ session_connect(struct peer *peer) return (-1); } - if (peer->conf.auth.method == AUTH_MD5SIG) { - if (sysdep.no_md5sig) { - log_peer_warnx(&peer->conf, - "md5sig configured but not available"); - bgp_fsm(peer, EVNT_CON_OPENFAIL); - return (-1); - } - if (setsockopt(peer->fd, IPPROTO_TCP, TCP_MD5SIG, - &opt, sizeof(opt)) == -1) { - log_peer_warn(&peer->conf, "setsockopt md5sig"); - bgp_fsm(peer, EVNT_CON_OPENFAIL); - return (-1); - } - } + tcp_md5_set(peer->fd, peer); peer->wbuf.fd = peer->fd; /* if update source is set we need to bind() */ @@ -3238,6 +3187,11 @@ merge_peers(struct bgpd_config *c, struct bgpd_config *nc) if (p->demoted && !p->conf.demote_group[0]) session_demote(p, -1); + /* if session is not open then refresh pfkey data */ + if (p->state < STATE_OPENSENT && !p->template) + imsg_compose(ibuf_main, IMSG_PFKEY_RELOAD, + p->conf.id, 0, -1, NULL, 0); + /* sync the RDE in case we keep the peer */ if (imsg_rde(IMSG_SESSION_ADD, p->conf.id, &p->conf, sizeof(struct peer_config)) == -1) @@ -3258,5 +3212,6 @@ merge_peers(struct bgpd_config *c, struct bgpd_config *nc) } } + /* pfkeys of new peers already loaded by the parent process */ TAILQ_CONCAT(&c->peers, &nc->peers, entry); } diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index c2f30c78fdb..0320545d570 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.136 2019/04/07 10:52:30 claudio Exp $ */ +/* $OpenBSD: session.h,v 1.137 2019/05/08 12:41:55 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -282,7 +282,10 @@ struct bgpd_config *parse_config(char *, struct peer_head *); int pfkey_read(int, struct sadb_msg *); int pfkey_establish(struct peer *); int pfkey_remove(struct peer *); -int pfkey_init(struct bgpd_sysdep *); +int pfkey_init(void); +int tcp_md5_check(int, struct peer *); +int tcp_md5_set(int, struct peer *); +int tcp_md5_listen(int, struct peer_head *); /* printconf.c */ void print_config(struct bgpd_config *, struct rib_names *); |