From: Claudio Jeker Subject: bgpd rtr version 0 support To: tech@openbsd.org Date: Tue, 9 Jan 2024 15:25:51 +0100 The RTR protocol version 0 has a End of Data pdu that is shorter compared to v1 and above. Add the logic for this into the code. Tested against stayrtr forced to protocol version 0. I think this is the least offensive way to implement this. -- :wq Claudio ? obj ? test ? test.c Index: rtr_proto.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rtr_proto.c,v diff -u -p -r1.25 rtr_proto.c --- rtr_proto.c 9 Jan 2024 14:15:15 -0000 1.25 +++ rtr_proto.c 9 Jan 2024 14:23:30 -0000 @@ -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, 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)) @@ -802,10 +812,42 @@ rtr_parse_aspa(struct rtr_session *rs, s } 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",