Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd rtr version 0 support
To:
tech@openbsd.org
Date:
Tue, 9 Jan 2024 15:25:51 +0100

Download raw body.

Thread
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",