|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
Capture<T extends CapturePacket> | A high level, active either a live network or offline file session. |
CaptureFactory.Factory | An Abstract Factory pattern which creates concrete capture objects. |
CaptureFactory.LocalFactory | Factory interface for local sessions. |
CaptureFactory.RemoteFactory | Factory interface for remote sessions. |
CaptureInterface | Describes the capture device that captured the packet. |
CapturePacket | A captured network packet. |
CapturePacketInput | CapturePacketInput interface reads CapturePacket objects from underlying storage or stream which is defined by the class implementing this interface. |
CapturePacketOutput | Allows writting of CapturePackets. |
DeserializedPacket | A packet that was sent accross a stream. |
FileCapture | Immutable interface to an open capture file. |
FileIterator | A bi-directional, random-access iterator. |
FilePacket | A file based packet. |
FileType | Base interface for all the known file types. |
LiveCapture | A network packet cature on a live network interface. |
LivePacket | A packet that was captured on a live network interface. |
MutableCapture<T extends CapturePacket> | Extends the immutable Capture interface and adds a number of methods to add, remove, move packets or seek within the underlying packet dataset. |
MutableCaptureInterface | Provides methods for setting various properties of the underlying CaptureInterface object. |
MutableFileCapture | Extends the immutable FileCapture and adds methods to manipulate the packets stored in a capture file. |
MutableFileIterator | Extends the immutable FileIterator and adds methods to add, remove, move or seek around the underlying packet dataset. |
RemoteSession | A remote session which allows remote capture of live packets or capture file manipulation. |
RemoteSession.RemoteSessionFactory | Remote session handler is an object that is called by the CaptureServer to handle an incomming RemoteSession connection. |
Class Summary | |
---|---|
CaptureFactory | Static factory methods for creating and accessing capture sessions. |
CaptureInputStream | A CaptureInputStream deserializes CapturePackets into DeserializedPacket objects previously written using a CaptureOutputStream. |
CaptureOutputStream | A CaptureOutputStream writes CapturePackets to an OutputStream. |
RemoteServer | Allows remote capture sessions to be started from non-local system. |
Enum Summary | |
---|---|
CapturedProperty | Enum constants that describe certain properties and thus information a particular type of record may contain. |
CaptureInterface.Capability | Enum structure which defines the capabilities of the capturing device such as a network interface and the kernel of this particular OS. |
CaptureInterface.TimestampResolution | |
DataEncapsulation | DLT (Data Link Type) specifies the type of data link protocol that encapsulates the packet data. |
LiveCapture.Option | Options which can be set on open captures. |
RemoteSession.Option | |
RemoteSession.RemoteService | Lists all the avaiable remote services that can be opened, changed, enabled and disabled. |
Exception Summary | |
---|---|
CaptureFormatException | Thrown when Invalid format has been encountered in the capture file. |
CaptureOpenException | Any errors while opening a capture session. |
RemoteAuthenticationException | |
RemoteProtocolException | If a protocol error occures between CaptureSender and CaptureReceiver this exception will contain specific information about the failure. |
A network packet capture framework. This is a high level packet capture framework that abstracts all
of the complexity of live network captures, reading captured packets from capture files (trace files),
streaming packet data accross java.io streams or enabling remote capture sesssion accross the network.
The jnetpcap.capture
package allows easy processing and capture of network packets. Live packets
can be captured on a local network interface or remotely.
The main class you will be dealing with is the Capture interface. You aquire
a reference to a Capture instance using factory methods in the CaptureFactory
class for local sessions
and RemoteSession for, you guessed it, remote sessions on a remote server. (To get a RemoteSession call
the static method RemoteServer.openSession(URI) .)
The factory methods return the most specific subclass of LiveCapture and FileCapture,
all of which are subclasses of the base Capture interface. So remember that LiveCapture and FileCapture
both extend Capture. You will see in the examples below the use of Capture and sometimes the more specific
subclass depending if the method involved in the example need something out of the more specific subclass such
as LiveCapture.interfaceSnapshot() method (see section "CaptureInterface state changes" below.)
CapturePacket is a high level object that holds a buffer with packet data as captured from a live network interface, a file or remote sender. It also contains some additional information needed for proper processing of the buffer. Also contains some meta data such as capture timestamp, a reference to the CaptureDevice which holds detailed descriptors about the network interface that the packet was captured on.
Capture capture = CaptureFactory.openLive(); // Opens up all network interfaces, except loopback ints while (capture.hasNext()) { CapturePacket packet = capture.next(); System.out.println("packet properties=" + packet.toString()); }Note: Note that you also need to catch some exceptions that are declared, but not included in the example.
Another common usage is to capture packets and store them in a file.
So we first setup a source of packets which is a live network capture from a specific network interface.
List<MutableCaptureInterface> ints = CaptureFactory.listInterfaces(); if (ints.isEmpty()) { return; // No interfaces on this system } CaptureInterface netint = ints.get(0); // Just grab the first network interface Capture capture = CaptureFactory.openLive(netint);So now we have a source of packets which is the first network interface returned all the interfaces. Next we want to create a new file and append all the captured packets to that file. We will create the file in PCAP format.
CaptureFactory.newFile(new File("mycapture.pcap", SuppliedFileTypes.PCAP, capture);The above line creates a new file called "mycapture.pcap" in PCAP format (2nd parameter). At this point all the needed initialization is done and a new file created with the right file header. The the last argument is the source of packets, our capture instance. The above method iterates through all the way to the end using
Capture#hasNext()
and Capture#next()
method calls until hasNext eventually returns false. Those
packets are written in the PCAP format into the capture file.
List<MutableCaptureInterface> ints = CaptureFactory.listInterfaces(); if (ints.isEmpty()) { return; // No interfaces on this system } MutableCaptureInterface netint = ints.get(0); // Just grab the first network interface Filter filter = new BpfFilter(new PcapExpression("ip")); Capture capture = CaptureFactory.openLive(filter, netint);
The filter is a BPF filter (Berkley Packet Filter) that efficiently filters incomming packets being captured and only allows packets that match the filter criteria to be returned. The filter is actually applied to operating system kernel (if OS supports this option) and the packet capture driver efficiently filters packets without any extraneous copies of packet contents. Lastly the filter is simply supplied as the first parameter to the openLive method.
An alternate way to set a filter is to set the filter on the MutableCaptureInterface. Such as in this case:
List<MutableCaptureInterface> ints = CaptureFactory.listInterfaces(); if (ints.isEmpty()) { return; // No interfaces on this system } MutableCaptureInterface netint = ints.get(0); // Just grab the first network interface Filter filter = new BpfFilter(new PcapExpression("ip")); netint.setFilter(filter); Capture capture = CaptureFactory.openLive(netint);
This sets the filter only on this interface and not any other interfaces if they were specified. You can also change the filter after the capture has begun and even some packets returned. The only way to change a filter after the CaptureInterface has been applied, is to set it on the capture itself and not on the device instance directly.
List<MutableCaptureInterface> ints = CaptureFactory.listInterfaces(); if (ints.isEmpty()) { return; // No interfaces on this system } MutableCaptureInterface netint = ints.get(0); // Just grab the first network interface Filter ipFilter = new BpfFilter(new PcapExpression("ip")); netint.setFilter(ipFilter); Capture capture = CaptureFactory.openLive(netint); // Get 10 IP packets for (int i = 0; i < 10 && capture.hasNext(); i ++) { System.out.println("CaptureInstance=" + capture.next().getCaptureInterface()); } // After netint has been applied it becomes immutable and we can no longer call // on its MutableCaptureInterface.setFilter method. Use CaptureInterface.isMutable() to check for this. Filter ipxFilter = new BpfFilter(new JpcapExpression("ipx")); CaptureInterface ni = capture.setFilter(filter, netint); // Sets a new filter and creates a new instance of CaptureInterface // Get 10 IPX packets for (int i = 0; i < 10 && capture.hasNext(); i ++) { System.out.println("CaptureInstance=" + capture.next().getCaptureInterface()); } capture.close();The call to
capture.setFilter(filter, netint)
does not modify the netint instance, this instance is
immutable after the call to CaptureFactory.openLive(netint). What happens is a new instance of CaptureInterface is
created based on the old one, and the new filter set in the new instance. The call returns the new CaptureInstance
reference, notice its no longer returned as MutableCaptureInterface as its immediately applied to captures and becomes immutable.
The reason for this strict mutable/immutable control is that any perviously captured packets will still reference
the same CaptureInterface reference at the time they were captured. New packets returned after the new filter
was applied to filter on IPX packets, will return references to new CaptureInterface that has the new filter
applied.
To append packets to an existing file you need to first get your source of packets setup, open up the
capture file and use the methods in MutableFileCapture or simply call a utility method in CaptureFactory.append()
to do the copying for you. This time lets use a NAP file and do the copying ourselves:
Capture capture = CaptureFactory.openLive(); // Opens up all network interfaces, except loopback MutableCaptureFile file = CaptureFiles.openFile(new File("mycapture.nap"); file.last(); // advance the iterator to past the last packet in the file while (capture.hasNext()) { CapturePacket packet = capture.next(); file.add(packet); }First we create a new capture which opens up all the network interfaces for live capture. Second we open a NAP file. Third we advance the file position to the end of the file by calling
MutableFileCapture#last
which returns the last packet and advances the position past it.
We want to append our packets to the end not insert them at the beginning although
for an empty file beginning is the last element.
Lastly we go into a loop that reads one packet at a time and using the mutable file adds or appends
the packets to the file.
We could have done steps 3 and 4 with a utility method. Here is the same example using the utility method:
Capture capture = CaptureFactory.openLive(); // Opens up all network interfaces CaptureFile file = CaptureFiles.openFile(new File("mycapture.nap")); CaptureFiles.append(file, capture);Or this compact notation:
CaptureFiles.catFile(new File("mycapture.nap"), CaptureFactory.openLive());
It is certainly possible for a network interface on which a capture is taking place to change state such as different set of LiveCapture.Option has been set by a separate instance of LiveCapture, someone had alterned the IP addresses assigned to the interface at runtime, a new filter applied, etc etc... All the while our capture session is still in progress. There is a simple way to record these changes by taking a snapshot of the interface config. After a snapshot is taken any packets returned will reference new CaptureInterface objects that reflect the exact config of the interface, while any previously returned packets will continue to reference the old CaptureInterface objects which contain the state before the snapshot took place. To take a snapshot simply call the LiveCapture.interfaceSnapshot method.
LiveCapture capture = CaptureFactory.openLive(); for (int i = 0; i < 10000 && capture.hasNext(); i ++) { LivePacket packet = capture.next(); // Do something with the packet } // Some even caused one of the interface to change state, i.e. new IP address alias added to the interface capture.interfaceSnapshot(); // Now capture 10000 more packets which reference new CaptureInterface objects for (int i = 0; i < 10000 && capture.hasNext(); i ++) { LivePacket packet = capture.next(); // Do something with the packet } capture.close();The call to interfaceSnapshot() creates new CaptureInterface instances on all currently open interfaces. The new CaptureInterfaces are initialized to the latest state of the network interface, reflecting the fact that new IP address alias has been added to one network interfaces. You could more specifically target the exact interface instead of taking a snapshot of all interface by using the variation of the method interfaceSnapshot(CaptureInterface).
Note that using the Capture.setFilter method to set a new filter automatically takes a snapshot to reflect the changed filter. It is not required to take a second snapshot by explicitely calling another interfaceSnapshot.
List<MutableCaptureInterface> ints; LiveCapture live; FileCapture file; CaptureFactory.LocalFactory lf = CaptureFactory.getLocal(); ints = lf.listInterfaces(); // List of all interfaces on local system live = lf.openLive(); // Open all interfaces on local system for capture file = lf.openFile(new File("myfile.pcap")); // Open file on local system for reading and writting live.close(); file.close(); CaptureFactory.RemoteFactory rf = RemoteServer.openSession(new URI("192.168.1.1")); ints = rf.listInterfaces(); // List of all interfaces on remote system live = rf.openLive(); // Open all interfaces on remote system for capture file = rf.openFile(new File("/tmp/myfile.pcap")); // Open file on remote system for reading and writting live.close(); file.close();Or even more abstracted since all these above methods are actually in the super interface CaptureFactory.Factory:
List<MutableCaptureInterface> ints; LiveCapture live; FileCapture file; CaptureFactory.Factory factory; factory = CaptureFactory.getLocal(); ints = factory.listInterfaces(); // List of all interfaces on local system live = factory.openLive(); // Open all interfaces on local system for capture file = factory.openFile(new File("myfile.pcap")); // Open file on local system for reading and writting live.close(); file.close(); RemoteSession session = RemoteServer.openSession(new URI("192.168.1.1")); factory = session; // RemoteSession extends RemoteFactory ints = factory.listInterfaces(); // List of all interfaces on remote system live = factory.openLive(); // Open all interfaces on remote system for capture file = factory.openFile(new File("/tmp/myfile.pcap")); // Open file on remote system for reading and writting live.close(); file.close(); session.close(); // We needed to keep RemoteSession reference only so that we could explicitly close it // because RemoteFactory itself is not Closeable.You get the point. There is not much difference in invoking factory methods for local or remote sessions. There are some restrictions and they are reflected in methods included in the LocalFactory and RemoteFactory interfaces. Certain methods that can only be invoked locally are not included in the RemoteFactory and vise versa. The above example assumes that you have an instance of RemoteServer running on the remote system at IP address 192.168.1.1. It should be clear at this point that the static CaptureFactory methods are only defined for all LocalFactory abstract methods. RemoteSession itself adds a few additional methods related to a remote session besides the methods extended from RemoteFactory.
Factory methods may be much more efficient at copying packets around as more efficient algorithms may be used to accomplish the task then simply iterating one packet at a time. For example if you were appending PCAP file as sources to a destination file that was also a PCAP file, then raw bulk buffers of source file data may be copied at once, without the need to even do the minimal decoding that is done when packets are iterated over. Or if the destination file was a PCAP file and the source LiveCapture was also based on libpcap implementation (as it is, part of the first release) the much more efficient offline capture would be initiated which uses kernel drivers to dump packets directly into the destination capture file; a much more efficient short cut indeed. So the capture framework will pick the most efficient algorithm available for the circumstances at hand.
The capture framework uses java.nio package extensively to allocate large direct buffers, map file contents into memory using native OS shortcuts and then, decodes only the smallest amount of data needed to accomplish the task. The objects returned such as CapturePacket and its subclassed variations reference into these buffers and don't typically allocate a lot of memory themselves. This means these objects can be created efficiently. Multiple packets are typically prefetched into a cache in larger chunks and share a single large buffer. Some buffers map file contents directly into buffer's memory ensuring that the file contents are only read into memory once; by the kernel.
Also use the methods that take entire collections instead of accomplishing the same task by using methods that take a single element and you doing the iteration. This is especially true when modifying files or inserting/deleting packets from files. The implementation algorithms are tuned for executing operations as efficiently as possible given all the information supplied. So inserting or deleting a bunch of packets at once in a file is much more efficient then inserting or deleting a single packet at a time. The same is true for all methods that accept collections or arrays.
Future enhancements may provide additional efficiencies as technologies develop and this project matures. The API is designed to hide the implementation details well and allows a lot of leaverage for the implementors to do their magic behind the scenes.
|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |