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).
This commit is contained in:
Timofei Istomin 2015-05-08 18:31:06 +02:00
parent df2cdbbd79
commit eae25d622d
2 changed files with 43 additions and 45 deletions

View File

@ -165,7 +165,7 @@ public class CC2420RadioPacketConverter {
}
/* 1 byte length */
len = data[pos];
len = data[pos] & 0xFF;
originalLen = len;
pos += 1;

View File

@ -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();