[cooja] plugins/analyzers: Indention and whitespace cleanups

This commit is contained in:
Enrico Joerns 2014-07-11 02:07:21 +02:00
parent 01bd045570
commit 3e9a780721
7 changed files with 1001 additions and 988 deletions

View file

@ -27,7 +27,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
*/ */
package org.contikios.cooja.plugins; package org.contikios.cooja.plugins;
import java.awt.BorderLayout; import java.awt.BorderLayout;
@ -111,6 +110,7 @@ import org.contikios.cooja.util.StringUtils;
@ClassDescription("Radio messages") @ClassDescription("Radio messages")
@PluginType(PluginType.SIM_PLUGIN) @PluginType(PluginType.SIM_PLUGIN)
public class RadioLogger extends VisPlugin { public class RadioLogger extends VisPlugin {
private static Logger logger = Logger.getLogger(RadioLogger.class); private static Logger logger = Logger.getLogger(RadioLogger.class);
private static final long serialVersionUID = -6927091711697081353L; private static final long serialVersionUID = -6927091711697081353L;
@ -141,7 +141,7 @@ public class RadioLogger extends VisPlugin {
private Observer radioMediumObserver; private Observer radioMediumObserver;
private AbstractTableModel model; private AbstractTableModel model;
private HashMap<String,Action> analyzerMap = new HashMap<String,Action>(); private HashMap<String, Action> analyzerMap = new HashMap<String, Action>();
private String analyzerName = null; private String analyzerName = null;
private ArrayList<PacketAnalyzer> analyzers = null; private ArrayList<PacketAnalyzer> analyzers = null;
private IEEE802154Analyzer analyzerWithPcap; private IEEE802154Analyzer analyzerWithPcap;
@ -290,14 +290,13 @@ public class RadioLogger extends VisPlugin {
/* TODO This entry may represent several hidden connections */ /* TODO This entry may represent several hidden connections */
RadioConnectionLog conn = connections.get(modelRowIndex); RadioConnectionLog conn = connections.get(modelRowIndex);
if (modelColumnIndex == COLUMN_TIME) { if (modelColumnIndex == COLUMN_TIME) {
return return "<html>"
"<html>" + + "Start time (us): " + conn.startTime
"Start time (us): " + conn.startTime + + "<br>"
"<br>" + + "End time (us): " + conn.endTime
"End time (us): " + conn.endTime + + "<br><br>"
"<br><br>" + + "Duration (us): " + (conn.endTime - conn.startTime)
"Duration (us): " + (conn.endTime - conn.startTime) + + "</html>";
"</html>";
} else if (modelColumnIndex == COLUMN_FROM) { } else if (modelColumnIndex == COLUMN_FROM) {
return conn.connection.getSource().getMote().toString(); return conn.connection.getSource().getMote().toString();
} else if (modelColumnIndex == COLUMN_TO) { } else if (modelColumnIndex == COLUMN_TO) {
@ -337,7 +336,7 @@ public class RadioLogger extends VisPlugin {
} }
formatTimeString = !formatTimeString; formatTimeString = !formatTimeString;
dataTable.getColumnModel().getColumn(COLUMN_TIME).setHeaderValue( dataTable.getColumnModel().getColumn(COLUMN_TIME).setHeaderValue(
dataTable.getModel().getColumnName(COLUMN_TIME)); dataTable.getModel().getColumnName(COLUMN_TIME));
repaint(); repaint();
} }
}); });
@ -346,16 +345,16 @@ public class RadioLogger extends VisPlugin {
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) { if (e.getKeyCode() == KeyEvent.VK_SPACE) {
showInAllAction.actionPerformed(null); showInAllAction.actionPerformed(null);
} else if (e.getKeyCode() == KeyEvent.VK_F && } else if (e.getKeyCode() == KeyEvent.VK_F
(e.getModifiers() & KeyEvent.CTRL_MASK) != 0) { && (e.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
searchField.setVisible(true); searchField.setVisible(true);
searchField.requestFocus(); searchField.requestFocus();
searchField.selectAll(); searchField.selectAll();
revalidate(); revalidate();
} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
searchField.setVisible(false); searchField.setVisible(false);
dataTable.requestFocus(); dataTable.requestFocus();
revalidate(); revalidate();
} }
} }
}); });
@ -367,21 +366,21 @@ public class RadioLogger extends VisPlugin {
dataTable.setRowSorter(logFilter); dataTable.setRowSorter(logFilter);
dataTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { dataTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
int row = dataTable.getSelectedRow(); int row = dataTable.getSelectedRow();
if (row < 0) { if (row < 0) {
return; return;
}
int modelRowIndex = dataTable.convertRowIndexToModel(row);
if (modelRowIndex >= 0) {
RadioConnectionLog conn = connections.get(modelRowIndex);
if (conn.tooltip == null) {
prepareTooltipString(conn);
}
verboseBox.setText(conn.tooltip);
verboseBox.setCaretPosition(0);
}
} }
int modelRowIndex = dataTable.convertRowIndexToModel(row);
if (modelRowIndex >= 0) {
RadioConnectionLog conn = connections.get(modelRowIndex);
if (conn.tooltip == null) {
prepareTooltipString(conn);
}
verboseBox.setText(conn.tooltip);
verboseBox.setCaretPosition(0);
}
}
}); });
// Set data column width greedy // Set data column width greedy
dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
@ -407,7 +406,6 @@ public class RadioLogger extends VisPlugin {
fileMenu.add(new JMenuItem(saveAction)); fileMenu.add(new JMenuItem(saveAction));
JPopupMenu popupMenu = new JPopupMenu(); JPopupMenu popupMenu = new JPopupMenu();
JMenu focusMenu = new JMenu("Show in"); JMenu focusMenu = new JMenu("Show in");
@ -418,7 +416,6 @@ public class RadioLogger extends VisPlugin {
popupMenu.add(focusMenu); popupMenu.add(focusMenu);
//a group of radio button menu items //a group of radio button menu items
ButtonGroup group = new ButtonGroup(); ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem( JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(
createAnalyzerAction("No Analyzer", "none", null, true)); createAnalyzerAction("No Analyzer", "none", null, true));
@ -426,7 +423,7 @@ public class RadioLogger extends VisPlugin {
analyzerMenu.add(rbMenuItem); analyzerMenu.add(rbMenuItem);
rbMenuItem = new JRadioButtonMenuItem(createAnalyzerAction( rbMenuItem = new JRadioButtonMenuItem(createAnalyzerAction(
"6LoWPAN Analyzer", "6lowpan", lowpanAnalyzers, false)); "6LoWPAN Analyzer", "6lowpan", lowpanAnalyzers, false));
group.add(rbMenuItem); group.add(rbMenuItem);
analyzerMenu.add(rbMenuItem); analyzerMenu.add(rbMenuItem);
@ -436,20 +433,20 @@ public class RadioLogger extends VisPlugin {
analyzerMenu.add(rbMenuItem); analyzerMenu.add(rbMenuItem);
/* Load additional analyzers specified by projects (cooja.config) */ /* Load additional analyzers specified by projects (cooja.config) */
String[] projectAnalyzerSuites = String[] projectAnalyzerSuites
gui.getProjectConfig().getStringArrayValue(RadioLogger.class, "ANALYZERS"); = gui.getProjectConfig().getStringArrayValue(RadioLogger.class, "ANALYZERS");
if (projectAnalyzerSuites != null) { if (projectAnalyzerSuites != null) {
for (String suiteName: projectAnalyzerSuites) { for (String suiteName: projectAnalyzerSuites) {
if (suiteName == null || suiteName.trim().isEmpty()) { if (suiteName == null || suiteName.trim().isEmpty()) {
continue; continue;
} }
Class<? extends RadioLoggerAnalyzerSuite> suiteClass = Class<? extends RadioLoggerAnalyzerSuite> suiteClass
gui.tryLoadClass(RadioLogger.this, RadioLoggerAnalyzerSuite.class, suiteName); = gui.tryLoadClass(RadioLogger.this, RadioLoggerAnalyzerSuite.class, suiteName);
try { try {
RadioLoggerAnalyzerSuite suite = suiteClass.newInstance(); RadioLoggerAnalyzerSuite suite = suiteClass.newInstance();
ArrayList<PacketAnalyzer> suiteAnalyzers = suite.getAnalyzers(); ArrayList<PacketAnalyzer> suiteAnalyzers = suite.getAnalyzers();
rbMenuItem = new JRadioButtonMenuItem(createAnalyzerAction( rbMenuItem = new JRadioButtonMenuItem(createAnalyzerAction(
suite.getDescription(), suiteName, suiteAnalyzers, false)); suite.getDescription(), suiteName, suiteAnalyzers, false));
group.add(rbMenuItem); group.add(rbMenuItem);
analyzerMenu.add(rbMenuItem); analyzerMenu.add(rbMenuItem);
logger.debug("Loaded radio logger analyzers: " + suite.getDescription()); logger.debug("Loaded radio logger analyzers: " + suite.getDescription());
@ -473,20 +470,20 @@ public class RadioLogger extends VisPlugin {
searchField.setVisible(false); searchField.setVisible(false);
searchField.addKeyListener(new KeyAdapter() { searchField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) { if (e.getKeyCode() == KeyEvent.VK_ENTER) {
searchSelectNext( searchSelectNext(
searchField.getText(), searchField.getText(),
(e.getModifiers() & KeyEvent.SHIFT_MASK) != 0); (e.getModifiers() & KeyEvent.SHIFT_MASK) != 0);
} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
searchField.setVisible(false); searchField.setVisible(false);
dataTable.requestFocus(); dataTable.requestFocus();
revalidate(); revalidate();
} }
} }
}); });
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
new JScrollPane(dataTable), new JScrollPane(verboseBox)); new JScrollPane(dataTable), new JScrollPane(verboseBox));
splitPane.setOneTouchExpandable(true); splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(150); splitPane.setDividerLocation(150);
add(BorderLayout.NORTH, searchField); add(BorderLayout.NORTH, searchField);
@ -528,8 +525,8 @@ public class RadioLogger extends VisPlugin {
setTitle("Radio messages: showing " + dataTable.getRowCount() + "/" + connections.size() + " packets"); setTitle("Radio messages: showing " + dataTable.getRowCount() + "/" + connections.size() + " packets");
} }
}); });
} }
}); });
setSize(500, 300); setSize(500, 300);
try { try {
@ -543,41 +540,41 @@ public class RadioLogger extends VisPlugin {
super.startPlugin(); super.startPlugin();
rebuildAllEntries(); rebuildAllEntries();
} }
private void searchSelectNext(String text, boolean reverse) { private void searchSelectNext(String text, boolean reverse) {
if (text.isEmpty()) { if (text.isEmpty()) {
return; return;
} }
int row = dataTable.getSelectedRow(); int row = dataTable.getSelectedRow();
if (row < 0) { if (row < 0) {
row = 0; row = 0;
} }
if (!reverse) { if (!reverse) {
row++; row++;
} else { } else {
row--; row--;
} }
int rows = dataTable.getModel().getRowCount(); int rows = dataTable.getModel().getRowCount();
for (int i=0; i < rows; i++) { for (int i = 0; i < rows; i++) {
int r; int r;
if (!reverse) { if (!reverse) {
r = (row + i + rows)%rows; r = (row + i + rows) % rows;
} else { } else {
r = (row - i + rows)%rows; r = (row - i + rows) % rows;
} }
String val = (String) dataTable.getModel().getValueAt(r, COLUMN_DATA); String val = (String) dataTable.getModel().getValueAt(r, COLUMN_DATA);
if (!val.contains(text)) { if (!val.contains(text)) {
continue; continue;
} }
dataTable.setRowSelectionInterval(r,r); dataTable.setRowSelectionInterval(r, r);
dataTable.scrollRectToVisible(dataTable.getCellRect(r, COLUMN_DATA, true)); dataTable.scrollRectToVisible(dataTable.getCellRect(r, COLUMN_DATA, true));
searchField.setBackground(Color.WHITE); searchField.setBackground(Color.WHITE);
return; return;
} }
searchField.setBackground(Color.RED); searchField.setBackground(Color.RED);
} }
/** /**
* Selects a logged radio packet close to the given time. * Selects a logged radio packet close to the given time.
@ -590,29 +587,29 @@ public class RadioLogger extends VisPlugin {
if (dataTable.getRowCount() == 0) { if (dataTable.getRowCount() == 0) {
return; return;
} }
for (int ai=0; ai < model.getRowCount(); ai++) { for (int ai = 0; ai < model.getRowCount(); ai++) {
int index = dataTable.convertRowIndexToModel(ai); int index = dataTable.convertRowIndexToModel(ai);
if (connections.get(index).endTime < time) { if (connections.get(index).endTime < time) {
continue; continue;
} }
dataTable.scrollRectToVisible(dataTable.getCellRect(ai, 0, true)); dataTable.scrollRectToVisible(dataTable.getCellRect(ai, 0, true));
dataTable.setRowSelectionInterval(ai, ai); dataTable.setRowSelectionInterval(ai, ai);
return; return;
} }
dataTable.scrollRectToVisible(dataTable.getCellRect(dataTable.getRowCount()-1, 0, true)); dataTable.scrollRectToVisible(dataTable.getCellRect(dataTable.getRowCount() - 1, 0, true));
dataTable.setRowSelectionInterval(dataTable.getRowCount()-1, dataTable.getRowCount()-1); dataTable.setRowSelectionInterval(dataTable.getRowCount() - 1, dataTable.getRowCount() - 1);
} }
}); });
} }
private void applyFilter() { private void applyFilter() {
for(RadioConnectionLog conn: connections) { for (RadioConnectionLog conn: connections) {
conn.data = null; conn.data = null;
conn.tooltip = null; conn.tooltip = null;
conn.hides = 0; conn.hides = 0;
conn.hiddenBy = null; conn.hiddenBy = null;
} }
try { try {
logFilter.setRowFilter(null); logFilter.setRowFilter(null);
@ -623,18 +620,18 @@ public class RadioLogger extends VisPlugin {
byte[] currentData = current.packet.getPacketData(); byte[] currentData = current.packet.getPacketData();
if (!showDuplicates && row > 0) { if (!showDuplicates && row > 0) {
RadioConnectionLog previous = connections.get(row-1); RadioConnectionLog previous = connections.get(row - 1);
byte[] previousData = previous.packet.getPacketData(); byte[] previousData = previous.packet.getPacketData();
if (!showDuplicates && if (!showDuplicates
Arrays.equals(previousData, currentData) && && Arrays.equals(previousData, currentData)
previous.connection.getSource() == current.connection.getSource() && && previous.connection.getSource() == current.connection.getSource()
Arrays.equals(previous.connection.getAllDestinations(), current.connection.getAllDestinations())) { && Arrays.equals(previous.connection.getAllDestinations(), current.connection.getAllDestinations())) {
if (connections.get(row-1).hiddenBy == null) { if (connections.get(row - 1).hiddenBy == null) {
connections.get(row-1).hides++; connections.get(row - 1).hides++;
connections.get(row).hiddenBy = connections.get(row-1); connections.get(row).hiddenBy = connections.get(row - 1);
} else { } else {
connections.get(row-1).hiddenBy.hides++; connections.get(row - 1).hiddenBy.hides++;
connections.get(row).hiddenBy = connections.get(row-1).hiddenBy; connections.get(row).hiddenBy = connections.get(row - 1).hiddenBy;
} }
return false; return false;
} }
@ -661,7 +658,7 @@ public class RadioLogger extends VisPlugin {
if (conn.packet == null) { if (conn.packet == null) {
data = null; data = null;
} else if (conn.packet instanceof ConvertedRadioPacket) { } else if (conn.packet instanceof ConvertedRadioPacket) {
data = ((ConvertedRadioPacket)conn.packet).getOriginalPacketData(); data = ((ConvertedRadioPacket) conn.packet).getOriginalPacketData();
} else { } else {
data = conn.packet.getPacketData(); data = conn.packet.getPacketData();
} }
@ -677,56 +674,56 @@ public class RadioLogger extends VisPlugin {
PacketAnalyzer.Packet packet = new PacketAnalyzer.Packet(data, PacketAnalyzer.MAC_LEVEL); PacketAnalyzer.Packet packet = new PacketAnalyzer.Packet(data, PacketAnalyzer.MAC_LEVEL);
if (analyzePacket(packet, brief, verbose)) { if (analyzePacket(packet, brief, verbose)) {
if (packet.hasMoreData()) { if (packet.hasMoreData()) {
byte[] payload = packet.getPayload(); byte[] payload = packet.getPayload();
brief.append(StringUtils.toHex(payload, 4)); brief.append(StringUtils.toHex(payload, 4));
if (verbose.length() > 0) {
verbose.append("<p>");
}
verbose.append("<b>Payload (")
.append(payload.length).append(" bytes)</b><br><pre>")
.append(StringUtils.hexDump(payload))
.append("</pre>");
}
conn.data = (data.length < 100 ? (data.length < 10 ? " " : " ") : "")
+ data.length + ": " + brief;
if (verbose.length() > 0) { if (verbose.length() > 0) {
conn.tooltip = verbose.toString(); verbose.append("<p>");
} }
verbose.append("<b>Payload (")
.append(payload.length).append(" bytes)</b><br><pre>")
.append(StringUtils.hexDump(payload))
.append("</pre>");
}
conn.data = (data.length < 100 ? (data.length < 10 ? " " : " ") : "")
+ data.length + ": " + brief;
if (verbose.length() > 0) {
conn.tooltip = verbose.toString();
}
} else { } else {
conn.data = data.length + ": 0x" + StringUtils.toHex(data, 4); conn.data = data.length + ": 0x" + StringUtils.toHex(data, 4);
} }
} }
private boolean analyzePacket(PacketAnalyzer.Packet packet, StringBuffer brief, StringBuffer verbose) { private boolean analyzePacket(PacketAnalyzer.Packet packet, StringBuffer brief, StringBuffer verbose) {
if (analyzers == null) return false; if (analyzers == null) return false;
try { try {
boolean analyze = true; boolean analyze = true;
while (analyze) { while (analyze) {
analyze = false; analyze = false;
for (int i = 0; i < analyzers.size(); i++) { for (int i = 0; i < analyzers.size(); i++) {
PacketAnalyzer analyzer = analyzers.get(i); PacketAnalyzer analyzer = analyzers.get(i);
if (analyzer.matchPacket(packet)) { if (analyzer.matchPacket(packet)) {
int res = analyzer.analyzePacket(packet, brief, verbose); int res = analyzer.analyzePacket(packet, brief, verbose);
if (packet.hasMoreData() && brief.length() > 0) { if (packet.hasMoreData() && brief.length() > 0) {
brief.append('|'); brief.append('|');
verbose.append("<br>"); verbose.append("<br>");
} }
if (res != PacketAnalyzer.ANALYSIS_OK_CONTINUE) { if (res != PacketAnalyzer.ANALYSIS_OK_CONTINUE) {
/* this was the final or the analysis failed - no analyzable payload possible here... */ /* this was the final or the analysis failed - no analyzable payload possible here... */
return brief.length() > 0; return brief.length() > 0;
} }
/* continue another round if more bytes left */ /* continue another round if more bytes left */
analyze = packet.hasMoreData(); analyze = packet.hasMoreData();
break; break;
}
} }
}
} }
} catch (Exception e) { } catch (Exception e) {
logger.debug("Error when analyzing packet: " + e.getMessage(), e); logger.debug("Error when analyzing packet: " + e.getMessage(), e);
return false; return false;
} }
return brief.length() > 0; return brief.length() > 0;
} }
private void prepareTooltipString(RadioConnectionLog conn) { private void prepareTooltipString(RadioConnectionLog conn) {
@ -737,29 +734,29 @@ public class RadioLogger extends VisPlugin {
} }
if (packet instanceof ConvertedRadioPacket && packet.getPacketData().length > 0) { if (packet instanceof ConvertedRadioPacket && packet.getPacketData().length > 0) {
byte[] original = ((ConvertedRadioPacket)packet).getOriginalPacketData(); byte[] original = ((ConvertedRadioPacket) packet).getOriginalPacketData();
byte[] converted = ((ConvertedRadioPacket)packet).getPacketData(); byte[] converted = ((ConvertedRadioPacket) packet).getPacketData();
conn.tooltip = "<html><font face=\"Monospaced\">" + conn.tooltip = "<html><font face=\"Monospaced\">"
"<b>Packet data (" + original.length + " bytes)</b><br>" + + "<b>Packet data (" + original.length + " bytes)</b><br>"
"<pre>" + StringUtils.hexDump(original) + "</pre>" + + "<pre>" + StringUtils.hexDump(original) + "</pre>"
"</font><font face=\"Monospaced\">" + + "</font><font face=\"Monospaced\">"
"<b>Cross-level packet data (" + converted.length + " bytes)</b><br>" + + "<b>Cross-level packet data (" + converted.length + " bytes)</b><br>"
"<pre>" + StringUtils.hexDump(converted) + "</pre>" + + "<pre>" + StringUtils.hexDump(converted) + "</pre>"
"</font></html>"; + "</font></html>";
} else if (packet instanceof ConvertedRadioPacket) { } else if (packet instanceof ConvertedRadioPacket) {
byte[] original = ((ConvertedRadioPacket)packet).getOriginalPacketData(); byte[] original = ((ConvertedRadioPacket) packet).getOriginalPacketData();
conn.tooltip = "<html><font face=\"Monospaced\">" + conn.tooltip = "<html><font face=\"Monospaced\">"
"<b>Packet data (" + original.length + " bytes)</b><br>" + + "<b>Packet data (" + original.length + " bytes)</b><br>"
"<pre>" + StringUtils.hexDump(original) + "</pre>" + + "<pre>" + StringUtils.hexDump(original) + "</pre>"
"</font><font face=\"Monospaced\">" + + "</font><font face=\"Monospaced\">"
"<b>No cross-level conversion available</b><br>" + + "<b>No cross-level conversion available</b><br>"
"</font></html>"; + "</font></html>";
} else { } else {
byte[] data = packet.getPacketData(); byte[] data = packet.getPacketData();
conn.tooltip = "<html><font face=\"Monospaced\">" + conn.tooltip = "<html><font face=\"Monospaced\">"
"<b>Packet data (" + data.length + " bytes)</b><br>" + + "<b>Packet data (" + data.length + " bytes)</b><br>"
"<pre>" + StringUtils.hexDump(data) + "</pre>" + + "<pre>" + StringUtils.hexDump(data) + "</pre>"
"</font></html>"; + "</font></html>";
} }
} }
@ -784,7 +781,7 @@ public class RadioLogger extends VisPlugin {
element = new Element("showdups"); element = new Element("showdups");
element.addContent(Boolean.toString(showDuplicates)); element.addContent(Boolean.toString(showDuplicates));
config.add(element); config.add(element);
element = new Element("hidenodests"); element = new Element("hidenodests");
element.addContent(Boolean.toString(hideNoDestinationPackets)); element.addContent(Boolean.toString(hideNoDestinationPackets));
config.add(element); config.add(element);
@ -796,7 +793,7 @@ public class RadioLogger extends VisPlugin {
} }
if (aliases != null) { if (aliases != null) {
for (Object key: aliases.keySet()) { for (Object key : aliases.keySet()) {
element = new Element("alias"); element = new Element("alias");
element.setAttribute("payload", (String) key); element.setAttribute("payload", (String) key);
element.setAttribute("alias", (String) aliases.get(key)); element.setAttribute("alias", (String) aliases.get(key));
@ -853,11 +850,12 @@ public class RadioLogger extends VisPlugin {
} }
private class RadioConnectionLog { private class RadioConnectionLog {
long startTime; long startTime;
long endTime; long endTime;
RadioConnection connection; RadioConnection connection;
RadioPacket packet; RadioPacket packet;
RadioConnectionLog hiddenBy = null; RadioConnectionLog hiddenBy = null;
int hides = 0; int hides = 0;
@ -865,14 +863,13 @@ public class RadioLogger extends VisPlugin {
String tooltip = null; String tooltip = null;
public String toString() { public String toString() {
if (data == null) { if (data == null) {
RadioLogger.this.prepareDataString(this); RadioLogger.this.prepareDataString(this);
} }
return return Long.toString(startTime / Simulation.MILLISECOND) + "\t"
Long.toString(startTime / Simulation.MILLISECOND) + "\t" + + connection.getSource().getMote().getID() + "\t"
connection.getSource().getMote().getID() + "\t" + + getDestString(this) + "\t"
getDestString(this) + "\t" + + data;
data;
} }
} }
@ -888,13 +885,13 @@ public class RadioLogger extends VisPlugin {
for (Radio dest: dests) { for (Radio dest: dests) {
sb.append(dest.getMote().getID()).append(','); sb.append(dest.getMote().getID()).append(',');
} }
sb.setLength(sb.length()-1); sb.setLength(sb.length() - 1);
return sb.toString(); return sb.toString();
} }
private void rebuildAllEntries() { private void rebuildAllEntries() {
applyFilter(); applyFilter();
if (connections.size() > 0) { if (connections.size() > 0) {
model.fireTableRowsUpdated(0, connections.size() - 1); model.fireTableRowsUpdated(0, connections.size() - 1);
} }
@ -903,23 +900,23 @@ public class RadioLogger extends VisPlugin {
setTitle("Radio messages: showing " + dataTable.getRowCount() + "/" + connections.size() + " packets"); setTitle("Radio messages: showing " + dataTable.getRowCount() + "/" + connections.size() + " packets");
simulation.getCooja().getDesktopPane().repaint(); simulation.getCooja().getDesktopPane().repaint();
} }
private Action createAnalyzerAction(String name, final String actionName,
final ArrayList<PacketAnalyzer> analyzerList, boolean selected) {
Action action = new AbstractAction(name) {
private static final long serialVersionUID = -608913700422638454L;
public void actionPerformed(ActionEvent event) { private Action createAnalyzerAction(String name, final String actionName,
if (analyzers != analyzerList) { final ArrayList<PacketAnalyzer> analyzerList, boolean selected) {
analyzers = analyzerList; Action action = new AbstractAction(name) {
analyzerName = actionName; private static final long serialVersionUID = -608913700422638454L;
rebuildAllEntries();
} public void actionPerformed(ActionEvent event) {
if (analyzers != analyzerList) {
analyzers = analyzerList;
analyzerName = actionName;
rebuildAllEntries();
} }
}; }
action.putValue(Action.SELECTED_KEY, selected ? Boolean.TRUE : Boolean.FALSE); };
analyzerMap.put(actionName, action); action.putValue(Action.SELECTED_KEY, selected ? Boolean.TRUE : Boolean.FALSE);
return action; analyzerMap.put(actionName, action);
return action;
} }
private Action clearAction = new AbstractAction("Clear") { private Action clearAction = new AbstractAction("Clear") {
@ -961,7 +958,7 @@ public class RadioLogger extends VisPlugin {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for(int i=0; i < connections.size(); i++) { for (int i = 0; i < connections.size(); i++) {
sb.append(connections.get(i).toString() + "\n"); sb.append(connections.get(i).toString() + "\n");
} }
@ -984,12 +981,12 @@ public class RadioLogger extends VisPlugin {
if (saveFile.exists()) { if (saveFile.exists()) {
String s1 = "Overwrite"; String s1 = "Overwrite";
String s2 = "Cancel"; String s2 = "Cancel";
Object[] options = { s1, s2 }; Object[] options = {s1, s2};
int n = JOptionPane.showOptionDialog( int n = JOptionPane.showOptionDialog(
Cooja.getTopParentContainer(), Cooja.getTopParentContainer(),
"A file with the same name already exists.\nDo you want to remove it?", "A file with the same name already exists.\nDo you want to remove it?",
"Overwrite existing file?", JOptionPane.YES_NO_OPTION, "Overwrite existing file?", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options, s1); JOptionPane.QUESTION_MESSAGE, null, options, s1);
if (n != JOptionPane.YES_OPTION) { if (n != JOptionPane.YES_OPTION) {
return; return;
} }
@ -1002,7 +999,7 @@ public class RadioLogger extends VisPlugin {
try { try {
PrintWriter outStream = new PrintWriter(new FileWriter(saveFile)); PrintWriter outStream = new PrintWriter(new FileWriter(saveFile));
for(int i=0; i < connections.size(); i++) { for (int i = 0; i < connections.size(); i++) {
outStream.print(connections.get(i).toString() + "\n"); outStream.print(connections.get(i).toString() + "\n");
} }
outStream.close(); outStream.close();
@ -1016,6 +1013,7 @@ public class RadioLogger extends VisPlugin {
private Action timeLineAction = new AbstractAction("Timeline") { private Action timeLineAction = new AbstractAction("Timeline") {
private static final long serialVersionUID = -4035633464748224192L; private static final long serialVersionUID = -4035633464748224192L;
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
int selectedRow = dataTable.getSelectedRow(); int selectedRow = dataTable.getSelectedRow();
if (selectedRow < 0) return; if (selectedRow < 0) return;
@ -1026,12 +1024,12 @@ public class RadioLogger extends VisPlugin {
Plugin[] plugins = simulation.getCooja().getStartedPlugins(); Plugin[] plugins = simulation.getCooja().getStartedPlugins();
for (Plugin p: plugins) { for (Plugin p: plugins) {
if (!(p instanceof TimeLine)) { if (!(p instanceof TimeLine)) {
continue; continue;
} }
/* Select simulation time */ /* Select simulation time */
TimeLine plugin = (TimeLine) p; TimeLine plugin = (TimeLine) p;
plugin.trySelectTime(time); plugin.trySelectTime(time);
} }
} }
@ -1039,6 +1037,7 @@ public class RadioLogger extends VisPlugin {
private Action logListenerAction = new AbstractAction("Mote output") { private Action logListenerAction = new AbstractAction("Mote output") {
private static final long serialVersionUID = 1985006491187878651L; private static final long serialVersionUID = 1985006491187878651L;
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
int selectedRow = dataTable.getSelectedRow(); int selectedRow = dataTable.getSelectedRow();
if (selectedRow < 0) return; if (selectedRow < 0) return;
@ -1049,12 +1048,12 @@ public class RadioLogger extends VisPlugin {
Plugin[] plugins = simulation.getCooja().getStartedPlugins(); Plugin[] plugins = simulation.getCooja().getStartedPlugins();
for (Plugin p: plugins) { for (Plugin p: plugins) {
if (!(p instanceof LogListener)) { if (!(p instanceof LogListener)) {
continue; continue;
} }
/* Select simulation time */ /* Select simulation time */
LogListener plugin = (LogListener) p; LogListener plugin = (LogListener) p;
plugin.trySelectTime(time); plugin.trySelectTime(time);
} }
} }
@ -1062,9 +1061,11 @@ public class RadioLogger extends VisPlugin {
private Action showInAllAction = new AbstractAction("Timeline and mote output") { private Action showInAllAction = new AbstractAction("Timeline and mote output") {
private static final long serialVersionUID = -3888292108886138128L; private static final long serialVersionUID = -3888292108886138128L;
{ {
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true));
} }
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
timeLineAction.actionPerformed(null); timeLineAction.actionPerformed(null);
logListenerAction.actionPerformed(null); logListenerAction.actionPerformed(null);
@ -1087,15 +1088,15 @@ public class RadioLogger extends VisPlugin {
} }
String alias = (String) JOptionPane.showInputDialog( String alias = (String) JOptionPane.showInputDialog(
Cooja.getTopParentContainer(), Cooja.getTopParentContainer(),
"Enter alias for all packets with identical payload.\n" + "Enter alias for all packets with identical payload.\n"
"An empty string removes the current alias.\n\n" + + "An empty string removes the current alias.\n\n"
connections.get(selectedRow).data + "\n", + connections.get(selectedRow).data + "\n",
"Create packet payload alias", "Create packet payload alias",
JOptionPane.QUESTION_MESSAGE, JOptionPane.QUESTION_MESSAGE,
null, null,
null, null,
current); current);
if (alias == null) { if (alias == null) {
/* Cancelled */ /* Cancelled */
return; return;
@ -1141,16 +1142,16 @@ public class RadioLogger extends VisPlugin {
}; };
public String getConnectionsString() { public String getConnectionsString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
RadioConnectionLog[] cs = connections.toArray(new RadioConnectionLog[0]); RadioConnectionLog[] cs = connections.toArray(new RadioConnectionLog[0]);
for(RadioConnectionLog c: cs) { for (RadioConnectionLog c : cs) {
sb.append(c.toString() + "\n"); sb.append(c.toString() + "\n");
} }
return sb.toString(); return sb.toString();
}; }
public void saveConnectionsToFile(String fileName) { public void saveConnectionsToFile(String fileName) {
StringUtils.saveToFile(new File(fileName), getConnectionsString()); StringUtils.saveToFile(new File(fileName), getConnectionsString());
}; }
} }

View file

@ -2,99 +2,101 @@ package org.contikios.cooja.plugins.analyzers;
public class ICMPv6Analyzer extends PacketAnalyzer { public class ICMPv6Analyzer extends PacketAnalyzer {
public static final byte ICMPv6_DISPATCH = 58; 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 = 0; /* DIS message */ public static final int ECHO_REQUEST = 128;
public static final int RPL_CODE_DIO = 1; /* DIO message */ public static final int ECHO_REPLY = 129;
public static final int RPL_CODE_DAO = 2;/* DAO message */ public static final int GROUP_QUERY = 130;
public static final int RPL_CODE_DAO_ACK = 3;/* DAO ACK message */ public static final int GROUP_REPORT = 131;
public static final int GROUP_REDUCTION = 132;
public static final int FLAG_ROUTER = 0x80; public static final int ROUTER_SOLICITATION = 133;
public static final int FLAG_SOLICITED = 0x40; public static final int ROUTER_ADVERTISEMENT = 134;
public static final int FLAG_OVERRIDE = 0x20; public static final int NEIGHBOR_SOLICITATION = 135;
public static final int NEIGHBOR_ADVERTISEMENT = 136;
public static final int ON_LINK = 0x80; public static final int RPL_CODE_DIS = 0; /* DIS message */
public static final int AUTOCONFIG = 0x40; public static final int RPL_CODE_DIO = 1; /* DIO message */
public static final int RPL_CODE_DAO = 2;/* DAO message */
public static final int RPL_CODE_DAO_ACK = 3;/* DAO ACK message */
public static final int SOURCE_LINKADDR = 1; public static final int FLAG_ROUTER = 0x80;
public static final int TARGET_LINKADDR = 2; public static final int FLAG_SOLICITED = 0x40;
public static final int PREFIX_INFO = 3; public static final int FLAG_OVERRIDE = 0x20;
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 static final int ON_LINK = 0x80;
public int analyzePacket(Packet packet, StringBuffer brief, public static final int AUTOCONFIG = 0x40;
StringBuffer verbose) {
int type = packet.get(0) & 0xff; public static final int SOURCE_LINKADDR = 1;
int code = packet.get(1) & 0xff; 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; // int checksum = ((packet.get(2) & 0xff) << 8) | packet.get(3) & 0xff;
brief.append("ICMPv6 "); brief.append("ICMPv6 ");
if (type >= 128 && (type - 128) < TYPE_NAME.length) { if (type >= 128 && (type - 128) < TYPE_NAME.length) {
brief.append(TYPE_NAME[type - 128]).append(' ').append(code); brief.append(TYPE_NAME[type - 128]).append(' ').append(code);
verbose.append("Type: ").append(TYPE_NAME[type - 128]); verbose.append("Type: ").append(TYPE_NAME[type - 128]);
verbose.append(" Code:").append(code); verbose.append(" Code:").append(code);
} else if (type == 155) { } else if (type == 155) {
/* RPL */ /* RPL */
brief.append("RPL "); brief.append("RPL ");
verbose.append("Type: RPL Code: "); verbose.append("Type: RPL Code: ");
switch(code) { switch (code) {
case RPL_CODE_DIS: case RPL_CODE_DIS:
brief.append("DIS"); brief.append("DIS");
verbose.append("DIS"); verbose.append("DIS");
break; break;
case RPL_CODE_DIO: case RPL_CODE_DIO:
brief.append("DIO"); brief.append("DIO");
verbose.append("DIO<br>"); verbose.append("DIO<br>");
int instanceID = packet.get(4) & 0xff;
int version = packet.get(5) & 0xff;
int rank = ((packet.get(6) & 0xff) << 8) + (packet.get(7) & 0xff);
int mop = (packet.get(8) >> 3) & 0x07;
int dtsn = packet.get(9);
verbose.append(" InstanceID: " + instanceID + " Version: " + version +
" Rank:" + rank + " MOP: " + mop + " DTSN: " + dtsn);
packet.consumeBytesStart(8);
break; int instanceID = packet.get(4) & 0xff;
case RPL_CODE_DAO: int version = packet.get(5) & 0xff;
brief.append("DAO"); int rank = ((packet.get(6) & 0xff) << 8) + (packet.get(7) & 0xff);
verbose.append("DAO"); int mop = (packet.get(8) >> 3) & 0x07;
break; int dtsn = packet.get(9);
case RPL_CODE_DAO_ACK:
brief.append("DAO ACK");
verbose.append("DAO ACK");
break;
default:
brief.append(code);
verbose.append(code);
}
}
/* remove type, code, crc */ verbose.append(" InstanceID: " + instanceID
packet.consumeBytesStart(4); + " Version: " + version
return ANALYSIS_OK_FINAL; + " Rank:" + rank
+ " MOP: " + mop
+ " DTSN: " + dtsn);
packet.consumeBytesStart(8);
break;
case RPL_CODE_DAO:
brief.append("DAO");
verbose.append("DAO");
break;
case RPL_CODE_DAO_ACK:
brief.append("DAO ACK");
verbose.append("DAO ACK");
break;
default:
brief.append(code);
verbose.append(code);
}
} }
@Override /* remove type, code, crc */
public boolean matchPacket(Packet packet) { packet.consumeBytesStart(4);
return packet.level == APPLICATION_LEVEL && packet.lastDispatch == ICMPv6_DISPATCH; return ANALYSIS_OK_FINAL;
} }
@Override
public boolean matchPacket(Packet packet) {
return packet.level == APPLICATION_LEVEL && packet.lastDispatch == ICMPv6_DISPATCH;
}
} }

View file

@ -7,175 +7,174 @@ import org.contikios.cooja.util.StringUtils;
public class IEEE802154Analyzer extends PacketAnalyzer { public class IEEE802154Analyzer extends PacketAnalyzer {
/* TODO: fix this to be correct */ /* TODO: fix this to be correct */
public static final int NO_ADDRESS = 0; public static final int NO_ADDRESS = 0;
public static final int RSV_ADDRESS = 1; public static final int RSV_ADDRESS = 1;
public static final int SHORT_ADDRESS = 2; public static final int SHORT_ADDRESS = 2;
public static final int LONG_ADDRESS = 3; public static final int LONG_ADDRESS = 3;
public static final int BEACONFRAME = 0x00; public static final int BEACONFRAME = 0x00;
public static final int DATAFRAME = 0x01; public static final int DATAFRAME = 0x01;
public static final int ACKFRAME = 0x02; public static final int ACKFRAME = 0x02;
public static final int CMDFRAME = 0x03; public static final int CMDFRAME = 0x03;
// private static final byte[] BROADCAST_ADDR = {(byte)0xff, (byte)0xff}; // private static final byte[] BROADCAST_ADDR = {(byte)0xff, (byte)0xff};
private static final String[] typeS = {"-", "D", "A"};
private static final String[] typeS = {"-", "D", "A"}; private static final String[] typeVerbose = {"BEACON", "DATA", "ACK"};
private static final String[] typeVerbose = {"BEACON", "DATA", "ACK"}; private PcapExporter pcapExporter;
private PcapExporter pcapExporter;
// private int defaultAddressMode = LONG_ADDRESS; // private int defaultAddressMode = LONG_ADDRESS;
// private byte seqNo = 0; // private byte seqNo = 0;
// private int myPanID = 0xabcd; // private int myPanID = 0xabcd;
public IEEE802154Analyzer(boolean pcap) {
public IEEE802154Analyzer(boolean pcap) { if (pcap) {
if (pcap) try { try {
pcapExporter = new PcapExporter(); pcapExporter = new PcapExporter();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
public void setPcapFile(File pcapFile) { public void setPcapFile(File pcapFile) {
if (pcapExporter != null) { if (pcapExporter != null) {
try { try {
pcapExporter.openPcap(pcapFile); pcapExporter.openPcap(pcapFile);
} catch (IOException e) { } catch (IOException e) {
System.err.println("Could not open pcap file"); System.err.println("Could not open pcap file");
e.printStackTrace(); e.printStackTrace();
} }
}
}
public boolean matchPacket(Packet packet) {
return packet.level == MAC_LEVEL;
}
/* this protocol always have network level packets as payload */
public int nextLevel(byte[] packet, int level) {
return NETWORK_LEVEL;
}
/* create a 802.15.4 packet of the bytes and "dispatch" to the
* next handler
*/
public int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose) {
if (pcapExporter != null) {
try {
pcapExporter.exportPacketData(packet.getPayload());
} catch (IOException e) {
System.err.println("Could not export PCap data");
e.printStackTrace();
} }
} }
public boolean matchPacket(Packet packet) { int pos = packet.pos;
return packet.level == MAC_LEVEL; int type = packet.data[pos + 0] & 7;
}
/* this protocol always have network level packets as payload */
public int nextLevel(byte[] packet, int level) {
return NETWORK_LEVEL;
}
/* create a 802.15.4 packet of the bytes and "dispatch" to the
* next handler
*/
public int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose) {
if (pcapExporter != null) {
try {
pcapExporter.exportPacketData(packet.getPayload());
} catch (IOException e) {
System.err.println("Could not export PCap data");
e.printStackTrace();
}
}
int pos = packet.pos;
int type = packet.data[pos + 0] & 7;
// int security = (packet.data[pos + 0] >> 3) & 1; // int security = (packet.data[pos + 0] >> 3) & 1;
// int pending = (packet.data[pos + 0] >> 4) & 1; // int pending = (packet.data[pos + 0] >> 4) & 1;
// int ackRequired = (packet.data[pos + 0] >> 5) & 1; // int ackRequired = (packet.data[pos + 0] >> 5) & 1;
int panCompression = (packet.data[pos + 0]>> 6) & 1; int panCompression = (packet.data[pos + 0] >> 6) & 1;
int destAddrMode = (packet.data[pos + 1] >> 2) & 3; int destAddrMode = (packet.data[pos + 1] >> 2) & 3;
// int frameVersion = (packet.data[pos + 1] >> 4) & 3; // int frameVersion = (packet.data[pos + 1] >> 4) & 3;
int srcAddrMode = (packet.data[pos + 1] >> 6) & 3; int srcAddrMode = (packet.data[pos + 1] >> 6) & 3;
int seqNumber = packet.data[pos + 2] & 0xff; int seqNumber = packet.data[pos + 2] & 0xff;
int destPanID = 0; int destPanID = 0;
int srcPanID = 0; int srcPanID = 0;
byte[] sourceAddress = null; byte[] sourceAddress = null;
byte[] destAddress = null; byte[] destAddress = null;
pos += 3; pos += 3;
if (destAddrMode > 0) { if (destAddrMode > 0) {
destPanID = (packet.data[pos] & 0xff) + ((packet.data[pos + 1] & 0xff) << 8); destPanID = (packet.data[pos] & 0xff) + ((packet.data[pos + 1] & 0xff) << 8);
pos += 2; pos += 2;
if (destAddrMode == SHORT_ADDRESS) { if (destAddrMode == SHORT_ADDRESS) {
destAddress = new byte[2]; destAddress = new byte[2];
destAddress[1] = packet.data[pos]; destAddress[1] = packet.data[pos];
destAddress[0] = packet.data[pos + 1]; destAddress[0] = packet.data[pos + 1];
pos += 2; pos += 2;
} else if (destAddrMode == LONG_ADDRESS) { } else if (destAddrMode == LONG_ADDRESS) {
destAddress = new byte[8]; destAddress = new byte[8];
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
destAddress[i] = packet.data[pos + 7 - i]; destAddress[i] = packet.data[pos + 7 - i];
}
pos += 8;
}
} }
pos += 8;
}
}
if (srcAddrMode > 0) { if (srcAddrMode > 0) {
if (panCompression == 0){ if (panCompression == 0) {
srcPanID = (packet.data[pos] & 0xff) + ((packet.data[pos + 1] & 0xff) << 8); srcPanID = (packet.data[pos] & 0xff) + ((packet.data[pos + 1] & 0xff) << 8);
pos += 2; pos += 2;
} else { } else {
srcPanID = destPanID; srcPanID = destPanID;
} }
if (srcAddrMode == SHORT_ADDRESS) { if (srcAddrMode == SHORT_ADDRESS) {
sourceAddress = new byte[2]; sourceAddress = new byte[2];
sourceAddress[1] = packet.data[pos]; sourceAddress[1] = packet.data[pos];
sourceAddress[0] = packet.data[pos + 1]; sourceAddress[0] = packet.data[pos + 1];
pos += 2; pos += 2;
} else if (srcAddrMode == LONG_ADDRESS) { } else if (srcAddrMode == LONG_ADDRESS) {
sourceAddress = new byte[8]; sourceAddress = new byte[8];
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
sourceAddress[i] = packet.data[pos + 7 - i]; sourceAddress[i] = packet.data[pos + 7 - i];
}
pos += 8;
}
} }
pos += 8;
}
}
// int payloadLen = packet.data.length - pos; // int payloadLen = packet.data.length - pos;
brief.append("15.4 ");
brief.append(type < typeS.length ? typeS[type] : "?").append(' ');
brief.append("15.4 "); verbose.append("<html><b>IEEE 802.15.4 ")
brief.append(type < typeS.length ? typeS[type] : "?").append(' '); .append(type < typeVerbose.length ? typeVerbose[type] : "?")
.append(' ').append(seqNumber);
if (type != ACKFRAME) {
printAddress(brief, srcAddrMode, sourceAddress);
brief.append(' ');
printAddress(brief, destAddrMode, destAddress);
verbose.append("<html><b>IEEE 802.15.4 ") verbose.append("</b><br>From ");
.append(type < typeVerbose.length ? typeVerbose[type] : "?") if (srcPanID != 0) {
.append(' ').append(seqNumber); verbose.append(StringUtils.toHex((byte) (srcPanID >> 8)))
if (type != ACKFRAME) { .append(StringUtils.toHex((byte) (srcPanID & 0xff)))
printAddress(brief, srcAddrMode, sourceAddress);
brief.append(' ');
printAddress(brief, destAddrMode, destAddress);
verbose.append("</b><br>From ");
if (srcPanID != 0) {
verbose.append(StringUtils.toHex((byte)(srcPanID >> 8)))
.append(StringUtils.toHex((byte)(srcPanID & 0xff)))
.append('/'); .append('/');
} }
printAddress(verbose, srcAddrMode, sourceAddress); printAddress(verbose, srcAddrMode, sourceAddress);
verbose.append(" to "); verbose.append(" to ");
if (destPanID != 0) { if (destPanID != 0) {
verbose.append(StringUtils.toHex((byte)(destPanID >> 8))) verbose.append(StringUtils.toHex((byte) (destPanID >> 8)))
.append(StringUtils.toHex((byte)(destPanID & 0xff))) .append(StringUtils.toHex((byte) (destPanID & 0xff)))
.append('/'); .append('/');
} }
printAddress(verbose, destAddrMode, destAddress); printAddress(verbose, destAddrMode, destAddress);
} else { } else {
/* got ack - no more to do ... */ /* got ack - no more to do ... */
return ANALYSIS_OK_FINAL; return ANALYSIS_OK_FINAL;
}
/* update packet */
packet.pos = pos;
packet.level = NETWORK_LEVEL;
/* remove CRC from the packet */
packet.consumeBytesEnd(2);
packet.llsender = sourceAddress;
packet.llreceiver = destAddress;
return ANALYSIS_OK_CONTINUE;
} }
private void printAddress(StringBuffer sb, int type, byte[] addr) { /* update packet */
if (type == SHORT_ADDRESS) { packet.pos = pos;
sb.append(StringUtils.toHex(addr)); packet.level = NETWORK_LEVEL;
} else if (type == LONG_ADDRESS) { /* remove CRC from the packet */
sb.append(StringUtils.toHex(addr[0]) + StringUtils.toHex(addr[1]) + ":" + packet.consumeBytesEnd(2);
StringUtils.toHex(addr[2]) + StringUtils.toHex(addr[3]) + ":" +
StringUtils.toHex(addr[4]) + StringUtils.toHex(addr[5]) + ":" + packet.llsender = sourceAddress;
StringUtils.toHex(addr[6]) + StringUtils.toHex(addr[7])); packet.llreceiver = destAddress;
} return ANALYSIS_OK_CONTINUE;
}
private void printAddress(StringBuffer sb, int type, byte[] addr) {
if (type == SHORT_ADDRESS) {
sb.append(StringUtils.toHex(addr));
} else if (type == LONG_ADDRESS) {
sb.append(StringUtils.toHex(addr[0]) + StringUtils.toHex(addr[1]) + ":"
+ StringUtils.toHex(addr[2]) + StringUtils.toHex(addr[3]) + ":"
+ StringUtils.toHex(addr[4]) + StringUtils.toHex(addr[5]) + ":"
+ StringUtils.toHex(addr[6]) + StringUtils.toHex(addr[7]));
} }
}
} }

View file

@ -4,365 +4,379 @@ import org.contikios.cooja.util.StringUtils;
public class IPHCPacketAnalyzer extends PacketAnalyzer { public class IPHCPacketAnalyzer extends PacketAnalyzer {
public final static int SICSLOWPAN_UDP_PORT_MIN = 0xF0B0; 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_UDP_PORT_MAX = 0xF0BF; /* F0B0 + 15 */
public final static int SICSLOWPAN_DISPATCH_IPV6 = 0x41; /* 01000001 = 65 */ 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_HC1 = 0x42; /* 01000010 = 66 */
public final static int SICSLOWPAN_DISPATCH_IPHC = 0x60; /* 011xxxxx = ... */ 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_FRAG1 = 0xc0; /* 1100= 0xxx */
public final static int SICSLOWPAN_DISPATCH_FRAGN = 0xe0; /* 1110= 0xxx */ public final static int SICSLOWPAN_DISPATCH_FRAGN = 0xe0; /* 1110= 0xxx */
/* /*
* Values of fields within the IPHC encoding first byte * Values of fields within the IPHC encoding first byte
* (C stands for compressed and I for inline) * (C stands for compressed and I for inline)
*/ */
public final static int SICSLOWPAN_IPHC_FL_C = 0x10; public final static int SICSLOWPAN_IPHC_FL_C = 0x10;
public final static int SICSLOWPAN_IPHC_TC_C = 0x08; public final static int SICSLOWPAN_IPHC_TC_C = 0x08;
public final static int SICSLOWPAN_IPHC_NH_C = 0x04; 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_1 = 0x01;
public final static int SICSLOWPAN_IPHC_TTL_64 = 0x02; 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_255 = 0x03;
public final static int SICSLOWPAN_IPHC_TTL_I = 0x00; public final static int SICSLOWPAN_IPHC_TTL_I = 0x00;
/* Values of fields within the IPHC encoding second byte */ /* Values of fields within the IPHC encoding second byte */
public final static int SICSLOWPAN_IPHC_CID = 0x80; public final static int SICSLOWPAN_IPHC_CID = 0x80;
public final static int SICSLOWPAN_IPHC_SAC = 0x40; public final static int SICSLOWPAN_IPHC_SAC = 0x40;
public final static int SICSLOWPAN_IPHC_SAM_00 = 0x00; 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_01 = 0x10;
public final static int SICSLOWPAN_IPHC_SAM_10 = 0x20; public final static int SICSLOWPAN_IPHC_SAM_10 = 0x20;
public final static int SICSLOWPAN_IPHC_SAM_11 = 0x30; public final static int SICSLOWPAN_IPHC_SAM_11 = 0x30;
public final static int SICSLOWPAN_IPHC_M = 0x08; public final static int SICSLOWPAN_IPHC_M = 0x08;
public final static int SICSLOWPAN_IPHC_DAC = 0x04; public final static int SICSLOWPAN_IPHC_DAC = 0x04;
public final static int SICSLOWPAN_IPHC_DAM_00 = 0x00; 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_01 = 0x01;
public final static int SICSLOWPAN_IPHC_DAM_10 = 0x02; public final static int SICSLOWPAN_IPHC_DAM_10 = 0x02;
public final static int SICSLOWPAN_IPHC_DAM_11 = 0x03; public final static int SICSLOWPAN_IPHC_DAM_11 = 0x03;
private static final int SICSLOWPAN_NDC_UDP_MASK = 0xf8; 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_ID = 0xf0;
private static final int SICSLOWPAN_NHC_UDP_C = 0xf3; private static final int SICSLOWPAN_NHC_UDP_C = 0xf3;
private static final int SICSLOWPAN_NHC_UDP_I = 0xf0; 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[][] { public final static int PROTO_UDP = 17;
{(byte)0xaa, (byte)0xaa, 0, 0, 0, 0, 0, 0} public final static int PROTO_TCP = 6;
}; public final static int PROTO_ICMP = 58;
private static final int IPHC_DISPATCH = 0x60; public final static byte[] UNSPECIFIED_ADDRESS
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* packet must be on network level && have a IPHC dispatch */ private static byte[][] addrContexts = new byte[][]{
public boolean matchPacket(Packet packet) { {(byte) 0xaa, (byte) 0xaa, 0, 0, 0, 0, 0, 0}
return packet.level == NETWORK_LEVEL && (packet.get(0) & 0xe0) == IPHC_DISPATCH; };
private static final int IPHC_DISPATCH = 0x60;
/* packet must be on network level && have a IPHC dispatch */
public boolean matchPacket(Packet packet) {
return packet.level == NETWORK_LEVEL && (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;
String error = null;
brief.append("IPHC");
/* need to decompress while analyzing - add that later... */
verbose.append("<b>IPHC HC-06</b><br>");
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("<br>Contexts: sci=" + (packet.get(2) >> 4) + " dci="
+ (packet.get(2) & 0x0f));
sci = packet.get(2) >> 4;
dci = packet.get(2) & 0x0f;
} }
public int analyzePacket(Packet packet, StringBuffer brief, int hc06_ptr = 2 + cid;
StringBuffer verbose) {
/* if packet has less than 3 bytes it is not interesting ... */ int version = 6;
if (packet.size() < 3) return ANALYSIS_FAILED; int trafficClass = 0;
int flowLabel = 0;
int tf = (packet.get(0) >> 3) & 0x03; int len = 0;
boolean nhc = (packet.get(0) & SICSLOWPAN_IPHC_NH_C) > 0; int proto = 0;
int hlim = (packet.get(0) & 0x03); int ttl = 0;
int cid = (packet.get(1) >> 7) & 0x01; byte[] srcAddress = new byte[16];
int sac = (packet.get(1) >> 6) & 0x01; byte[] destAddress = new byte[16];
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;
String error = null; int srcPort = 0;
int destPort = 0;
brief.append("IPHC");
/* need to decompress while analyzing - add that later... */ try {
/* Traffic class and flow label */
verbose.append("<b>IPHC HC-06</b><br>"); if ((packet.get(0) & SICSLOWPAN_IPHC_FL_C) == 0) {
verbose.append("tf = " + tf + " nhc = " + nhc + " hlim = " + hlim /* Flow label are carried inline */
+ " cid = " + cid + " sac = " + sac + " sam = " + sam if ((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) {
+ " MCast = " + m + " dac = " + dac + " dam = " + dam); /* Traffic class is carried inline */
if (cid == 1) { flowLabel = packet.getInt(hc06_ptr + 1, 3);
verbose.append("<br>Contexts: sci=" + (packet.get(2) >> 4) + " dci=" int tmp = packet.get(hc06_ptr);
+ (packet.get(2) & 0x0f)); hc06_ptr += 4;
sci = packet.get(2) >> 4; /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
dci = packet.get(2) & 0x0f; trafficClass = ((tmp >> 2) & 0x3f) | (tmp << 6) & (0x80 + 0x40);
} /* ECN rolled down two steps + lowest DSCP bits at top two bits */
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 = new byte[16];
byte[] destAddress = new byte[16];
int srcPort = 0;
int destPort = 0;
try {
/* 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 { } else {
/* Version is always 6! */ /* highest flow label bits + ECN bits */
/* Version and flow label are compressed */ int tmp = packet.get(hc06_ptr);
if((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) { trafficClass = (tmp >> 6) & 0x0f;
/* Traffic class is inline */ flowLabel = packet.getInt(hc06_ptr + 1, 2);
trafficClass =((packet.get(hc06_ptr) >> 6) & 0x03); hc06_ptr += 3;
trafficClass |= (packet.get(hc06_ptr) << 2);
hc06_ptr += 1;
}
} }
} else {
/* Next Header */ /* Version is always 6! */
if((packet.get(0) & SICSLOWPAN_IPHC_NH_C) == 0) { /* Version and flow label are compressed */
/* Next header is carried inline */ if ((packet.get(0) & SICSLOWPAN_IPHC_TC_C) == 0) {
proto = packet.get(hc06_ptr); /* Traffic class is inline */
hc06_ptr += 1; trafficClass = ((packet.get(hc06_ptr) >> 6) & 0x03);
trafficClass |= (packet.get(hc06_ptr) << 2);
hc06_ptr += 1;
} }
}
/* Hop limit */ /* Next Header */
switch(packet.get(0) & 0x03) { 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: case SICSLOWPAN_IPHC_TTL_1:
ttl = 1; ttl = 1;
break; break;
case SICSLOWPAN_IPHC_TTL_64: case SICSLOWPAN_IPHC_TTL_64:
ttl = 2; ttl = 2;
break; break;
case SICSLOWPAN_IPHC_TTL_255: case SICSLOWPAN_IPHC_TTL_255:
ttl = 255; ttl = 255;
break; break;
case SICSLOWPAN_IPHC_TTL_I: case SICSLOWPAN_IPHC_TTL_I:
ttl = packet.get(hc06_ptr); ttl = packet.get(hc06_ptr);
hc06_ptr += 1; 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 */
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 */
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 */
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; 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 */
/* context based compression */ packet.copy(hc06_ptr, srcAddress, 0, 16);
if((packet.get(1) & SICSLOWPAN_IPHC_SAC) > 0) { hc06_ptr += 16;
/* Source address */ break;
byte[] context = null; case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */
if((packet.get(1) & SICSLOWPAN_IPHC_SAM_11) != SICSLOWPAN_IPHC_SAM_00) {
context = addrContexts[sci];
}
switch(packet.get(1) & SICSLOWPAN_IPHC_SAM_11) { srcAddress[0] = (byte) 0xfe;
case SICSLOWPAN_IPHC_SAM_00: srcAddress[1] = (byte) 0x80;
/* copy the unspecificed address */ /* copy IID from packet */
srcAddress = UNSPECIFIED_ADDRESS; packet.copy(hc06_ptr, srcAddress, 8, 8);
break; hc06_ptr += 8;
case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */ break;
/* copy prefix from context */ case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */
System.arraycopy(context, 0, srcAddress, 0, 8);
/* copy IID from packet */ srcAddress[0] = (byte) 0xfe;
packet.copy(hc06_ptr, srcAddress, 8, 8); srcAddress[1] = (byte) 0x80;
hc06_ptr += 8; packet.copy(hc06_ptr, srcAddress, 14, 2);
break; hc06_ptr += 2;
case SICSLOWPAN_IPHC_SAM_10: /* 16 bits */ break;
/* unicast address */ case SICSLOWPAN_IPHC_SAM_11: /* 0 bits */
System.arraycopy(context, 0, srcAddress, 0, 8); /* setup link-local address */
/* copy 6 NULL bytes then 2 last bytes of IID */
packet.copy(hc06_ptr, srcAddress, 14, 2); srcAddress[0] = (byte) 0xfe;
hc06_ptr += 2; srcAddress[1] = (byte) 0x80;
break; /* infer IID from L2 address */
case SICSLOWPAN_IPHC_SAM_11: /* 0-bits */ System.arraycopy(packet.llsender, 0, srcAddress,
/* copy prefix from context */ 16 - packet.llsender.length, packet.llsender.length);
System.arraycopy(context, 0, srcAddress, 0, 8); break;
/* 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 */
packet.copy(hc06_ptr, srcAddress, 0, 16);
hc06_ptr += 16;
break;
case SICSLOWPAN_IPHC_SAM_01: /* 64 bits */
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[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[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 */ /* Destination address */
/* multicast compression */ /* multicast compression */
if((packet.get(1) & SICSLOWPAN_IPHC_M) != 0) { if ((packet.get(1) & SICSLOWPAN_IPHC_M) != 0) {
/* context based multicast compression */ /* context based multicast compression */
if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { if ((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) {
/* TODO: implement this */ /* 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 */
packet.copy(hc06_ptr, destAddress, 0, 16);
hc06_ptr += 16;
break;
case SICSLOWPAN_IPHC_DAM_01: /* 48 bits FFXX::00XX:XXXX:XXXX */
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[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[0] = (byte) 0xff;
destAddress[1] = (byte) 0x02;
destAddress[15] = packet.get(hc06_ptr);
hc06_ptr++;
break;
}
}
} else { } else {
/* no multicast */ /* non-context based multicast compression */
/* Context based */ switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) {
if((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) { case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */
byte[] context = addrContexts[dci]; /* copy whole address from packet */
switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { packet.copy(hc06_ptr, destAddress, 0, 16);
case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */ hc06_ptr += 16;
System.arraycopy(context, 0, destAddress, 0, 8); break;
/* copy IID from packet */ case SICSLOWPAN_IPHC_DAM_01: /* 48 bits FFXX::00XX:XXXX:XXXX */
packet.copy(hc06_ptr, destAddress, 8, 8);
hc06_ptr += 8; destAddress[0] = (byte) 0xff;
break; destAddress[1] = packet.get(hc06_ptr);
case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */ packet.copy(hc06_ptr + 1, destAddress, 11, 5);
/* unicast address */ hc06_ptr += 6;
System.arraycopy(context, 0, destAddress, 0, 8); break;
/* copy IID from packet */ case SICSLOWPAN_IPHC_DAM_10: /* 32 bits FFXX::00XX:XXXX */
packet.copy(hc06_ptr, destAddress, 14, 2);
hc06_ptr += 2; destAddress[0] = (byte) 0xff;
break; destAddress[1] = packet.get(hc06_ptr);
case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ packet.copy(hc06_ptr + 1, destAddress, 13, 3);
/* unicast address */ hc06_ptr += 4;
System.arraycopy(context, 0, destAddress, 0, 8); break;
/* infer IID from L2 address */ case SICSLOWPAN_IPHC_DAM_11: /* 8 bits FF02::00XX */
System.arraycopy(packet.llreceiver, 0, destAddress,
16 - packet.llreceiver.length, packet.llreceiver.length); destAddress[0] = (byte) 0xff;
break; destAddress[1] = (byte) 0x02;
} destAddress[15] = packet.get(hc06_ptr);
} else { hc06_ptr++;
/* not context based => link local M = 0, DAC = 0 - same as SAC */ break;
switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) { }
case SICSLOWPAN_IPHC_DAM_00: /* 128 bits */
packet.copy(hc06_ptr, destAddress, 0, 16);
hc06_ptr += 16;
break;
case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */
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[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[0] = (byte) 0xfe;
destAddress[1] = (byte) 0x80;
System.arraycopy(packet.llreceiver, 0, destAddress,
16 - packet.llreceiver.length, packet.llreceiver.length);
break;
}
}
} }
} else {
/* no multicast */
/* Context based */
if ((packet.get(1) & SICSLOWPAN_IPHC_DAC) != 0) {
byte[] context = addrContexts[dci];
/* Next header processing - continued */ switch (packet.get(1) & SICSLOWPAN_IPHC_DAM_11) {
if(nhc) { case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */
/* TODO: check if this is correct in hc-06 */
/* The next header is compressed, NHC is following */ System.arraycopy(context, 0, destAddress, 0, 8);
if((packet.get(hc06_ptr) & SICSLOWPAN_NDC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) { /* copy IID from packet */
proto = PROTO_UDP; packet.copy(hc06_ptr, destAddress, 8, 8);
switch(packet.get(hc06_ptr)) { hc06_ptr += 8;
case (byte) SICSLOWPAN_NHC_UDP_C: break;
/* 1 byte for NHC, 1 byte for ports, 2 bytes chksum */ case SICSLOWPAN_IPHC_DAM_10: /* 16 bits */
srcPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) >> 4); /* unicast address */
destPort = SICSLOWPAN_UDP_PORT_MIN + (packet.get(hc06_ptr + 1) & 0x0F);
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 */
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 */
packet.copy(hc06_ptr, destAddress, 0, 16);
hc06_ptr += 16;
break;
case SICSLOWPAN_IPHC_DAM_01: /* 64 bits */
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[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[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); // memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 2, 2);
// PRINTF("IPHC: Uncompressed UDP ports (4): %x, %x\n", // PRINTF("IPHC: Uncompressed UDP ports (4): %x, %x\n",
// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); // SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport);
hc06_ptr += 4; hc06_ptr += 4;
break; break;
case (byte) SICSLOWPAN_NHC_UDP_I: case (byte) SICSLOWPAN_NHC_UDP_I:
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */ /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
srcPort = packet.getInt(hc06_ptr + 1, 2); srcPort = packet.getInt(hc06_ptr + 1, 2);
destPort = packet.getInt(hc06_ptr + 3, 2); destPort = packet.getInt(hc06_ptr + 3, 2);
// memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 5, 2); // memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr + 5, 2);
// PRINTF("IPHC: Uncompressed UDP ports (7): %x, %x\n", // PRINTF("IPHC: Uncompressed UDP ports (7): %x, %x\n",
// SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport); // SICSLOWPAN_UDP_BUF->srcport, SICSLOWPAN_UDP_BUF->destport);
hc06_ptr += 7; hc06_ptr += 7;
break; break;
default: default:
// PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n"); // PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
return ANALYSIS_FAILED; return ANALYSIS_FAILED;
} }
}
} }
}
// /* IP length field. */ // /* IP length field. */
// if(ip_len == 0) { // if(ip_len == 0) {
@ -374,54 +388,54 @@ public class IPHCPacketAnalyzer extends PacketAnalyzer {
// SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8; // SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
// SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF; // SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
// } // }
// /* length field in UDP header */ // /* length field in UDP header */
// if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) { // if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
// memcpy(&SICSLOWPAN_UDP_BUF->udplen, ipBuf + len[0], 2); // memcpy(&SICSLOWPAN_UDP_BUF->udplen, ipBuf + len[0], 2);
// } // }
/*--------------------------------------------- */ /*--------------------------------------------- */
} catch (Exception e) {
// some kind of unexpected error...
error = " error during IPHC parsing: " + e.getMessage();
}
packet.pos += hc06_ptr;
} catch (Exception e) { String protoStr = "" + proto;
// some kind of unexpected error... if (proto == PROTO_ICMP) {
error = " error during IPHC parsing: " + e.getMessage(); protoStr = "ICMPv6";
} } else if (proto == PROTO_UDP) {
packet.pos += hc06_ptr; protoStr = "UDP";
} else if (proto == PROTO_TCP) {
String protoStr = "" + proto; protoStr = "TCP";
if (proto == PROTO_ICMP) {
protoStr = "ICMPv6";
} else if (proto == PROTO_UDP) protoStr = "UDP";
else if (proto == PROTO_TCP) protoStr = "TCP";
verbose.append("<br><b>IPv6 ").append(protoStr).append("</b> TC = " + trafficClass +
" FL: " + flowLabel + "<br>");
verbose.append("From ");
printAddress(verbose, srcAddress);
verbose.append(" to ");
printAddress(verbose, destAddress);
if (error != null) verbose.append(" " + error);
packet.lastDispatch = (byte) (proto & 0xff);
if (proto == PROTO_UDP || proto == PROTO_ICMP ||
proto == PROTO_TCP) {
packet.level = APPLICATION_LEVEL;
return ANALYSIS_OK_CONTINUE;
} else {
packet.level = NETWORK_LEVEL;
return ANALYSIS_OK_CONTINUE;
}
} }
public static void printAddress(StringBuffer out, byte[] address) { verbose.append("<br><b>IPv6 ").append(protoStr)
for (int i = 0; i < 16; i+=2) { .append("</b> TC = " + trafficClass
out.append(StringUtils.toHex((byte) (address[i] & 0xff)) + + " FL: " + flowLabel + "<br>");
StringUtils.toHex((byte) (address[i + 1] & 0xff))); verbose.append("From ");
if (i < 14) { printAddress(verbose, srcAddress);
out.append(":"); verbose.append(" to ");
} printAddress(verbose, destAddress);
} if (error != null) verbose.append(" " + error);
}
packet.lastDispatch = (byte) (proto & 0xff);
if (proto == PROTO_UDP || proto == PROTO_ICMP
|| proto == PROTO_TCP) {
packet.level = APPLICATION_LEVEL;
return ANALYSIS_OK_CONTINUE;
} else {
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(":");
}
}
}
} }

View file

@ -4,78 +4,77 @@ import org.contikios.cooja.util.StringUtils;
public class IPv6PacketAnalyzer extends PacketAnalyzer { public class IPv6PacketAnalyzer extends PacketAnalyzer {
public final static int PROTO_UDP = 17;
public final static int PROTO_UDP = 17; public final static int PROTO_TCP = 6;
public final static int PROTO_TCP = 6; public final static int PROTO_ICMP = 58;
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 final int IPV6_DISPATCH = 0x41; public final static byte[] UNSPECIFIED_ADDRESS
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public boolean matchPacket(Packet packet) { private static final int IPV6_DISPATCH = 0x41;
return packet.level == NETWORK_LEVEL && packet.get(0) == IPV6_DISPATCH;
public boolean matchPacket(Packet packet) {
return packet.level == NETWORK_LEVEL && packet.get(0) == IPV6_DISPATCH;
}
public int analyzePacket(Packet packet, StringBuffer brief,
StringBuffer verbose) {
/* if packet has less than 40 bytes it is not interesting ... */
if (packet.size() < 40) return ANALYSIS_FAILED;
brief.append("IPv6");
/* need to decompress while analyzing - add that later... */
verbose.append("<b>IPv6</b><br>");
int pos = 1;
int version = 6;
int trafficClass = 0;
int flowLabel = 0;
int len = packet.getInt(pos + 4, 2);
int proto = packet.getInt(pos + 6, 1);
int ttl = packet.getInt(pos + 7, 1);
byte[] srcAddress = new byte[16];
byte[] destAddress = new byte[16];
packet.copy(pos + 8, srcAddress, 0, 16);
packet.copy(pos + 24, destAddress, 0, 16);
String protoStr = "" + proto;
if (proto == PROTO_ICMP) {
protoStr = "ICMPv6";
} else if (proto == PROTO_UDP) {
protoStr = "UDP";
} else if (proto == PROTO_TCP) {
protoStr = "TCP";
} }
public int analyzePacket(Packet packet, StringBuffer brief, /* consume dispatch + IP header */
StringBuffer verbose) { packet.pos += 41;
/* if packet has less than 40 bytes it is not interesting ... */ verbose.append("<br><b>IPv6 ").append(protoStr)
if (packet.size() < 40) return ANALYSIS_FAILED; .append("</b> TC = " + trafficClass
+ " FL: " + flowLabel + "<br>");
verbose.append("From ");
printAddress(verbose, srcAddress);
verbose.append(" to ");
printAddress(verbose, destAddress);
brief.append("IPv6"); packet.lastDispatch = (byte) (proto & 0xff);
packet.level = APPLICATION_LEVEL;
return ANALYSIS_OK_CONTINUE;
}
/* need to decompress while analyzing - add that later... */ public static void printAddress(StringBuffer out, byte[] address) {
for (int i = 0; i < 16; i += 2) {
verbose.append("<b>IPv6</b><br>"); out.append(StringUtils.toHex((byte) (address[i] & 0xff))
+ StringUtils.toHex((byte) (address[i + 1] & 0xff)));
int pos = 1; if (i < 14) {
out.append(":");
int version = 6;
int trafficClass = 0;
int flowLabel = 0;
int len = packet.getInt(pos + 4, 2);
int proto = packet.getInt(pos + 6, 1);
int ttl = packet.getInt(pos + 7, 1);
byte[] srcAddress = new byte[16];
byte[] destAddress = new byte[16];
packet.copy(pos + 8, srcAddress, 0, 16);
packet.copy(pos + 24, destAddress, 0, 16);
String protoStr = "" + proto;
if (proto == PROTO_ICMP) {
protoStr = "ICMPv6";
} else if (proto == PROTO_UDP) protoStr = "UDP";
else if (proto == PROTO_TCP) protoStr = "TCP";
/* consume dispatch + IP header */
packet.pos += 41;
verbose.append("<br><b>IPv6 ").append(protoStr).append("</b> TC = " + trafficClass +
" FL: " + flowLabel + "<br>");
verbose.append("From ");
printAddress(verbose, srcAddress);
verbose.append(" to ");
printAddress(verbose, destAddress);
packet.lastDispatch = (byte) (proto & 0xff);
packet.level = APPLICATION_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(":");
}
}
} }
}
}
} }

View file

@ -2,88 +2,86 @@ package org.contikios.cooja.plugins.analyzers;
public abstract class PacketAnalyzer { public abstract class PacketAnalyzer {
public static final int ANALYSIS_FAILED = -1; public static final int ANALYSIS_FAILED = -1;
public static final int ANALYSIS_OK_CONTINUE = 1; public static final int ANALYSIS_OK_CONTINUE = 1;
public static final int ANALYSIS_OK_FINAL = 2; 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;
public static final int APPLICATION_LEVEL = 3;
public static class Packet {
byte[] data;
int pos;
int level;
/* size = length - consumed bytes at tail */
int size;
/* L2 addresseses */
byte[] llsender;
byte[] llreceiver;
byte lastDispatch = 0; public static final int RADIO_LEVEL = 0;
public static final int MAC_LEVEL = 1;
public Packet(byte[] data, int level) { public static final int NETWORK_LEVEL = 2;
this.level = level; public static final int APPLICATION_LEVEL = 3;
this.data = data;
this.size = data.length;
}
public static class Packet {
public void consumeBytesStart(int bytes) { byte[] data;
pos += bytes; int pos;
} int level;
/* size = length - consumed bytes at tail */
int size;
public void consumeBytesEnd(int bytes) { /* L2 addresseses */
size -= bytes; byte[] llsender;
} byte[] llreceiver;
public boolean hasMoreData() {
return size > pos;
}
public int size() {
return size - pos;
}
public byte get(int index) {
if (index >= size) return 0;
return data[pos + index];
}
public int getInt(int index, int size) { byte lastDispatch = 0;
int value = 0;
for (int i = 0; i < size; i++) {
value = (value << 8) + get(index + i);
}
return value;
}
public Packet(byte[] data, int level) {
public byte[] getPayload() { this.level = level;
byte[] pload = new byte[size - pos]; this.data = data;
System.arraycopy(data, pos, pload, 0, pload.length); this.size = data.length;
return pload; }
}
public void copy(int srcpos, byte[] arr, int pos, int len) { public void consumeBytesStart(int bytes) {
for (int i = 0; i < len; i++) { pos += bytes;
arr[pos + i] = get(srcpos + i); }
}
}
public byte[] getLLSender() { public void consumeBytesEnd(int bytes) {
return llsender; size -= bytes;
} }
public byte[] getLLReceiver() { public boolean hasMoreData() {
return llreceiver; return size > pos;
} }
};
public int size() {
public abstract boolean matchPacket(Packet packet); return size - pos;
}
public abstract int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose);
} public byte get(int index) {
if (index >= size) return 0;
return data[pos + index];
}
public int getInt(int index, int size) {
int value = 0;
for (int i = 0; i < size; i++) {
value = (value << 8) + get(index + i);
}
return value;
}
public byte[] getPayload() {
byte[] pload = new byte[size - pos];
System.arraycopy(data, pos, pload, 0, pload.length);
return pload;
}
public void copy(int srcpos, byte[] arr, int pos, int len) {
for (int i = 0; i < len; i++) {
arr[pos + i] = get(srcpos + i);
}
}
public byte[] getLLSender() {
return llsender;
}
public byte[] getLLReceiver() {
return llreceiver;
}
};
public abstract boolean matchPacket(Packet packet);
public abstract int analyzePacket(Packet packet, StringBuffer brief, StringBuffer verbose);
}

View file

@ -9,55 +9,55 @@ import java.io.File;
public class PcapExporter { public class PcapExporter {
DataOutputStream out; DataOutputStream out;
public PcapExporter() throws IOException {
}
public void openPcap(File pcapFile) throws IOException {
if ( out != null ) {
closePcap();
}
if ( pcapFile == null ) {
/* pcap file not specified, use default file name */
pcapFile = new File("radiolog-" + System.currentTimeMillis() + ".pcap");
}
out = new DataOutputStream(new FileOutputStream(pcapFile));
/* pcap header */
out.writeInt(0xa1b2c3d4);
out.writeShort(0x0002);
out.writeShort(0x0004);
out.writeInt(0);
out.writeInt(0);
out.writeInt(4096);
out.writeInt(195); /* 195 for LINKTYPE_IEEE802_15_4 */
out.flush();
System.out.println("Opened pcap file " + pcapFile);
}
public void closePcap() throws IOException {
out.close();
out = null;
}
public void exportPacketData(byte[] data) throws IOException { public PcapExporter() throws IOException {
if (out == null) { }
/* pcap file never set, open default */
openPcap(null); public void openPcap(File pcapFile) throws IOException {
} if (out != null) {
try { closePcap();
/* pcap packet header */
out.writeInt((int) (System.currentTimeMillis() / 1000));
out.writeInt((int) ((System.currentTimeMillis() % 1000) * 1000));
out.writeInt(data.length);
out.writeInt(data.length);
/* and the data */
out.write(data);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
} }
if (pcapFile == null) {
/* pcap file not specified, use default file name */
pcapFile = new File("radiolog-" + System.currentTimeMillis() + ".pcap");
}
out = new DataOutputStream(new FileOutputStream(pcapFile));
/* pcap header */
out.writeInt(0xa1b2c3d4);
out.writeShort(0x0002);
out.writeShort(0x0004);
out.writeInt(0);
out.writeInt(0);
out.writeInt(4096);
out.writeInt(195); /* 195 for LINKTYPE_IEEE802_15_4 */
out.flush();
System.out.println("Opened pcap file " + pcapFile);
}
public void closePcap() throws IOException {
out.close();
out = null;
}
public void exportPacketData(byte[] data) throws IOException {
if (out == null) {
/* pcap file never set, open default */
openPcap(null);
}
try {
/* pcap packet header */
out.writeInt((int) (System.currentTimeMillis() / 1000));
out.writeInt((int) ((System.currentTimeMillis() % 1000) * 1000));
out.writeInt(data.length);
out.writeInt(data.length);
/* and the data */
out.write(data);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
} }