Adding skipped packets analysis.
[pingpong.git] / Code / Projects / PacketLevelSignatureExtractor / src / main / java / edu / uci / iotproject / detection / layer3 / Layer3ClusterMatcher.java
index a4ad857d4be6ace06f81415d2c8ebade80e20fb7..56b4b0a47a3db12b2c751bc215c4b9ed32dd27d1 100644 (file)
@@ -1,5 +1,6 @@
 package edu.uci.iotproject.detection.layer3;
 
+import edu.uci.iotproject.analysis.TriggerTrafficExtractor;
 import edu.uci.iotproject.detection.AbstractClusterMatcher;
 import edu.uci.iotproject.detection.ClusterMatcherObserver;
 import edu.uci.iotproject.trafficreassembly.layer3.Conversation;
@@ -24,33 +25,6 @@ import static edu.uci.iotproject.util.PcapPacketUtils.*;
  */
 public class Layer3ClusterMatcher extends AbstractClusterMatcher implements PacketListener {
 
-    // Test client
-    public static void main(String[] args) throws PcapNativeException, NotOpenException {
-
-//        String path = "/scratch/July-2018"; // Rahmadi
-//        String path = "/Users/varmarken/temp/UCI IoT Project/experiments"; // Janus
-//        final String inputPcapFile = path + "/2018-07/dlink/dlink.wlan1.local.pcap";
-//        final String signatureFile = path + "/2018-07/dlink/offSignature1.sig";
-//
-//        List<List<PcapPacket>> signature = PrintUtils.deserializeClustersFromFile(signatureFile);
-//        Layer3ClusterMatcher clusterMatcher = new Layer3ClusterMatcher(signature, null,
-//                (sig, match) -> System.out.println(
-//                        String.format("[ !!! SIGNATURE DETECTED AT %s !!! ]",
-//                                match.get(0).getTimestamp().atZone(ZoneId.of("America/Los_Angeles")))
-//                )
-//        );
-//
-//        PcapHandle handle;
-//        try {
-//            handle = Pcaps.openOffline(inputPcapFile, PcapHandle.TimestampPrecision.NANO);
-//        } catch (PcapNativeException pne) {
-//            handle = Pcaps.openOffline(inputPcapFile);
-//        }
-//        PcapHandleReader reader = new PcapHandleReader(handle, p -> true, clusterMatcher);
-//        reader.readFromHandle();
-//        clusterMatcher.performDetection();
-    }
-
     /**
      * The ordered directions of packets in the sequences that make up {@link #mCluster}.
      */
@@ -67,27 +41,30 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
     private final String mRouterWanIp;
 
     /**
-     * Range-based vs. strict matching.
+     * Epsilon value used by the DBSCAN algorithm; it is used again for range-based matching here.
      */
-    private final boolean mRangeBased;
+    private final double mEps;
 
     /**
-     * Epsilon value used by the DBSCAN algorithm; it is used again for range-based matching here.
+     * The packet inclusion time for signature.
      */
-    private final double mEps;
+    private int mInclusionTimeMillis;
 
     /**
      * Create a {@link Layer3ClusterMatcher}.
      * @param cluster The cluster that traffic is matched against.
      * @param routerWanIp The router's WAN IP if examining traffic captured at the ISP's point of view (used for
      *                    determining the direction of packets).
+     * @param inclusionTimeMillis The packet inclusion time for signature.
      * @param isRangeBased The boolean that decides if it is range-based vs. strict matching.
+     * @param eps The epsilon value used in the DBSCAN algorithm.
      * @param detectionObservers Client code that wants to get notified whenever the {@link Layer3ClusterMatcher} detects that
      *                          (a subset of) the examined traffic is similar to the traffic that makes up
      *                          {@code cluster}, i.e., when the examined traffic is classified as pertaining to
      *                          {@code cluster}.
      */
-    public Layer3ClusterMatcher(List<List<PcapPacket>> cluster, String routerWanIp, boolean isRangeBased, double eps,
+    public Layer3ClusterMatcher(List<List<PcapPacket>> cluster, String routerWanIp, int inclusionTimeMillis,
+                                boolean isRangeBased, double eps,
                                 ClusterMatcherObserver... detectionObservers) {
         super(cluster, isRangeBased);
         Objects.requireNonNull(detectionObservers, "detectionObservers cannot be null");
@@ -103,8 +80,7 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
          * on in favor of performance. However, it is only run once (at instantiation), so the overhead may be warranted
          * in order to ensure correctness, especially during the development/debugging phase.
          */
-        mRangeBased = isRangeBased;
-        if (!mRangeBased) {    // Only when it is not range-based
+        if (!isRangeBased) {    // Only when it is not range-based
             if (mCluster.stream().
                     anyMatch(inner -> !Arrays.equals(mClusterMemberDirections, getPacketDirections(inner, null)))) {
                 throw new IllegalArgumentException(
@@ -115,6 +91,8 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
         }
         mEps = eps;
         mRouterWanIp = routerWanIp;
+        mInclusionTimeMillis =
+                inclusionTimeMillis == 0 ? TriggerTrafficExtractor.INCLUSION_WINDOW_MILLIS : inclusionTimeMillis;
     }
 
     @Override
@@ -154,7 +132,8 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
                     isPresent()) {
                 List<PcapPacket> matchSeq = match.get();
                 // Notify observers about the match.
-                mObservers.forEach(o -> o.onMatch(Layer3ClusterMatcher.this, matchSeq));
+                // Max number of skipped packets in layer 3 is 0 (no skipped packets)
+                mObservers.forEach(o -> o.onMatch(Layer3ClusterMatcher.this, matchSeq, 0));
                 /*
                  * Get the index in cPkts of the last packet in the sequence of packets that matches the searched
                  * signature sequence.
@@ -196,7 +175,8 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
                         isPresent()) {
                     List<PcapPacket> matchSeq = match.get();
                     // Notify observers about the match.
-                    mObservers.forEach(o -> o.onMatch(Layer3ClusterMatcher.this, matchSeq));
+                    // Max number of skipped packets in layer 3 is 0 (no skipped packets)
+                    mObservers.forEach(o -> o.onMatch(Layer3ClusterMatcher.this, matchSeq, 0));
                     /*
                      * Get the index in cPkts of the last packet in the sequence of packets that matches the searched
                      * signature sequence.
@@ -370,9 +350,16 @@ public class Layer3ClusterMatcher extends AbstractClusterMatcher implements Pack
             PcapPacket seqPkt = sequence.get(seqIdx);
             // We only have a match if packet lengths and directions match.
             // The packet lengths have to be in the range of [lowerBound - eps, upperBound+eps]
-            // TODO: Maybe we could do better here for the double to integer conversion?
-            int epsLowerBound = lowBndPkt.length() - (int) mEps;
-            int epsUpperBound = upBndPkt.length() + (int) mEps;
+            // We initialize the lower and upper bounds first
+            int epsLowerBound = lowBndPkt.length();
+            int epsUpperBound = upBndPkt.length();
+            // Do strict matching if the lower and upper bounds are the same length
+            // Do range matching with eps otherwise
+            if (epsLowerBound != epsUpperBound) {
+                // TODO: Maybe we could do better here for the double to integer conversion?
+                epsLowerBound = epsLowerBound - (int) mEps;
+                epsUpperBound = epsUpperBound + (int) mEps;
+            }
             if (epsLowerBound <= seqPkt.getOriginalLength() &&
                     seqPkt.getOriginalLength() <= epsUpperBound &&
                     subsequenceDirections[subseqIdx] == sequenceDirections[seqIdx]) {