Package org.jnetpcap

Core libpcap functionality available on all platforms.

See:
          Description

Interface Summary
ByteBufferHandler<T> A handler, listener or call back inteface that gets notified when a new packet has been captured.
DataLinkType  
JBufferHandler<T> This is a test interface with classes imbeded for a possible replacement to loop and dispatch handers.
JCaptureHeader Interface to to capture header provided by the capturing library.
PcapHandler<T> Deprecated. replaced by ByteBufferHandler
 

Class Summary
Pcap This class is the main class peered with native pcap_t structure in libpcap and winpcap library impelementations.
PcapAddr Class peered with native pcap_addr structure.
PcapBpfProgram Class peered with native bpf_program structure.
PcapDumper Class peered with native pcap_dumper structure.
PcapHeader struct pkt_header { struct timeval ts; // ts.tv_sec, ts.tv_usec uint32 caplen; // captured length uint32 len; // original length }
PcapIf Class peered with native pcap_if_t structure.
PcapInteger Deprecated. replaced by JNumber
PcapPktBuffer Deprecated. replaced by JBuffer
PcapPktHdr Deprecated. replaced by PcapHeader
PcapSockAddr Class peered with native struct sockaddr structure.
PcapStat Class peered with native pcap_stat structure providing only the core statistics.
PcapTask<T> A pcap background task handle.
PcapUtils A Pcap utility class which provides certain additional and convenience methods.
 

Enum Summary
PcapDLT Constants that represent the Pcap's Payload Link Type assignments.
 

Exception Summary
IncompatiblePeer  
PcapClosedException Thrown if Pcap object is access after it has been closed.
PcapExtensionNotAvailableException Exception is thrown when a pcap extension is accessed, one of its methods, while it is not supported on this particular platform.
 

Package org.jnetpcap Description

Core libpcap functionality available on all platforms. jNetPCAP uses Java JNI (Java Native Interface) extensions that are platform specific in order to provide access to libpcap functionality from java programs. The goal of jNetPCAP was to stick as closely as possible to the actual libpcap API so that another API did not have to be learned. Thus it should be fairely easy to get started with jNetPcap if you are already familiar with the native libpcap and winpcap libraries.

Getting Started!

The starting point for jNetPcap is the Pcap class. The Pcap class works directly with the native libpcap library by peering methods and class fields directly with the underlying C structures and function calls. The Pcap class class contains several static methods that create a dynamic Pcap object (a handle in native libpcap lingo) with which you will work with, also refered to as a "Capture Session". Once you have a reference to a Pcap object, most other operations are done through the dynamic Pcap methods. There are other static methods that have more global affect, such as tuning kernel buffer sizes, compiling filter expressions offline, etc. You will also find a number of predefined constants in Pcap class that conveniently provide status return codes and bit flag options.

Primary purpose of a capture session is to capture network packets. There are 3 main static methods provided by Pcap class. They are openLive, openOffline and openDead. openLive captures packets from a live network interface. openOffline reads packets from a file, and openDead is used to create a dummy pcap session for use with certain functions.

Once you have either an open live or offline session, you can capture packets using either a dispatch model, or read one packet at a time method. Methods dispatch and loop allow the user to register a packet handler to which all packets will be dispatched. Methods next and nextEx return one packet at a time.

libpcap library also provides an efficient filtering mechanism that works at the kernel level and even hardware level in certain cases, where a text expression is used to construct a binary filter that can be applied to capture sessions. The methods compile, compileNoPcap and setFilter are used to compile and activate filters.

Decoding packets

The native libpcap, on which jNetPcap is based on, does not provide facilities to decode packet contents. The users of the native library are expected to utilize existing system C structures to decode the content themselves. libpcap only returns pointers to buffers that contain the data and some information about the packet, mainly amount of data captured and detailed timestamp of when the packet was captured.

Decoding packets manually

jNetPcap library does not offer any decoding services by itself, just like native libpcap . You must utilize a higher level library such as jNetStream for packet decoding. For basic and simple decoding needs you can do some manual decoding of the raw packet buffers obtained from a capture. Since you know what the first protocol header within the buffer is using Pcap.datalink() instance method call, you can decode each header structure using java.nio.ByteBuffer which provides a number of getter methods for accessing integers, shorts and other types of java primitives. Here is a short example of how to capture a single packet, make sure its an ethernet packet, and decode a single field within the ethernet header.
StringBuilder errbuf = new StringBuilder();
String file = "capturefile.pcap";
PcapPktHdr hdr = new PcapPktHdr(); // Capture header, filled in at capture

Pcap pcap = Pcap.openOffline(file, errbuf);
if (pcap == null ) { return; }
ByteBuffer buffer = pcap.next(hdr);
if (buffer == null) { return; }

int dlt = pcap.datalink(); // First header type.
pcap.close(); // We're done capturing, only needed 1 packet

if (dlt == PcapDLT.CONST_EN10MB) {
        int protocol = buffer.getShort(12); // Get a 16-bit short, at 12th byte in
        
        // convert from signed short, to unsigned short and store in an integer
        protocol = (protocol < 0)?protocol + Short.MAX_VALUE * 2 : protocol;
        
        // 
        System.out.printf("The value of Ethernet.protocol field is=0x%X\n", protocol);
}
Using the manual approach only works for simple tasks and protocols. The complexity of protocol interactions are vast and not well handled manually. A better approach is to use decoder library to do the manual work for us.

Decoding packets with jNetStream

OpenSource jNetStream is a higher layer API, built upon jNetPcap library and provides very comprehesive decoding and and encoding facilities. jNetStream comes with a rich library of protocols. It also hides all of the low level details of jNetPcap API. Users work with higher level Capture sessions. Both jNetPcap and jNetStream were written by same author.

jNetStream is fusion of Ethereal/Wireshark and NetDude for capture file manipulation. Utilizes the latest advances in Java technology, to provide comparable level of performance to its C counter parts.

Here is a small code example of how to decode a packet using jNetStream library.

StringBuilder errbuf = new StringBuilder();
String file = "capturefile.pcap";
PcapPktHdr hdr = new PcapPktHdr(); // Capture header, filled in at capture

Pcap pcap = Pcap.openOffline(file, errbuf);
if (pcap == null ) { return; }
ByteBuffer buffer = pcap.next(hdr);
if (buffer == null) { return; }

int dlt = pcap.datalink(); // First header type.
pcap.close(); // We're done capturing, only needed 1 packet

long seconds = hdr.getSeconds();
int nanosecs = hdr.getUSeconds() * 1000; // Convert from micro to nano
int snaplen = hdr.getCaplen();
int length = hdr.getLen();
Upto this point, we haven't used any jNetStream code. Now jNetStream library steps in.
ProtocolID dlt = PcapDlt.valueOf(dlt); // In org.jnetstream.capture.file.pcap pkg

Packet packet = Packets.newPacket(buffer, dlt, snaplen, length, seconds, nanosecs);

// Now we can work with a decoded packet
if (packet.hasHeader(Ip4.class)) {
        Ip4 ip = packet.getHeader(Ip4.class);
        
        System.out.println("IP.version = %\n", ip.version());
        System.out.printf("%s -> %s\n", ip.source().toString(), ip.destination().toString());
}
// and so on...
Since jNetStream is already layered ontop of jNetPcap , we could have saved ourselves a bunch of trouble. Here is the same example using only jNetStream API:
File file = new File("capturefile.pcap");
for (Packet packet: Captures.openFile(file)) {
        if (packet.hasHeader(Ip4.class)) {
                Ip4 ip = packet.get(Ip4.class);
                
                System.out.println("IP.version = %\n", ip.version());
                System.out.printf("%s -> %s\n", ip.source().toString(), ip.destination().toString());
        }
        break; // We just wanted 1 packet
}
Captures.close();

Loading the native shared jNetPcap library

The jNetPcap project is made up of 2 parts. The first part is the Java API described in this documentation along with Java class files. The second part is a native dynamically loaded C library, named jnetpcap . The library is loaded once when any of the jNetPcap class files are referenced. The Pcap class automatically requests to load the appropriate library for the native platform and initializes it.

UnsatisfiedLinkError when accessing any of the native java methods

If you get this exception thrown when accessing or intializing jNetPcap java library, it means that Java VM did not load/find the native shared library, and corresponding JNI methods are unlinked. Java VM DOES NOT USE CLASSPATH to load native libraries. Therefore it is not enough to have the library or just the jar file in classpath.

Java supports the following command line option to determine the location of a native library -Djava.library.path= to which you can assign a relative or absolute path where the library is stored. All implementations also look for libraries in the java extension point, which is in the $JAVA_HOME/lib/ext directory.

Library loading procedure on win32 systems

In addition, on windows systems, Java looks in the \windows and \windows\system32 directories. Windows also uses the familiar PATH environment variable to search for library. Just like when its looking for an executable. So just add the directory to the PATH variable. Here is how you would do it from the DOS cmd . (Note, to get cmd on WinXP or WinVista go to Start -> Run and type cmd . A cmd window should open up.) Lets assume that the library resides in c:\jnetpcap\lib directory.
C:\> PATH=%PATH%;c:\jnetpcap\lib
C:\> 
In IDE's (Integrated Development Environment tool such as Eclipse, NetBeans, etc) you would add the environment variable to the "launch" profile or build properties. Of course, setting the -Djava.library.path= on Java VM command line is the prefered way.
(i.e. C:\> java -Djava.library.path=c:\jnetpcap\lib -jar myJNetPcapApp.jar )

Library loading procedure on unix based systems

On all unix systems the typical LD_LIBRARY_PATH environmental variable is used to search for the library.

Name of the native library

The name of jNetPcap 's native library is jnetpcap all lower case letters. When placing a call to System.loadLibrary(String) do not specify any suffixes, postfixes or extensions. This holds true for all operating systems. Further information can be found in JavaDoc API documentation for System.loadLibrary() .

Where to find jnetpcap shared native library

In library distribution package, the top level installation directory within the package, will have jnetpcap library for the appropriate native operating system. (i.e. on windows this is ./jnetpcap.dll.) Source code is also distributed with the binary library package. You can find library source in ./src/c directory.