From: claudio Date: Tue, 9 Apr 2024 12:09:19 +0000 (+0000) Subject: Increase RTR PDU limit to 48k and limit number of SPAS to 10'000. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=623585da7ab87663ef3d39942e1ac201c5150bb6;p=openbsd Increase RTR PDU limit to 48k and limit number of SPAS to 10'000. PDU larger then 48k will result in a session reset while ASPA records with more than 10'000 entries will be implicitly withdrawn. Also truncate RTR error PDUs to only include 256 bytes of the faulty PDU. It makes no sense to include more to identify the issue. OK tb@ --- 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");