[cooja] plugins/analyzers: Indention and whitespace cleanups
This commit is contained in:
parent
01bd045570
commit
3e9a780721
|
@ -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());
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(":");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue