From 0d6339a20f5ba5e4ae918b1be148e85c93d32cd3 Mon Sep 17 00:00:00 2001 From: claudio Date: Tue, 9 Jan 2024 15:13:49 +0000 Subject: [PATCH] The End of Data PDU changed between v0 (RFC6810) and v1 (RFC8210). Add struct rtr_endofdata_v0 and rtr_parse_end_of_data_v0() to handle this oddity. With this bgpd supports RFC6810 and RFC8210 and some form of draft-ietf-sidrops-8210bis OK tb@ --- usr.sbin/bgpd/rtr_proto.c | 48 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/usr.sbin/bgpd/rtr_proto.c b/usr.sbin/bgpd/rtr_proto.c index f81b143bed6..5b65b167d76 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.26 2024/01/09 14:43:41 claudio Exp $ */ +/* $OpenBSD: rtr_proto.c,v 1.27 2024/01/09 15:13:49 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker @@ -122,6 +122,11 @@ struct rtr_endofdata { uint32_t expire; } __packed; +struct rtr_endofdata_v0 { + struct rtr_header hdr; + uint32_t serial; +} __packed; + enum rtr_event { RTR_EVNT_START, RTR_EVNT_CON_OPEN, @@ -457,8 +462,13 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr, goto badlen; break; case END_OF_DATA: - if (len != sizeof(struct rtr_endofdata)) - goto badlen; + if (rs->version == 0) { + if (len != sizeof(struct rtr_endofdata_v0)) + goto badlen; + } else { + if (len != sizeof(struct rtr_endofdata)) + goto badlen; + } break; case CACHE_RESET: if (len != sizeof(struct rtr_reset)) @@ -800,12 +810,44 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu) return 0; } +static int +rtr_parse_end_of_data_v0(struct rtr_session *rs, struct ibuf *pdu) +{ + struct rtr_endofdata_v0 eod; + + if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) { + log_warnx("rtr %s: received %s: bad pdu length", + log_rtr(rs), log_rtr_type(END_OF_DATA)); + rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu); + return -1; + } + + if (rtr_check_session_id(rs, rs->session_id, &eod.hdr, pdu) == -1) + return -1; + + if (rs->state != RTR_STATE_EXCHANGE) { + log_warnx("rtr %s: received %s: out of context", + log_rtr(rs), log_rtr_type(END_OF_DATA)); + rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu); + return -1; + } + + rs->serial = ntohl(eod.serial); + + rtr_fsm(rs, RTR_EVNT_END_OF_DATA); + return 0; +} + static int rtr_parse_end_of_data(struct rtr_session *rs, struct ibuf *pdu) { struct rtr_endofdata eod; uint32_t t; + /* version 0 does not have the timing values */ + if (rs->version == 0) + return rtr_parse_end_of_data_v0(rs, pdu); + if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) { log_warnx("rtr %s: received %s: bad pdu length", log_rtr(rs), log_rtr_type(END_OF_DATA)); -- 2.20.1