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 *);

Reply via email to