Package org.jnetpcap

Core libpcap functionality available on all platforms.

See:
          Description

Interface Summary
PcapHandler<T> A handler, listener or call back inteface that gets notified when a new packet has been captured.
 

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.
PcapIf Class peered with native pcap_if_t structure.
PcapInteger An 32-bit integer reference that can be used to pass into pcap methods that require an integer pointer to be set as a return value.
PcapPktBuffer Class used to pass back a reference to a ByteBuffer containing the packet data.
PcapPktHdr Class peered with native pcap_pkthdr structure.
PcapSockAddr Class peered with native struct sockaddr structure.
PcapStat Class peered with native pcap_stat structure providing only the core statistics.
 

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

Exception Summary
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 to give access to libpcap functionality from java programs. The goal of jNetPCAP was to stick as close as possible to the actual libpcap API so that another API did not have to be learned. Thus its fairely easy to pickup with jNetPCAP and use it right away if you are familiar with existing "C" counter part libpcap and winpcap libraries.

Getting Started!

The starting point for jNetPcap is the Pcap class . The Pcap class works directly with the native Libpcap by peering through the use of a native library and Java's JNI API. The class contains several static methods that create capture sessions at which point a dynamic session reference is returned. From then on, all 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.

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.

Pcap 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. For basic things you can do some manual decoding of the raw packet buffers obtained from a capture. You know what the first protocol header within the buffer is using Pcap.datalink() instance method call. java.nio.ByteBuffer provides a a number of getter methods for accessing ints, 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 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(Ip.class)) {
        Ip ip = packet.getHeader(Ip.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:
String file = "capturefile.pcap";
for (Packet packet: Captures.openFile(file)) {
        if (packet.hasHeader(Ip.class)) {
                Ip ip = packet.get(Ip.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 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 Pcap library, it means that it did not load 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 you would add the environment variable to the "launch" profile or build properties. But 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 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 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.