From: Claudio Jeker Subject: bgpd: add infrastructure to support rtr sessions with tcp md5 and ipsec To: tech@openbsd.org Date: Wed, 2 Oct 2024 14:53:05 +0200 This diff adds the infrastructure to support tcp md5 and ipsec authentication options for rtr sessions. I did not include the parse.y and printconf bits yet since those are just a lot of noise. In other words the pfkey calls in here are currently NOPs. To properly support tcp md5 the parent needs to know when a session is closed, so this adds a new IMSG for that and keeps the connect_elm struct for open sockets on its own list. I do not expect more than a handful of rtr sessions configured so a linear list should be fine. -- :wq Claudio Index: bgpd.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v diff -u -p -r1.269 bgpd.c --- bgpd.c 1 Oct 2024 11:49:24 -0000 1.269 +++ bgpd.c 2 Oct 2024 12:45:53 -0000 @@ -55,6 +55,7 @@ int imsg_send_sockets(struct imsgbuf *, struct imsgbuf *); void bgpd_rtr_connect(struct rtr_config *); void bgpd_rtr_connect_done(int, struct bgpd_config *); +void bgpd_rtr_close(uint32_t); int cflags; volatile sig_atomic_t mrtdump; @@ -71,12 +72,15 @@ char *rcname; struct connect_elm { TAILQ_ENTRY(connect_elm) entry; + struct auth_state auth_state; uint32_t id; int fd; }; TAILQ_HEAD(, connect_elm) connect_queue = \ - TAILQ_HEAD_INITIALIZER(connect_queue); + TAILQ_HEAD_INITIALIZER(connect_queue), + socket_queue = \ + TAILQ_HEAD_INITIALIZER(socket_queue); u_int connect_cnt; #define MAX_CONNECT_CNT 32 @@ -657,7 +661,7 @@ send_config(struct bgpd_config *conf) if (p->reconf_action == RECONF_REINIT) 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"); + log_peer_warnx(&p->conf, "auth setup failed"); } /* networks go via kroute to the RDE */ @@ -1057,17 +1061,25 @@ dispatch_imsg(struct imsgbuf *imsgbuf, i if (idx != PFD_PIPE_RTR) { log_warnx("connect request not from RTR"); } else { + uint32_t rtrid = imsg_get_id(&imsg); SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { - if (imsg_get_id(&imsg) == r->id) + if (rtrid == r->id) break; } if (r == NULL) - log_warnx("unknown rtr id %d", - imsg_get_id(&imsg)); + log_warnx("unknown rtr id %d", rtrid); else bgpd_rtr_connect(r); } break; + case IMSG_SOCKET_CLOSE: + if (idx != PFD_PIPE_RTR) { + log_warnx("connect request not from RTR"); + } else { + uint32_t rtrid = imsg_get_id(&imsg); + bgpd_rtr_close(rtrid); + } + break; case IMSG_CTL_SHOW_RTR: if (idx == PFD_PIPE_SESSION) { SIMPLEQ_FOREACH(r, &conf->rtrs, entry) { @@ -1377,13 +1389,16 @@ bgpd_rtr_connect(struct rtr_config *r) return; } + if (pfkey_establish(&ce->auth_state, &r->auth, + &r->local_addr, &r->remote_addr) == -1) + log_warnx("rtr %s: pfkey setup failed", r->descr); + ce->id = r->id; ce->fd = socket(aid2af(r->remote_addr.aid), SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_TCP); if (ce->fd == -1) { log_warn("rtr %s", r->descr); - free(ce); - return; + goto fail; } switch (r->remote_addr.aid) { @@ -1409,13 +1424,14 @@ bgpd_rtr_connect(struct rtr_config *r) return; } + if (tcp_md5_set(ce->fd, &r->auth, &r->remote_addr) == -1) + log_warn("rtr %s: setting md5sig", r->descr); + if ((sa = addr2sa(&r->local_addr, 0, &len)) != NULL) { if (bind(ce->fd, sa, len) == -1) { log_warn("rtr %s: bind to %s", r->descr, log_addr(&r->local_addr)); - close(ce->fd); - free(ce); - return; + goto fail; } } @@ -1424,9 +1440,7 @@ bgpd_rtr_connect(struct rtr_config *r) if (errno != EINPROGRESS) { log_warn("rtr %s: connect to %s:%u", r->descr, log_addr(&r->remote_addr), r->remote_port); - close(ce->fd); - free(ce); - return; + goto fail; } TAILQ_INSERT_TAIL(&connect_queue, ce, entry); connect_cnt++; @@ -1434,6 +1448,12 @@ bgpd_rtr_connect(struct rtr_config *r) } imsg_compose(ibuf_rtr, IMSG_SOCKET_CONN, ce->id, 0, ce->fd, NULL, 0); + TAILQ_INSERT_TAIL(&socket_queue, ce, entry); + return; + + fail: + if (ce->fd != -1) + close(ce->fd); free(ce); } @@ -1478,10 +1498,25 @@ bgpd_rtr_connect_done(int fd, struct bgp } imsg_compose(ibuf_rtr, IMSG_SOCKET_CONN, ce->id, 0, ce->fd, NULL, 0); - free(ce); + TAILQ_INSERT_TAIL(&socket_queue, ce, entry); return; fail: close(fd); free(ce); +} + +void +bgpd_rtr_close(uint32_t id) +{ + struct connect_elm *ce; + + TAILQ_FOREACH(ce, &socket_queue, entry) { + if (ce->id == id) { + pfkey_remove(&ce->auth_state); + TAILQ_REMOVE(&socket_queue, ce, entry); + free(ce); + return; + } + } } Index: bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v diff -u -p -r1.497 bgpd.h --- bgpd.h 1 Oct 2024 11:49:24 -0000 1.497 +++ bgpd.h 1 Oct 2024 13:08:48 -0000 @@ -569,6 +569,7 @@ enum rtr_error { struct rtr_config { SIMPLEQ_ENTRY(rtr_config) entry; char descr[PEER_DESCR_LEN]; + struct auth_config auth; struct bgpd_addr remote_addr; struct bgpd_addr local_addr; uint32_t id; @@ -643,6 +644,7 @@ enum imsg_type { IMSG_FLOWSPEC_FLUSH, IMSG_FILTER_SET, IMSG_SOCKET_CONN, + IMSG_SOCKET_CLOSE, IMSG_SOCKET_CONN_CTL, IMSG_SOCKET_CONN_RTR, IMSG_RECONF_CONF, Index: rtr_proto.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rtr_proto.c,v diff -u -p -r1.40 rtr_proto.c --- rtr_proto.c 10 Sep 2024 08:41:13 -0000 1.40 +++ rtr_proto.c 26 Sep 2024 19:00:21 -0000 @@ -1130,6 +1130,7 @@ rtr_fsm(struct rtr_session *rs, enum rtr rs->r.wpos = 0; close(rs->fd); rs->fd = -1; + rtr_imsg_compose(IMSG_SOCKET_CLOSE, rs->id, 0, NULL, 0); } /* try to reopen session */ if (!rs->errored)