Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: rde ibuf parser part 3
To:
tech@openbsd.org
Date:
Wed, 24 Jan 2024 15:43:29 +0100

Download raw body.

Thread
This switches IMSG_CTL_SHOW_RIB_COMMUNITIES over to use ibufs in bgpctl.
This converts some of the community code in bgpctl but not all. The
reminder will follow at a later stage. Those code paths are only used by
the mrt parser.

This big change is how fmt_ext_community() works. It now just operates on
a uint64_t instead of passing in unchecked pointers.
-- 
:wq Claudio

Index: bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
diff -u -p -r1.301 bgpctl.c
--- bgpctl.c	23 Jan 2024 16:16:15 -0000	1.301
+++ bgpctl.c	24 Jan 2024 14:36:48 -0000
@@ -470,6 +470,7 @@ show(struct imsg *imsg, struct parse_res
 	struct flowspec		 f;
 	struct ctl_show_rib	 rib;
 	struct rde_memstats	 stats;
+	struct ibuf		 ibuf;
 	u_char			*asdata;
 	u_int			 rescode, ilen;
 	size_t			 aslen;
@@ -539,14 +540,11 @@ show(struct imsg *imsg, struct parse_res
 		output->rib(&rib, asdata, aslen, res);
 		break;
 	case IMSG_CTL_SHOW_RIB_COMMUNITIES:
-		ilen = imsg->hdr.len - IMSG_HEADER_SIZE;
-		if (ilen % sizeof(struct community)) {
-			warnx("bad IMSG_CTL_SHOW_RIB_COMMUNITIES received");
-			break;
-		}
 		if (output->communities == NULL)
 			break;
-		output->communities(imsg->data, ilen, res);
+		if (imsg_get_ibuf(imsg, &ibuf) == -1)
+			err(1, "imsg_get_ibuf");
+		output->communities(&ibuf, res);
 		break;
 	case IMSG_CTL_SHOW_RIB_ATTR:
 		ilen = imsg->hdr.len - IMSG_HEADER_SIZE;
@@ -1044,53 +1042,47 @@ fmt_large_community(uint32_t d1, uint32_
 }
 
 const char *
-fmt_ext_community(uint8_t *data)
+fmt_ext_community(uint64_t ext)
 {
 	static char	buf[32];
-	uint64_t	ext;
 	struct in_addr	ip;
 	uint32_t	as4, u32;
 	uint16_t	as2, u16;
 	uint8_t		type, subtype;
 
-	type = data[0];
-	subtype = data[1];
+	type = ext >> 56;
+	subtype = ext >> 48;
 
 	switch (type) {
 	case EXT_COMMUNITY_TRANS_TWO_AS:
 	case EXT_COMMUNITY_GEN_TWO_AS:
-		memcpy(&as2, data + 2, sizeof(as2));
-		memcpy(&u32, data + 4, sizeof(u32));
+		as2 = ext >> 32;
+		u32 = ext;
 		snprintf(buf, sizeof(buf), "%s %s:%u",
-		    log_ext_subtype(type, subtype),
-		    log_as(ntohs(as2)), ntohl(u32));
+		    log_ext_subtype(type, subtype), log_as(as2), u32);
 		return buf;
 	case EXT_COMMUNITY_TRANS_IPV4:
 	case EXT_COMMUNITY_GEN_IPV4:
-		memcpy(&ip, data + 2, sizeof(ip));
-		memcpy(&u16, data + 6, sizeof(u16));
+		ip.s_addr = ext >> 16;
+		u16 = ext;
 		snprintf(buf, sizeof(buf), "%s %s:%hu",
-		    log_ext_subtype(type, subtype),
-		    inet_ntoa(ip), ntohs(u16));
+		    log_ext_subtype(type, subtype), inet_ntoa(ip), u16);
 		return buf;
 	case EXT_COMMUNITY_TRANS_FOUR_AS:
 	case EXT_COMMUNITY_GEN_FOUR_AS:
-		memcpy(&as4, data + 2, sizeof(as4));
-		memcpy(&u16, data + 6, sizeof(u16));
+		as4 = ext >> 16;
+		u16 = ext;
 		snprintf(buf, sizeof(buf), "%s %s:%hu",
-		    log_ext_subtype(type, subtype),
-		    log_as(ntohl(as4)), ntohs(u16));
+		    log_ext_subtype(type, subtype), log_as(as4), u16);
 		return buf;
 	case EXT_COMMUNITY_TRANS_OPAQUE:
 	case EXT_COMMUNITY_TRANS_EVPN:
-		memcpy(&ext, data, sizeof(ext));
-		ext = be64toh(ext) & 0xffffffffffffLL;
+		ext &= 0xffffffffffffULL;
 		snprintf(buf, sizeof(buf), "%s 0x%llx",
 		    log_ext_subtype(type, subtype), (unsigned long long)ext);
 		return buf;
 	case EXT_COMMUNITY_NON_TRANS_OPAQUE:
-		memcpy(&ext, data, sizeof(ext));
-		ext = be64toh(ext) & 0xffffffffffffLL;
+		ext &= 0xffffffffffffULL;
 		if (subtype == EXT_COMMUNITY_SUBTYPE_OVS) {
 			switch (ext) {
 			case EXT_COMMUNITY_OVS_VALID:
@@ -1119,10 +1111,10 @@ fmt_ext_community(uint8_t *data)
 		}
 		break;
 	default:
-		memcpy(&ext, data, sizeof(ext));
+		ext &= 0xffffffffffffULL;
 		snprintf(buf, sizeof(buf), "%s 0x%llx",
 		    log_ext_subtype(type, subtype),
-		    (unsigned long long)be64toh(ext));
+		    (unsigned long long)ext);
 		return buf;
 	}
 }
