From 3efa84ecc81e6b925e67350e82a8441f3931c45b Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sun, 17 Mar 2013 23:55:01 +0100 Subject: [PATCH] New mechanism for computing the 6lowpan header length dynamically, depending on how large header the framer creates. Also check the incoming packet for buffer overflow. --- core/net/sicslowpan.c | 46 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/core/net/sicslowpan.c b/core/net/sicslowpan.c index 2bb94574f..1f196c304 100644 --- a/core/net/sicslowpan.c +++ b/core/net/sicslowpan.c @@ -163,7 +163,11 @@ void uip_log(char *msg); /** \brief Size of the 802.15.4 payload (127byte - 25 for MAC header) */ +#ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD +#define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD +#else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ #define MAC_MAX_PAYLOAD 102 +#endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ /** \brief Some MAC layers need a minimum payload, which is @@ -1355,6 +1359,8 @@ send_packet(rimeaddr_t *dest) static uint8_t output(uip_lladdr_t *localdest) { + int framer_hdrlen; + /* The MAC address of the destination of the packet */ rimeaddr_t dest; @@ -1422,7 +1428,24 @@ output(uip_lladdr_t *localdest) } PRINTFO("sicslowpan output: header of len %d\n", rime_hdr_len); - if(uip_len - uncomp_hdr_len > MAC_MAX_PAYLOAD - rime_hdr_len) { + /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC. + * We calculate it here only to make a better decision of whether the outgoing packet + * needs to be fragmented or not. */ +#define USE_FRAMER_HDRLEN 1 +#if USE_FRAMER_HDRLEN + packetbuf_clear(); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); + framer_hdrlen = NETSTACK_FRAMER.create(); + if(framer_hdrlen < 0) { + /* Framing failed, we assume the maximum header length */ + framer_hdrlen = 21; + } + packetbuf_clear(); +#else /* USE_FRAMER_HDRLEN */ + framer_hdrlen = 21; +#endif /* USE_FRAMER_HDRLEN */ + + if((int)uip_len - (int)uncomp_hdr_len > (int)MAC_MAX_PAYLOAD - framer_hdrlen - (int)rime_hdr_len) { #if SICSLOWPAN_CONF_FRAG struct queuebuf *q; /* @@ -1434,7 +1457,7 @@ output(uip_lladdr_t *localdest) */ PRINTFO("Fragmentation sending packet len %d\n", uip_len); - + /* Create 1st Fragment */ PRINTFO("sicslowpan output: 1rst fragment "); @@ -1455,7 +1478,7 @@ output(uip_lladdr_t *localdest) /* Copy payload and send */ rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN; - rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8; + rime_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - rime_hdr_len) & 0xf8; PRINTFO("(len %d, tag %d)\n", rime_payload_len, my_tag); memcpy(rime_ptr + rime_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len, rime_payload_len); @@ -1491,7 +1514,7 @@ output(uip_lladdr_t *localdest) /* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */ SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len)); - rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8; + rime_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - rime_hdr_len) & 0xf8; while(processed_ip_out_len < uip_len) { PRINTFO("sicslowpan output: fragment "); RIME_FRAG_PTR[RIME_FRAG_OFFSET] = processed_ip_out_len >> 3; @@ -1530,6 +1553,7 @@ output(uip_lladdr_t *localdest) return 0; #endif /* SICSLOWPAN_CONF_FRAG */ } else { + /* * The packet does not need to be fragmented * copy "payload" and send @@ -1709,6 +1733,20 @@ input(void) return; } rime_payload_len = packetbuf_datalen() - rime_hdr_len; + + /* Sanity-check size of incoming packet to avoid buffer overflow */ + { + int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3) + + rime_payload_len; + if(req_size > sizeof(sicslowpan_buf)) { + PRINTF( + "SICSLOWPAN: packet dropped, minimum required SICSLOWPAN_IP_BUF size: %d+%d+%d+%d=%d (current size: %d)\n", + UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3), + rime_payload_len, req_size, sizeof(sicslowpan_buf)); + return; + } + } + memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), rime_ptr + rime_hdr_len, rime_payload_len); /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */