Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
adjust bgpd rtr code to draft-ietf-sidrops-8210bis-14
To:
tech@openbsd.org
Date:
Wed, 7 Aug 2024 21:27:55 +0200

Download raw body.

Thread
Had this sitting in my tree for about 6 month now (maybe it has been a
year, who knows...). This uses the sane RTR ASPA PDU format that
draft-ietf-sidrops-8210bis-14 finally adopted.

I tested this against a hacked up stayrtr version but testing right now is
a bit hard.
-- 
:wq Claudio

Index: rtr_proto.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rtr_proto.c,v
diff -u -p -r1.35 rtr_proto.c
--- rtr_proto.c	9 Apr 2024 12:09:20 -0000	1.35
+++ rtr_proto.c	7 Aug 2024 19:19:58 -0000
@@ -31,7 +31,14 @@
 struct rtr_header {
 	uint8_t		version;
 	uint8_t		type;
-	uint16_t	session_id; /* or error code */
+	union {
+		uint16_t	session_id;
+		uint16_t	errcode;
+		struct {
+			uint8_t flags;
+			uint8_t zero;
+		};
+	};
 	uint32_t	length;
 } __packed;
 
@@ -108,11 +115,8 @@ struct rtr_routerkey {
 #define FLAG_AFI_MASK	FLAG_AFI_V6
 struct rtr_aspa {
 	struct rtr_header	hdr;
-	uint8_t			flags;
-	uint8_t			afi_flags;
-	uint16_t		cnt;
 	uint32_t		cas;
-	/* array of spas with cnt elements follows */
+	/* array of spas filling the rest of the packet */
 } __packed;
 
 struct rtr_endofdata {
@@ -737,16 +741,15 @@ static int
 rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
 {
 	struct rtr_aspa rtr_aspa;
-	struct aspa_tree *aspatree;
 	struct aspa_set *aspa, *a;
-	uint16_t cnt, i;
+	uint32_t cnt, i;
+	uint8_t flags;
 
 	if (ibuf_get(pdu, &rtr_aspa, sizeof(rtr_aspa)) == -1)
 		goto badlen;
 
-	cnt = ntohs(rtr_aspa.cnt);
-	if (ibuf_size(pdu) != cnt * sizeof(uint32_t))
-		goto badlen;
+	flags = rtr_aspa.hdr.flags;
+	cnt = ibuf_size(pdu) / sizeof(uint32_t);
 
 	if (rs->state != RTR_STATE_EXCHANGE) {
 		rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
@@ -754,12 +757,6 @@ rtr_parse_aspa(struct rtr_session *rs, s
 		return -1;
 	}
 
-	if (rtr_aspa.afi_flags & FLAG_AFI_V6) {
-		aspatree = &rs->aspa_oldv6;
-	} else {
-		aspatree = &rs->aspa;
-	}
-
 	/* treat ASPA records with too many SPAS like a withdraw */
 	if (cnt > MAX_ASPA_SPAS_COUNT) {
 		struct aspa_set needle = { 0 };
@@ -768,9 +765,9 @@ rtr_parse_aspa(struct rtr_session *rs, s
 		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);
+		a = RB_FIND(aspa_tree, &rs->aspa, &needle);
 		if (a != NULL) {
-			RB_REMOVE(aspa_tree, aspatree, a);
+			RB_REMOVE(aspa_tree, &rs->aspa, a);
 			free_aspa(a);
 		}
 		return 0;
@@ -796,13 +793,13 @@ rtr_parse_aspa(struct rtr_session *rs, s
 		}
 	}
 
-	if (rtr_aspa.flags & FLAG_ANNOUNCE) {
-		a = RB_INSERT(aspa_tree, aspatree, aspa);
+	if (flags & FLAG_ANNOUNCE) {
+		a = RB_INSERT(aspa_tree, &rs->aspa, aspa);
 		if (a != NULL) {
-			RB_REMOVE(aspa_tree, aspatree, a);
+			RB_REMOVE(aspa_tree, &rs->aspa, a);
 			free_aspa(a);
 
-			if (RB_INSERT(aspa_tree, aspatree, aspa) != NULL) {
+			if (RB_INSERT(aspa_tree, &rs->aspa, aspa) != NULL) {
 				rtr_send_error(rs, NULL, INTERNAL_ERROR,
 				    "corrupt aspa tree");
 				free_aspa(aspa);
@@ -810,14 +807,14 @@ rtr_parse_aspa(struct rtr_session *rs, s
 			}
 		}
 	} else {
-		a = RB_FIND(aspa_tree, aspatree, aspa);
+		a = RB_FIND(aspa_tree, &rs->aspa, aspa);
 		if (a == NULL) {
 			rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s",
 			    log_rtr_type(ASPA), log_aspa(aspa));
 			free_aspa(aspa);
 			return -1;
 		}
-		RB_REMOVE(aspa_tree, aspatree, a);
+		RB_REMOVE(aspa_tree, &rs->aspa, a);
 		free_aspa(a);
 		free_aspa(aspa);
 	}
@@ -954,7 +951,7 @@ rtr_parse_error(struct rtr_session *rs, 
 
 	if (ibuf_get(pdu, &rh, sizeof(rh)) == -1)
 		goto fail;
-	errcode = ntohs(rh.session_id);
+	errcode = ntohs(rh.errcode);
 
 	if (ibuf_get_n32(pdu, &pdu_len) == -1)
 		goto fail;