Rework the pfkey and tcp md5 API to not depend on struct peer.
authorclaudio <claudio@openbsd.org>
Tue, 1 Oct 2024 11:49:24 +0000 (11:49 +0000)
committerclaudio <claudio@openbsd.org>
Tue, 1 Oct 2024 11:49:24 +0000 (11:49 +0000)
Instead use struct auth_config and struct auth_state in the pfkey calls
and those tcp_md5 calls where it matters.

This is preparation work to allow RTR to use TCP MD5 as well.
OK tb@

usr.sbin/bgpd/bgpd.c
usr.sbin/bgpd/bgpd.h
usr.sbin/bgpd/config.c
usr.sbin/bgpd/control.c
usr.sbin/bgpd/parse.y
usr.sbin/bgpd/pfkey.c
usr.sbin/bgpd/printconf.c
usr.sbin/bgpd/session.c
usr.sbin/bgpd/session.h

index 572551c..671fb06 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.c,v 1.268 2024/09/30 09:42:24 claudio Exp $ */
+/*     $OpenBSD: bgpd.c,v 1.269 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -467,7 +467,7 @@ BROKEN      if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
        pftable_clear_all();
 
        RB_FOREACH(p, peer_head, &conf->peers)
-               pfkey_remove(p);
+               pfkey_remove(&p->auth_state);
 
        while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
                SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
@@ -651,9 +651,12 @@ send_config(struct bgpd_config *conf)
                if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
                    &p->conf, sizeof(p->conf)) == -1)
                        return (-1);
+               if (pfkey_send_conf(ibuf_se, p->conf.id, &p->auth_conf) == -1)
+                       return (-1);
 
                if (p->reconf_action == RECONF_REINIT)
-                       if (pfkey_establish(p) == -1)
+                       if (pfkey_establish(&p->auth_state, &p->auth_conf,
+                           session_localaddr(p), &p->conf.remote_addr) == -1)
                                log_peer_warnx(&p->conf, "pfkey setup failed");
        }
 
@@ -943,7 +946,9 @@ dispatch_imsg(struct imsgbuf *imsgbuf, int idx, struct bgpd_config *conf)
                        }
                        p = getpeerbyid(conf, imsg_get_id(&imsg));
                        if (p != NULL) {
-                               if (pfkey_establish(p) == -1)
+                               if (pfkey_establish(&p->auth_state,
+                                   &p->auth_conf, session_localaddr(p),
+                                   &p->conf.remote_addr) == -1)
                                        log_peer_warnx(&p->conf,
                                            "pfkey setup failed");
                        }
index c558d63..43322c1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.h,v 1.496 2024/09/04 15:06:36 claudio Exp $ */
+/*     $OpenBSD: bgpd.h,v 1.497 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -379,7 +379,7 @@ enum auth_enc_alg {
        AUTH_EALG_AES,
 };
 
-struct peer_auth {
+struct auth_config {
        char                    md5key[TCP_MD5_KEY_LEN];
        char                    auth_key_in[IPSEC_AUTH_KEY_LEN];
        char                    auth_key_out[IPSEC_AUTH_KEY_LEN];
@@ -452,7 +452,6 @@ struct peer_config {
        struct bgpd_addr         remote_addr;
        struct bgpd_addr         local_addr_v4;
        struct bgpd_addr         local_addr_v6;
-       struct peer_auth         auth;
        struct capabilities      capabilities;
        struct addpath_eval      eval;
        char                     group[PEER_DESCR_LEN];
@@ -649,6 +648,7 @@ enum imsg_type {
        IMSG_RECONF_CONF,
        IMSG_RECONF_RIB,
        IMSG_RECONF_PEER,
+       IMSG_RECONF_PEER_AUTH,
        IMSG_RECONF_FILTER,
        IMSG_RECONF_LISTENER,
        IMSG_RECONF_CTRL,
index 94efad7..4821dea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: config.c,v 1.111 2024/09/04 13:30:10 claudio Exp $ */
+/*     $OpenBSD: config.c,v 1.112 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -440,8 +440,8 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
                np = getpeerbyid(conf, p->conf.id);
                if (np != NULL) {
                        np->reconf_action = RECONF_KEEP;
-                       /* copy the auth state since parent uses it */
-                       np->auth = p->auth;
+                       /* keep the auth state since parent needs it */
+                       np->auth_state = p->auth_state;
 
                        RB_REMOVE(peer_head, &xconf->peers, p);
                        free(p);
