[PATCH RFC 1/2] babel: Define helper macro for looping through TLVs
Toke Høiland-Jørgensen
toke at toke.dk
Fri Jul 13 22:16:16 CEST 2018
Since we have several places where we loop over a TLV stream, define a
helper macro to deal with framing checks and looping.
Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
proto/babel/packets.c | 64 ++++++++++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 30 deletions(-)
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index d4ecf649..9c767874 100644
--- a/proto/babel/packets.c
+++ b/proto/babel/packets.c
@@ -167,6 +167,30 @@ struct babel_write_state {
#define NET_SIZE(n) BYTES(net_pxlen(n))
+
+/* Helper macros to loop over a series of TLVs.
+ * @start pointer to first TLV
+ * @end byte * pointer to TLV stream end
+ * @tlv struct babel_tlv pointer used as iterator
+ */
+#define LOOP_TLVS(start, end, tlv) \
+ for (tlv = (void *)start; \
+ (byte *)tlv < end; \
+ tlv = NEXT_TLV(tlv)) \
+ { \
+ byte *loop_pos; \
+ /* Ugly special case */ \
+ if (tlv->type == BABEL_TLV_PAD1) \
+ continue; \
+ \
+ /* The end of the common TLV header */ \
+ loop_pos = (byte *)tlv + sizeof(struct babel_tlv); \
+ if ((loop_pos > end) || (loop_pos + tlv->length > end)) \
+ goto frame_err; \
+
+#define LOOP_TLVS_END }
+
+
static inline uint
bytes_equal(u8 *b1, u8 *b2, uint maxlen)
{
@@ -1090,22 +1114,11 @@ babel_read_subtlvs(struct babel_tlv *hdr,
struct babel_parse_state *state)
{
struct babel_tlv *tlv;
- byte *pos, *end = (byte *) hdr + TLV_LENGTH(hdr);
+ byte *end = (byte *) hdr + TLV_LENGTH(hdr);
int res;
- for (tlv = (void *) hdr + state->current_tlv_endpos;
- (byte *) tlv < end;
- tlv = NEXT_TLV(tlv))
+ LOOP_TLVS(hdr + state->current_tlv_endpos, end, tlv)
{
- /* Ugly special case */
- if (tlv->type == BABEL_TLV_PAD1)
- continue;
-
- /* The end of the common TLV header */
- pos = (byte *)tlv + sizeof(struct babel_tlv);
- if ((pos > end) || (pos + tlv->length > end))
- return PARSE_ERROR;
-
/*
* The subtlv type space is non-contiguous (due to the mandatory bit), so
* use a switch for dispatch instead of the mapping array we use for TLVs
@@ -1126,8 +1139,12 @@ babel_read_subtlvs(struct babel_tlv *hdr,
break;
}
}
+ LOOP_TLVS_END;
return PARSE_SUCCESS;
+
+frame_err:
+ return PARSE_ERROR;
}
static inline int
@@ -1337,7 +1354,6 @@ babel_process_packet(struct babel_pkt_header *pkt, int len,
int res;
int plen = sizeof(struct babel_pkt_header) + get_u16(&pkt->length);
- byte *pos;
byte *end = (byte *)pkt + plen;
struct babel_parse_state state = {
@@ -1369,23 +1385,8 @@ babel_process_packet(struct babel_pkt_header *pkt, int len,
/* First pass through the packet TLV by TLV, parsing each into internal data
structures. */
- for (tlv = FIRST_TLV(pkt);
- (byte *)tlv < end;
- tlv = NEXT_TLV(tlv))
+ LOOP_TLVS(FIRST_TLV(pkt), end, tlv)
{
- /* Ugly special case */
- if (tlv->type == BABEL_TLV_PAD1)
- continue;
-
- /* The end of the common TLV header */
- pos = (byte *)tlv + sizeof(struct babel_tlv);
- if ((pos > end) || (pos + tlv->length > end))
- {
- LOG_PKT("Bad TLV from %I via %s type %d pos %d - framing error",
- saddr, ifa->iface->name, tlv->type, (byte *)tlv - (byte *)pkt);
- break;
- }
-
msg = sl_alloc(p->msg_slab);
res = babel_read_tlv(tlv, &msg->msg, &state);
if (res == PARSE_SUCCESS)
@@ -1405,6 +1406,9 @@ babel_process_packet(struct babel_pkt_header *pkt, int len,
break;
}
}
+ LOOP_TLVS_END;
+
+frame_err:
/* Parsing done, handle all parsed TLVs */
WALK_LIST_FIRST(msg, msgs)
More information about the Bird-users
mailing list