Package org.jnetpcap

Source Code of org.jnetpcap.TestPcapJNI

/*
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Sly Technologies, Inc.
*
* This file is part of jNetPcap.
*
* jNetPcap is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.jnetpcap;

import java.io.File;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import junit.framework.TestCase;
import junit.textui.TestRunner;

import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.nio.JMemory;
import org.jnetpcap.nio.JNumber;
import org.jnetpcap.nio.JNumber.Type;

// TODO: Auto-generated Javadoc
/**
* @author Mark Bednarczyk
* @author Sly Technologies, Inc.
*/
@SuppressWarnings("deprecation")
public class TestPcapJNI
    extends
    TestCase {

  // private final static String device =
  // "\\Device\\NPF_{BC81C4FC-242F-4F1C-9DAD-EA9523CC992D}";

  /** The Constant fname. */
  private final static String fname = "tests/test-l2tp.pcap";

  /**
   * Will generate HTTP traffic to a website. Use start() to start in a test
   * method, and always put stop() in tearDown. Safe to call stop even when
   * never started.
   */
  private static final HttpTrafficGenerator gen = new HttpTrafficGenerator();

  /** The Constant isWindows. */
  private final static boolean isWindows =
      "Windows XP".equals(System.getProperty("os.name"));

  /** The Constant linux. */
  private final static String linux = "any";

  /** The Constant OK. */
  private static final int OK = 0;

  /** The Constant oneSecond. */
  private static final int oneSecond = 1000;

  /** The Constant promisc. */
  private static final int promisc = 1;

  /** The Constant snaplen. */
  private static final int snaplen = 64 * 1024;

    /** The tmp file. */
    private static File tmpFile;

  /** The Constant win. */
  private final static String win =
      "\\Device\\NPF_{BC81C4FC-242F-4F1C-9DAD-EA9523CC992D}";

  /** The Constant device. */
  private final static String device = (isWindows) ? win : linux;
 
  static {
    try {
      tmpFile = File.createTempFile("temp-", "-TestPcapJNI");
    } catch (IOException e) {
      tmpFile = null;
      System.err.println("Unable to initialize a temporary file");
    }

  }

  /**
   * Command line launcher to run the jUnit tests cases in this test class.
   *
   * @param args
   *          -h for help
   */
  public static void main(String[] args) {
    if (args.length == 1 && "-h".equals(args[0])) {
      System.out
          .println("Usage: java -jar jnetpcap.jar [-h]\n"
              + "  -h  This help message\n"
              + "   (No other command line options are supported.)\n"
              + "----------------------------------------------------------------\n\n"
              + "The 'main' method invoked here, runs several dozen jUnit tests\n"
              + "which test the functionality of this jNetPcap library.\n"
              + "The tests are actual excersizes using native libpcap\n"
              + "library linked with 'jnetpcap.dll' or 'libjnetpcap.so' on\n"
              + "unix systems.\n\n"
              + "If you are having trouble linking the native library and get\n"
              + "'UnsatisfiedLinkError', which means java is not finding the\n"
              + "library, here are a few pointers:\n\n"
              + "Java's native library loader DOES NOT USE CLASSPATH variable\n"
              + "to locate native libraries. Each operating system uses different\n"
              + "algorithm to locate files, as described below. You can always\n"
              + "force java to look for native library with Java VM command\n"
              + "line option 'java -Djava.library.path=lib' where lib is\n"
              + "a directory where 'jnetpcap.dll' or 'libjnetpcap.so' resides\n"
              + "relative to the installation directory of jNetStream package.\n"
              + "Or replace lib with the directory where you have installed the\n"
              + "library.\n\n"
              + "On Win32 systems:\n"
              + "  Windows systems use /windows and /windows/system32 folder\n"
              + "  to search for jnetpcap.dll. Also the 'PATH' variable, the same\n"
              + "  one used to specify executable commands, is used as well.\n\n"
              + "On Unix systems:\n"
              + "  All unix systems use the standard 'LD_LIBRARY_PATH' variable.\n\n"
              + "Of course as mentioned earlier, to override this behaviour use\n"
              + "the '-Djava.library.path=' directory, to force java to look in\n"
              + "that particular directory. Do not set the path which includes the\n"
              + "name of the library itself, just the directory to search in.\n\n"
              + "Final note, native librariers can not be loaded from jar files.\n"
              + "You have to extract it to a physical directory if you want java to\n"
              + "load it. This was done purposely by Sun for security reasons.");

      return;
    }

    TestRunner.main(new String[] { "org.jnetpcap.TestPcapJNI" });

  }

  /** The do nothing handler. */
  private final PcapHandler<?> doNothingHandler = new PcapHandler<Object>() {

    public void nextPacket(
        Object userObject,
        long seconds,
        int useconds,
        int caplen,
        int len,
        ByteBuffer buffer) {
      // Do nothing handler
    }
  };

  /** The errbuf. */
  private StringBuilder errbuf = new StringBuilder();

  /**
   * Test stats.
   */
  public void testStats() {
    PcapStat stats = new PcapStat();

    Pcap pcap = Pcap.openLive(device, snaplen, promisc, oneSecond, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    pcap.loop(5, doNothingHandler, null);
    pcap.stats(stats);
    // System.out.printf("stats=%s\n", stats.toString());

    pcap.loop(5, doNothingHandler, null);
    pcap.stats(stats);
    // System.out.printf("stats=%s\n", stats.toString());

    pcap.close();
  }

  /* (non-Javadoc)
   * @see junit.framework.TestCase#setUp()
   */
  protected void setUp() throws Exception {

    errbuf = new StringBuilder();

    if (tmpFile.exists()) {
      assertTrue(tmpFile.delete());
    }

  }

  /**
   * SKI ptest dumper.
   */
  public void SKIPtestDumper() {

    gen.start(); // Generate network traffic - async method

    System.out.printf("tmpFile=%s\n", tmpFile.getAbsoluteFile());

    Pcap pcap = Pcap.openLive(device, snaplen, promisc, oneSecond, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapDumper dumper = pcap.dumpOpen(tmpFile.getAbsolutePath());
    assertNotNull(pcap.getErr(), dumper);

    PcapHandler<PcapDumper> dumpHandler = new PcapHandler<PcapDumper>() {

      public void nextPacket(
          PcapDumper dumper,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        dumper.dump(seconds, useconds, caplen, len, buffer);
      }
    };

    pcap.loop(10, dumpHandler, dumper);

    assertTrue("Empty dump file " + tmpFile.getAbsolutePath(),
        tmpFile.length() > 0);

    // System.out.printf("Temp dumpfile size=%s\n", tmpFile.length());
    pcap.close();

  }

  /**
   * Test disabled, as it requires live packets to capture. To enable the test
   * just rename the method, by removing the prefix SKIP. Then make sure there
   * are live packets to be captured.
   */
  public void SKIPtestOpenLiveAndDispatch() {

    Pcap pcap = Pcap.openLive(device, 10000, 1, 60 * 1000, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapHandler<String> handler = new PcapHandler<String>() {

      public void nextPacket(
          String user,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        // System.out.printf("%s, ts=%s caplen=%d len=%d capacity=%d\n", user
        // .toString(), new Date(seconds * 1000).toString(), caplen, len,
        // buffer.capacity());

      }

    };

    pcap.dispatch(10, handler, "Hello");

    pcap.close();
  }

  /* (non-Javadoc)
   * @see junit.framework.TestCase#tearDown()
   */
  protected void tearDown() throws Exception {
    errbuf = null;

    /*
     * Stop the traffic generator, even when not running need to call to make
     * sure its not running.
     */
    gen.stop();

    if (tmpFile != null && tmpFile.exists()) {
      tmpFile.delete();
    }
  }

  /**
   * Test compile no pcap null ptr handling.
   */
  public void testCompileNoPcapNullPtrHandling() {
    try {
      Pcap.compileNoPcap(1, 1, null, null, 1, 1);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test compile null ptr handling.
   */
  public void testCompileNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.compile(null, null, 1, 0);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test data link name to val null ptr handling.
   */
  public void testDataLinkNameToValNullPtrHandling() {
    try {
      Pcap.datalinkNameToVal(null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test datalink name to value.
   */
  public void testDatalinkNameToValue() {
    assertEquals(1, Pcap.datalinkNameToVal("EN10MB"));
  }

  /**
   * Test datalink value to description.
   */
  public void testDatalinkValueToDescription() {
    assertEquals("Ethernet", Pcap.datalinkValToDescription(1));

  }

  /**
   * Test datalink value to name.
   */
  public void testDatalinkValueToName() {
    assertEquals("EN10MB", Pcap.datalinkValToName(1));

  }

  /**
   * Test dispatch null ptr handling.
   */
  public void testDispatchNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.dispatch(1, (ByteBufferHandler<String>) null, "");
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test dispatch pcap dumper.
   */
  public void testDispatchPcapDumper() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(pcap.getErr(), pcap);

    PcapDumper dumper = pcap.dumpOpen(tmpFile.getPath());
    assertNotNull(pcap.getErr(), dumper);

    try {
      int r = pcap.loop(Pcap.LOOP_INFINATE, dumper);
      assertEquals(pcap.getErr(), Pcap.OK, r);

      assertEquals("dumped file and source file lengths don't match", tmpFile
          .length(), new File(fname).length());
    } finally {
      pcap.close();
      dumper.close();
    }

  }

  /**
   * Test errbuf.
   *
   * @throws SocketException
   *           the socket exception
   * @throws InterruptedException
   *           the interrupted exception
   */
  public void testErrbuf() throws SocketException, InterruptedException {

    // Test using a bogus device name that's sure to fail
    errbuf.append("def"); // Set dummy message and it should be replaced
    Pcap pcap = Pcap.openLive("abc", 101, 1, 60, errbuf);
    assertNull(pcap);

    assertFalse("Our pre-initialized error message should have been cleared",
        "def".equals(errbuf.toString()));

    assertTrue("Error buffer should contain an error message",
        errbuf.length() != 0);
  }

  /**
   * Test filter compile and set filter.
   */
  public void testFilterCompileAndSetFilter() {
    PcapBpfProgram bpf = new PcapBpfProgram();
    String str = "host 192.168.101";

    // System.out.println("trying to compiler the filter() OK\n");
    // System.out.flush();
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    // System.out.println("filter was compiled OK\n"); System.out.flush();
    assertNotNull(errbuf.toString(), pcap);

    int r = pcap.compile(bpf, str, 0, 0);
    assertEquals(pcap.getErr(), 0, r);

    PcapHandler<String> handler = new PcapHandler<String>() {
      public void nextPacket(
          String user,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        // System.out.printf("%s, ts=%s caplen=%d len=%d capacity=%d\n", user
        // .toString(), new Date(seconds * 1000).toString(), caplen, len,
        // buffer.capacity());
      }
    };

    // System.out.println("trying to set the filter() OK\n");
    // System.out.flush();
    assertEquals(OK, pcap.setFilter(bpf));
    // System.out.println("filter was set OK\n"); System.out.flush();
    assertEquals(OK, pcap.loop(10, handler, str));

    Pcap.freecode(bpf);

    pcap.close();
  }

  /**
   * Test filter compile no pcap and accessors.
   */
  public void testFilterCompileNoPcapAndAccessors() {
    PcapBpfProgram bpf = new PcapBpfProgram();

    String str = "host 192.168.1.1";

    int r = Pcap.compileNoPcap(1024, 1, bpf, str, 0, 0);
    assertEquals(OK, r);

    assertEquals(26, bpf.getInstructionCount());
    assertEquals(120259084320L, bpf.getInstruction(10));

    // Boundary checks
    try {
      bpf.getInstruction(-10);
      fail("Failed to generate exception on low index boundary");
    } catch (IndexOutOfBoundsException e) {
      // OK
    }

    // Boundary checks
    try {
      bpf.getInstruction(26);
      fail("Failed to generate exception on upper index boundary");
    } catch (IndexOutOfBoundsException e) {
      // OK
    }

    Pcap.freecode(bpf);
  }

  /**
   * Test find all devs.
   */
  public void testFindAllDevs() {
    List<PcapIf> devs = new ArrayList<PcapIf>(); // List filled in by
    // findAllDevs

    int r = Pcap.findAllDevs(devs, errbuf);
    assertEquals(errbuf.toString(), 0, r);
    assertFalse(devs.isEmpty());

    // System.out.println(devs);
  }

  /**
   * Test find all devs null ptr handling.
   */
  public void testFindAllDevsNullPtrHandling() {
    try {
      Pcap.findAllDevs(null, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test free all devs null ptr handling.
   */
  public void testFreeAllDevsNullPtrHandling() {
    try {
      Pcap.freeAllDevs(null, (StringBuilder) null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test free code null ptr handling.
   */
  public void testFreeCodeNullPtrHandling() {
    try {
      Pcap.freecode(null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test get hardware address.
   *
   * @throws IOException
   *           Signals that an I/O exception has occurred.
   */
  public void testGetHardwareAddress() throws IOException {
    List<PcapIf> alldevs = new ArrayList<PcapIf>();

    Pcap.findAllDevs(alldevs, errbuf);

    for (PcapIf p : alldevs) {
      byte[] mac = p.getHardwareAddress();
      if (mac != null && mac.length == 6) {
        return; // Found atleast 1 interface with MAC address
      }
    }

    fail("Unable to find any interfaces with MAC address");
  }

  /**
   * Test get non block null ptr handling.
   */
  public void testGetNonBlockNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.getNonBlock(null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test is inject supported win32.
   */
  public void testIsInjectSupportedWin32() {
    if (System.getProperty("os.name").toLowerCase().contains("win")) {
      assertFalse(Pcap.isInjectSupported());
    } else {
      assertTrue(true); // Be explicit
    }
  }

  /**
   * Test is sendpacket supported win32.
   */
  public void testIsSendpacketSupportedWin32() {
    if (System.getProperty("os.name").toLowerCase().contains("win")) {
      assertTrue(Pcap.isSendPacketSupported());
    } else {
      assertTrue(true); // Be explicit
    }
  }

  /**
   * Test lib version.
   */
  public void testLibVersion() {
    assertNotNull(Pcap.libVersion());
  }

  /**
   * Test lookup dev and lookup net deprecated api.
   */
  @SuppressWarnings("deprecation")
  public void testLookupDevAndLookupNetDeprecatedAPI() {
    String device = Pcap.lookupDev(errbuf);
    assertNotNull(errbuf.toString(), device);

    JNumber netp = new JNumber(Type.INT);
    JNumber maskp = new JNumber(Type.INT);

    int r = Pcap.lookupNet(device, netp, maskp, errbuf);
    assertEquals(errbuf.toString(), 0, r);

    System.out.printf("device=%s netp=%X maskp=%X errbuf=%s\n", device, netp
        .intValue(), maskp.intValue(), errbuf.toString());
  }

  /**
   * Test loop null ptr handling.
   */
  public void testLoopNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.loop(1, (ByteBufferHandler<String>) null, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test loop pcap dumper.
   */
  public void testLoopPcapDumper() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(pcap.getErr(), pcap);

    PcapDumper dumper = pcap.dumpOpen(tmpFile.getPath());
    assertNotNull(pcap.getErr(), dumper);

    try {
      int r = pcap.loop(Pcap.LOOP_INFINATE, dumper);
      assertEquals(pcap.getErr(), Pcap.OK, r);

      assertEquals("dumped file and source file lengths don't match", tmpFile
          .length(), new File(fname).length());
    } finally {
      pcap.close();
      dumper.close();
    }

  }

  /**
   * Test next.
   */
  public void testNext() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      PcapHeader header = new PcapHeader(); // allocated memory
      JBuffer buffer = new JBuffer(JMemory.Type.POINTER);

      buffer = pcap.next(header, buffer);

      assertNotNull(buffer);
      assertEquals(114, header.caplen());
      assertEquals(114, buffer.size());
    } finally {
      pcap.close();
    }
  }

  /**
   * Test next ex.
   */
  public void testNextEx() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      PcapHeader header = new PcapHeader(JMemory.Type.POINTER);
      JBuffer buffer = new JBuffer(JMemory.Type.POINTER);

      assertEquals(1, pcap.nextEx(header, buffer));

      assertEquals(114, header.caplen());
      assertEquals(114, buffer.size());

    } finally {
      pcap.close();
    }
  }

  /**
   * Test next ex null ptr handling.
   */
  public void testNextExNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.nextEx((PcapHeader) null, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test next null ptr handling.
   */
  public void testNextNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.next((PcapHeader) null, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test open dead and close.
   */
  public void testOpenDeadAndClose() {

    Pcap pcap = Pcap.openDead(1, 10000); // DLT, SNAPLEN
    assertNotNull(errbuf.toString(), pcap);

    pcap.close();
  }

  /**
   * Test open live and datalink and close.
   *
   * @throws SocketException
   *           the socket exception
   * @throws InterruptedException
   *           the interrupted exception
   */
  public void testOpenLiveAndDatalinkAndClose() throws SocketException,
      InterruptedException {

    // System.out.println(System.getProperty("os.name"));
    Pcap pcap = Pcap.openLive(device, 101, 1, 60, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    // Physical field initialized from JNI space
    assertFalse("0".equals(pcap.toString()));

    // Check linklayer 1 is for DLT_EN10MB
    // assertEquals(113, pcap.datalink());

    pcap.close();

    try {
      pcap.close();
      fail();
    } catch (IllegalStateException e) {
      // Expecting this exception on second call to close()
    }
  }

  /**
   * Test open live and loop with breakloop.
   */
  public void testOpenLiveAndLoopWithBreakloop() {

    Pcap pcap = Pcap.openLive(device, 10000, 1, 60 * 1000, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapHandler<String> handler = new PcapHandler<String>() {

      public void nextPacket(
          String user,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        // System.out.printf("%s, ts=%s caplen=%d len=%d capacity=%d\n", user
        // .toString(), new Date(seconds * 1000).toString(), caplen, len,
        // buffer.capacity());

      }

    };

    pcap.breakloop(); // Should cause it to exit immediately
    assertEquals(
        "Error code does not indicate breakloop interrupted the loop when it should have",
        -2, pcap.loop(10, handler, "Hello"));

    pcap.close();
  }

  /**
   * Test open offline and close.
   */
  public void testOpenOfflineAndClose() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapHandler<String> handler = new PcapHandler<String>() {

      public void nextPacket(
          String user,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        // System.out.printf("%s, ts=%s caplen=%d len=%d capacity=%d\n", user
        // .toString(), new Date(seconds * 1000).toString(), caplen, len,
        // buffer.capacity());

      }

    };

    assertEquals("Expected to receive exactly 10 packets", 10, pcap.dispatch(
        10, handler, "Hello"));
    pcap.close();
  }

  /**
   * Test open offline and loop.
   */
  public void testOpenOfflineAndLoop() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapHandler<String> handler = new PcapHandler<String>() {

      public void nextPacket(
          String user,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        // System.out.printf("%s, ts=%s caplen=%d len=%d capacity=%d\n", user
        // .toString(), new Date(seconds * 1000).toString(), caplen, len,
        // buffer.capacity());

      }

    };

    assertEquals(OK, pcap.loop(10, handler, "Hello"));

    pcap.close();
  }

  /**
   * Test open offline and next.
   */
  public void testOpenOfflineAndNext() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);
    PcapPktHdr hdr = new PcapPktHdr();

    ByteBuffer buffer = pcap.next(hdr);

    assertEquals(114, buffer.capacity()); // length of the packet should match
    assertEquals(114, hdr.getCaplen()); // Should match within the header too
    assertEquals(114, hdr.getLen()); // Should match within the header too

    // System.out.println(new Date(hdr.getSeconds() * 1000).toString());

    pcap.close();
  }

  /**
   * Test open offline and next ex.
   */
  public void testOpenOfflineAndNextEx() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);
    PcapPktHdr hdr = new PcapPktHdr();
    PcapPktBuffer buf = new PcapPktBuffer();

    int r = pcap.nextEx(hdr, buf);
    assertEquals(1, r);
    assertNotNull(buf.getBuffer());

    assertEquals(114, buf.getBuffer().capacity()); // length of the packet
    // should match
    assertEquals(114, hdr.getCaplen()); // Should match within the header too
    assertEquals(114, hdr.getLen()); // Should match within the header too

    // System.out.println(new Date(hdr.getSeconds() * 1000).toString());

    pcap.close();
  }

  /**
   * Test pcap closed exception handling.
   */
  public void testPcapClosedExceptionHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    pcap.close();

    try {
      pcap.breakloop();
      fail("Expected PcapClosedException");
    } catch (PcapClosedException e) {
      // Success
    }
  }

  /**
   * Test pcap dlt and do name to value comparison.
   */
  public void testPcapDLTAndDoNameToValueComparison() {
    int match = 0; // counts how many constants compared OK

    for (PcapDLT c : PcapDLT.values()) {
      int dlt = c.value;
      String libName = Pcap.datalinkValToName(dlt);
      if (libName == null) {
        // System.out.printf("no dlt: dlt=%d enum=%s\n", dlt, c.toString());
        continue;
      }

      if (libName.equals(c.name())) {
        match++;

        // System.out.printf("matched: dlt=%d enum=%s pcap=%s desc=%s\n", dlt, c
        // .toString(), libName, c.description);
      } else {
        // System.out.printf("unmatched: dlt=%d enum=%s pcap=%s desc=%s\n", dlt,
        // c
        // .toString(), libName, c.description);
      }
    }

    // System.out.println("Have " + match + " matches out of "
    // + PcapDLT.values().length);

    assertTrue(
        "Something is wrong, most constants should match native pcap library",
        match > 20);

    // for (int dlt = 0; dlt < 100; dlt ++) {
    // String libName = Pcap.datalinkValToName(dlt);
    // PcapDLT c = PcapDLT.valueOf(dlt);
    //     
    // if (c == null && libName != null) {
    // System.out.printf("We don't have dlt=%d pcap=%s\n", dlt, libName);
    // }
    // }
  }

  /**
   * Test pcap dumper using dispatch.
   */
  public void testPcapDumperUsingDispatch() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapDumper dumper = pcap.dumpOpen(tmpFile.getPath());
    assertNotNull(pcap.getErr(), dumper);

    PcapHandler<PcapDumper> handler = new PcapHandler<PcapDumper>() {

      public void nextPacket(
          PcapDumper dumper,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        dumper.dump(seconds, useconds, caplen, len, buffer);
      }
    };

    /*
     * Our test file is small, about 24K bytes in size, should fit inside a
     * buffer full.
     */
    int r = pcap.dispatch(Pcap.DISPATCH_BUFFER_FULL, handler, dumper);
    assertTrue("Something happened in dispatch", r == Pcap.OK);

    dumper.close();
    pcap.close();

    // System.out.printf("%s: tmp=%d, source=%d\n", tmpFile.getName(), tmpFile
    // .length(), new File(fname).length());
    //
    assertEquals("dumped file and source file lengths don't match", tmpFile
        .length(), new File(fname).length());
  }

  /**
   * Test pcap dumper using loop.
   */
  public void testPcapDumperUsingLoop() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    PcapDumper dumper = pcap.dumpOpen(tmpFile.getPath());
    assertNotNull(pcap.getErr(), dumper);

    PcapHandler<PcapDumper> handler = new PcapHandler<PcapDumper>() {

      public void nextPacket(
          PcapDumper dumper,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        dumper.dump(seconds, useconds, caplen, len, buffer);
      }
    };

    int r = pcap.loop(Pcap.LOOP_INFINATE, handler, dumper);
    assertTrue("Something happened in the loop", r == Pcap.OK);

    dumper.close();
    pcap.close();

    // System.out.printf("%s: tmp=%d, source=%d\n", tmpFile.getName(), tmpFile
    // .length(), new File(fname).length());
    //
    assertEquals("dumped file and source file lengths don't match", tmpFile
        .length(), new File(fname).length());
  }

  /**
   * <p>
   * Test case in response to
   * <code>Bug #1767744 - PcapHandler object ptr error in loop() and dispatch()</code>.
   * The bug was that PcapHandler jobject ptr in JNI jnetpcap.cpp, was set
   * incorrectly to jobject of the parent which is the Pcap object itself. The
   * neccessary method "nextPacket" was looked up correctly using the proper
   * object but method execution was based on the parent Pcap object not the
   * PcapHandler object passed in. Therefore Java code when it was setting and
   * accessing properties within the PcapHandler sub-class, it was actually
   * clobering data within the Pcap object. Both object's states were terribly
   * incosinstent, private fields had bogus values, that changed for no reason,
   * etc... Very easy fix, the jobject for 'jhandler' was substituted for
   * jobject 'obj' that was used to fix this problem. The problem was both in
   * dispatch() and loop() methods since they are nearly an identical copy of
   * each other.
   * </p>
   * <p>
   * To test this we have to create a PcapHandler object set private fields
   * within it, we'll use an anonymous class, then read in the contents of the
   * entire contents of a test datafile, while updating the value of the field.
   * Then at the end we should have consitent value in that private field. Since
   * the problem seemed complex, but was actually a very easy fix, this should
   * never really break again, but we will check for it anyhow.
   * </p>
   */
  public void testPcapHandlerParentOverrideBugUsingDispatch() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    if (pcap == null) {
      fail("Unable to open test data file because " + errbuf.toString());
    }
    final Pcap parent = pcap;

    // Tracking variable #1
    final AtomicInteger pcapCount = new AtomicInteger();

    final PcapHandler<?> handler = new PcapHandler<Object>() {

      // Tracking variable #2
      private int count = 0;

      public void nextPacket(
          Object userObject,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        pcapCount.addAndGet(1);
        count++;

        if (pcapCount.get() != count) {
          parent.breakloop(); // We exit with breakloop which means FAIL
        }
      }
    };

    int r = pcap.dispatch(Pcap.DISPATCH_BUFFER_FULL, handler, null);
    if (r == Pcap.LOOP_INTERRUPTED) {

      /*
       * Tracking variables are used to make sure they can sustain their
       * assigned values. The bug caused fields and object state to be overriden
       * by object of PcapHandler type.
       */
      fail("Handler indicates that 2 tracking variables in 2 objects, "
          + "did not match");
    } else if (r != Pcap.OK) {
      fail("Error occured: " + pcap.getErr());
    }

    pcap.close();
  }

  /**
   * <p>
   * Test case in response to
   * <code>Bug #1767744 - PcapHandler object ptr error in loop() and dispatch()</code>.
   * The bug was that PcapHandler jobject ptr in JNI jnetpcap.cpp, was set
   * incorrectly to jobject of the parent which is the Pcap object itself. The
   * neccessary method "nextPacket" was looked up correctly using the proper
   * object but method execution was based on the parent Pcap object not the
   * PcapHandler object passed in. Therefore Java code when it was setting and
   * accessing properties within the PcapHandler sub-class, it was actually
   * clobering data within the Pcap object. Both object's states were terribly
   * incosinstent, private fields had bogus values, that changed for no reason,
   * etc... Very easy fix, the jobject for 'jhandler' was substituted for
   * jobject 'obj' that was used to fix this problem. The problem was both in
   * dispatch() and loop() methods since they are nearly an identical copy of
   * each other.
   * </p>
   * <p>
   * To test this we have to create a PcapHandler object set private fields
   * within it, we'll use an anonymous class, then read in the contents of the
   * entire contents of a test datafile, while updating the value of the field.
   * Then at the end we should have consitent value in that private field. Since
   * the problem seemed complex, but was actually a very easy fix, this should
   * never really break again, but we will check for it anyhow.
   * </p>
   */
  public void testPcapHandlerParentOverrideBugUsingLoop() {

    Pcap pcap = Pcap.openOffline(fname, errbuf);
    if (pcap == null) {
      fail("Unable to open test data file because " + errbuf.toString());
    }
    final Pcap parent = pcap;

    // Tracking variable #1
    final AtomicInteger pcapCount = new AtomicInteger();

    final PcapHandler<?> handler = new PcapHandler<Object>() {

      // Tracking variable #2
      private int count = 0;

      public void nextPacket(
          Object userObject,
          long seconds,
          int useconds,
          int caplen,
          int len,
          ByteBuffer buffer) {

        pcapCount.addAndGet(1);
        count++;

        if (pcapCount.get() != count) {
          parent.breakloop(); // We exit with breakloop which means FAIL
        }
      }
    };

    int r = pcap.loop(Pcap.LOOP_INFINATE, handler, null);
    if (r == Pcap.LOOP_INTERRUPTED) {

      /*
       * Tracking variables are used to make sure they can sustain their
       * assigned values. The bug caused fields and object state to be overriden
       * by object of PcapHandler type.
       */
      fail("Handler indicates that 2 tracking variables in 2 objects, "
          + "did not match");
    } else if (r != Pcap.OK) {
      fail("Error occured: " + pcap.getErr());
    }

    pcap.close();
  }

  /**
   * Test pcap open live null ptr handling.
   */
  public void testPcapOpenLiveNullPtrHandling() {
    try {
      Pcap.openLive(null, 1, 1, 1, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test pcap open offline null ptr handling.
   */
  public void testPcapOpenOfflineNullPtrHandling() {
    try {
      Pcap.openOffline(null, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    }
  }

  /**
   * Test set and get nonblock.
   */
  public void testSetAndGetNonblock() {
    Pcap pcap = Pcap.openLive(device, 10000, 1, 60 * 1000, errbuf);
    assertNotNull(errbuf.toString(), pcap);

    assertEquals(OK, pcap.getNonBlock(errbuf));

    pcap.close();
  }

  /**
   * Test set filter null ptr handling.
   */
  public void testSetFilterNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.setFilter(null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }

  /**
   * Test set non block null ptr handling.
   */
  public void testSetNonBlockNullPtrHandling() {
    Pcap pcap = Pcap.openOffline(fname, errbuf);
    try {
      pcap.setNonBlock(1, null);
      fail("Expected a NULL pointer exception.");
    } catch (NullPointerException e) {
      // OK
    } finally {
      pcap.close();
    }
  }
}
TOP

Related Classes of org.jnetpcap.TestPcapJNI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.