@@ -467,7 +467,7 @@ free_deleted_peers(struct bgpd_config *conf)
        RB_FOREACH_SAFE(p, peer_head, &conf->peers, nextp) {
                if (p->reconf_action == RECONF_DELETE) {
                        /* peer no longer exists, clear pfkey state */
-                       pfkey_remove(p);
+                       pfkey_remove(&p->auth_state);
                        RB_REMOVE(peer_head, &conf->peers, p);
                        free(p);
                }
index 2ef1221..b474a48 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: control.c,v 1.118 2024/08/20 11:59:39 claudio Exp $ */
+/*     $OpenBSD: control.c,v 1.119 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -544,6 +544,7 @@ control_imsg_relay(struct imsg *imsg, struct peer *p)
        /* special handling for peers since only the stats are sent from RDE */
        if (type == IMSG_CTL_SHOW_NEIGHBOR) {
                struct rde_peer_stats stats;
+               struct peer peer;
 
                if (p == NULL) {
                        log_warnx("%s: no such peer: id=%u", __func__,
@@ -554,20 +555,22 @@ control_imsg_relay(struct imsg *imsg, struct peer *p)
                        log_warnx("%s: imsg_get_data", __func__);
                        return (0);
                }
-               p->stats.prefix_cnt = stats.prefix_cnt;
-               p->stats.prefix_out_cnt = stats.prefix_out_cnt;
-               p->stats.prefix_rcvd_update = stats.prefix_rcvd_update;
-               p->stats.prefix_rcvd_withdraw = stats.prefix_rcvd_withdraw;
-               p->stats.prefix_rcvd_eor = stats.prefix_rcvd_eor;
-               p->stats.prefix_sent_update = stats.prefix_sent_update;
-               p->stats.prefix_sent_withdraw = stats.prefix_sent_withdraw;
-               p->stats.prefix_sent_eor = stats.prefix_sent_eor;
-               p->stats.pending_update = stats.pending_update;
-               p->stats.pending_withdraw = stats.pending_withdraw;
-               p->stats.msg_queue_len = msgbuf_queuelen(&p->wbuf);
+               peer = *p;
+               explicit_bzero(&peer.auth_conf, sizeof(peer.auth_conf));
+               peer.stats.prefix_cnt = stats.prefix_cnt;
+               peer.stats.prefix_out_cnt = stats.prefix_out_cnt;
+               peer.stats.prefix_rcvd_update = stats.prefix_rcvd_update;
+               peer.stats.prefix_rcvd_withdraw = stats.prefix_rcvd_withdraw;
+               peer.stats.prefix_rcvd_eor = stats.prefix_rcvd_eor;
+               peer.stats.prefix_sent_update = stats.prefix_sent_update;
+               peer.stats.prefix_sent_withdraw = stats.prefix_sent_withdraw;
+               peer.stats.prefix_sent_eor = stats.prefix_sent_eor;
+               peer.stats.pending_update = stats.pending_update;
+               peer.stats.pending_withdraw = stats.pending_withdraw;
+               peer.stats.msg_queue_len = msgbuf_queuelen(&p->wbuf);
 
                return imsg_compose(&c->imsgbuf, type, 0, pid, -1,
-                   p, sizeof(*p));
+                   &peer, sizeof(peer));
        }
 
        /* if command finished no need to send exit message */
index c2f24cc..166c0e7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.468 2024/09/20 02:00:46 jsg Exp $ */
+/*     $OpenBSD: parse.y,v 1.469 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -2076,59 +2076,59 @@ peeropts        : REMOTEAS as4number    {
                        curpeer->conf.max_out_prefix_restart = $4;
                }
                | TCP MD5SIG PASSWORD string {
-                       if (curpeer->conf.auth.method) {
+                       if (curpeer->auth_conf.method) {
                                yyerror("auth method cannot be redefined");
                                free($4);
                                YYERROR;
                        }
-                       if (strlcpy(curpeer->conf.auth.md5key, $4,
-                           sizeof(curpeer->conf.auth.md5key)) >=
-                           sizeof(curpeer->conf.auth.md5key)) {
+                       if (strlcpy(curpeer->auth_conf.md5key, $4,
+                           sizeof(curpeer->auth_conf.md5key)) >=
+                           sizeof(curpeer->auth_conf.md5key)) {
                                yyerror("tcp md5sig password too long: max %zu",
-                                   sizeof(curpeer->conf.auth.md5key) - 1);
+                                   sizeof(curpeer->auth_conf.md5key) - 1);
                                free($4);
                                YYERROR;
                        }
-                       curpeer->conf.auth.method = AUTH_MD5SIG;
-                       curpeer->conf.auth.md5key_len = strlen($4);
+                       curpeer->auth_conf.method = AUTH_MD5SIG;
+                       curpeer->auth_conf.md5key_len = strlen($4);
                        free($4);
                }
                | TCP MD5SIG KEY string {
-                       if (curpeer->conf.auth.method) {
+                       if (curpeer->auth_conf.method) {
                                yyerror("auth method cannot be redefined");
                                free($4);
                                YYERROR;
                        }
 
-                       if (str2key($4, curpeer->conf.auth.md5key,
-                           sizeof(curpeer->conf.auth.md5key)) == -1) {
+                       if (str2key($4, curpeer->auth_conf.md5key,
+                           sizeof(curpeer->auth_conf.md5key)) == -1) {
                                free($4);
                                YYERROR;
                        }
-                       curpeer->conf.auth.method = AUTH_MD5SIG;
-                       curpeer->conf.auth.md5key_len = strlen($4) / 2;
+                       curpeer->auth_conf.method = AUTH_MD5SIG;
+                       curpeer->auth_conf.md5key_len = strlen($4) / 2;
                        free($4);
                }
                | IPSEC espah IKE {
-                       if (curpeer->conf.auth.method) {
+                       if (curpeer->auth_conf.method) {
                                yyerror("auth method cannot be redefined");
                                YYERROR;
                        }
                        if ($2)
-                               curpeer->conf.auth.method = AUTH_IPSEC_IKE_ESP;
+                               curpeer->auth_conf.method = AUTH_IPSEC_IKE_ESP;
                        else
-                               curpeer->conf.auth.method = AUTH_IPSEC_IKE_AH;
+                               curpeer->auth_conf.method = AUTH_IPSEC_IKE_AH;
                }
                | IPSEC espah inout SPI NUMBER STRING STRING encspec {
                        enum auth_alg   auth_alg;
                        uint8_t         keylen;
 
-                       if (curpeer->conf.auth.method &&
-                           (((curpeer->conf.auth.spi_in && $3 == 1) ||
-                           (curpeer->conf.auth.spi_out && $3 == 0)) ||
-                           ($2 == 1 && curpeer->conf.auth.method !=
+                       if (curpeer->auth_conf.method &&
+                           (((curpeer->auth_conf.spi_in && $3 == 1) ||
+                           (curpeer->auth_conf.spi_out && $3 == 0)) ||
+                           ($2 == 1 && curpeer->auth_conf.method !=
                            AUTH_IPSEC_MANUAL_ESP) ||
-                           ($2 == 0 && curpeer->conf.auth.method !=
+                           ($2 == 0 && curpeer->auth_conf.method !=
                            AUTH_IPSEC_MANUAL_AH))) {
                                yyerror("auth method cannot be redefined");
                                free($6);
@@ -2158,7 +2158,7 @@ peeropts  : REMOTEAS as4number    {
                        }
 
                        if ($2)
-                               curpeer->conf.auth.method =
+                               curpeer->auth_conf.method =
                                    AUTH_IPSEC_MANUAL_ESP;
                        else {
                                if ($8.enc_alg) {
@@ -2167,7 +2167,7 @@ peeropts  : REMOTEAS as4number    {
                                        free($7);
                                        YYERROR;
                                }
-                               curpeer->conf.auth.method =
+                               curpeer->auth_conf.method =
                                    AUTH_IPSEC_MANUAL_AH;
                        }
 
@@ -2178,37 +2178,37 @@ peeropts        : REMOTEAS as4number    {
                        }
 
                        if ($3 == 1) {
-                               if (str2key($7, curpeer->conf.auth.auth_key_in,
-                                   sizeof(curpeer->conf.auth.auth_key_in)) ==
+                               if (str2key($7, curpeer->auth_conf.auth_key_in,
+                                   sizeof(curpeer->auth_conf.auth_key_in)) ==
                                    -1) {
                                        free($7);
                                        YYERROR;
                                }
-                               curpeer->conf.auth.spi_in = $5;
-                               curpeer->conf.auth.auth_alg_in = auth_alg;
-                               curpeer->conf.auth.enc_alg_in = $8.enc_alg;
-                               memcpy(&curpeer->conf.auth.enc_key_in,
+                               curpeer->auth_conf.spi_in = $5;
+                               curpeer->auth_conf.auth_alg_in = auth_alg;
+                               curpeer->auth_conf.enc_alg_in = $8.enc_alg;
+                               memcpy(&curpeer->auth_conf.enc_key_in,
                                    &$8.enc_key,
-                                   sizeof(curpeer->conf.auth.enc_key_in));
-                               curpeer->conf.auth.enc_keylen_in =
+                                   sizeof(curpeer->auth_conf.enc_key_in));
+                               curpeer->auth_conf.enc_keylen_in =
                                    $8.enc_key_len;
-                               curpeer->conf.auth.auth_keylen_in = keylen;
+                               curpeer->auth_conf.auth_keylen_in = keylen;
                        } else {
-                               if (str2key($7, curpeer->conf.auth.auth_key_out,
-                                   sizeof(curpeer->conf.auth.auth_key_out)) ==
+                               if (str2key($7, curpeer->auth_conf.auth_key_out,
+                                   sizeof(curpeer->auth_conf.auth_key_out)) ==
                                    -1) {
                                        free($7);
                                        YYERROR;
                                }
-                               curpeer->conf.auth.spi_out = $5;
-                               curpeer->conf.auth.auth_alg_out = auth_alg;
-                               curpeer->conf.auth.enc_alg_out = $8.enc_alg;
-                               memcpy(&curpeer->conf.auth.enc_key_out,
+                               curpeer->auth_conf.spi_out = $5;
+                               curpeer->auth_conf.auth_alg_out = auth_alg;
+                               curpeer->auth_conf.enc_alg_out = $8.enc_alg;
+                               memcpy(&curpeer->auth_conf.enc_key_out,
                                    &$8.enc_key,
-                                   sizeof(curpeer->conf.auth.enc_key_out));
-                               curpeer->conf.auth.enc_keylen_out =
+                                   sizeof(curpeer->auth_conf.enc_key_out));
+                               curpeer->auth_conf.enc_keylen_out =
                                    $8.enc_key_len;
-                               curpeer->conf.auth.auth_keylen_out = keylen;
+                               curpeer->auth_conf.auth_keylen_out = keylen;
                        }
                        free($7);
                }
@@ -5073,10 +5073,10 @@ neighbor_consistent(struct peer *p)
        }
 
        /* with any form of ipsec local-address is required */
-       if ((p->conf.auth.method == AUTH_IPSEC_IKE_ESP ||
-           p->conf.auth.method == AUTH_IPSEC_IKE_AH ||
-           p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
-           p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
+       if ((p->auth_conf.method == AUTH_IPSEC_IKE_ESP ||
+           p->auth_conf.method == AUTH_IPSEC_IKE_AH ||
+           p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
+           p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
            local_addr->aid == AID_UNSPEC) {
                yyerror("neighbors with any form of IPsec configured "
                    "need local-address to be specified");
@@ -5084,9 +5084,9 @@ neighbor_consistent(struct peer *p)
        }
 
        /* with static keying we need both directions */
-       if ((p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
-           p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
-           (!p->conf.auth.spi_in || !p->conf.auth.spi_out)) {
+       if ((p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
+           p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
+           (!p->auth_conf.spi_in || !p->auth_conf.spi_out)) {
                yyerror("with manual keyed IPsec, SPIs and keys "
                    "for both directions are required");
                return (-1);
index 7918775..d300e99 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfkey.c,v 1.68 2022/11/07 22:39:13 mbuhl Exp $ */
+/*     $OpenBSD: pfkey.c,v 1.69 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -45,31 +45,19 @@ static uint32_t     sadb_msg_seq = 0;
 static uint32_t        pid = 0; /* should pid_t but pfkey needs uint32_t */
 static int             pfkey_fd;
 
-int    pfkey_reply(int, uint32_t *);
-int    pfkey_send(int, uint8_t, uint8_t, uint8_t,
-           struct bgpd_addr *, struct bgpd_addr *,
-           uint32_t, uint8_t, int, char *, uint8_t, int, char *,
-           uint16_t, uint16_t);
+static int     pfkey_reply(int, uint32_t *);
+static int     pfkey_send(int, uint8_t, uint8_t, uint8_t,
+                   const struct bgpd_addr *, const struct bgpd_addr *,
+                   uint32_t, uint8_t, int, char *, uint8_t, int, char *,
+                   uint16_t, uint16_t);
 
 #define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport) \
        pfkey_send(fd, satype, cmd, dir, from, to, \
            0, 0, 0, NULL, 0, 0, NULL, sport, dport)
 
-static struct bgpd_addr *
-pfkey_localaddr(struct peer *p)
-{
-       switch (p->conf.remote_addr.aid) {
-       case AID_INET:
-               return &p->conf.local_addr_v4;
-       case AID_INET6:
-               return &p->conf.local_addr_v6;
-       }
-       fatalx("Unknown AID in pfkey_localaddr");
-}
-
-int
+static int
 pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
-    struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t spi,
+    const struct bgpd_addr *src, const struct bgpd_addr *dst, uint32_t spi,
     uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
     uint16_t sport, uint16_t dport)
 {
@@ -447,7 +435,7 @@ pfkey_read(int sd, struct sadb_msg *h)
        return (1);
 }
 
-int
+static int
 pfkey_reply(int sd, uint32_t *spi)
 {
        struct sadb_msg hdr, *msg;
@@ -511,8 +499,8 @@ pfkey_reply(int sd, uint32_t *spi)
 }
 
 static int
-pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, uint8_t keylen,
-    char *key, uint32_t *spi)
+pfkey_sa_add(const struct bgpd_addr *src, const struct bgpd_addr *dst,
+    uint8_t keylen, char *key, uint32_t *spi)
 {
        if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
            src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
@@ -528,7 +516,8 @@ pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, uint8_t keylen,
 }
 
 static int
-pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t *spi)
+pfkey_sa_remove(const struct bgpd_addr *src, const struct bgpd_addr *dst,
+    uint32_t *spi)
 {
        if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
            src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
@@ -540,56 +529,54 @@ pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t *spi)
 }
 
 static int
-pfkey_md5sig_establish(struct peer *p)
+pfkey_md5sig_establish(struct auth_state *as, struct auth_config *auth,
+    const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
 {
        uint32_t spi_out = 0;
        uint32_t spi_in = 0;
 
-       if (pfkey_sa_add(pfkey_localaddr(p), &p->conf.remote_addr,
-           p->conf.auth.md5key_len, p->conf.auth.md5key,
-           &spi_out) == -1)
+       if (pfkey_sa_add(local_addr, remote_addr,
+           auth->md5key_len, auth->md5key, &spi_out) == -1)
                goto fail;
 
-       if (pfkey_sa_add(&p->conf.remote_addr, pfkey_localaddr(p),
-           p->conf.auth.md5key_len, p->conf.auth.md5key,
-           &spi_in) == -1)
+       if (pfkey_sa_add(remote_addr, local_addr,
+           auth->md5key_len, auth->md5key, &spi_in) == -1)
                goto fail;
 
        /* cleanup old flow if one was present */
-       if (p->auth.established) {
-               if (pfkey_remove(p) == -1)
+       if (as->established) {
+               if (pfkey_remove(as) == -1)
                        return (-1);
        }
 
-       p->auth.established = 1;
-       p->auth.spi_out = spi_out;
-       p->auth.spi_in = spi_in;
+       as->established = 1;
+       as->method = auth->method;
+       as->local_addr = *local_addr;
+       as->remote_addr = *remote_addr;
+       as->spi_out = spi_out;
+       as->spi_in = spi_in;
        return (0);
 
 fail:
-       log_peer_warn(&p->conf, "failed to insert md5sig");
        return (-1);
 }
 
 static int
-pfkey_md5sig_remove(struct peer *p)
+pfkey_md5sig_remove(struct auth_state *as)
 {
-       if (p->auth.spi_out)
-               if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
-                   &p->auth.spi_out) == -1)
+       if (as->spi_out)
+               if (pfkey_sa_remove(&as->local_addr, &as->remote_addr,
+                   &as->spi_out) == -1)
                        goto fail;
-       if (p->auth.spi_in)
-               if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
-                   &p->auth.spi_in) == -1)
+       if (as->spi_in)
+               if (pfkey_sa_remove(&as->remote_addr, &as->local_addr,
+                   &as->spi_in) == -1)
                        goto fail;
 
-       p->auth.established = 0;
-       p->auth.spi_out = 0;
-       p->auth.spi_in = 0;
+       explicit_bzero(as, sizeof(*as));
        return (0);
 
 fail:
-       log_peer_warn(&p->conf, "failed to remove md5sig");
        return (-1);
 }
 
@@ -620,18 +607,18 @@ pfkey_enc_alg(enum auth_enc_alg alg)
 }
 
 static int
-pfkey_ipsec_establish(struct peer *p)
+pfkey_ipsec_establish(struct auth_state *as, struct auth_config *auth,
+    const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
 {
        uint8_t satype = SADB_SATYPE_ESP;
-       struct bgpd_addr *local_addr = pfkey_localaddr(p);
 
        /* cleanup first, unlike in the TCP MD5 case */
-       if (p->auth.established) {
-               if (pfkey_remove(p) == -1)
+       if (as->established) {
+               if (pfkey_remove(as) == -1)
                        return (-1);
        }
 
-       switch (p->auth.method) {
+       switch (auth->method) {
        case AUTH_IPSEC_IKE_ESP:
                satype = SADB_SATYPE_ESP;
                break;
@@ -640,30 +627,30 @@ pfkey_ipsec_establish(struct peer *p)
                break;
        case AUTH_IPSEC_MANUAL_ESP:
        case AUTH_IPSEC_MANUAL_AH:
-               satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
+               satype = auth->method == AUTH_IPSEC_MANUAL_ESP ?
                    SADB_SATYPE_ESP : SADB_SATYPE_AH;
                if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
-                   local_addr, &p->conf.remote_addr,
-                   p->conf.auth.spi_out,
-                   pfkey_auth_alg(p->conf.auth.auth_alg_out),
-                   p->conf.auth.auth_keylen_out,
-                   p->conf.auth.auth_key_out,
-                   pfkey_enc_alg(p->conf.auth.enc_alg_out),
-                   p->conf.auth.enc_keylen_out,
-                   p->conf.auth.enc_key_out,
+                   local_addr, remote_addr,
+                   auth->spi_out,
+                   pfkey_auth_alg(auth->auth_alg_out),
+                   auth->auth_keylen_out,
+                   auth->auth_key_out,
+                   pfkey_enc_alg(auth->enc_alg_out),
+                   auth->enc_keylen_out,
+                   auth->enc_key_out,
                    0, 0) == -1)
                        goto fail_key;
                if (pfkey_reply(pfkey_fd, NULL) == -1)
                        goto fail_key;
                if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
-                   &p->conf.remote_addr, local_addr,
-                   p->conf.auth.spi_in,
-                   pfkey_auth_alg(p->conf.auth.auth_alg_in),
-                   p->conf.auth.auth_keylen_in,
-                   p->conf.auth.auth_key_in,
-                   pfkey_enc_alg(p->conf.auth.enc_alg_in),
-                   p->conf.auth.enc_keylen_in,
-                   p->conf.auth.enc_key_in,
+                   remote_addr, local_addr,
+                   auth->spi_in,
+                   pfkey_auth_alg(auth->auth_alg_in),
+                   auth->auth_keylen_in,
+                   auth->auth_key_in,
+                   pfkey_enc_alg(auth->enc_alg_in),
+                   auth->enc_keylen_in,
+                   auth->enc_key_in,
                    0, 0) == -1)
                        goto fail_key;
                if (pfkey_reply(pfkey_fd, NULL) == -1)
@@ -674,49 +661,52 @@ pfkey_ipsec_establish(struct peer *p)
        }
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
-           local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
+           local_addr, remote_addr, 0, BGP_PORT) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
-           local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
+           local_addr, remote_addr, BGP_PORT, 0) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
-           &p->conf.remote_addr, local_addr, 0, BGP_PORT) == -1)
+           remote_addr, local_addr, 0, BGP_PORT) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
-           &p->conf.remote_addr, local_addr, BGP_PORT, 0) == -1)
+           remote_addr, local_addr, BGP_PORT, 0) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        /* save SPI so that they can be removed later on */
-       p->auth.spi_in = p->conf.auth.spi_in;
-       p->auth.spi_out = p->conf.auth.spi_out;
-       p->auth.established = 1;
+       as->established = 1;
+       as->method = auth->method;
+       as->local_addr = *local_addr;
+       as->remote_addr = *remote_addr;
+       as->spi_in = auth->spi_in;
+       as->spi_out = auth->spi_out;
        return (0);
 
 fail_key:
