Download raw body.
bgpd: add infrastructure to support rtr sessions with tcp md5 and ipsec
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)
bgpd: add infrastructure to support rtr sessions with tcp md5 and ipsec