Index: bgpctl.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
diff -u -p -r1.21 bgpctl.h
--- bgpctl.h	20 Apr 2023 14:01:50 -0000	1.21
+++ bgpctl.h	24 Jan 2024 14:24:40 -0000
@@ -28,7 +28,7 @@ struct output {
 	void	(*nexthop)(struct ctl_show_nexthop *);
 	void	(*interface)(struct ctl_show_interface *);
 	void	(*attr)(u_char *, size_t, int, int);
-	void	(*communities)(u_char *, size_t, struct parse_result *);
+	void	(*communities)(struct ibuf *, struct parse_result *);
 	void	(*rib)(struct ctl_show_rib *, u_char *, size_t,
 		    struct parse_result *);
 	void	(*rib_mem)(struct rde_memstats *);
@@ -57,7 +57,7 @@ const char	*fmt_errstr(uint8_t, uint8_t)
 const char	*fmt_attr(uint8_t, int);
 const char	*fmt_community(uint16_t, uint16_t);
 const char	*fmt_large_community(uint32_t, uint32_t, uint32_t);
-const char	*fmt_ext_community(uint8_t *);
+const char	*fmt_ext_community(uint64_t);
 const char	*fmt_set_type(struct ctl_show_set *);
 
 #define MPLS_LABEL_OFFSET 12
Index: output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
diff -u -p -r1.47 output.c
--- output.c	23 Jan 2024 16:16:15 -0000	1.47
+++ output.c	24 Jan 2024 14:37:02 -0000
@@ -646,18 +646,17 @@ show_interface(struct ctl_show_interface
 }
 
 static void
-show_communities(u_char *data, size_t len, struct parse_result *res)
+show_communities(struct ibuf *data, struct parse_result *res)
 {
 	struct community c;
-	size_t	i;
 	uint64_t ext;
 	uint8_t type = 0;
 
-	if (len % sizeof(c))
-		return;
-
-	for (i = 0; i < len; i += sizeof(c)) {
-		memcpy(&c, data + i, sizeof(c));
+	while (ibuf_size(data) != 0) {
+		if (ibuf_get(data, &c, sizeof(c)) == -1) {
+			warn("communities");
+			break;
+		}
 
 		if (type != c.flags) {
 			if (type != 0)
@@ -690,9 +689,7 @@ show_communities(u_char *data, size_t le
 				ext |= (uint64_t)c.data2 & 0xffff;
 				break;
 			}
-			ext = htobe64(ext);
-
-			printf(" %s", fmt_ext_community((void *)&ext));
+			printf(" %s", fmt_ext_community(ext));
 			break;
 		}
 	}
@@ -751,6 +748,7 @@ show_large_community(u_char *data, uint1
 static void
 show_ext_community(u_char *data, uint16_t len)
 {
+	uint64_t	ext;
 	uint16_t	i;
 
 	if (len & 0x7) {
@@ -759,7 +757,9 @@ show_ext_community(u_char *data, uint16_
 	}
 
 	for (i = 0; i < len; i += 8) {
-		printf("%s", fmt_ext_community(data + i));
+		memcpy(&ext, data + i, sizeof(ext));
+		ext = be64toh(ext);
+		printf("%s", fmt_ext_community(ext));
 
 		if (i + 8 < len)
 			printf(" ");
Index: output_json.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output_json.c,v
diff -u -p -r1.39 output_json.c
--- output_json.c	23 Jan 2024 16:16:15 -0000	1.39
+++ output_json.c	24 Jan 2024 14:37:12 -0000
@@ -465,19 +465,17 @@ json_interface(struct ctl_show_interface
 }
 
 static void
-json_communities(u_char *data, size_t len, struct parse_result *res)
+json_communities(struct ibuf *data, struct parse_result *res)
 {
 	struct community c;
-	size_t  i;
 	uint64_t ext;
 
-	if (len % sizeof(c)) {
-		warnx("communities: bad size");
-		return;
-	}
 
-	for (i = 0; i < len; i += sizeof(c)) {
-		memcpy(&c, data + i, sizeof(c));
+	while (ibuf_size(data) != 0) {
+		if (ibuf_get(data, &c, sizeof(c)) == -1) {
+			warn("communities");
+			return;
+		}
 
 		switch (c.flags) {
 		case COMMUNITY_TYPE_BASIC:
@@ -505,11 +503,9 @@ json_communities(u_char *data, size_t le
 				ext |= (uint64_t)c.data2 & 0xffff;
 				break;
 			}
-			ext = htobe64(ext);
 
 			json_do_array("extended_communities");
-			json_do_string("community",
-			    fmt_ext_community((void *)&ext));
+			json_do_string("community", fmt_ext_community(ext));
 			break;
 		}
 	}
@@ -569,6 +565,7 @@ json_do_large_community(u_char *data, ui
 static void
 json_do_ext_community(u_char *data, uint16_t len)
 {
+	uint64_t ext;
 	uint16_t i;
 
 	if (len & 0x7) {
@@ -578,8 +575,11 @@ json_do_ext_community(u_char *data, uint
 
 	json_do_array("extended_communities");
 
-	for (i = 0; i < len; i += 8)
-		json_do_string("community", fmt_ext_community(data + i));
+	for (i = 0; i < len; i += 8) {
+		memcpy(&ext, data + i, sizeof(ext));
+		ext = be64toh(ext);
+		json_do_string("community", fmt_ext_community(ext));
+	}
 
 	json_do_end();
 }