-       log_peer_warn(&p->conf, "failed to insert ipsec key");
+       log_warn("failed to insert ipsec key");
        return (-1);
 fail_flow:
-       log_peer_warn(&p->conf, "failed to insert ipsec flow");
+       log_warn("failed to insert ipsec flow");
        return (-1);
 }
 
 static int
-pfkey_ipsec_remove(struct peer *p)
+pfkey_ipsec_remove(struct auth_state *as)
 {
        uint8_t satype;
 
-       switch (p->auth.method) {
+       switch (as->method) {
        case AUTH_IPSEC_IKE_ESP:
                satype = SADB_SATYPE_ESP;
                break;
@@ -725,20 +715,18 @@ pfkey_ipsec_remove(struct peer *p)
                break;
        case AUTH_IPSEC_MANUAL_ESP:
        case AUTH_IPSEC_MANUAL_AH:
-               satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
+               satype = as->method == AUTH_IPSEC_MANUAL_ESP ?
                    SADB_SATYPE_ESP : SADB_SATYPE_AH;
                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) == -1)
+                   &as->local_addr, &as->remote_addr,
+                   as->spi_out, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
                        goto fail_key;
                if (pfkey_reply(pfkey_fd, NULL) == -1)
                        goto fail_key;
 
                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) == -1)
