From c1ce8721d8cb2232863d518a0076941a7ebe4b2a Mon Sep 17 00:00:00 2001 From: joxe Date: Sun, 7 Mar 2010 20:44:40 +0000 Subject: [PATCH] added support for icmpv6 analysis / RPL --- .../se/sics/cooja/plugins/RadioLogger.java | 20 +++-- .../plugins/analyzers/ICMPv6Analyzer.java | 86 +++++++++++++++++++ .../plugins/analyzers/IEEE802154Analyzer.java | 4 +- .../plugins/analyzers/IPHCPacketAnalyzer.java | 16 ++-- .../plugins/analyzers/PacketAnalyzer.java | 8 +- 5 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java diff --git a/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java b/tools/cooja/java/se/sics/cooja/plugins/RadioLogger.java index 4c2fdf79d..a65a169d4 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.30 2010/03/07 19:53:07 joxe Exp $ + * $Id: RadioLogger.java,v 1.31 2010/03/07 20:44:40 joxe Exp $ */ package se.sics.cooja.plugins; @@ -77,6 +77,7 @@ import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; import se.sics.cooja.dialogs.TableColumnAdjuster; import se.sics.cooja.interfaces.Radio; +import se.sics.cooja.plugins.analyzers.ICMPv6Analyzer; import se.sics.cooja.plugins.analyzers.IEEE802154Analyzer; import se.sics.cooja.plugins.analyzers.IPHCPacketAnalyzer; import se.sics.cooja.plugins.analyzers.PacketAnalyzer; @@ -128,6 +129,7 @@ public class RadioLogger extends VisPlugin { ArrayList lowpanAnalyzers = new ArrayList(); lowpanAnalyzers.add(new IEEE802154Analyzer()); lowpanAnalyzers.add(new IPHCPacketAnalyzer()); + lowpanAnalyzers.add(new ICMPv6Analyzer()); model = new AbstractTableModel() { private static final long serialVersionUID = 1692207305977527004L; @@ -421,11 +423,17 @@ public class RadioLogger extends VisPlugin { analyze = false; for (int i = 0; i < analyzers.size(); i++) { PacketAnalyzer analyzer = analyzers.get(i); - if (analyzer.matchPacket(packet) && analyzer.analyzePacket(packet, brief, verbose)) { - /* continue another round if more bytes left */ - analyze = packet.hasMoreData(); - brief.append('|'); - verbose.append("

"); + if (analyzer.matchPacket(packet)) { + int res = analyzer.analyzePacket(packet, brief, verbose); + if (res != analyzer.ANALYSIS_OK_FINAL) { + /* continue another round if more bytes left */ + analyze = packet.hasMoreData(); + brief.append('|'); + verbose.append("

"); + } else { + /* this was the final - no analyzable payload possible here... */ + return brief.length() > 0; + } 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 new file mode 100644 index 000000000..358534b29 --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/ICMPv6Analyzer.java @@ -0,0 +1,86 @@ +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; + } + +} diff --git a/tools/cooja/java/se/sics/cooja/plugins/analyzers/IEEE802154Analyzer.java b/tools/cooja/java/se/sics/cooja/plugins/analyzers/IEEE802154Analyzer.java index b46ac4df3..119dc9cd9 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/analyzers/IEEE802154Analyzer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/IEEE802154Analyzer.java @@ -42,7 +42,7 @@ public class IEEE802154Analyzer extends PacketAnalyzer { /* create a 802.15.4 packet of the bytes and "dispatch" to the * next handler */ - public boolean analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose) { + public int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose) { int pos = packet.pos; int type = packet.data[pos + 0] & 7; // int security = (packet.data[pos + 0] >> 3) & 1; @@ -134,7 +134,7 @@ public class IEEE802154Analyzer extends PacketAnalyzer { packet.llsender = sourceAddress; packet.llreceiver = destAddress; - return true; + return ANALYSIS_OK_CONTINUE; } private void printAddress(StringBuffer sb, int type, byte[] addr) { 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 53a683591..5d2b08625 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/IPHCPacketAnalyzer.java @@ -64,11 +64,11 @@ public class IPHCPacketAnalyzer extends PacketAnalyzer { return (packet.get(0) & 0xe0) == IPHC_DISPATCH; } - public boolean analyzePacket(Packet packet, StringBuffer brief, + 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 false; + if (packet.size() < 3) return ANALYSIS_FAILED; int tf = (packet.get(0) >> 3) & 0x03; int nh = (packet.get(0) >> 2) & 0x01; @@ -375,7 +375,7 @@ public class IPHCPacketAnalyzer extends PacketAnalyzer { break; default: // PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n"); - return false; + return ANALYSIS_FAILED; } } } @@ -400,11 +400,10 @@ public class IPHCPacketAnalyzer extends PacketAnalyzer { /*--------------------------------------------- */ -// packet.pos += cid == 1 ? 3 : 2; - String protoStr = "" + proto; - if (proto == PROTO_ICMP) protoStr = "ICMPv6"; - else if (proto == PROTO_UDP) protoStr = "UDP"; + 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("
"); @@ -413,8 +412,9 @@ public class IPHCPacketAnalyzer extends PacketAnalyzer { verbose.append(" to "); printAddress(verbose, destAddress); + packet.lastDispatch = (byte) (proto & 0xff); packet.level = NETWORK_LEVEL; - return true; + return ANALYSIS_OK_CONTINUE; } public static void printAddress(StringBuffer out, byte[] address) { diff --git a/tools/cooja/java/se/sics/cooja/plugins/analyzers/PacketAnalyzer.java b/tools/cooja/java/se/sics/cooja/plugins/analyzers/PacketAnalyzer.java index a4762754e..c309c6106 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/analyzers/PacketAnalyzer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/analyzers/PacketAnalyzer.java @@ -2,6 +2,10 @@ package se.sics.cooja.plugins.analyzers; public abstract class PacketAnalyzer { + public static final int ANALYSIS_FAILED = -1; + public static final int ANALYSIS_OK_CONTINUE = 1; + public static final int ANALYSIS_OK_FINAL = 2; + public static final int RADIO_LEVEL = 0; public static final int MAC_LEVEL = 1; public static final int NETWORK_LEVEL = 2; @@ -17,6 +21,8 @@ public abstract class PacketAnalyzer { byte[] llsender; byte[] llreceiver; + byte lastDispatch = 0; + public Packet(byte[] data, int level) { this.level = level; this.data = data; @@ -78,5 +84,5 @@ public abstract class PacketAnalyzer { public abstract boolean matchPacket(Packet packet); - public abstract boolean analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose); + public abstract int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose); } \ No newline at end of file