From eae25d622d3cdcde5770c8ceeb9257985999cf0b Mon Sep 17 00:00:00 2001 From: Timofei Istomin Date: Fri, 8 May 2015 18:31:06 +0200 Subject: [PATCH] Check the frame preamble and MPDU length before parsing Due to errors in mspsim and/or radio drivers, packets of incorrect length are sometimes transmitted. The length might be larger than the 127-byte maximum (considered negative in the current code) or not matching the actual number of transmitted bytes. This leads to wrong packet delimiting when converting from the mspsim-level stream of bytes to Cooja-level packets causing unhandled exceptions that terminate the simulation. This patch checks the frame preamble (0000007A) and the length field. If they are wrong, no decoding attempt is done. The transmitted bytes are still delivered to the receivers untouched. The connection is terminated when the radio state is changed (which alway s happens when TX is done). --- .../CC2420RadioPacketConverter.java | 2 +- .../mspmote/interfaces/Msp802154Radio.java | 86 +++++++++---------- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/CC2420RadioPacketConverter.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/CC2420RadioPacketConverter.java index fd62da50f..3fda7681d 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/CC2420RadioPacketConverter.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/CC2420RadioPacketConverter.java @@ -165,7 +165,7 @@ public class CC2420RadioPacketConverter { } /* 1 byte length */ - len = data[pos]; + len = data[pos] & 0xFF; originalLen = len; pos += 1; diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java index 18dcffb37..c99710f3d 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java @@ -75,6 +75,7 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { private boolean isInterfered = false; private boolean isTransmitting = false; private boolean isReceiving = false; + private boolean isSynchronized = false; private byte lastOutgoingByte; private byte lastIncomingByte; @@ -91,22 +92,19 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { radio.addRFListener(new RFListener() { int len = 0; - int expLen = 0; - byte[] buffer = new byte[127 + 15]; + int expMpduLen = 0; + byte[] buffer = new byte[127 + 6]; + final private byte[] syncSeq = {0,0,0,0,0x7A}; + public void receivedByte(byte data) { if (!isTransmitting()) { lastEvent = RadioEvent.TRANSMISSION_STARTED; isTransmitting = true; len = 0; - /*logger.debug("----- 802.15.4 TRANSMISSION STARTED -----");*/ + expMpduLen = 0; setChanged(); notifyObservers(); - } - - if (len >= buffer.length) { - /* Bad size packet, too large */ - logger.debug("Error: bad size: " + len + ", dropping outgoing byte: " + data); - return; + /*logger.debug("----- 802.15.4 TRANSMISSION STARTED -----");*/ } /* send this byte to all nodes */ @@ -115,31 +113,40 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { setChanged(); notifyObservers(); - buffer[len++] = data; + if (len < buffer.length) + buffer[len] = data; - if (len == 6) { + len ++; + + if (len == 5) { + isSynchronized = true; + for (int i=0; i<5; i++) { + if (buffer[i] != syncSeq[i]) { + // this should never happen, but it happens + logger.error(String.format("Bad outgoing sync sequence %x %x %x %x %x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4])); + isSynchronized = false; + break; + } + } + } + else if (len == 6) { // System.out.println("## CC2420 Packet of length: " + data + " expected..."); - expLen = data + 6; + expMpduLen = data & 0xFF; + if ((expMpduLen & 0x80) != 0) { + logger.error("Outgoing length field is larger than 127: " + expMpduLen); + } } - if (len == expLen) { - /*logger.debug("----- 802.15.4 CUSTOM DATA TRANSMITTED -----");*/ - + if (((expMpduLen & 0x80) == 0) && len == expMpduLen + 6 && isSynchronized) { lastOutgoingPacket = CC2420RadioPacketConverter.fromCC2420ToCooja(buffer); lastEvent = RadioEvent.PACKET_TRANSMITTED; - /*logger.debug("----- 802.15.4 PACKET TRANSMITTED -----");*/ + //logger.debug("----- 802.15.4 PACKET TRANSMITTED -----"); setChanged(); notifyObservers(); - - /*logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----");*/ - isTransmitting = false; - lastEvent = RadioEvent.TRANSMISSION_FINISHED; - setChanged(); - notifyObservers(); - len = 0; + isSynchronized = false; } } - }); + }); /* addRFListener */ radio.addOperatingModeListener(new OperatingModeListener() { public void modeChanged(Chip source, int mode) { @@ -148,7 +155,7 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { setChanged(); notifyObservers(); } else { - radioOff(); + radioOff(); // actually it is a state change, not necessarily to OFF } } }); @@ -163,32 +170,23 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { }); } - private void radioOff() { - /* Radio was turned off during transmission. - * May for example happen if watchdog triggers */ + + private void finishTransmission() + { if (isTransmitting()) { - logger.warn("Turning off radio while transmitting, ending packet prematurely"); - - /* Simulate end of packet */ - lastOutgoingPacket = new RadioPacket() { - public byte[] getPacketData() { - return new byte[0]; - } - }; - - lastEvent = RadioEvent.PACKET_TRANSMITTED; - /*logger.debug("----- 802.15.4 PACKET TRANSMITTED -----");*/ - setChanged(); - notifyObservers(); - - /* Register that transmission ended in radio medium */ - /*logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----");*/ + //logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----"); isTransmitting = false; + isSynchronized = false; lastEvent = RadioEvent.TRANSMISSION_FINISHED; setChanged(); notifyObservers(); } + } + private void radioOff() { + if (isSynchronized) + logger.warn("Turning off radio while transmitting a packet"); + finishTransmission(); lastEvent = RadioEvent.HW_OFF; setChanged(); notifyObservers();