+                   &as->remote_addr, &as->local_addr,
+                   as->spi_in, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
                        goto fail_key;
                if (pfkey_reply(pfkey_fd, NULL) == -1)
                        goto fail_key;
@@ -748,88 +736,75 @@ pfkey_ipsec_remove(struct peer *p)
        }
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
-           &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
+           &as->local_addr, &as->remote_addr, 0, BGP_PORT) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
-           &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
+           &as->local_addr, &as->remote_addr, BGP_PORT, 0) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
-           &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) == -1)
+           &as->remote_addr, &as->local_addr, 0, BGP_PORT) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
        if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
-           &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) == -1)
+           &as->remote_addr, &as->local_addr, BGP_PORT, 0) == -1)
                goto fail_flow;
        if (pfkey_reply(pfkey_fd, NULL) == -1)
                goto fail_flow;
 
-       p->auth.established = 0;
-       p->auth.spi_out = 0;
-       p->auth.spi_in = 0;
+       explicit_bzero(as, sizeof(*as));
        return (0);
 
 fail_key:
-       log_peer_warn(&p->conf, "failed to remove ipsec key");
+       log_warn("failed to remove ipsec key");
        return (-1);
 fail_flow:
-       log_peer_warn(&p->conf, "failed to remove ipsec flow");
+       log_warn("failed to remove ipsec flow");
        return (-1);
 }
 
 int
