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 <t...@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)