summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h4
-rw-r--r--usr.sbin/bgpd/control.c8
-rw-r--r--usr.sbin/bgpd/rde.c176
-rw-r--r--usr.sbin/bgpd/session.c3
4 files changed, 185 insertions, 6 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index b410d47b849..d0dd9850f65 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.473 2023/04/19 07:12:22 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.474 2023/04/20 12:53:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -599,6 +599,7 @@ enum imsg_type {
IMSG_CTL_SHOW_RIB_COMMUNITIES,
IMSG_CTL_SHOW_RIB_ATTR,
IMSG_CTL_SHOW_NETWORK,
+ IMSG_CTL_SHOW_FLOWSPEC,
IMSG_CTL_SHOW_RIB_MEM,
IMSG_CTL_SHOW_TERSE,
IMSG_CTL_SHOW_TIMER,
@@ -616,6 +617,7 @@ enum imsg_type {
IMSG_FLOWSPEC_ADD,
IMSG_FLOWSPEC_DONE,
IMSG_FLOWSPEC_REMOVE,
+ IMSG_FLOWSPEC_FLUSH,
IMSG_FILTER_SET,
IMSG_SOCKET_CONN,
IMSG_SOCKET_CONN_CTL,
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index a6248a074d2..fc516b8fd75 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.109 2023/02/09 13:43:23 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.110 2023/04/20 12:53:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -279,6 +279,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_CTL_SHOW_TERSE:
case IMSG_CTL_SHOW_TIMER:
case IMSG_CTL_SHOW_NETWORK:
+ case IMSG_CTL_SHOW_FLOWSPEC:
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_PREFIX:
case IMSG_CTL_SHOW_SET:
@@ -498,6 +499,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
break;
case IMSG_CTL_SHOW_NETWORK:
+ case IMSG_CTL_SHOW_FLOWSPEC:
c->terminate = 1;
/* FALLTHROUGH */
case IMSG_CTL_SHOW_RIB_MEM:
@@ -512,6 +514,10 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_NETWORK_REMOVE:
case IMSG_NETWORK_FLUSH:
case IMSG_NETWORK_DONE:
+ case IMSG_FLOWSPEC_ADD:
+ case IMSG_FLOWSPEC_REMOVE:
+ case IMSG_FLOWSPEC_DONE:
+ case IMSG_FLOWSPEC_FLUSH:
case IMSG_FILTER_SET:
imsg_ctl_rde(imsg.hdr.type, 0, 0,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index f71218a4042..1fecf6c5151 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.603 2023/04/19 13:23:33 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.604 2023/04/20 12:53:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -105,6 +105,9 @@ static void network_flush_upcall(struct rib_entry *, void *);
void flowspec_add(struct flowspec *, struct filterstate *,
struct filter_set_head *);
void flowspec_delete(struct flowspec *);
+static void flowspec_flush_upcall(struct rib_entry *, void *);
+static void flowspec_dump_upcall(struct rib_entry *, void *);
+static void flowspec_dump_done(void *, uint8_t);
void rde_shutdown(void);
static int ovs_match(struct prefix *, uint32_t);
@@ -361,6 +364,7 @@ struct filter_set_head parent_set = TAILQ_HEAD_INITIALIZER(parent_set);
void
rde_dispatch_imsg_session(struct imsgbuf *ibuf)
{
+ static struct flowspec *curflow;
struct imsg imsg;
struct rde_peer_stats stats;
struct ctl_show_set cset;
@@ -577,6 +581,97 @@ badnetdel:
NULL, NULL) == -1)
log_warn("rde_dispatch: IMSG_NETWORK_FLUSH");
break;
+ case IMSG_FLOWSPEC_ADD:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE <= FLOWSPEC_SIZE) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ if (curflow != NULL) {
+ log_warnx("rde_dispatch: "
+ "unexpected flowspec add");
+ break;
+ }
+ curflow = malloc(imsg.hdr.len - IMSG_HEADER_SIZE);
+ if (curflow == NULL)
+ fatal(NULL);
+ memcpy(curflow, imsg.data,
+ imsg.hdr.len - IMSG_HEADER_SIZE);
+ if (curflow->len + FLOWSPEC_SIZE !=
+ imsg.hdr.len - IMSG_HEADER_SIZE) {
+ free(curflow);
+ curflow = NULL;
+ log_warnx("rde_dispatch: wrong flowspec len");
+ break;
+ }
+ rde_filterstate_init(&netconf_state);
+ asp = &netconf_state.aspath;
+ asp->aspath = aspath_get(NULL, 0);
+ asp->origin = ORIGIN_IGP;
+ asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
+ F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED |
+ F_ANN_DYNAMIC;
+ break;
+ case IMSG_FLOWSPEC_DONE:
+ if (curflow == NULL) {
+ log_warnx("rde_dispatch: "
+ "unexpected flowspec done");
+ break;
+ }
+
+ if (flowspec_valid(curflow->data, curflow->len,
+ curflow->aid == AID_FLOWSPECv6) == -1)
+ log_warnx("invalid flowspec update received "
+ "from bgpctl");
+ else
+ flowspec_add(curflow, &netconf_state,
+ &session_set);
+
+ rde_filterstate_clean(&netconf_state);
+ filterset_free(&session_set);
+ free(curflow);
+ curflow = NULL;
+ break;
+ case IMSG_FLOWSPEC_REMOVE:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE <= FLOWSPEC_SIZE) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ if (curflow != NULL) {
+ log_warnx("rde_dispatch: "
+ "unexpected flowspec remove");
+ break;
+ }
+ curflow = malloc(imsg.hdr.len - IMSG_HEADER_SIZE);
+ if (curflow == NULL)
+ fatal(NULL);
+ memcpy(curflow, imsg.data,
+ imsg.hdr.len - IMSG_HEADER_SIZE);
+ if (curflow->len + FLOWSPEC_SIZE !=
+ imsg.hdr.len - IMSG_HEADER_SIZE) {
+ free(curflow);
+ curflow = NULL;
+ log_warnx("rde_dispatch: wrong flowspec len");
+ break;
+ }
+
+ if (flowspec_valid(curflow->data, curflow->len,
+ curflow->aid == AID_FLOWSPECv6) == -1)
+ log_warnx("invalid flowspec withdraw received "
+ "from bgpctl");
+ else
+ flowspec_delete(curflow);
+
+ free(curflow);
+ curflow = NULL;
+ break;
+ case IMSG_FLOWSPEC_FLUSH:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ prefix_flowspec_dump(AID_UNSPEC, NULL,
+ flowspec_flush_upcall, NULL);
+ break;
case IMSG_FILTER_SET:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(struct filter_set)) {
@@ -603,6 +698,15 @@ badnetdel:
memcpy(&req, imsg.data, sizeof(req));
rde_dump_ctx_new(&req, imsg.hdr.pid, imsg.hdr.type);
break;
+ case IMSG_CTL_SHOW_FLOWSPEC:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ memcpy(&req, imsg.data, sizeof(req));
+ prefix_flowspec_dump(req.aid, &imsg.hdr.pid,
+ flowspec_dump_upcall, flowspec_dump_done);
+ break;
case IMSG_CTL_SHOW_NEIGHBOR:
if (imsg.hdr.len - IMSG_HEADER_SIZE != 0) {
log_warnx("rde_dispatch: wrong imsg len");
@@ -893,12 +997,14 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
log_warnx("rde_dispatch: wrong flowspec len");
break;
}
+
if (flowspec_valid(curflow->data, curflow->len,
curflow->aid == AID_FLOWSPECv6) == -1)
log_warnx("invalid flowspec withdraw received "
"from parent");
else
flowspec_delete(curflow);
+
free(curflow);
curflow = NULL;
break;
@@ -4538,8 +4644,7 @@ network_dump_upcall(struct rib_entry *re, void *ptr)
kf.flags = F_STATIC;
if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0,
ctx->req.pid, -1, &kf, sizeof(kf)) == -1)
- log_warnx("network_dump_upcall: "
- "imsg_compose error");
+ log_warnx("%s: imsg_compose error", __func__);
}
}
@@ -4609,6 +4714,71 @@ flowspec_delete(struct flowspec *f)
peerself->stats.prefix_cnt--;
}
+static void
+flowspec_flush_upcall(struct rib_entry *re, void *ptr)
+{
+ struct prefix *p;
+
+ p = prefix_bypeer(re, peerself, 0);
+ if (p == NULL)
+ return;
+ if ((prefix_aspath(p)->flags & F_ANN_DYNAMIC) != F_ANN_DYNAMIC)
+ return;
+ if (prefix_flowspec_withdraw(peerself, re->prefix) == 1)
+ peerself->stats.prefix_cnt--;
+}
+
+static void
+flowspec_dump_upcall(struct rib_entry *re, void *ptr)
+{
+ pid_t *pid = ptr;
+ struct prefix *p;
+ struct rde_aspath *asp;
+ struct rde_community *comm;
+ struct flowspec ff;
+ struct ibuf *ibuf;
+ uint8_t *flow;
+ int len;
+
+ TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) {
+ asp = prefix_aspath(p);
+ if (!(asp->flags & F_PREFIX_ANNOUNCED))
+ continue;
+ comm = prefix_communities(p);
+
+ len = pt_getflowspec(p->pt, &flow);
+
+ memset(&ff, 0, sizeof(ff));
+ ff.aid = p->pt->aid;
+ ff.len = len;
+ if ((asp->flags & F_ANN_DYNAMIC) == 0)
+ ff.flags = F_STATIC;
+ if ((ibuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_FLOWSPEC, 0,
+ *pid, FLOWSPEC_SIZE + len)) == NULL)
+ continue;
+ if (imsg_add(ibuf, &ff, FLOWSPEC_SIZE) == -1 ||
+ imsg_add(ibuf, flow, len) == -1)
+ continue;
+ imsg_close(ibuf_se_ctl, ibuf);
+ if (comm->nentries > 0) {
+ if (imsg_compose(ibuf_se_ctl,
+ IMSG_CTL_SHOW_RIB_COMMUNITIES, 0, *pid, -1,
+ comm->communities,
+ comm->nentries * sizeof(struct community)) == -1)
+ continue;
+ }
+ }
+}
+
+static void
+flowspec_dump_done(void *ptr, uint8_t aid)
+{
+ pid_t *pid = ptr;
+
+ imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, *pid, -1, NULL, 0);
+}
+
+
/* clean up */
void
rde_shutdown(void)
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index 68e76737d12..137fda97619 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.442 2023/03/09 13:12:19 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.443 2023/04/20 12:53:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -3205,6 +3205,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
case IMSG_CTL_SHOW_RIB_ATTR:
case IMSG_CTL_SHOW_RIB_MEM:
case IMSG_CTL_SHOW_NETWORK:
+ case IMSG_CTL_SHOW_FLOWSPEC:
case IMSG_CTL_SHOW_SET:
if (idx != PFD_PIPE_ROUTE_CTL)
fatalx("ctl rib request not from RDE");