-pfkey_establish(struct peer *p)
+pfkey_establish(struct auth_state *as, struct auth_config *auth, 
+    const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
 {
        int rv;
 
-       switch (p->conf.auth.method) {
+       switch (auth->method) {
        case AUTH_NONE:
                rv = 0;
-               if (p->auth.established)
-                       rv = pfkey_remove(p);
+               if (as->established)
+                       rv = pfkey_remove(as);
                break;
        case AUTH_MD5SIG:
-               rv = pfkey_md5sig_establish(p);
+               rv = pfkey_md5sig_establish(as, auth, local_addr, remote_addr);
                break;
        default:
-               rv = pfkey_ipsec_establish(p);
+               rv = pfkey_ipsec_establish(as, auth, local_addr, remote_addr);
                break;
        }
-       /*
-        * make sure we keep copies of everything we need to
-        * remove SAs and flows later again, even if the
-        * info in p->conf changed due to reload.
-        * We need: SPIs, method, local_addr, remote_addr.
-        * remote_addr cannot change, so no copy, SPI are
-        * handled by the method specific functions.
-        */
-       memcpy(&p->auth.local_addr, pfkey_localaddr(p),
-           sizeof(p->auth.local_addr));
-       p->auth.method = p->conf.auth.method;
-
        return (rv);
 }
 
 int
-pfkey_remove(struct peer *p)
+pfkey_remove(struct auth_state *as)
 {
-       if (p->auth.established == 0)
+       if (as->established == 0)
                return (0);
 
-       switch (p->auth.method) {
+       switch (as->method) {
        case AUTH_NONE:
                return (0);
        case AUTH_MD5SIG:
-               return (pfkey_md5sig_remove(p));
+               return (pfkey_md5sig_remove(as));
        default:
-               return (pfkey_ipsec_remove(p));
+               return (pfkey_ipsec_remove(as));
        }
 }
 
@@ -847,26 +822,40 @@ pfkey_init(void)
        return (pfkey_fd);
 }
 
+int
+pfkey_send_conf(struct imsgbuf *imsgbuf, uint32_t id, struct auth_config *auth)
+{
+       /* SE only needs the auth method */
+       return imsg_compose(imsgbuf, IMSG_RECONF_PEER_AUTH, id, 0, -1,
+           &auth->method, sizeof(auth->method));
+}
+
+int
+pfkey_recv_conf(struct peer *p, struct imsg *imsg)
+{
+       struct auth_config *auth = &p->auth_conf;
+
+       return imsg_get_data(imsg, &auth->method, sizeof(auth->method));
+}
+
 /* verify that connection is using TCP MD5UM if required by config */
 int
-tcp_md5_check(int fd, struct peer *p)
+tcp_md5_check(int fd, struct auth_config *auth)
 {
        socklen_t len;
        int opt;
 
-       if (p->conf.auth.method == AUTH_MD5SIG) {
+       if (auth->method == AUTH_MD5SIG) {
                if (sysdep.no_md5sig) {
-                       log_peer_warnx(&p->conf,
-                           "md5sig configured but not available");
+                       errno = ENOPROTOOPT;
                        return -1;
                }
                len = sizeof(opt);
                if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
                    &opt, &len) == -1)
-                       fatal("getsockopt TCP_MD5SIG");
+                       return -1;
                if (!opt) {     /* non-md5'd connection! */
-                       log_peer_warnx(&p->conf,
-                           "connection attempt without md5 signature");
+                       errno = ECONNREFUSED;
                        return -1;
                }
        }
@@ -875,21 +864,18 @@ tcp_md5_check(int fd, struct peer *p)
 
 /* enable or set TCP MD5SIG on a new client connection */
 int
-tcp_md5_set(int fd, struct peer *p)
+tcp_md5_set(int fd, struct auth_config *auth, struct bgpd_addr *remote_addr)
 {
        int opt = 1;
 
-       if (p->conf.auth.method == AUTH_MD5SIG) {
+       if (auth->method == AUTH_MD5SIG) {
                if (sysdep.no_md5sig) {
-                       log_peer_warnx(&p->conf,
-                           "md5sig configured but not available");
+                       errno = ENOPROTOOPT;
                        return -1;
                }
                if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
-                   &opt, sizeof(opt)) == -1) {
-                       log_peer_warn(&p->conf, "setsockopt md5sig");
+                   &opt, sizeof(opt)) == -1)
                        return -1;
-               }
        }
        return 0;
 }
