This diff changes a bit the way tcp md5sum (and ike) is setup. The big change is that the pfkey handling is moved from the session engine to the parent process. In a later step this should allow to no longer distribute autentication data to the unprivileged childs (but this is not done yet since this diff is already big enough). The reloading of pfkey info is changed a bit (it is now done more often since it will trigger whenever a session is in state idle or active) and should hopefully help when you change tcp md5sum settings in your config. As before bgpd will not reload pfkey on running sessions so after a bgpctl reload you may want to bgpctl nei foo clear the sessions you want to refresh but in general the regular timeout mechanisms will kick in and do the same. In my testing this works great but please give this also a spin and report any problems you can find.
-- :wq Claudio Index: bgpd.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v retrieving revision 1.215 diff -u -p -r1.215 bgpd.c --- bgpd.c 31 Mar 2019 16:57:38 -0000 1.215 +++ bgpd.c 4 May 2019 13:05:06 -0000 @@ -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 cpa 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 cpa 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 cpa 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_ 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 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) Index: bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.381 diff -u -p -r1.381 bgpd.h --- bgpd.h 3 May 2019 15:25:47 -0000 1.381 +++ bgpd.h 4 May 2019 11:45:39 -0000 @@ -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, Index: config.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/config.c,v retrieving revision 1.87 diff -u -p -r1.87 config.c --- config.c 31 Mar 2019 16:57:38 -0000 1.87 +++ config.c 4 May 2019 13:02:53 -0000 @@ -318,8 +318,11 @@ merge_config(struct bgpd_config *xconf, 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); Index: pfkey.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/pfkey.c,v retrieving revision 1.54 diff -u -p -r1.54 pfkey.c --- pfkey.c 20 Feb 2019 16:29:01 -0000 1.54 +++ pfkey.c 4 May 2019 13:03:35 -0000 @@ -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, stru 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; } Index: session.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/session.c,v retrieving revision 1.379 diff -u -p -r1.379 session.c --- session.c 25 Apr 2019 12:12:16 -0000 1.379 +++ session.c 4 May 2019 13:01:47 -0000 @@ -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_ /* 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 ses 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 ses } 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, struc 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, struc } } + /* pfkeys of new peers already loaded by the parent process */ TAILQ_CONCAT(&c->peers, &nc->peers, entry); } Index: session.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/session.h,v retrieving revision 1.136 diff -u -p -r1.136 session.h --- session.h 7 Apr 2019 10:52:30 -0000 1.136 +++ session.h 4 May 2019 12:42:54 -0000 @@ -282,7 +282,10 @@ struct bgpd_config *parse_config(char *, 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 *);