diff --git a/tools/.classpath b/tools/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..205625cc4c22bb1a948a5a60fabc50af99ef925d --- /dev/null +++ b/tools/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/.project b/tools/.project new file mode 100644 index 0000000000000000000000000000000000000000..cee79a6d9c0dcfbb44141706cd2913f009a472e7 --- /dev/null +++ b/tools/.project @@ -0,0 +1,17 @@ + + + pcapdump + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/tools/.settings/org.eclipse.jdt.core.prefs b/tools/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..bb35fa0a87b032ee9d0b128004c1edbd464f07bf --- /dev/null +++ b/tools/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/tools/PcapDump.bat b/tools/PcapDump.bat new file mode 100644 index 0000000000000000000000000000000000000000..1fd507d799a3473d026cf0952a6b6a43b6595a0e --- /dev/null +++ b/tools/PcapDump.bat @@ -0,0 +1,19 @@ +@echo "Starting PcapDump..." +@title PcapDump + +@set JAVA_PATH=C:\Program Files\Java\jre1.8.0_101\bin +@rem set BASE_PATH=C:\Users\garciay\Documents\ETSI\ITS + +@rem Home laptop +@rem set JAVA_PATH=C:\Program Files\Java\jre1.8.0_101\bin +@rem set JAVA_PATH=C:\Program Files (x86)\Java\jre8\bin +@set BASE_PATH=F:\FSCOM\ETSI\ITS + +@set LOG_PATH=%BASE_PATH%\STF517_ITS_Valid_Conform_Frmwk.2016\workspace_eclipse\pcapdump\lib +@set CODEC_PATH=%LOG_PATH%\PcapDump.jar +@set JNETPCAP_PATH=%BASE_PATH%\STF517_ITS_Valid_Conform_Frmwk.2016\workspace_ttwb\STF517\tt3plugins\EtsiItsAdapter\jnetpcap-1.4.r1425\jnetpcap.jar + +@"%JAVA_PATH%\java.exe" -cp "%CODEC_PATH%;%JNETPCAP_PATH%" org.etsi.its.pcapdump.pcapdump +@rem --FileName yann.pcap --NicAddr 00FF6BADBFC2 --FrameType=8947 +@rem pause + diff --git a/tools/PcapDump.jardesc b/tools/PcapDump.jardesc new file mode 100644 index 0000000000000000000000000000000000000000..dcec9a4d075c2853c57aad6cccf41837e3b531c7 --- /dev/null +++ b/tools/PcapDump.jardesc @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tools/bin/org/etsi/common/ByteHelper.class b/tools/bin/org/etsi/common/ByteHelper.class new file mode 100644 index 0000000000000000000000000000000000000000..fef8374559dfe286e98db182ae2f3117f222e892 Binary files /dev/null and b/tools/bin/org/etsi/common/ByteHelper.class differ diff --git a/tools/bin/org/etsi/common/ITuple.class b/tools/bin/org/etsi/common/ITuple.class new file mode 100644 index 0000000000000000000000000000000000000000..0ad0044427480d216ab7a29379c49c28692c07e2 Binary files /dev/null and b/tools/bin/org/etsi/common/ITuple.class differ diff --git a/tools/bin/org/etsi/common/KPM.class b/tools/bin/org/etsi/common/KPM.class new file mode 100644 index 0000000000000000000000000000000000000000..f8a5f2fe8af3c9e3b8e7ab6982bea5fd1fd3f69b Binary files /dev/null and b/tools/bin/org/etsi/common/KPM.class differ diff --git a/tools/bin/org/etsi/common/Tuple.class b/tools/bin/org/etsi/common/Tuple.class new file mode 100644 index 0000000000000000000000000000000000000000..9a69048106381cab04fa969e3451b7c2dc6df91e Binary files /dev/null and b/tools/bin/org/etsi/common/Tuple.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$IllegalOptionValueException.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$IllegalOptionValueException.class new file mode 100644 index 0000000000000000000000000000000000000000..4fd582c600d42de7fe809746a62070492ef8c82b Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$IllegalOptionValueException.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$NotFlagException.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$NotFlagException.class new file mode 100644 index 0000000000000000000000000000000000000000..01199f0bf0d1c2a9c64246711cdb9ba3034f83b3 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$NotFlagException.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$BooleanOption.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$BooleanOption.class new file mode 100644 index 0000000000000000000000000000000000000000..45250e5c4cf65ca7691d2415bd65e9956d30e7c7 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$BooleanOption.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$DoubleOption.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$DoubleOption.class new file mode 100644 index 0000000000000000000000000000000000000000..547ad8ffc02d91d806857b7f42c5b57de14c7c72 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$DoubleOption.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$IntegerOption.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$IntegerOption.class new file mode 100644 index 0000000000000000000000000000000000000000..62f6dc1d307306d8609a2096ff402ba970eed515 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$IntegerOption.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$LongOption.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$LongOption.class new file mode 100644 index 0000000000000000000000000000000000000000..4e108eeec310b1925111d37ca8dba7e0ff743352 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$LongOption.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$StringOption.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$StringOption.class new file mode 100644 index 0000000000000000000000000000000000000000..6c91be837cf951d7773b038207c4c237de380dd9 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option$StringOption.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option.class new file mode 100644 index 0000000000000000000000000000000000000000..2442b1a0dc88166f99f4255cbacb6e30046cdacd Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$Option.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$OptionException.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$OptionException.class new file mode 100644 index 0000000000000000000000000000000000000000..b54e43a72f08753b8f1f60b1c29e7220dab80d9b Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$OptionException.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownOptionException.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownOptionException.class new file mode 100644 index 0000000000000000000000000000000000000000..921ebf8776f3f9b694f74588290e815a57a7d5bb Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownOptionException.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownSuboptionException.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownSuboptionException.class new file mode 100644 index 0000000000000000000000000000000000000000..e87f730097a852b8baa15e0456ee321ca59e11bd Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser$UnknownSuboptionException.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/CmdLineParser.class b/tools/bin/org/etsi/its/pcapdump/CmdLineParser.class new file mode 100644 index 0000000000000000000000000000000000000000..f35caca8f7230bb8d6a5df9d9363cb9bd59151a7 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/CmdLineParser.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/ILayer.class b/tools/bin/org/etsi/its/pcapdump/ILayer.class new file mode 100644 index 0000000000000000000000000000000000000000..80a9aa1245a8b9ad6be0f301b3c2efb715402b30 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/ILayer.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer$1.class b/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer$1.class new file mode 100644 index 0000000000000000000000000000000000000000..88f40a53fe1642745fb7c8fce1acb82f9ed98d5e Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer$1.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer.class b/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer.class new file mode 100644 index 0000000000000000000000000000000000000000..12e506ff1aa94768e503f932f2e521106cc651db Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/PcapMultiplexer.class differ diff --git a/tools/bin/org/etsi/its/pcapdump/pcapdump.class b/tools/bin/org/etsi/its/pcapdump/pcapdump.class new file mode 100644 index 0000000000000000000000000000000000000000..ad4271bcbf88ca4416f511a201729e11b8dd4d99 Binary files /dev/null and b/tools/bin/org/etsi/its/pcapdump/pcapdump.class differ diff --git a/tools/itsdump.pcapng b/tools/itsdump.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..07d7efd2ab1a93b3c655401a672df18bb9330a19 Binary files /dev/null and b/tools/itsdump.pcapng differ diff --git a/tools/itsdump.pcapng_1475823029887 b/tools/itsdump.pcapng_1475823029887 new file mode 100644 index 0000000000000000000000000000000000000000..82d353e51e55027d3ff1eff9dc4de369b7396786 Binary files /dev/null and b/tools/itsdump.pcapng_1475823029887 differ diff --git a/tools/lib/PcapDump.jar b/tools/lib/PcapDump.jar new file mode 100644 index 0000000000000000000000000000000000000000..f67ac0813a5ea190f94ccfc6e43c9592f4819365 Binary files /dev/null and b/tools/lib/PcapDump.jar differ diff --git a/tools/src/org/etsi/common/ByteHelper.java b/tools/src/org/etsi/common/ByteHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..b595b4c1c26e5265bc55f7bd14d304378f23dd2d --- /dev/null +++ b/tools/src/org/etsi/common/ByteHelper.java @@ -0,0 +1,284 @@ +package org.etsi.common; + +import java.nio.ByteOrder; + +public class ByteHelper { + + public static byte[] changeEndianness(byte [] in) { + byte[] out = new byte[in.length]; + for(int i=0; i < in.length; i++) { + out[in.length - i -1] = in[i]; + } + return out; + } + + public static byte[] intToByteArray(int value, int length, ByteOrder byteOrder) { + if(byteOrder == ByteOrder.LITTLE_ENDIAN) { + return changeEndianness(intToByteArray(value, length)); + } + return intToByteArray(value, length); + } + + public static byte[] intToByteArray(int value, int length) { + byte[] b = new byte[length]; + for (int i = length - 1; i >= 0; i--) { + int offset = (b.length - 1 - i) * 8; + b[i] = (byte) ((value >>> offset) & 0xFF); + } + return b; + } + + public static byte[] longToByteArray(long value, int length, ByteOrder byteOrder) { + if(byteOrder == ByteOrder.LITTLE_ENDIAN) { + return changeEndianness(longToByteArray(value, length)); + } + return longToByteArray(value, length); + } + + public static byte[] longToByteArray(long value, int length) { + byte[] b = new byte[length]; + for (int i = length - 1; i >= 0; i--) { + int offset = (b.length - 1 - i) * 8; + b[i] = (byte) ((value >>> offset) & 0xFF); + } + return b; + } + + /** Convert a byte array into a boolean + * + * @param b The byte array to convert + * @return The boolean value on success, false otherwise + */ + public static Boolean byteArrayToBoolean(byte[] b) { + // Sanity check + if ((b == null) || (b.length != 1)) { + return null; + } + + return new Boolean(b[0] == 0x01); + } // End of method byteArrayToBoolean + + public static Short byteArrayToShort(final byte[] b, ByteOrder byteOrder) { + if(byteOrder == ByteOrder.LITTLE_ENDIAN) { + return byteArrayToShort(changeEndianness(b)); + } + return byteArrayToShort(b); + } + + /** Convert a byte array into a short value assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The short value on success, 'Integer.MAX_VALUE' otherwise + */ + public static Short byteArrayToShort(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Short.SIZE)) { + return Short.MAX_VALUE; + } + + short value = 0; + for (Short i = 0; i < b.length; i++) { + value = (short)((value << 8) + (b[i] & 0xff)); + } + + return new Short(value); + } // End of method byteArrayToInt + + public static Integer byteArrayToInt(final byte[] b, ByteOrder byteOrder) { + if(byteOrder == ByteOrder.LITTLE_ENDIAN) { + return byteArrayToInt(changeEndianness(b)); + } + return byteArrayToInt(b); + } + + /** Convert a byte array into an integer assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The integer value on success, 'Integer.MAX_VALUE' otherwise + */ + public static Integer byteArrayToInt(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Integer.SIZE)) { + return Integer.MAX_VALUE; + } + + int value = 0; + for (int i = 0; i < b.length; i++) { + value = (value << 8) + (b[i] & 0xff); + } + + return new Integer(value); + } // End of method byteArrayToInt + + public static Long byteArrayToLong(final byte[] b, ByteOrder byteOrder) { + if(byteOrder == ByteOrder.LITTLE_ENDIAN) { + return byteArrayToLong(changeEndianness(b)); + } + return byteArrayToLong(b); + } + + /** Convert a byte array into a Long assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The Long value on success, 'Long.MAX_VALUE' otherwise + */ + public static Long byteArrayToLong(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Long.SIZE)) { + return Long.MAX_VALUE; + } + + long value = 0; + for (int i = 0; i < b.length; i++) { + value = (value << 8) + (b[i] & 0xff); + } + + return new Long(value); + } // End of method byteArrayToLong + + public static byte[] hexStringToByteArray(final String s) { + String str = ""; + for(String ss : s.split("[^0-9A-Fa-f]")) { + str = str + ss; + } + int len = str.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + + Character.digit(str.charAt(i+1), 16)); + } + return data; + } + + public static byte[] concat(byte[]... arrays) { + int length = 0; + for (byte[] array : arrays) { + if(array != null) { + length += array.length; + } + } + byte[] result = new byte[length]; + int position = 0; + for (byte[] array : arrays) { + if(array != null) { + System.arraycopy(array, 0, result, position, array.length); + position += array.length; + } + } + return result; + } + + + /** Extract a sub part of a byte array + * @param array The original array + * @param offset The offset to start the extract operation + * @param length The number of bytes to extract + * @return The sub part of a provided byte array + */ + public static byte[] extract(final byte[] array, final int offset, final int length) { + // Sanity check + if ((array == null) || (array.length == 0) || (offset > array.length)) { + return null; + } + + byte[] result = new byte[length]; + System.arraycopy(array, offset, result, 0, length); + return result; + } + + /** + * This method convert a byte array containing the couple (length + string) into a string + * @param b The byte array to convert + * @return A string value + */ + public static String byteArrayWithLengthToString(final byte[] b) { + // Sanity check + if (b == null) { + return null; + } else if (b.length == 0) { + return ""; + } + + // Extract the length of the string + int length = byteArrayToInt(extract(b, 0, 4)); + // Extract the the string + String result = ""; + for (int i = 0; i < length; i++) { + result += (char)(b[4 + i]); + } // End of 'for' statement + + return result; + } + + public static String byteArrayToString(final byte[] buffer) { + + String result = ""; + if (buffer != null) { + for(int i=0; i < buffer.length; ++i) { + result += String.format("%02X", (byte)buffer[i]); + } + } + return result; + } + + /** + * Dump a byte array in hex/ascii mode. + * @param label The dump label + * @param buffer The byte array to dump + */ + public synchronized static void dump(final String label, final byte[] buffer) + { + if ((buffer != null) && (buffer.length != 0)) + { + System.out.println(label); + StringBuilder finalHexLine = new StringBuilder(); + StringBuilder finalCharLine = new StringBuilder(); + int nCounter = 0; + int nOffset = 0; + // Flush header. + System.out.println(" HEX | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F : 0 1 2 3 4 5 6 7 8 9 A B C D E F "); + System.out.println("-----|+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-:--+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); + for (int i = 0; i < buffer.length; ++i) + { + byte c = (byte)buffer[i]; + + String fmtHex = String.format("%02x ", c); + String fmtChar = String.format("%c ", Character.isISOControl((char)c) || c < 0 ? '.' : (char)c); + + if (nOffset % 16 == 0) + { + finalHexLine.append(String.format("%05x| ", nOffset)); + } + + finalHexLine.append(fmtHex); + finalCharLine.append(fmtChar); + if (nCounter == 15) + { + // Flush line. + System.out.println(String.format("%s : %s", finalHexLine.toString(), finalCharLine.toString())); + // Reset buffer. + finalHexLine.delete(0, finalHexLine.length()); + finalCharLine.delete(0, finalCharLine.length()); + + nCounter = 0; + } + else + { + nCounter++; + } + nOffset++; + } + if (nCounter < 16) + { + // Pad till 15. + for (int i = nCounter; i < 16; i++) + { + finalHexLine.append(" "); + finalCharLine.append(" "); + } + // Flush line. + System.out.println(String.format("%s : %s", finalHexLine.toString(), finalCharLine.toString())); + } + } + } +} diff --git a/tools/src/org/etsi/common/ITuple.java b/tools/src/org/etsi/common/ITuple.java new file mode 100644 index 0000000000000000000000000000000000000000..cb44900511a4ad90be6ca006bfda0b4339f23d31 --- /dev/null +++ b/tools/src/org/etsi/common/ITuple.java @@ -0,0 +1,25 @@ +/** + * @author STF 424_ITS_Test_Platform + * @version $URL$ + * $Id$ + */ +package org.etsi.common; + +/** + * This interface provides mandatory method to be implemented by a Tuple {A, B} + * @param Type of the first member of the Tuple + * @param Type of the second member of the Tuple + */ +public interface ITuple { + + /** Retrieve the A element of the tuple + * @return the _a + */ + public abstract A getA(); + + /** Retrieve the B element of the tuple + * @return the _b + */ + public abstract B getB(); + +} \ No newline at end of file diff --git a/tools/src/org/etsi/common/KPM.java b/tools/src/org/etsi/common/KPM.java new file mode 100644 index 0000000000000000000000000000000000000000..abf88b67a58927cfca78d886ac0049a7301564eb --- /dev/null +++ b/tools/src/org/etsi/common/KPM.java @@ -0,0 +1,61 @@ +/** + * Knuth-Morris-Pratt Algorithm implementation + * @author ETSI / STF481 + * @version $URL$ + * $Id$ + * Credit http://www.fmi.uni-sofia.bg/ + */ +package org.etsi.common; + +public class KPM { + + /** + * Search the data byte array for the first occurrence of the byte array pattern within given boundaries. + * @param data + * @param start First index in data + * @param stop Last index in data so that stop-start = length + * @param pattern What is being searched. '*' can be used as wildcard for "ANY character" + * @return + */ + public static int indexOf( byte[] data, int start, int stop, byte[] pattern) { + if( data == null || pattern == null) return -1; + + int[] failure = computeFailure(pattern); + + int j = 0; + + for( int i = start; i < stop; i++) { + while (j > 0 && ( pattern[j] != '*' && pattern[j] != data[i])) { + j = failure[j - 1]; + } + if (pattern[j] == '*' || pattern[j] == data[i]) { + j++; + } + if (j == pattern.length) { + return i - pattern.length + 1; + } + } + return -1; + } + + /** + * Computes the failure function using a boot-strapping process, + * where the pattern is matched against itself. + */ + private static int[] computeFailure(byte[] pattern) { + int[] failure = new int[pattern.length]; + + int j = 0; + for (int i = 1; i < pattern.length; i++) { + while (j>0 && pattern[j] != pattern[i]) { + j = failure[j - 1]; + } + if (pattern[j] == pattern[i]) { + j++; + } + failure[i] = j; + } + + return failure; + } +} // End of class KPM \ No newline at end of file diff --git a/tools/src/org/etsi/common/Tuple.java b/tools/src/org/etsi/common/Tuple.java new file mode 100644 index 0000000000000000000000000000000000000000..424a603aa76e222e958f3d5c00a7439d60674b1f --- /dev/null +++ b/tools/src/org/etsi/common/Tuple.java @@ -0,0 +1,52 @@ +/** + * @author STF 424_ITS_Test_Platform + * @version $URL$ + * $Id$ + */ +package org.etsi.common; + +/** + * This class implements the ITuple interface + * @param Type of the first member of the Tuple + * @param Type of the second member of the Tuple + */ +public class Tuple implements ITuple { + + /** + * A element of the tuple + */ + private A _a; + + /** + * B element of the tuple + */ + private B _b; + + /** + * Constructor + * @param a The A element of the new tuple + * @param b The B element of the new tuple + */ + public Tuple(A a, B b) { + _a = a; + _b = b; + } + + /** + * Retrieve the A element of the tuple + * @return the _a + */ + @Override + public A getA() { + return _a; + } + + /** + * Retrieve the B element of the tuple + * @return the _b + */ + @Override + public B getB() { + return _b; + } +} diff --git a/tools/src/org/etsi/its/pcapdump/CmdLineParser.java b/tools/src/org/etsi/its/pcapdump/CmdLineParser.java new file mode 100644 index 0000000000000000000000000000000000000000..195d5a59f412dc2af5eb13bee314fc947245001b --- /dev/null +++ b/tools/src/org/etsi/its/pcapdump/CmdLineParser.java @@ -0,0 +1,568 @@ +package org.etsi.its.pcapdump; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + + +/** + * Largely GNU-compatible command-line options parser. Has short (-v) and + * long-form (--verbose) option support, and also allows options with + * associated values (-d 2, --debug 2, --debug=2). Option processing + * can be explicitly terminated by the argument '--'. + * + * @author Steve Purcell + * @version $Revision$ + */ +public class CmdLineParser { + + /** + * UID + */ + private static final long serialVersionUID = -5690842973330286842L; + + /** + * Base class for exceptions that may be thrown when options are parsed + */ + public static abstract class OptionException extends Exception { + OptionException(String msg) { super(msg); } + } + + /** + * Thrown when the parsed command-line contains an option that is not + * recognised. getMessage() returns + * an error string suitable for reporting the error to the user (in + * English). + */ + public static class UnknownOptionException extends OptionException { + /** + * UID + */ + private static final long serialVersionUID = -5690842973330286842L; + + /** + * Constructor + * @param optionName Option identifier + */ + UnknownOptionException( String optionName ) { + this(optionName, "Unknown option '" + optionName + "'"); + } + + /** + * Constructor + * @param optionName Option identifier + * @param msg Error message + */ + UnknownOptionException( String optionName, String msg ) { + super(msg); + this.optionName = optionName; + } + + /** + * @return the name of the option that was unknown (e.g. "-u") + */ + public String getOptionName() { return this.optionName; } + private String optionName = null; + } + + /** + * Thrown when the parsed commandline contains multiple concatenated + * short options, such as -abcd, where one is unknown. + * getMessage() returns an english human-readable error + * string. + * @author Vidar Holen + */ + public static class UnknownSuboptionException extends UnknownOptionException { + + /** + * UID + */ + private static final long serialVersionUID = -3886188976129160327L; + + private char suboption; + + /** + * Constructor + * @param option Option value + * @param suboption Sub-option value + */ + UnknownSuboptionException( String option, char suboption ) { + super(option, "Illegal option: '"+suboption+"' in '"+option+"'"); + this.suboption=suboption; + } + /** + * @return The sub-option value + */ + public char getSuboption() { return suboption; } + } + + /** + * Thrown when the parsed commandline contains multiple concatenated + * short options, such as -abcd, where one or more requires a value. + * getMessage() returns an english human-readable error + * string. + * @author Vidar Holen + */ + public static class NotFlagException extends UnknownOptionException { + /** + * UID + */ + private static final long serialVersionUID = -5862485101945261269L; + + private char notflag; + + NotFlagException( String option, char unflaggish ) { + super(option, "Illegal option: '"+option+"', '"+ + unflaggish+"' requires a value"); + notflag=unflaggish; + } + + /** + * @return the first character which wasn't a boolean (e.g 'c') + */ + public char getOptionChar() { return notflag; } + } + + /** + * Thrown when an illegal or missing value is given by the user for + * an option that takes a value. getMessage() returns + * an error string suitable for reporting the error to the user (in + * English). + */ + public static class IllegalOptionValueException extends OptionException { + /** + * UID + */ + private static final long serialVersionUID = -3519380930288555047L; + + public IllegalOptionValueException( Option opt, String value ) { + super("Illegal value '" + value + "' for option " + + (opt.shortForm() != null ? "-" + opt.shortForm() + "/" : "") + + "--" + opt.longForm()); + this.option = opt; + this.value = value; + } + + /** + * @return the name of the option whose value was illegal (e.g. "-u") + */ + public Option getOption() { return this.option; } + + /** + * @return the illegal value + */ + public String getValue() { return this.value; } + private Option option; + private String value; + } + + /** + * Representation of a command-line option + */ + public static abstract class Option { + + protected Option( String longForm, boolean wantsValue ) { + this(null, longForm, wantsValue); + } + + protected Option( char shortForm, String longForm, + boolean wantsValue ) { + this(new String(new char[]{shortForm}), longForm, wantsValue); + } + + private Option( String shortForm, String longForm, boolean wantsValue ) { + if ( longForm == null ) + throw new IllegalArgumentException("Null longForm not allowed"); + this.shortForm = shortForm; + this.longForm = longForm; + this.wantsValue = wantsValue; + } + + public String shortForm() { return this.shortForm; } + + public String longForm() { return this.longForm; } + + /** + * Tells whether or not this option wants a value + */ + public boolean wantsValue() { return this.wantsValue; } + + public final Object getValue( String arg, Locale locale ) + throws IllegalOptionValueException { + if ( this.wantsValue ) { + if ( arg == null ) { + throw new IllegalOptionValueException(this, ""); + } + return this.parseValue(arg, locale); + } + else { + return Boolean.TRUE; + } + } + + /** + * Override to extract and convert an option value passed on the + * command-line + */ + protected Object parseValue( String arg, Locale locale ) + throws IllegalOptionValueException { + return null; + } + + private String shortForm = null; + private String longForm = null; + private boolean wantsValue = false; + + public static class BooleanOption extends Option { + public BooleanOption( char shortForm, String longForm ) { + super(shortForm, longForm, false); + } + public BooleanOption( String longForm ) { + super(longForm, false); + } + } + + /** + * An option that expects an integer value + */ + public static class IntegerOption extends Option { + public IntegerOption( char shortForm, String longForm ) { + super(shortForm, longForm, true); + } + public IntegerOption( String longForm ) { + super(longForm, true); + } + protected Object parseValue( String arg, Locale locale ) + throws IllegalOptionValueException { + try { + return new Integer(arg); + } + catch (NumberFormatException e) { + throw new IllegalOptionValueException(this, arg); + } + } + } + + /** + * An option that expects a long integer value + */ + public static class LongOption extends Option { + public LongOption( char shortForm, String longForm ) { + super(shortForm, longForm, true); + } + public LongOption( String longForm ) { + super(longForm, true); + } + protected Object parseValue( String arg, Locale locale ) + throws IllegalOptionValueException { + try { + return new Long(arg); + } + catch (NumberFormatException e) { + throw new IllegalOptionValueException(this, arg); + } + } + } + + /** + * An option that expects a floating-point value + */ + public static class DoubleOption extends Option { + public DoubleOption( char shortForm, String longForm ) { + super(shortForm, longForm, true); + } + public DoubleOption( String longForm ) { + super(longForm, true); + } + protected Object parseValue( String arg, Locale locale ) + throws IllegalOptionValueException { + try { + NumberFormat format = NumberFormat.getNumberInstance(locale); + Number num = (Number)format.parse(arg); + return new Double(num.doubleValue()); + } + catch (ParseException e) { + throw new IllegalOptionValueException(this, arg); + } + } + } + + /** + * An option that expects a string value + */ + public static class StringOption extends Option { + public StringOption( char shortForm, String longForm ) { + super(shortForm, longForm, true); + } + public StringOption( String longForm ) { + super(longForm, true); + } + protected Object parseValue( String arg, Locale locale ) { + return arg; + } + } + } + + /** + * Add the specified Option to the list of accepted options + */ + public final Option addOption( Option opt ) { + if ( opt.shortForm() != null ) + this.options.put("-" + opt.shortForm(), opt); + this.options.put("--" + opt.longForm(), opt); + return opt; + } + + /** + * Convenience method for adding a string option. + * @return the new Option + */ + public final Option addStringOption( char shortForm, String longForm ) { + return addOption(new Option.StringOption(shortForm, longForm)); + } + + /** + * Convenience method for adding a string option. + * @return the new Option + */ + public final Option addStringOption( String longForm ) { + return addOption(new Option.StringOption(longForm)); + } + + /** + * Convenience method for adding an integer option. + * @return the new Option + */ + public final Option addIntegerOption( char shortForm, String longForm ) { + return addOption(new Option.IntegerOption(shortForm, longForm)); + } + + /** + * Convenience method for adding an integer option. + * @return the new Option + */ + public final Option addIntegerOption( String longForm ) { + return addOption(new Option.IntegerOption(longForm)); + } + + /** + * Convenience method for adding a long integer option. + * @return the new Option + */ + public final Option addLongOption( char shortForm, String longForm ) { + return addOption(new Option.LongOption(shortForm, longForm)); + } + + /** + * Convenience method for adding a long integer option. + * @return the new Option + */ + public final Option addLongOption( String longForm ) { + return addOption(new Option.LongOption(longForm)); + } + + /** + * Convenience method for adding a double option. + * @return the new Option + */ + public final Option addDoubleOption( char shortForm, String longForm ) { + return addOption(new Option.DoubleOption(shortForm, longForm)); + } + + /** + * Convenience method for adding a double option. + * @return the new Option + */ + public final Option addDoubleOption( String longForm ) { + return addOption(new Option.DoubleOption(longForm)); + } + + /** + * Convenience method for adding a boolean option. + * @return the new Option + */ + public final Option addBooleanOption( char shortForm, String longForm ) { + return addOption(new Option.BooleanOption(shortForm, longForm)); + } + + /** + * Convenience method for adding a boolean option. + * @return the new Option + */ + public final Option addBooleanOption( String longForm ) { + return addOption(new Option.BooleanOption(longForm)); + } + + /** + * Equivalent to {@link #getOptionValue(Option, Object) getOptionValue(o, + * null)}. + */ + + public final Object getOptionValue( Option o ) { + return getOptionValue(o, null); + } + + + /** + * @return the parsed value of the given Option, or the given default 'def' + * if the option was not set + */ + public final Object getOptionValue( Option o, Object def ) { + Vector v = (Vector)values.get(o.longForm()); + + if (v == null) { + return def; + } + else if (v.isEmpty()) { + return null; + } + else { + Object result = v.elementAt(0); + v.removeElementAt(0); + return result; + } + } + + + /** + * @return A Vector giving the parsed values of all the occurrences of the + * given Option, or an empty Vector if the option was not set. + */ + public final Vector getOptionValues( Option option ) { + Vector result = new Vector(); + + while (true) { + Object o = getOptionValue(option, null); + + if (o == null) { + return result; + } + else { + result.addElement(o); + } + } + } + + + /** + * @return the non-option arguments + */ + public final String[] getRemainingArgs() { + return this.remainingArgs; + } + + /** + * Extract the options and non-option arguments from the given + * list of command-line arguments. The default locale is used for + * parsing options whose values might be locale-specific. + */ + public final void parse( String[] argv ) + throws IllegalOptionValueException, UnknownOptionException { + + // It would be best if this method only threw OptionException, but for + // backwards compatibility with old user code we throw the two + // exceptions above instead. + + parse(argv, Locale.getDefault()); + } + + /** + * Extract the options and non-option arguments from the given + * list of command-line arguments. The specified locale is used for + * parsing options whose values might be locale-specific. + */ + public final void parse( String[] argv, Locale locale ) + throws IllegalOptionValueException, UnknownOptionException { + + // It would be best if this method only threw OptionException, but for + // backwards compatibility with old user code we throw the two + // exceptions above instead. + + Vector otherArgs = new Vector(); + int position = 0; + this.values = new Hashtable(10); + while ( position < argv.length ) { + String curArg = argv[position]; + if ( curArg.startsWith("-") ) { + if ( curArg.equals("--") ) { // end of options + position += 1; + break; + } + String valueArg = null; + if ( curArg.startsWith("--") ) { // handle --arg=value + int equalsPos = curArg.indexOf("="); + if ( equalsPos != -1 ) { + valueArg = curArg.substring(equalsPos+1); + curArg = curArg.substring(0,equalsPos); + } + } else if(curArg.length() > 2) { // handle -abcd + for(int i=1; i alldevs = new ArrayList(); // Will be filled with NICs + + + int r = Pcap.findAllDevs(alldevs, errbuf); + if (r != Pcap.OK || alldevs.isEmpty()) { + System.err.printf("Can't read list of devices, error is %s", errbuf.toString()); + return; + } + + // Find the right interface + int ifaceIndex = 0; + String expectedIface = PcapMultiplexer.ExpectedIface; + for( ; ifaceIndex < alldevs.size(); ifaceIndex++) { + try { + if (expectedIface.equalsIgnoreCase(ByteHelper.byteArrayToString(alldevs.get(ifaceIndex).getHardwareAddress()))) { + // Interface found + break; + } + } catch (IOException e) { + // ignore + } + } + // Check result + if (ifaceIndex == alldevs.size()) { + throw new RuntimeException(String.format("EthernetLayer.register: Network interface %s not found", expectedIface)); + } + + device = alldevs.get(ifaceIndex); + System.out.println("Listening: " + device.getName()); + } + + /** + * Gets the unique factory instance + * @return PcapMultiplexer instance + */ + public static PcapMultiplexer getInstance(final String macAddress){ + ExpectedIface = macAddress; + return (instance = new PcapMultiplexer()); + } + + /** + * Gets the unique factory instance + * @return PcapMultiplexer instance + */ + public static PcapMultiplexer getInstance(){ + return instance; + } + + public synchronized void register(ILayer client, short frameType) { + // Open interface + int snaplen = 64 * 1024; // Capture all packets, no truncation + int flags = Pcap.MODE_PROMISCUOUS; // capture all packets + int timeout = 10; // 10 millis + pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf); + + if (pcap == null) { + System.err.printf("Error while opening device for capture: " + errbuf.toString()); + return; + } + captureThread = new Thread(this); + captureThread.start(); + filter = String.format("ether proto 0x%04x", frameType); + System.out.println("New filter: " + filter); + + // Apply filter + PcapBpfProgram bpfFilter = new PcapBpfProgram(); + int optimize = 0; // 1 means true, 0 means false + int netmask = 0; + int r = pcap.compile(bpfFilter, filter, optimize, netmask); + if (r != Pcap.OK) { + System.out.println("Filter error: " + pcap.getErr()); + } + pcap.setFilter(bpfFilter); + + dumper = pcap.dumpOpen(client.getFileName()); + + _client = client; + } + + public synchronized void unregister(ILayer client) { + pcap.breakloop(); + dumper.close(); + try { + captureThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + pcap.close(); + } + + /** + * Thread function for jpcap capture loop + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + + PcapPacketHandler dumpHandler = new PcapPacketHandler() { + + private int counter = 0; + + @Override + public void nextPacket(PcapPacket packet, String user) { + dumper.dump(packet); + counter += 1; + if (counter == 500) { + System.out.println("nextPacket: Flushing file"); + dumper.flush(); + counter = 0; + } + } + }; + + pcap.loop(-1, dumpHandler, "pcapdump"); + } + + /** + * Jpcap capture device + */ + private Pcap pcap; + + /** + * Jpcap capture thread instance. + */ + private Thread captureThread; + + PcapIf device; + private String filter; +} \ No newline at end of file diff --git a/tools/src/org/etsi/its/pcapdump/pcapdump.java b/tools/src/org/etsi/its/pcapdump/pcapdump.java new file mode 100644 index 0000000000000000000000000000000000000000..d679f2f77a7a09eb6ee5d7274bbd827ea722a6ec --- /dev/null +++ b/tools/src/org/etsi/its/pcapdump/pcapdump.java @@ -0,0 +1,188 @@ +/** + * + */ +package org.etsi.its.pcapdump; + +import java.io.File; +import java.io.IOException; +import java.net.DatagramPacket; +import java.util.Date; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.etsi.common.ByteHelper; +import org.etsi.its.pcapdump.CmdLineParser.IllegalOptionValueException; +import org.etsi.its.pcapdump.CmdLineParser.UnknownOptionException; + +/** + * @author yann + * + */ +public class pcapdump implements ILayer { + + /** + * Module version + */ + public static final String Version = "1.0.0.0"; + + /** + * Logger instance + */ + private final static Logger _logger = Logger.getLogger("org.etsi.its.pcapdump"); + + private static String NicAddr = "00FF6BADBFC2"; + + private static String FileName = "itsdump.pcapng"; + + /** + * Debug mode. Default: false + */ + private static Level Debug = Level.OFF; + + /** + * ITS Ehter type + */ + private static short FrameType = (short) 0x8947; + + /** + * Default ctor + */ + public pcapdump() { + // Nothing to do + } + + @Override + public void dispose() { + PcapMultiplexer.getInstance().unregister(this); + } + /** + * @param args + */ + public static void main(String[] args) { + // Process command line arguments + processCommandLine(args); + + // Set traces + _logger.addHandler(new ConsoleHandler()); + _logger.setLevel(Debug); + + + // Check if the file exist, never remove or scratch files + File file = new File(FileName); + if (file.exists()) { + File newFile = new File(FileName + "_" + System.currentTimeMillis()); + file.renameTo(newFile); + } + + ILayer layer = new pcapdump(); + PcapMultiplexer.getInstance(NicAddr); + PcapMultiplexer.getInstance().register(layer, FrameType); + + boolean bContinue = true; + while (bContinue) { + try { + // Check keyboard + if (System.in.available() > 0) { + int token = System.in.read(); + switch (token) { + case 'h': // Help + // No break; + case '?': // Help + cmdeLineUsage(); + break; + case 'q': + bContinue = false; + _logger.info("Terminate application..."); + break; + } // End of 'switch' statement + } + // Wait + java.lang.Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } // End of 'while' statement + + layer.dispose(); + System.err.println("Terminated"); + System.exit(0); + } + + /** + * Parse the command line and set options + * @param args Command line arguments + */ + private static void processCommandLine(String[] args) { + // Sanity checks + if (args.length == 0) { + return; + } + + CmdLineParser parser = new CmdLineParser(); + CmdLineParser.Option debug = parser.addBooleanOption("Debug"); + CmdLineParser.Option fileName = parser.addStringOption("FileName"); + CmdLineParser.Option frameType = parser.addStringOption("FrameType"); + CmdLineParser.Option NICAddr = parser.addStringOption("NicAddr"); + try { + parser.parse(args); + } catch (IllegalOptionValueException e) { + e.printStackTrace(); + printUsage(); + System.exit(2); + } catch (UnknownOptionException e) { + e.printStackTrace(); + printUsage(); + System.exit(3); + } + + Object value; + if ((value = parser.getOptionValue(debug, false)) != null) { + Debug = (((Boolean)value).booleanValue() == true) ? Level.ALL : Level.OFF; + } + if ((value = parser.getOptionValue(fileName, "")) != null) { + if (!((String)value).isEmpty()) { + FileName = (String)value; + } + } + if ((value = parser.getOptionValue(frameType, "")) != null) { + if (!((String)value).isEmpty()) { + FrameType = (short)Integer.parseInt((String)value, 16); + } + } + if ((value = parser.getOptionValue(NICAddr, "")) != null) { + if (!((String)value).isEmpty()) { + NicAddr = (String)value; + } + } + + } // End of method processCommandLine + + /** + * Display application usage + */ + private static void printUsage() { + System.err.println("Usage: [--Debug (default:false)]\n" + + " [--FileName=filename \"Output file name \"]\n" + + " [--FrameType=0x8947 \"Ethernet prototype\" (0x8947)]\n" + + " \n" + ); + } + + private static void cmdeLineUsage() { + System.err.println("Command Line Usage: \n" + + // TODO + " [q to exit]\n" + + " \n" + ); + + } + + @Override + public String getFileName() { + return FileName; + } + +}