index 8aeeeee..e34380f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: printconf.c,v 1.174 2024/08/14 19:09:51 claudio Exp $ */
+/*     $OpenBSD: printconf.c,v 1.175 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -45,8 +45,7 @@ void           print_originsets(struct prefixset_head *);
 void            print_roa(struct roa_tree *);
 void            print_aspa(struct aspa_tree *);
 void            print_rtrs(struct rtr_config_head *);
-void            print_peer(struct peer_config *, struct bgpd_config *,
-                   const char *);
+void            print_peer(struct peer *, struct bgpd_config *, const char *);
 const char     *print_auth_alg(enum auth_alg);
 const char     *print_enc_alg(enum auth_enc_alg);
 void            print_announce(struct peer_config *, const char *);
@@ -729,10 +728,12 @@ print_rtrs(struct rtr_config_head *rh)
 }
 
 void
-print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
+print_peer(struct peer *peer, struct bgpd_config *conf, const char *c)
 {
-       char            *method;
-       struct in_addr   ina;
+       struct in_addr           ina;
+       char                    *method;
+       struct peer_config      *p = &peer->conf;
+       struct auth_config      *auth = &peer->auth_conf;
 
        if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) ||
            (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128))
@@ -831,30 +832,30 @@ print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
        if (p->flags & PEERFLAG_LOG_UPDATES)
                printf("%s\tlog updates\n", c);
 
-       if (p->auth.method == AUTH_MD5SIG)
+       if (auth->method == AUTH_MD5SIG)
                printf("%s\ttcp md5sig\n", c);
-       else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP ||
-           p->auth.method == AUTH_IPSEC_MANUAL_AH) {
-               if (p->auth.method == AUTH_IPSEC_MANUAL_ESP)
+       else if (auth->method == AUTH_IPSEC_MANUAL_ESP ||
+           auth->method == AUTH_IPSEC_MANUAL_AH) {
+               if (auth->method == AUTH_IPSEC_MANUAL_ESP)
                        method = "esp";
                else
                        method = "ah";
 
                printf("%s\tipsec %s in spi %u %s XXXXXX", c, method,
-                   p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in));
-               if (p->auth.enc_alg_in)
-                       printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in));
+                   auth->spi_in, print_auth_alg(auth->auth_alg_in));
+               if (auth->enc_alg_in)
+                       printf(" %s XXXXXX", print_enc_alg(auth->enc_alg_in));
                printf("\n");
 
                printf("%s\tipsec %s out spi %u %s XXXXXX", c, method,
-                   p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out));
-               if (p->auth.enc_alg_out)
+                   auth->spi_out, print_auth_alg(auth->auth_alg_out));
+               if (auth->enc_alg_out)
                        printf(" %s XXXXXX",
-                           print_enc_alg(p->auth.enc_alg_out));
+                           print_enc_alg(auth->enc_alg_out));
                printf("\n");
-       } else if (p->auth.method == AUTH_IPSEC_IKE_AH)
+       } else if (auth->method == AUTH_IPSEC_IKE_AH)
                printf("%s\tipsec ah ike\n", c);
-       else if (p->auth.method == AUTH_IPSEC_IKE_ESP)
+       else if (auth->method == AUTH_IPSEC_IKE_ESP)
                printf("%s\tipsec esp ike\n", c);
 
        if (p->ttlsec)
@@ -1196,39 +1197,36 @@ print_mrt(struct bgpd_config *conf, uint32_t pid, uint32_t gid,
 void
 print_groups(struct bgpd_config *conf)
 {
-       struct peer_config      **peerlist;
-       struct peer              *p;
-       u_int                     peer_cnt, i;
-       uint32_t                  prev_groupid;
-       const char               *tab   = "\t";
-       const char               *nada  = "";
-       const char               *c;
+       struct peer     **peerlist;
+       struct peer      *p;
+       u_int             peer_cnt, i;
+       uint32_t          prev_groupid;
+       const char       *c;
 
        peer_cnt = 0;
        RB_FOREACH(p, peer_head, &conf->peers)
                peer_cnt++;
-
-       if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL)
+       if ((peerlist = calloc(peer_cnt, sizeof(*peerlist))) == NULL)
                fatal("print_groups calloc");
-
        i = 0;
        RB_FOREACH(p, peer_head, &conf->peers)
-               peerlist[i++] = &p->conf;
+               peerlist[i++] = p;
 
-       qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare);
+       qsort(peerlist, peer_cnt, sizeof(*peerlist), peer_compare);
 
        prev_groupid = 0;
        for (i = 0; i < peer_cnt; i++) {
-               if (peerlist[i]->groupid) {
-                       c = tab;
-                       if (peerlist[i]->groupid != prev_groupid) {
+               if (peerlist[i]->conf.groupid) {
+                       c = "\t";
+                       if (peerlist[i]->conf.groupid != prev_groupid) {
                                if (prev_groupid)
                                        printf("}\n\n");
-                               printf("group \"%s\" {\n", peerlist[i]->group);
-                               prev_groupid = peerlist[i]->groupid;
+                               printf("group \"%s\" {\n",
+                                   peerlist[i]->conf.group);
+                               prev_groupid = peerlist[i]->conf.groupid;
                        }
                } else
-                       c = nada;
+                       c = "";
 
                print_peer(peerlist[i], conf, c);
        }
@@ -1242,13 +1240,13 @@ print_groups(struct bgpd_config *conf)
 int
 peer_compare(const void *aa, const void *bb)
 {
-       const struct peer_config * const *a;
-       const struct peer_config * const *b;
+       const struct peer * const *a;
+       const struct peer * const *b;
 
        a = aa;
        b = bb;
 
-       return ((*a)->groupid - (*b)->groupid);
+       return ((*a)->conf.groupid - (*b)->conf.groupid);
 }
 
 void
index c176edb..a423400 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: session.c,v 1.482 2024/09/09 12:59:49 claudio Exp $ */
+/*     $OpenBSD: session.c,v 1.483 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -1032,14 +1032,15 @@ session_accept(int listenfd)
                }
 
 open:
-               if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
+               if (p->auth_conf.method != AUTH_NONE && sysdep.no_pfkey) {
                        log_peer_warnx(&p->conf,
                            "ipsec or md5sig configured but not available");
                        close(connfd);
                        return;
                }
 
-               if (tcp_md5_check(connfd, p) == -1) {
+               if (tcp_md5_check(connfd, &p->auth_conf) == -1) {
+                       log_peer_warn(&p->conf, "check md5sig");
                        close(connfd);
                        return;
                }
@@ -1066,7 +1067,7 @@ int
 session_connect(struct peer *peer)
 {
        struct sockaddr         *sa;
-       struct bgpd_addr        *bind_addr = NULL;
+       struct bgpd_addr        *bind_addr;
        socklen_t                sa_len;
 
        /*
@@ -1084,25 +1085,20 @@ session_connect(struct peer *peer)
                return (-1);
        }
 
-       if (peer->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
+       if (peer->auth_conf.method != AUTH_NONE && sysdep.no_pfkey) {
                log_peer_warnx(&peer->conf,
                    "ipsec or md5sig configured but not available");
                bgp_fsm(peer, EVNT_CON_OPENFAIL);
                return (-1);
        }
 
-       tcp_md5_set(peer->fd, peer);
+       if (tcp_md5_set(peer->fd, &peer->auth_conf,
+           &peer->conf.remote_addr) == -1)
+               log_peer_warn(&peer->conf, "setting md5sig");
        peer->wbuf.fd = peer->fd;
 
        /* if local-address is set we need to bind() */
