diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 8e791d0cec2..6cf22dcb033 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.490 2024/04/09 09:03:18 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.491 2024/04/09 12:09:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -53,6 +53,7 @@ #define RT_BUF_SIZE 16384 #define MAX_RTSOCK_BUF (2 * 1024 * 1024) #define MAX_COMM_MATCH 3 +#define MAX_ASPA_SPAS_COUNT 10000 #define BGPD_OPT_VERBOSE 0x0001 #define BGPD_OPT_VERBOSE2 0x0002 diff --git a/usr.sbin/bgpd/rtr_proto.c b/usr.sbin/bgpd/rtr_proto.c index 7ceda79704b..ddb3ba4ffbc 100644 --- a/usr.sbin/bgpd/rtr_proto.c +++ b/usr.sbin/bgpd/rtr_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtr_proto.c,v 1.34 2024/03/22 15:41:34 claudio Exp $ */ +/* $OpenBSD: rtr_proto.c,v 1.35 2024/04/09 12:09:20 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker @@ -36,7 +36,8 @@ struct rtr_header { } __packed; #define RTR_MAX_VERSION 2 -#define RTR_MAX_LEN 2048 +#define RTR_MAX_PDU_SIZE 49152 /* XXX < IBUF_READ_SIZE */ +#define RTR_MAX_PDU_ERROR_SIZE 256 #define RTR_DEFAULT_REFRESH 3600 #define RTR_DEFAULT_RETRY 600 #define RTR_DEFAULT_EXPIRE 7200 @@ -272,7 +273,7 @@ rtr_newmsg(struct rtr_session *rs, enum rtr_pdu_type type, uint32_t len, struct ibuf *buf; int saved_errno; - if (len > RTR_MAX_LEN) { + if (len > RTR_MAX_PDU_SIZE) { errno = ERANGE; return NULL; } @@ -328,6 +329,11 @@ rtr_send_error(struct rtr_session *rs, struct ibuf *pdu, enum rtr_error err, if (pdu != NULL) { ibuf_rewind(pdu); len = ibuf_size(pdu); + if (len > RTR_MAX_PDU_ERROR_SIZE) { + len = RTR_MAX_PDU_ERROR_SIZE; + /* truncate down can not fail */ + ibuf_truncate(pdu, RTR_MAX_PDU_ERROR_SIZE); + } } buf = rtr_newmsg(rs, ERROR_REPORT, 2 * sizeof(uint32_t) + len + mlen, @@ -426,7 +432,7 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr, len = ntohl(rh.length); - if (len > RTR_MAX_LEN) { + if (len > RTR_MAX_PDU_SIZE) { rtr_send_error(rs, hdr, CORRUPT_DATA, "%s: too big: %zu bytes", log_rtr_type(rh.type), len); return -1; @@ -754,6 +760,22 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu) aspatree = &rs->aspa; } + /* treat ASPA records with too many SPAS like a withdraw */ + if (cnt > MAX_ASPA_SPAS_COUNT) { + struct aspa_set needle = { 0 }; + needle.as = ntohl(rtr_aspa.cas); + + log_warnx("rtr %s: oversized ASPA PDU: " + "imlicit withdraw of customerAS %s", + log_rtr(rs), log_as(needle.as)); + a = RB_FIND(aspa_tree, aspatree, &needle); + if (a != NULL) { + RB_REMOVE(aspa_tree, aspatree, a); + free_aspa(a); + } + return 0; + } + /* create aspa_set entry from the rtr aspa pdu */ if ((aspa = calloc(1, sizeof(*aspa))) == NULL) { rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory");