[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