jNetPcap 1.X

jNetPcap 1.X module: libpcap and packet decoder

Tutorial 1 - creating IP fragment reassembler

IP fragment reassembly is a bit more advanced topic. The tutorial will demonstrate more typical usage of Packet Decoding Framework, part of jNetPcap API.

In order to understand some of the networking concepts discussed in this tutorial you need to first study IP fragmentation and reassembly. Wikipedia has a nice short write up on Ip fragmentation and reassembly (link: Wikipedia). Only a cursory overview understanding is needed to follow the tutorial.

Then we will plan out our strategy for our little application and implement it.

Here are some key concepts about the API that are covered in this tutorial:

  • Building a custom handler that will dispatch reassembled datagram buffers
  • Working with multiple buffers and peering protocol headers to them
  • Overriding specific protocol header fields with our custom values
  • Working with JMemoryPacket to create our custom IP only packet and telling the scanner to decode the reassembled datagram

The complete application source code can be downloaded here: IpReassemblyExample.java

2.8 - Dumping captured packet to an offline file

We've covered reading packets from an offline file, what about writing captured packets to an offline file.

Libpcap library provides a mechanism for doing just that. We first open up our normal pcap capture, either online or offline, doesn't really matter, its a source of packets. Then we create a pcap dumper using PcapDumper class, that is associated with our pcap capture. Then we setup a handler and we pass into it our dumper which we instruct to dump every packet received.

StringBuilder errbuf = new StringBuilder();
String fname = "tests/test-afs.pcap";

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

String ofile = "tmp-capture-file.cap";
PcapDumper dumper = pcap.dumpOpen(ofile); // output file

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

  public void nextPacket(PcapHeader header, JBuffer buffer, PcapDumper dumper) {

    dumper.dump(header, buffer);
  }
};

pcap.loop(10, dumpHandler, dumper);
                
File file = new File(ofile);
System.out.printf("%s file has %d bytes in it!\n", ofile, file.length());
                
dumper.close(); // Won't be able to delete without explicit close
    pcap.close();

And that will do it.

If the only thing you want to do is dump packets to a file, jNetPcap provides a performance enhancing native dumper. This dumper dumps packets natively without entering "java" space.

StringBuilder errbuf = new StringBuilder();
String fname = "tests/test-afs.pcap";

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

String ofile = "tmp-capture-file.cap";
PcapDumper dumper = pcap.dumpOpen(ofile); // output file

pcap.loop(10, dumper); // Special native dumper call to loop
                
File file = new File(ofile);
System.out.printf("%s file has %d bytes in it!\n", ofile, file.length());
                
dumper.close(); // Won't be able to delete without explicit close
    pcap.close();

2.2 - Getting a List of Interfaces

Java package: org.jnetpcap


When you want to capture packets directly from a live network, you first must acquire a list of available network interfaces and then choose which one to open. Interface names differ greatly on each platform and can change order at anytime even on the same system.

Therefore it is not usually easy to programmaticaly choose a network interface on behalf of the user, and usually that decision is left up to the user either through a configuration option in your application or some user interface that lets the user choose one interface.

There is a function provided by Pcap class to do retrieve a list of interfaces. It is Pcap.findAllDevs() function. It returns an integer error code and fills in a supplied collections List object with PcapIf objects. Each PcapIf is a separate interface found on this particular system.

List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
StringBuilder errbuf = new StringBuilder();     // For any error msgs
                
int r = Pcap.findAllDevs(alldevs, errbuf);
if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
  System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
  return;
}

Notice that the supplied list to Pcap.findAllDevs() is a regular JRE list which is filled with interfaces. This was another place where following the actual native libpcap programming style did not make sense. So we use a much more java friendly list than a linked list of some objects.

The important thing we are trying to acquire is the name of the interface the user or your application is interested in capturing on. We can get the name of the interface using PcapIf.getName() method and pass that into Pcap.openLive() for example or build a menu for the user with it.

PcapExtension NotAvailable exception

Q: I get this exception when I try to access any methods from org.jnetpcap.winpcap package.

A: The exception is telling you that on this particular platform the winpcap extension is not available and can not be used.

WinPcap native library is a windows implementation of libpcap library. It supports all of the libpcap functions and adds several new capabilities but only on windows platforms. jNetPcap API provides WinPcap extention only on windows platform.

In order to avoid having this error thrown, the user must check if WinPcap extension is supported on this particular platform at runtime. To check for support use WinPcap.isSupported():boolean method which will return a boolean true if it is supported, otherwise false. This method never throws an exception and needs to be used before your code relies on any features within that winpcap package.

UnsatisfiedLinkError exception

Q: When accessing jNetPcap API I get this exception thrown: "UnsatisfiedLinkError".

A: The exception is thrown when you access a method that requires the native jnetpcap shared library (.dll or .so library on different systems) and its not found.

The library is supplied with jNetPcap. You need to ensure that you correctly define on each particular system, the folder or directory where the library is located.

You can use a OS specific environment variable to define the directory where the library resides or you can tell java VM directly using -Djava.library.path=path bypassing and overriding any environmental settings. Notice that its directory path not a fully qualified path to the library itself. Another words don't include the name of the library file in the path, just the directory.

On Unix systems

On any unix system make sure that that variable is exported in the environment

LD_LIBRARY_PATH=/usr/lib

On Win32 systems

In your c:\autoexec.bat
set path="%path%;/windows/system32"

Syndicate content