From 7db978ca035907c2b59b3046225c6d0b783e6389 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Mon, 26 Feb 2018 21:47:24 +0100 Subject: [PATCH] lowpan6.c: rework lowpan6_input processing of the ieee 802.15.4 header This should fix bug #48825 (lowpan6: source PAN ID is skipped without checking PAN ID compression flag) --- src/netif/lowpan6.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/netif/lowpan6.c b/src/netif/lowpan6.c index 3eaf0576..a043d85b 100644 --- a/src/netif/lowpan6.c +++ b/src/netif/lowpan6.c @@ -1025,10 +1025,24 @@ lowpan6_input(struct pbuf *p, struct netif *netif) MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - /* Analyze header. @todo validate. */ + if (p->len != p->tot_len) { + /* for now, this needs a pbuf in one piece */ + goto lowpan6_input_discard; + } + + /* Parse IEEE 802.15.4 header */ puc = (u8_t *)p->payload; frame_control = puc[0] | (puc[1] << 8); - datagram_offset = 5; + datagram_offset = 2; + if (frame_control & IEEE_802154_FC_SEQNO_SUPPR) { + if (IEEE_802154_FC_FRAME_VERSION_GET(frame_control) <= 1) { + /* sequence number suppressed, this is not valid for versions 0/1 */ + goto lowpan6_input_discard; + } + } else { + datagram_offset++; + } + datagram_offset += 2; /* Skip destination PAN ID */ addr_mode = frame_control & IEEE_802154_FC_DST_ADDR_MODE_MASK; if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_EXT) { /* extended address (64 bit) */ @@ -1038,16 +1052,22 @@ lowpan6_input(struct pbuf *p, struct netif *netif) dest.addr[i] = puc[datagram_offset + 7 - i]; } datagram_offset += 8; - } else { + } else if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_SHORT) { /* short address (16 bit) */ dest.addr_len = 2; /* reverse memcpy: */ dest.addr[0] = puc[datagram_offset + 1]; dest.addr[1] = puc[datagram_offset]; datagram_offset += 2; + } else { + /* unsupported address mode */ + goto lowpan6_input_discard; } - datagram_offset += 2; /* skip PAN ID. */ + if (!(frame_control & IEEE_802154_FC_PANID_COMPR)) { + /* No PAN ID compression, skip source PAN ID */ + datagram_offset += 2; + } addr_mode = frame_control & IEEE_802154_FC_SRC_ADDR_MODE_MASK; if (addr_mode == IEEE_802154_FC_SRC_ADDR_MODE_EXT) { @@ -1058,16 +1078,21 @@ lowpan6_input(struct pbuf *p, struct netif *netif) src.addr[i] = puc[datagram_offset + 7 - i]; } datagram_offset += 8; - } else { + } else if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_SHORT) { /* short address (16 bit) */ src.addr_len = 2; - /* reverse memcpy: */ src.addr[0] = puc[datagram_offset + 1]; src.addr[1] = puc[datagram_offset]; datagram_offset += 2; + } else { + /* unsupported address mode */ + goto lowpan6_input_discard; } - pbuf_remove_header(p, datagram_offset); /* hide IEEE802.15.4 header. */ + /* hide IEEE802.15.4 header. */ + if (pbuf_remove_header(p, datagram_offset)) { + goto lowpan6_input_discard; + } /* Check dispatch. */ puc = (u8_t *)p->payload;