From 6d9f904627e3cf4c7f11f9ac0aa3e4ae95157141 Mon Sep 17 00:00:00 2001 From: nifi Date: Tue, 6 Apr 2010 23:38:18 +0000 Subject: [PATCH] Minor cleanup of the radio logger output (packet description). --- .../se/sics/cooja/plugins/RadioLogger.java | 17 +- .../plugins/analyzers/ICMPv6Analyzer.java | 171 ++-- .../plugins/analyzers/IPHCPacketAnalyzer.java | 854 +++++++++--------- 3 files changed, 523 insertions(+), 519 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java b/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java index d38142aa9..d0af04e0f 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java +++ b/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: RadioLogger.java,v 1.34 2010/03/17 22:44:20 nifi Exp $ + * $Id: RadioLogger.java,v 1.35 2010/04/06 23:38:18 nifi Exp $ */ package se.sics.cooja.plugins; @@ -266,6 +266,7 @@ public class RadioLogger extends VisPlugin { prepareTooltipString(conn); } verboseBox.setText(conn.tooltip); + verboseBox.setCaretPosition(0); } } }); @@ -427,12 +428,16 @@ public class RadioLogger extends VisPlugin { if (packet.hasMoreData()) { byte[] payload = packet.getPayload(); brief.append(StringUtils.toHex(payload, 4)); + if (verbose.length() > 0) { + verbose.append("

"); + } verbose.append("Payload (") .append(payload.length).append(" bytes)

")
             .append(StringUtils.hexDump(payload))
             .append("
"); } - conn.data = (data.length < 10 ? " " : "") + data.length + ": " + brief; + conn.data = (data.length < 100 ? (data.length < 10 ? " " : " ") : "") + + data.length + ": " + brief; if (verbose.length() > 0) { conn.tooltip = verbose.toString(); } @@ -450,16 +455,16 @@ public class RadioLogger extends VisPlugin { PacketAnalyzer analyzer = analyzers.get(i); if (analyzer.matchPacket(packet)) { int res = analyzer.analyzePacket(packet, brief, verbose); + if (packet.hasMoreData() && brief.length() > 0) { + brief.append('|'); + verbose.append("
"); + } if (res != PacketAnalyzer.ANALYSIS_OK_CONTINUE) { /* this was the final or the analysis failed - no analyzable payload possible here... */ return brief.length() > 0; } /* continue another round if more bytes left */ analyze = packet.hasMoreData(); - if (analyze) { - brief.append('|'); - verbose.append("

"); - } break; } } diff --git a/tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java b/tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java index 358534b29..1260d8c1d 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java @@ -1,86 +1,85 @@ -package se.sics.cooja.plugins.analyzers; - -public class ICMPv6Analyzer extends PacketAnalyzer { - - public static final byte ICMPv6_DISPATCH = 58; - - public static final int ECHO_REQUEST = 128; - public static final int ECHO_REPLY = 129; - public static final int GROUP_QUERY = 130; - public static final int GROUP_REPORT = 131; - public static final int GROUP_REDUCTION = 132; - public static final int ROUTER_SOLICITATION = 133; - public static final int ROUTER_ADVERTISEMENT = 134; - public static final int NEIGHBOR_SOLICITATION = 135; - public static final int NEIGHBOR_ADVERTISEMENT = 136; - - public static final int RPL_CODE_DIS = 1; /* DIS message */ - public static final int RPL_CODE_DIO = 2; /* DIO message */ - public static final int RPL_CODE_DAO = 4;/* DAO message */ - - public static final int FLAG_ROUTER = 0x80; - public static final int FLAG_SOLICITED = 0x40; - public static final int FLAG_OVERRIDE = 0x20; - - public static final int ON_LINK = 0x80; - public static final int AUTOCONFIG = 0x40; - - public static final int SOURCE_LINKADDR = 1; - public static final int TARGET_LINKADDR = 2; - public static final int PREFIX_INFO = 3; - public static final int MTU_INFO = 5; - - public static final String[] TYPE_NAME = new String[] { - "ECHO_REQUEST", "ECHO_REPLY", - "GROUP_QUERY", "GROUP_REPORT", "GROUP_REDUCTION", - "ROUTER_SOLICITATION", "ROUTER_ADVERTISEMENT", - "NEIGHBOR_SOLICITATION", "NEIGHBOR_ADVERTISEMENT", "REDIRECT", - "ROUTER RENUMBER", "NODE INFORMATION QUERY", "NODE INFORMATION RESPONSE"}; - - - public int analyzePacket(Packet packet, StringBuffer brief, - StringBuffer verbose) { - int type = packet.get(0) & 0xff; - int code = packet.get(1) & 0xff; - int checksum = ((packet.get(2) & 0xff) << 8) | packet.get(3) & 0xff; - - brief.append("ICMPv6 "); - if (type >= 128 && (type - 128) < TYPE_NAME.length) { - brief.append(TYPE_NAME[type - 128]).append(" "); - brief.append(" " + code); - verbose.append("Type: " + TYPE_NAME[type - 128]).append("
"); - verbose.append("Code:" + code + "
"); - } else if (type == 155) { - /* RPL */ - brief.append("RPL "); - verbose.append("Type: RPL
"); - switch(code) { - case RPL_CODE_DIS: - brief.append("DIS "); - verbose.append("Code: DIS
"); - break; - case RPL_CODE_DIO: - brief.append("DIO "); - verbose.append("Code: DIO
"); - break; - case RPL_CODE_DAO: - brief.append("DAO "); - verbose.append("Code: DAO
"); - break; - default: - brief.append(" " + code); - verbose.append("Code: " + code); - } - } - - /* remove type, code, crc */ - packet.consumeBytesStart(4); - return ANALYSIS_OK_FINAL; - } - - @Override - public boolean matchPacket(Packet packet) { - return packet.level == NETWORK_LEVEL && packet.lastDispatch == ICMPv6_DISPATCH; - } - -} +package se.sics.cooja.plugins.analyzers; + +public class ICMPv6Analyzer extends PacketAnalyzer { + + public static final byte ICMPv6_DISPATCH = 58; + + public static final int ECHO_REQUEST = 128; + public static final int ECHO_REPLY = 129; + public static final int GROUP_QUERY = 130; + public static final int GROUP_REPORT = 131; + public static final int GROUP_REDUCTION = 132; + public static final int ROUTER_SOLICITATION = 133; + public static final int ROUTER_ADVERTISEMENT = 134; + public static final int NEIGHBOR_SOLICITATION = 135; + public static final int NEIGHBOR_ADVERTISEMENT = 136; + + public static final int RPL_CODE_DIS = 1; /* DIS message */ + public static final int RPL_CODE_DIO = 2; /* DIO message */ + public static final int RPL_CODE_DAO = 4;/* DAO message */ + + public static final int FLAG_ROUTER = 0x80; + public static final int FLAG_SOLICITED = 0x40; + public static final int FLAG_OVERRIDE = 0x20; + + public static final int ON_LINK = 0x80; + public static final int AUTOCONFIG = 0x40; + + public static final int SOURCE_LINKADDR = 1; + public static final int TARGET_LINKADDR = 2; + public static final int PREFIX_INFO = 3; + public static final int MTU_INFO = 5; + + public static final String[] TYPE_NAME = new String[] { + "ECHO_REQUEST", "ECHO_REPLY", + "GROUP_QUERY", "GROUP_REPORT", "GROUP_REDUCTION", + "ROUTER_SOLICITATION", "ROUTER_ADVERTISEMENT", + "NEIGHBOR_SOLICITATION", "NEIGHBOR_ADVERTISEMENT", "REDIRECT", + "ROUTER RENUMBER", "NODE INFORMATION QUERY", "NODE INFORMATION RESPONSE"}; + + + public int analyzePacket(Packet packet, StringBuffer brief, + StringBuffer verbose) { + int type = packet.get(0) & 0xff; + int code = packet.get(1) & 0xff; +// int checksum = ((packet.get(2) & 0xff) << 8) | packet.get(3) & 0xff; + + brief.append("ICMPv6 "); + if (type >= 128 && (type - 128) < TYPE_NAME.length) { + brief.append(TYPE_NAME[type - 128]).append(' ').append(code); + verbose.append("Type: ").append(TYPE_NAME[type - 128]); + verbose.append(" Code:").append(code); + } else if (type == 155) { + /* RPL */ + brief.append("RPL "); + verbose.append("Type: RPL Code: "); + switch(code) { + case RPL_CODE_DIS: + brief.append("DIS"); + verbose.append("DIS"); + break; + case RPL_CODE_DIO: + brief.append("DIO"); + verbose.append("DIO"); + break; + case RPL_CODE_DAO: + brief.append("DAO"); + verbose.append("DAO"); + break; + default: + brief.append(code); + verbose.append(code); + } + } + + /* remove type, code, crc */ + packet.consumeBytesStart(4); + return ANALYSIS_OK_FINAL; + } + + @Override + public boolean matchPacket(Packet packet) { + return packet.level == NETWORK_LEVEL && packet.lastDispatch == ICMPv6_DISPATCH; + } + +} diff --git a/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java b/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java index faa34c109..6e1332146 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java @@ -1,427 +1,427 @@ -package se.sics.cooja.plugins.analyzers; - -import se.sics.cooja.util.StringUtils; - -public class IPHCPacketAnalyzer extends PacketAnalyzer { - - public final static int SICSLOWPAN_UDP_PORT_MIN = 0xF0B0; - public final static int SICSLOWPAN_UDP_PORT_MAX = 0xF0BF; /* F0B0 + 15 */ - - public final static int SICSLOWPAN_DISPATCH_IPV6 = 0x41; /* 01000001 = 65 */ - public final static int SICSLOWPAN_DISPATCH_HC1 = 0x42; /* 01000010 = 66 */ - public final static int SICSLOWPAN_DISPATCH_IPHC = 0x60; /* 011xxxxx = ... */ - public final static int SICSLOWPAN_DISPATCH_FRAG1 = 0xc0; /* 1100= 0xxx */ - public final static int SICSLOWPAN_DISPATCH_FRAGN = 0xe0; /* 1110= 0xxx */ - - /* - * Values of fields within the IPHC encoding first byte - * (C stands for compressed and I for inline) - */ - public final static int SICSLOWPAN_IPHC_TC_C = 0x10; - public final static int SICSLOWPAN_IPHC_FL_C = 0x08; - public final static int SICSLOWPAN_IPHC_NH_C = 0x04; - public final static int SICSLOWPAN_IPHC_TTL_1 = 0x01; - public final static int SICSLOWPAN_IPHC_TTL_64 = 0x02; - public final static int SICSLOWPAN_IPHC_TTL_255 = 0x03; - public final static int SICSLOWPAN_IPHC_TTL_I = 0x00; - - - /* Values of fields within the IPHC encoding second byte */ - public final static int SICSLOWPAN_IPHC_CID = 0x80; - - public final static int SICSLOWPAN_IPHC_SAC = 0x40; - public final static int SICSLOWPAN_IPHC_SAM_00 = 0x00; - public final static int SICSLOWPAN_IPHC_SAM_01 = 0x10; - public final static int SICSLOWPAN_IPHC_SAM_10 = 0x20; - public final static int SICSLOWPAN_IPHC_SAM_11 = 0x30; - - public final static int SICSLOWPAN_IPHC_M = 0x08; - public final static int SICSLOWPAN_IPHC_DAC = 0x04; - public final static int SICSLOWPAN_IPHC_DAM_00 = 0x00; - public final static int SICSLOWPAN_IPHC_DAM_01 = 0x01; - public final static int SICSLOWPAN_IPHC_DAM_10 = 0x02; - public final static int SICSLOWPAN_IPHC_DAM_11 = 0x03; - - private static final int SICSLOWPAN_NDC_UDP_MASK = 0xf8; - private static final int SICSLOWPAN_NHC_UDP_ID = 0xf0; - private static final int SICSLOWPAN_NHC_UDP_C = 0xf3; - private static final int SICSLOWPAN_NHC_UDP_I = 0xf0; - - public final static int PROTO_UDP = 17; - public final static int PROTO_TCP = 6; - public final static int PROTO_ICMP = 58; - - - public final static byte[] UNSPECIFIED_ADDRESS = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - private static byte[][] addrContexts = new byte[][] { - {(byte)0xaa, (byte)0xaa, 0, 0, 0, 0, 0, 0} - }; - - private static final int IPHC_DISPATCH = 0x60; - - public boolean matchPacket(Packet packet) { - return (packet.get(0) & 0xe0) == IPHC_DISPATCH; - } - - public int analyzePacket(Packet packet, StringBuffer brief, - StringBuffer verbose) { - - /* if packet has less than 3 bytes it is not interesting ... */ - if (packet.size() < 3) return ANALYSIS_FAILED; - - int tf = (packet.get(0) >> 3) & 0x03; - boolean nhc = (packet.get(0) & SICSLOWPAN_IPHC_NH_C) > 0; - int hlim = (packet.get(0) & 0x03); - int cid = (packet.get(1) >> 7) & 0x01; - int sac = (packet.get(1) >> 6) & 0x01; - int sam = (packet.get(1) >> 4) & 0x03; - int m = (packet.get(1) >> 3) & 0x01; - int dac = (packet.get(1) >> 2) & 0x01; - int dam = packet.get(1) & 0x03; - int sci = 0; - int dci = 0; - - brief.append("IPHC"); - - /* need to decompress while analyzing - add that later... */ - - verbose.append("IPHC HC-06
"); - verbose.append("tf = " + tf + " nhc = " + nhc + " hlim = " + hlim - + " cid = " + cid + " sac = " + sac + " sam = " + sam - + " MCast = " + m + " dac = " + dac + " dam = " + dam + "
"); - if (cid == 1) { - verbose.append("Contexts: sci=" + (packet.get(2) >> 4) + " dci=" - + (packet.get(2) & 0x0f) + "
"); - sci = packet.get(2) >> 4; - dci = packet.get(2) & 0x0f; - } - - int hc06_ptr = 2 + cid; - - int version = 6; - int trafficClass = 0; - int flowLabel = 0; - int len = 0; - int proto = 0; - int ttl = 0; - byte[] srcAddress = null; - byte[] destAddress = null; - - int srcPort = 0; - int destPort = 0; - - /* Traffic class and flow label */ - if((packet.get(0) & SICSLOWPAN_IPHC_FL_C) == 0) { - /* Flow label are carried inline */ - if((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) { - /* Traffic class is carried inline */ - flowLabel = packet.getInt(hc06_ptr + 1, 3); - int tmp = packet.get(hc06_ptr); - hc06_ptr += 4; - /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */ - trafficClass = ((tmp >> 2) & 0x3f) | (tmp << 6) & (0x80 + 0x40); - /* ECN rolled down two steps + lowest DSCP bits at top two bits */ - } else { - /* highest flow label bits + ECN bits */ - int tmp = packet.get(hc06_ptr); - trafficClass = (tmp >> 6) & 0x0f; - flowLabel = packet.getInt(hc06_ptr + 1, 2); - hc06_ptr += 3; - } - } else { - /* Version is always 6! */ - /* Version and flow label are compressed */ - if((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) { - /* Traffic class is inline */ - trafficClass =((packet.get(hc06_ptr) >> 6) & 0x03); - trafficClass = (packet.get(hc06_ptr) << 2); - hc06_ptr += 1; - } - } - - /* Next Header */ - if((packet.get(0) & SICSLOWPAN_IPHC_NH_C) == 0) { - /* Next header is carried inline */ - proto = packet.get(hc06_ptr); - hc06_ptr += 1; - } - - /* Hop limit */ - switch(packet.get(0) & 0x03) { - case SICSLOWPAN_IPHC_TTL_1: - ttl = 1; - break; - case SICSLOWPAN_IPHC_TTL_64: - ttl = 2; - break; - case SICSLOWPAN_IPHC_TTL_255: - ttl = 255; - break; - case SICSLOWPAN_IPHC_TTL_I: - ttl = packet.get(hc06_ptr); - hc06_ptr += 1; - break; - } - - /* context based compression */ - if((packet.get(1) & SICSLOWPAN_IPHC_SAC) > 0) { - /* Source address */ - byte[] context = null; - if((packet.get(1) & SICSLOWPAN_IPHC_SAM_11) != SICSLOWPAN_IPHC_SAM_00) { - context = addrContexts[sci]; - } - - switch(packet.get(1) & SICSLOWPAN_IPHC_SAM_11) { - case SICSLOWPAN_IPHC_SAM_00: - /* copy the unspecificed address */ - srcAddress = UNSPECIFIED_ADDRESS; - break; - case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */ - /* copy prefix from context */ - srcAddress = new byte[16]; - System.arraycopy(context, 0, srcAddress, 0, 8); - /* copy IID from packet */ - packet.copy(hc06_ptr, srcAddress, 8, 8); - hc06_ptr += 8; - break; - case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */ - /* unicast address */ - srcAddress = new byte[16]; - System.arraycopy(context, 0, srcAddress, 0, 8); - /* copy 6 NULL bytes then 2 last bytes of IID */ - packet.copy(hc06_ptr, srcAddress, 14, 2); - hc06_ptr += 2; - break; - case SICSLOWPAN_IPHC_SAM_11: /* 0-bits */ - /* copy prefix from context */ - srcAddress = new byte[16]; - System.arraycopy(context, 0, srcAddress, 0, 8); - /* infer IID from L2 address */ - System.arraycopy(packet.llsender, 0, srcAddress, - 16 - packet.llsender.length, packet.llsender.length); - break; - } - /* end context based compression */ - } else { - /* no compression and link local */ - switch(packet.get(1) & SICSLOWPAN_IPHC_SAM_11) { - case SICSLOWPAN_IPHC_SAM_00: /* 128 bits */ - /* copy whole address from packet */ - srcAddress = new byte[16]; - packet.copy(hc06_ptr, srcAddress, 0, 16); - hc06_ptr += 16; - break; - case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */ - srcAddress = new byte[16]; - srcAddress[0] = (byte) 0xfe; - srcAddress[1] = (byte) 0x80; - /* copy IID from packet */ - packet.copy(hc06_ptr, srcAddress, 8, 8); - hc06_ptr += 8; - break; - case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */ - srcAddress = new byte[16]; - srcAddress[0] = (byte) 0xfe; - srcAddress[1] = (byte) 0x80; - packet.copy(hc06_ptr, srcAddress, 14, 2); - hc06_ptr += 2; - break; - case SICSLOWPAN_IPHC_SAM_11: /* 0 bits */ - /* setup link-local address */ - srcAddress = new byte[16]; - srcAddress[0] = (byte) 0xfe; - srcAddress[1] = (byte) 0x80; - /* infer IID from L2 address */ - System.arraycopy(packet.llsender, 0, srcAddress, - 16 - packet.llsender.length, packet.llsender.length); - break; - } - } - - /* Destination address */ - - /* multicast compression */ - if((packet.get(1) & SICSLOWPAN_IPHC_M) != 0) { - /* context based multicast compression */ - if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { - /* TODO: implement this */ - } else { - /* non-context based multicast compression */ - switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { - case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */ - /* copy whole address from packet */ - destAddress = new byte[16]; - packet.copy(hc06_ptr, destAddress, 0, 16); - hc06_ptr += 16; - break; - case SICSLOWPAN_IPHC_DAM_01: /* 48 bits FFXX::00XX:XXXX:XXXX */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xff; - destAddress[1] = packet.get(hc06_ptr); - packet.copy(hc06_ptr + 1, destAddress, 11, 5); - hc06_ptr += 6; - break; - case SICSLOWPAN_IPHC_DAM_10: /* 32 bits FFXX::00XX:XXXX */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xff; - destAddress[1] = packet.get(hc06_ptr); - packet.copy(hc06_ptr + 1, destAddress, 13, 3); - hc06_ptr += 4; - break; - case SICSLOWPAN_IPHC_DAM_11: /* 8 bits FF02::00XX */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xff; - destAddress[1] = (byte) 0x02; - destAddress[15] = packet.get(hc06_ptr); - hc06_ptr++; - break; - } - } - } else { - /* no multicast */ - /* Context based */ - if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { - byte[] context = addrContexts[dci]; - - switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { - case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */ - destAddress = new byte[16]; - System.arraycopy(context, 0, destAddress, 0, 8); - /* copy IID from packet */ - packet.copy(hc06_ptr, destAddress, 8, 8); - hc06_ptr += 8; - break; - case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */ - /* unicast address */ - destAddress = new byte[16]; - System.arraycopy(context, 0, destAddress, 0, 8); - /* copy IID from packet */ - packet.copy(hc06_ptr, destAddress, 14, 2); - hc06_ptr += 2; - break; - case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ - /* unicast address */ - destAddress = new byte[16]; - System.arraycopy(context, 0, destAddress, 0, 8); - /* infer IID from L2 address */ - System.arraycopy(packet.llreceiver, 0, destAddress, - 16 - packet.llreceiver.length, packet.llreceiver.length); - break; - } - } else { - /* not context based => link local M = 0, DAC = 0 - same as SAC */ - switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { - case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */ - destAddress = new byte[16]; - packet.copy(hc06_ptr, destAddress, 0, 16); - hc06_ptr += 16; - break; - case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xfe; - destAddress[1] = (byte) 0x80; - packet.copy(hc06_ptr, destAddress, 8, 8); - hc06_ptr += 8; - break; - case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xfe; - destAddress[1] = (byte) 0x80; - packet.copy(hc06_ptr, destAddress, 14, 2); - hc06_ptr += 2; - break; - case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ - destAddress = new byte[16]; - destAddress[0] = (byte) 0xfe; - destAddress[1] = (byte) 0x80; - System.arraycopy(packet.llreceiver, 0, destAddress, - 16 - packet.llreceiver.length, packet.llreceiver.length); - break; - } - } - } - - /* Next header processing - continued */ - if(nhc) { - /* TODO: check if this is correct in hc-06 */ - /* The next header is compressed, NHC is following */ - if((packet.get(hc06_ptr) & SICSLOWPAN_NDC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) { - proto = PROTO_UDP; - switch(packet.get(hc06_ptr)) { - case (byte) SICSLOWPAN_NHC_UDP_C: - /* 1 byte for NHC, 1 byte for ports, 2 bytes chksum */ - srcPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) >> 4); - destPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) & 0x0F); -// memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 2, 2); -// PRINTF("IPHC: Uncompressed UDP ports (4): %x, %x\n", -// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); - hc06_ptr += 4; - break; - case (byte) SICSLOWPAN_NHC_UDP_I: - /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */ - srcPort = packet.getInt(hc06_ptr + 1, 2); - destPort = packet.getInt(hc06_ptr + 3, 2); -// memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 5, 2); -// PRINTF("IPHC: Uncompressed UDP ports (7): %x, %x\n", -// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); - - hc06_ptr += 7; - break; - default: -// PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n"); - return ANALYSIS_FAILED; - } - } - } - - packet.pos += hc06_ptr; - -// /* IP length field. */ -// if(ip_len == 0) { -// /* This is not a fragmented packet */ -// SICSLOWPAN_IP_BUF->len[0] = 0; -// SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN; -// } else { -// /* This is a 1st fragment */ -// SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8; -// SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF; -// } - -// /* length field in UDP header */ -// if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) { -// memcpy(&SICSLOWPAN_UDP_BUF->udplen, ipBuf + len[0], 2); -// } - - /*--------------------------------------------- */ - - String protoStr = "" + proto; - if (proto == PROTO_ICMP) { - protoStr = "ICMPv6"; - } else if (proto == PROTO_UDP) protoStr = "UDP"; - else if (proto == PROTO_TCP) protoStr = "TCP"; - - verbose.append("
IPv6 ").append(protoStr).append("
"); - verbose.append("From "); - printAddress(verbose, srcAddress); - verbose.append(" to "); - printAddress(verbose, destAddress); - - packet.lastDispatch = (byte) (proto & 0xff); - packet.level = NETWORK_LEVEL; - return ANALYSIS_OK_CONTINUE; - } - - public static void printAddress(StringBuffer out, byte[] address) { - for (int i = 0; i < 16; i+=2) { - out.append(StringUtils.toHex((byte) (address[i] & 0xff)) + - StringUtils.toHex((byte) (address[i + 1] & 0xff))); - if (i < 14) { - out.append(":"); - } - } - } - - -} +package se.sics.cooja.plugins.analyzers; + +import se.sics.cooja.util.StringUtils; + +public class IPHCPacketAnalyzer extends PacketAnalyzer { + + public final static int SICSLOWPAN_UDP_PORT_MIN = 0xF0B0; + public final static int SICSLOWPAN_UDP_PORT_MAX = 0xF0BF; /* F0B0 + 15 */ + + public final static int SICSLOWPAN_DISPATCH_IPV6 = 0x41; /* 01000001 = 65 */ + public final static int SICSLOWPAN_DISPATCH_HC1 = 0x42; /* 01000010 = 66 */ + public final static int SICSLOWPAN_DISPATCH_IPHC = 0x60; /* 011xxxxx = ... */ + public final static int SICSLOWPAN_DISPATCH_FRAG1 = 0xc0; /* 1100= 0xxx */ + public final static int SICSLOWPAN_DISPATCH_FRAGN = 0xe0; /* 1110= 0xxx */ + + /* + * Values of fields within the IPHC encoding first byte + * (C stands for compressed and I for inline) + */ + public final static int SICSLOWPAN_IPHC_TC_C = 0x10; + public final static int SICSLOWPAN_IPHC_FL_C = 0x08; + public final static int SICSLOWPAN_IPHC_NH_C = 0x04; + public final static int SICSLOWPAN_IPHC_TTL_1 = 0x01; + public final static int SICSLOWPAN_IPHC_TTL_64 = 0x02; + public final static int SICSLOWPAN_IPHC_TTL_255 = 0x03; + public final static int SICSLOWPAN_IPHC_TTL_I = 0x00; + + + /* Values of fields within the IPHC encoding second byte */ + public final static int SICSLOWPAN_IPHC_CID = 0x80; + + public final static int SICSLOWPAN_IPHC_SAC = 0x40; + public final static int SICSLOWPAN_IPHC_SAM_00 = 0x00; + public final static int SICSLOWPAN_IPHC_SAM_01 = 0x10; + public final static int SICSLOWPAN_IPHC_SAM_10 = 0x20; + public final static int SICSLOWPAN_IPHC_SAM_11 = 0x30; + + public final static int SICSLOWPAN_IPHC_M = 0x08; + public final static int SICSLOWPAN_IPHC_DAC = 0x04; + public final static int SICSLOWPAN_IPHC_DAM_00 = 0x00; + public final static int SICSLOWPAN_IPHC_DAM_01 = 0x01; + public final static int SICSLOWPAN_IPHC_DAM_10 = 0x02; + public final static int SICSLOWPAN_IPHC_DAM_11 = 0x03; + + private static final int SICSLOWPAN_NDC_UDP_MASK = 0xf8; + private static final int SICSLOWPAN_NHC_UDP_ID = 0xf0; + private static final int SICSLOWPAN_NHC_UDP_C = 0xf3; + private static final int SICSLOWPAN_NHC_UDP_I = 0xf0; + + public final static int PROTO_UDP = 17; + public final static int PROTO_TCP = 6; + public final static int PROTO_ICMP = 58; + + + public final static byte[] UNSPECIFIED_ADDRESS = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + private static byte[][] addrContexts = new byte[][] { + {(byte)0xaa, (byte)0xaa, 0, 0, 0, 0, 0, 0} + }; + + private static final int IPHC_DISPATCH = 0x60; + + public boolean matchPacket(Packet packet) { + return (packet.get(0) & 0xe0) == IPHC_DISPATCH; + } + + public int analyzePacket(Packet packet, StringBuffer brief, + StringBuffer verbose) { + + /* if packet has less than 3 bytes it is not interesting ... */ + if (packet.size() < 3) return ANALYSIS_FAILED; + + int tf = (packet.get(0) >> 3) & 0x03; + boolean nhc = (packet.get(0) & SICSLOWPAN_IPHC_NH_C) > 0; + int hlim = (packet.get(0) & 0x03); + int cid = (packet.get(1) >> 7) & 0x01; + int sac = (packet.get(1) >> 6) & 0x01; + int sam = (packet.get(1) >> 4) & 0x03; + int m = (packet.get(1) >> 3) & 0x01; + int dac = (packet.get(1) >> 2) & 0x01; + int dam = packet.get(1) & 0x03; + int sci = 0; + int dci = 0; + + brief.append("IPHC"); + + /* need to decompress while analyzing - add that later... */ + + verbose.append("IPHC HC-06
"); + verbose.append("tf = " + tf + " nhc = " + nhc + " hlim = " + hlim + + " cid = " + cid + " sac = " + sac + " sam = " + sam + + " MCast = " + m + " dac = " + dac + " dam = " + dam); + if (cid == 1) { + verbose.append("
Contexts: sci=" + (packet.get(2) >> 4) + " dci=" + + (packet.get(2) & 0x0f)); + sci = packet.get(2) >> 4; + dci = packet.get(2) & 0x0f; + } + + int hc06_ptr = 2 + cid; + + int version = 6; + int trafficClass = 0; + int flowLabel = 0; + int len = 0; + int proto = 0; + int ttl = 0; + byte[] srcAddress = null; + byte[] destAddress = null; + + int srcPort = 0; + int destPort = 0; + + /* Traffic class and flow label */ + if((packet.get(0) & SICSLOWPAN_IPHC_FL_C) == 0) { + /* Flow label are carried inline */ + if((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) { + /* Traffic class is carried inline */ + flowLabel = packet.getInt(hc06_ptr + 1, 3); + int tmp = packet.get(hc06_ptr); + hc06_ptr += 4; + /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */ + trafficClass = ((tmp >> 2) & 0x3f) | (tmp << 6) & (0x80 + 0x40); + /* ECN rolled down two steps + lowest DSCP bits at top two bits */ + } else { + /* highest flow label bits + ECN bits */ + int tmp = packet.get(hc06_ptr); + trafficClass = (tmp >> 6) & 0x0f; + flowLabel = packet.getInt(hc06_ptr + 1, 2); + hc06_ptr += 3; + } + } else { + /* Version is always 6! */ + /* Version and flow label are compressed */ + if((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) { + /* Traffic class is inline */ + trafficClass =((packet.get(hc06_ptr) >> 6) & 0x03); + trafficClass = (packet.get(hc06_ptr) << 2); + hc06_ptr += 1; + } + } + + /* Next Header */ + if((packet.get(0) & SICSLOWPAN_IPHC_NH_C) == 0) { + /* Next header is carried inline */ + proto = packet.get(hc06_ptr); + hc06_ptr += 1; + } + + /* Hop limit */ + switch(packet.get(0) & 0x03) { + case SICSLOWPAN_IPHC_TTL_1: + ttl = 1; + break; + case SICSLOWPAN_IPHC_TTL_64: + ttl = 2; + break; + case SICSLOWPAN_IPHC_TTL_255: + ttl = 255; + break; + case SICSLOWPAN_IPHC_TTL_I: + ttl = packet.get(hc06_ptr); + hc06_ptr += 1; + break; + } + + /* context based compression */ + if((packet.get(1) & SICSLOWPAN_IPHC_SAC) > 0) { + /* Source address */ + byte[] context = null; + if((packet.get(1) & SICSLOWPAN_IPHC_SAM_11) != SICSLOWPAN_IPHC_SAM_00) { + context = addrContexts[sci]; + } + + switch(packet.get(1) & SICSLOWPAN_IPHC_SAM_11) { + case SICSLOWPAN_IPHC_SAM_00: + /* copy the unspecificed address */ + srcAddress = UNSPECIFIED_ADDRESS; + break; + case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */ + /* copy prefix from context */ + srcAddress = new byte[16]; + System.arraycopy(context, 0, srcAddress, 0, 8); + /* copy IID from packet */ + packet.copy(hc06_ptr, srcAddress, 8, 8); + hc06_ptr += 8; + break; + case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */ + /* unicast address */ + srcAddress = new byte[16]; + System.arraycopy(context, 0, srcAddress, 0, 8); + /* copy 6 NULL bytes then 2 last bytes of IID */ + packet.copy(hc06_ptr, srcAddress, 14, 2); + hc06_ptr += 2; + break; + case SICSLOWPAN_IPHC_SAM_11: /* 0-bits */ + /* copy prefix from context */ + srcAddress = new byte[16]; + System.arraycopy(context, 0, srcAddress, 0, 8); + /* infer IID from L2 address */ + System.arraycopy(packet.llsender, 0, srcAddress, + 16 - packet.llsender.length, packet.llsender.length); + break; + } + /* end context based compression */ + } else { + /* no compression and link local */ + switch(packet.get(1) & SICSLOWPAN_IPHC_SAM_11) { + case SICSLOWPAN_IPHC_SAM_00: /* 128 bits */ + /* copy whole address from packet */ + srcAddress = new byte[16]; + packet.copy(hc06_ptr, srcAddress, 0, 16); + hc06_ptr += 16; + break; + case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */ + srcAddress = new byte[16]; + srcAddress[0] = (byte) 0xfe; + srcAddress[1] = (byte) 0x80; + /* copy IID from packet */ + packet.copy(hc06_ptr, srcAddress, 8, 8); + hc06_ptr += 8; + break; + case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */ + srcAddress = new byte[16]; + srcAddress[0] = (byte) 0xfe; + srcAddress[1] = (byte) 0x80; + packet.copy(hc06_ptr, srcAddress, 14, 2); + hc06_ptr += 2; + break; + case SICSLOWPAN_IPHC_SAM_11: /* 0 bits */ + /* setup link-local address */ + srcAddress = new byte[16]; + srcAddress[0] = (byte) 0xfe; + srcAddress[1] = (byte) 0x80; + /* infer IID from L2 address */ + System.arraycopy(packet.llsender, 0, srcAddress, + 16 - packet.llsender.length, packet.llsender.length); + break; + } + } + + /* Destination address */ + + /* multicast compression */ + if((packet.get(1) & SICSLOWPAN_IPHC_M) != 0) { + /* context based multicast compression */ + if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { + /* TODO: implement this */ + } else { + /* non-context based multicast compression */ + switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { + case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */ + /* copy whole address from packet */ + destAddress = new byte[16]; + packet.copy(hc06_ptr, destAddress, 0, 16); + hc06_ptr += 16; + break; + case SICSLOWPAN_IPHC_DAM_01: /* 48 bits FFXX::00XX:XXXX:XXXX */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xff; + destAddress[1] = packet.get(hc06_ptr); + packet.copy(hc06_ptr + 1, destAddress, 11, 5); + hc06_ptr += 6; + break; + case SICSLOWPAN_IPHC_DAM_10: /* 32 bits FFXX::00XX:XXXX */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xff; + destAddress[1] = packet.get(hc06_ptr); + packet.copy(hc06_ptr + 1, destAddress, 13, 3); + hc06_ptr += 4; + break; + case SICSLOWPAN_IPHC_DAM_11: /* 8 bits FF02::00XX */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xff; + destAddress[1] = (byte) 0x02; + destAddress[15] = packet.get(hc06_ptr); + hc06_ptr++; + break; + } + } + } else { + /* no multicast */ + /* Context based */ + if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { + byte[] context = addrContexts[dci]; + + switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { + case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */ + destAddress = new byte[16]; + System.arraycopy(context, 0, destAddress, 0, 8); + /* copy IID from packet */ + packet.copy(hc06_ptr, destAddress, 8, 8); + hc06_ptr += 8; + break; + case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */ + /* unicast address */ + destAddress = new byte[16]; + System.arraycopy(context, 0, destAddress, 0, 8); + /* copy IID from packet */ + packet.copy(hc06_ptr, destAddress, 14, 2); + hc06_ptr += 2; + break; + case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ + /* unicast address */ + destAddress = new byte[16]; + System.arraycopy(context, 0, destAddress, 0, 8); + /* infer IID from L2 address */ + System.arraycopy(packet.llreceiver, 0, destAddress, + 16 - packet.llreceiver.length, packet.llreceiver.length); + break; + } + } else { + /* not context based => link local M = 0, DAC = 0 - same as SAC */ + switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { + case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */ + destAddress = new byte[16]; + packet.copy(hc06_ptr, destAddress, 0, 16); + hc06_ptr += 16; + break; + case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xfe; + destAddress[1] = (byte) 0x80; + packet.copy(hc06_ptr, destAddress, 8, 8); + hc06_ptr += 8; + break; + case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xfe; + destAddress[1] = (byte) 0x80; + packet.copy(hc06_ptr, destAddress, 14, 2); + hc06_ptr += 2; + break; + case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ + destAddress = new byte[16]; + destAddress[0] = (byte) 0xfe; + destAddress[1] = (byte) 0x80; + System.arraycopy(packet.llreceiver, 0, destAddress, + 16 - packet.llreceiver.length, packet.llreceiver.length); + break; + } + } + } + + /* Next header processing - continued */ + if(nhc) { + /* TODO: check if this is correct in hc-06 */ + /* The next header is compressed, NHC is following */ + if((packet.get(hc06_ptr) & SICSLOWPAN_NDC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) { + proto = PROTO_UDP; + switch(packet.get(hc06_ptr)) { + case (byte) SICSLOWPAN_NHC_UDP_C: + /* 1 byte for NHC, 1 byte for ports, 2 bytes chksum */ + srcPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) >> 4); + destPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) & 0x0F); +// memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 2, 2); +// PRINTF("IPHC: Uncompressed UDP ports (4): %x, %x\n", +// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); + hc06_ptr += 4; + break; + case (byte) SICSLOWPAN_NHC_UDP_I: + /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */ + srcPort = packet.getInt(hc06_ptr + 1, 2); + destPort = packet.getInt(hc06_ptr + 3, 2); +// memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 5, 2); +// PRINTF("IPHC: Uncompressed UDP ports (7): %x, %x\n", +// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); + + hc06_ptr += 7; + break; + default: +// PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n"); + return ANALYSIS_FAILED; + } + } + } + + packet.pos += hc06_ptr; + +// /* IP length field. */ +// if(ip_len == 0) { +// /* This is not a fragmented packet */ +// SICSLOWPAN_IP_BUF->len[0] = 0; +// SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN; +// } else { +// /* This is a 1st fragment */ +// SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8; +// SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF; +// } + +// /* length field in UDP header */ +// if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) { +// memcpy(&SICSLOWPAN_UDP_BUF->udplen, ipBuf + len[0], 2); +// } + + /*--------------------------------------------- */ + + String protoStr = "" + proto; + if (proto == PROTO_ICMP) { + protoStr = "ICMPv6"; + } else if (proto == PROTO_UDP) protoStr = "UDP"; + else if (proto == PROTO_TCP) protoStr = "TCP"; + + verbose.append("
IPv6 ").append(protoStr).append("
"); + verbose.append("From "); + printAddress(verbose, srcAddress); + verbose.append(" to "); + printAddress(verbose, destAddress); + + packet.lastDispatch = (byte) (proto & 0xff); + packet.level = NETWORK_LEVEL; + return ANALYSIS_OK_CONTINUE; + } + + public static void printAddress(StringBuffer out, byte[] address) { + for (int i = 0; i < 16; i+=2) { + out.append(StringUtils.toHex((byte) (address[i] & 0xff)) + + StringUtils.toHex((byte) (address[i + 1] & 0xff))); + if (i < 14) { + out.append(":"); + } + } + } + + +}