diff options
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/rtr_proto.c | 48 |
1 files 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 <claudio@openbsd.org> @@ -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)) @@ -801,11 +811,43 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu) } 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)); |