sicslowpan: when compressing, make sure never to overflow packetbuf with headers
This commit is contained in:
parent
418faf5084
commit
0c9d2b4049
|
@ -97,6 +97,7 @@
|
||||||
|
|
||||||
/* define the buffer as a byte array */
|
/* define the buffer as a byte array */
|
||||||
#define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
|
#define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
|
||||||
|
#define PACKETBUF_PAYLOAD_END ((uint8_t *)(packetbuf_ptr + mac_max_payload))
|
||||||
|
|
||||||
#define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len)
|
#define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len)
|
||||||
#define PACKETBUF_6LO_DISPATCH 0 /* 8 bit */
|
#define PACKETBUF_6LO_DISPATCH 0 /* 8 bit */
|
||||||
|
@ -197,6 +198,11 @@ static int packetbuf_payload_len;
|
||||||
*/
|
*/
|
||||||
static uint8_t uncomp_hdr_len;
|
static uint8_t uncomp_hdr_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mac_max_payload is the maimum payload space on the MAC frame.
|
||||||
|
*/
|
||||||
|
static int mac_max_payload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current page (RFC 4944)
|
* The current page (RFC 4944)
|
||||||
*/
|
*/
|
||||||
|
@ -663,8 +669,9 @@ uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
|
||||||
* compress the IID.
|
* compress the IID.
|
||||||
* \param link_destaddr L2 destination address, needed to compress IP
|
* \param link_destaddr L2 destination address, needed to compress IP
|
||||||
* dest
|
* dest
|
||||||
|
* \return 1 if success, else 0
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
compress_hdr_iphc(linkaddr_t *link_destaddr)
|
compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
{
|
{
|
||||||
uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
|
uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
|
||||||
|
@ -681,7 +688,23 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
LOG_DBG_("\n");
|
LOG_DBG_("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Macro used only internally, during header compression. Checks if there
|
||||||
|
* is sufficient space in packetbuf before writing any further. */
|
||||||
|
#define CHECK_BUFFER_SPACE(writelen) do { \
|
||||||
|
if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \
|
||||||
|
LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \
|
||||||
|
(unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
hc06_ptr = PACKETBUF_IPHC_BUF + 2;
|
hc06_ptr = PACKETBUF_IPHC_BUF + 2;
|
||||||
|
|
||||||
|
/* Check if there is enough space for the compressed IPv6 header, in the
|
||||||
|
* worst case (least compressed case). Extension headers and transport
|
||||||
|
* layer will be checked when they are compressed. */
|
||||||
|
CHECK_BUFFER_SPACE(38);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As we copy some bit-length fields, in the IPHC encoding bytes,
|
* As we copy some bit-length fields, in the IPHC encoding bytes,
|
||||||
* we sometimes use |=
|
* we sometimes use |=
|
||||||
|
@ -910,11 +933,13 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
NHC byte extra - before the next header here. This is due to
|
NHC byte extra - before the next header here. This is due to
|
||||||
next not being elided in that case. */
|
next not being elided in that case. */
|
||||||
if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
|
if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
|
||||||
|
CHECK_BUFFER_SPACE(1);
|
||||||
hc06_ptr++;
|
hc06_ptr++;
|
||||||
LOG_INFO("Keeping the next header in this ext hdr: %d\n",
|
LOG_INFO("Keeping the next header in this ext hdr: %d\n",
|
||||||
ext_hdr->next);
|
ext_hdr->next);
|
||||||
}
|
}
|
||||||
/* copy the ext-hdr into the hc06 buffer */
|
/* copy the ext-hdr into the hc06 buffer */
|
||||||
|
CHECK_BUFFER_SPACE(len);
|
||||||
memcpy(hc06_ptr, ext_hdr, len);
|
memcpy(hc06_ptr, ext_hdr, len);
|
||||||
/* modify the len to octets */
|
/* modify the len to octets */
|
||||||
ext_hdr = (struct uip_ext_hdr *) hc06_ptr;
|
ext_hdr = (struct uip_ext_hdr *) hc06_ptr;
|
||||||
|
@ -944,6 +969,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
/* we can compress 12 bits of both source and dest */
|
/* we can compress 12 bits of both source and dest */
|
||||||
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
|
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
|
||||||
LOG_INFO("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
|
LOG_INFO("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
|
||||||
|
CHECK_BUFFER_SPACE(1);
|
||||||
*hc06_ptr =
|
*hc06_ptr =
|
||||||
(uint8_t)((UIP_HTONS(udp_buf->srcport) -
|
(uint8_t)((UIP_HTONS(udp_buf->srcport) -
|
||||||
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
||||||
|
@ -954,6 +980,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
/* we can compress 8 bits of dest, leave source. */
|
/* we can compress 8 bits of dest, leave source. */
|
||||||
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
|
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
|
||||||
LOG_INFO("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
|
LOG_INFO("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
|
||||||
|
CHECK_BUFFER_SPACE(3);
|
||||||
memcpy(hc06_ptr, &udp_buf->srcport, 2);
|
memcpy(hc06_ptr, &udp_buf->srcport, 2);
|
||||||
*(hc06_ptr + 2) =
|
*(hc06_ptr + 2) =
|
||||||
(uint8_t)((UIP_HTONS(udp_buf->destport) -
|
(uint8_t)((UIP_HTONS(udp_buf->destport) -
|
||||||
|
@ -963,6 +990,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
/* we can compress 8 bits of src, leave dest. Copy compressed port */
|
/* we can compress 8 bits of src, leave dest. Copy compressed port */
|
||||||
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
|
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
|
||||||
LOG_INFO("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
|
LOG_INFO("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
|
||||||
|
CHECK_BUFFER_SPACE(3);
|
||||||
*hc06_ptr =
|
*hc06_ptr =
|
||||||
(uint8_t)((UIP_HTONS(udp_buf->srcport) -
|
(uint8_t)((UIP_HTONS(udp_buf->srcport) -
|
||||||
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
||||||
|
@ -972,10 +1000,12 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
/* we cannot compress. Copy uncompressed ports, full checksum */
|
/* we cannot compress. Copy uncompressed ports, full checksum */
|
||||||
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
|
*next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
|
||||||
LOG_INFO("IPHC: cannot compress UDP headers\n");
|
LOG_INFO("IPHC: cannot compress UDP headers\n");
|
||||||
|
CHECK_BUFFER_SPACE(4);
|
||||||
memcpy(hc06_ptr, &udp_buf->srcport, 4);
|
memcpy(hc06_ptr, &udp_buf->srcport, 4);
|
||||||
hc06_ptr += 4;
|
hc06_ptr += 4;
|
||||||
}
|
}
|
||||||
/* always inline the checksum */
|
/* always inline the checksum */
|
||||||
|
CHECK_BUFFER_SPACE(2);
|
||||||
memcpy(hc06_ptr, &udp_buf->udpchksum, 2);
|
memcpy(hc06_ptr, &udp_buf->udpchksum, 2);
|
||||||
hc06_ptr += 2;
|
hc06_ptr += 2;
|
||||||
uncomp_hdr_len += UIP_UDPH_LEN;
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
||||||
|
@ -1006,6 +1036,8 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
|
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
|
@ -1477,7 +1509,6 @@ static uint8_t
|
||||||
output(const linkaddr_t *localdest)
|
output(const linkaddr_t *localdest)
|
||||||
{
|
{
|
||||||
int framer_hdrlen;
|
int framer_hdrlen;
|
||||||
int max_payload;
|
|
||||||
|
|
||||||
/* The MAC address of the destination of the packet */
|
/* The MAC address of the destination of the packet */
|
||||||
linkaddr_t dest;
|
linkaddr_t dest;
|
||||||
|
@ -1513,6 +1544,20 @@ output(const linkaddr_t *localdest)
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
|
||||||
uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
|
uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
|
||||||
|
|
||||||
|
/* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */
|
||||||
|
#ifndef SICSLOWPAN_USE_FIXED_HDRLEN
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
|
||||||
|
framer_hdrlen = NETSTACK_FRAMER.length();
|
||||||
|
if(framer_hdrlen < 0) {
|
||||||
|
/* Framing failed, we assume the maximum header length */
|
||||||
|
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
||||||
|
}
|
||||||
|
#else /* USE_FRAMER_HDRLEN */
|
||||||
|
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
||||||
|
#endif /* USE_FRAMER_HDRLEN */
|
||||||
|
|
||||||
|
mac_max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
||||||
|
|
||||||
/* Try to compress the headers */
|
/* Try to compress the headers */
|
||||||
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
|
||||||
compress_hdr_ipv6(&dest);
|
compress_hdr_ipv6(&dest);
|
||||||
|
@ -1526,26 +1571,14 @@ output(const linkaddr_t *localdest)
|
||||||
}
|
}
|
||||||
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
|
||||||
#if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
|
#if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
|
||||||
compress_hdr_iphc(&dest);
|
if(compress_hdr_iphc(&dest) == 0) {
|
||||||
|
/* Warning should already be issued by function above */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
|
#endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
|
||||||
LOG_INFO("output: header of len %d\n", packetbuf_hdr_len);
|
LOG_INFO("output: header of len %d\n", packetbuf_hdr_len);
|
||||||
|
|
||||||
/* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC.
|
if((int)uip_len - (int)uncomp_hdr_len > mac_max_payload - (int)packetbuf_hdr_len) {
|
||||||
* We calculate it here only to make a better decision of whether the outgoing packet
|
|
||||||
* needs to be fragmented or not. */
|
|
||||||
#ifndef SICSLOWPAN_USE_FIXED_HDRLEN
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
|
|
||||||
framer_hdrlen = NETSTACK_FRAMER.length();
|
|
||||||
if(framer_hdrlen < 0) {
|
|
||||||
/* Framing failed, we assume the maximum header length */
|
|
||||||
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
|
||||||
}
|
|
||||||
#else /* USE_FRAMER_HDRLEN */
|
|
||||||
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
|
||||||
#endif /* USE_FRAMER_HDRLEN */
|
|
||||||
|
|
||||||
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
|
||||||
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
|
|
||||||
#if SICSLOWPAN_CONF_FRAG
|
#if SICSLOWPAN_CONF_FRAG
|
||||||
/* Number of bytes processed. */
|
/* Number of bytes processed. */
|
||||||
uint16_t processed_ip_out_len;
|
uint16_t processed_ip_out_len;
|
||||||
|
@ -1560,7 +1593,7 @@ output(const linkaddr_t *localdest)
|
||||||
* IPv6/IPHC/HC_UDP dispatchs/headers.
|
* IPv6/IPHC/HC_UDP dispatchs/headers.
|
||||||
* The following fragments contain only the fragn dispatch.
|
* The following fragments contain only the fragn dispatch.
|
||||||
*/
|
*/
|
||||||
int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
|
int estimated_fragments = ((int)uip_len) / (mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
|
||||||
int freebuf = queuebuf_numfree() - 1;
|
int freebuf = queuebuf_numfree() - 1;
|
||||||
LOG_INFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
|
LOG_INFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
|
||||||
if(freebuf < estimated_fragments) {
|
if(freebuf < estimated_fragments) {
|
||||||
|
@ -1590,7 +1623,7 @@ output(const linkaddr_t *localdest)
|
||||||
|
|
||||||
/* Copy payload and send */
|
/* Copy payload and send */
|
||||||
packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
||||||
packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
packetbuf_payload_len = (mac_max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
||||||
LOG_INFO_("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag);
|
LOG_INFO_("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag);
|
||||||
memcpy(packetbuf_ptr + packetbuf_hdr_len,
|
memcpy(packetbuf_ptr + packetbuf_hdr_len,
|
||||||
(uint8_t *)UIP_IP_BUF + uncomp_hdr_len, packetbuf_payload_len);
|
(uint8_t *)UIP_IP_BUF + uncomp_hdr_len, packetbuf_payload_len);
|
||||||
|
@ -1626,7 +1659,7 @@ output(const linkaddr_t *localdest)
|
||||||
/* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
|
/* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
|
||||||
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
|
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
|
||||||
((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
|
((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
|
||||||
packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
packetbuf_payload_len = (mac_max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
||||||
while(processed_ip_out_len < uip_len) {
|
while(processed_ip_out_len < uip_len) {
|
||||||
LOG_INFO("output: fragment ");
|
LOG_INFO("output: fragment ");
|
||||||
PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
|
PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
|
||||||
|
|
Loading…
Reference in New Issue