-       switch (peer->conf.remote_addr.aid) {
-       case AID_INET:
-               bind_addr = &peer->conf.local_addr_v4;
-               break;
-       case AID_INET6:
-               bind_addr = &peer->conf.local_addr_v6;
-               break;
-       }
+       bind_addr = session_localaddr(peer);
        if ((sa = addr2sa(bind_addr, 0, &sa_len)) != NULL) {
                if (bind(peer->fd, sa, sa_len) == -1) {
                        log_peer_warn(&peer->conf, "session_connect bind");
@@ -3003,6 +2999,16 @@ session_dispatch_imsg(struct imsgbuf *imsgbuf, int idx, u_int *listener_cnt)
                        if (RB_INSERT(peer_head, &nconf->peers, p) != NULL)
                                fatalx("%s: peer tree is corrupt", __func__);
                        break;
+               case IMSG_RECONF_PEER_AUTH:
+                       if (idx != PFD_PIPE_MAIN)
+                               fatalx("reconf request not from parent");
+                       if ((p = getpeerbyid(nconf, peerid)) == NULL) {
+                               log_warnx("no such peer: id=%u", peerid);
+                               break;
+                       }
+                       if (pfkey_recv_conf(p, &imsg) == -1)
+                               fatal("pfkey_recv_conf");
+                       break;
                case IMSG_RECONF_LISTENER:
                        if (idx != PFD_PIPE_MAIN)
                                fatalx("reconf request not from parent");
@@ -3641,6 +3647,18 @@ session_stop(struct peer *peer, uint8_t subcode, const char *reason)
        bgp_fsm(peer, EVNT_STOP);
 }
 
+struct bgpd_addr *
+session_localaddr(struct peer *p)
+{
+       switch (p->conf.remote_addr.aid) {
+       case AID_INET:
+               return &p->conf.local_addr_v4;
+       case AID_INET6:
+               return &p->conf.local_addr_v6;
+       }
+       fatalx("Unknown AID in %s", __func__);
+}
+
 void
 merge_peers(struct bgpd_config *c, struct bgpd_config *nc)
 {
@@ -3657,10 +3675,10 @@ merge_peers(struct bgpd_config *c, struct bgpd_config *nc)
                }
 
                /* peer no longer uses TCP MD5SIG so deconfigure */
-               if (p->conf.auth.method == AUTH_MD5SIG &&
-                   np->conf.auth.method != AUTH_MD5SIG)
+               if (p->auth_conf.method == AUTH_MD5SIG &&
+                   np->auth_conf.method != AUTH_MD5SIG)
                        tcp_md5_del_listener(c, p);
-               else if (np->conf.auth.method == AUTH_MD5SIG)
+               else if (np->auth_conf.method == AUTH_MD5SIG)
                        tcp_md5_add_listener(c, np);
 
                memcpy(&p->conf, &np->conf, sizeof(p->conf));
@@ -3706,7 +3724,7 @@ merge_peers(struct bgpd_config *c, struct bgpd_config *nc)
                RB_REMOVE(peer_head, &nc->peers, np);
                if (RB_INSERT(peer_head, &c->peers, np) != NULL)
                        fatalx("%s: peer tree is corrupt", __func__);
-               if (np->conf.auth.method == AUTH_MD5SIG)
+               if (np->auth_conf.method == AUTH_MD5SIG)
                        tcp_md5_add_listener(c, np);
        }
 }
index 12e871e..38c624c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: session.h,v 1.173 2024/09/04 13:30:10 claudio Exp $ */
+/*     $OpenBSD: session.h,v 1.174 2024/10/01 11:49:24 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -163,6 +163,15 @@ struct peer_stats {
        char                     last_reason[REASON_LEN];
 };
 
+struct auth_state {
+       struct bgpd_addr        local_addr;
+       struct bgpd_addr        remote_addr;
+       uint32_t                spi_in;
+       uint32_t                spi_out;
+       enum auth_method        method;
+       uint8_t                 established;
+};
+
 enum Timer {
        Timer_None,
        Timer_ConnectRetry,
@@ -197,13 +206,8 @@ struct peer {
                struct capabilities     peer;
                struct capabilities     neg;
        }                        capa;
-       struct {
-               struct bgpd_addr        local_addr;
-               uint32_t                spi_in;
-               uint32_t                spi_out;
-               enum auth_method        method;
-               uint8_t                 established;
-       }                        auth;
+       struct auth_state        auth_state;
+       struct auth_config       auth_conf;
        struct bgpd_addr         local;
        struct bgpd_addr         local_alt;
        struct bgpd_addr         remote;
@@ -278,11 +282,14 @@ void       mrt_done(struct mrt *);
 /* pfkey.c */
 struct sadb_msg;
 int    pfkey_read(int, struct sadb_msg *);
-int    pfkey_establish(struct peer *);
-int    pfkey_remove(struct peer *);
+int    pfkey_establish(struct auth_state *, struct auth_config *,
+           const struct bgpd_addr *, const struct bgpd_addr *);
+int    pfkey_remove(struct auth_state *);
 int    pfkey_init(void);
-int    tcp_md5_check(int, struct peer *);
-int    tcp_md5_set(int, struct peer *);
+int    pfkey_send_conf(struct imsgbuf *, uint32_t, struct auth_config *);
+int    pfkey_recv_conf(struct peer *, struct imsg *);
+int    tcp_md5_check(int, struct auth_config *);
+int    tcp_md5_set(int, struct auth_config *, struct bgpd_addr *);
 int    tcp_md5_prep_listener(struct listen_addr *, struct peer_head *);
 void   tcp_md5_add_listener(struct bgpd_config *, struct peer *);
 void   tcp_md5_del_listener(struct bgpd_config *, struct peer *);
@@ -334,6 +341,7 @@ int          imsg_ctl_parent(struct imsg *);
 int             imsg_ctl_rde(struct imsg *);
 int             imsg_ctl_rde_msg(int, uint32_t, pid_t);
 void            session_stop(struct peer *, uint8_t, const char *);
+struct bgpd_addr *session_localaddr(struct peer *);
 
 /* timer.c */
 struct timer   *timer_get(struct timer_head *, enum Timer);