I have written a code snippet to cpature ping using JPCAP. the code I have written is given below :
while (true) {
try {
PacketCapture m_pcap;
m_pcap = new PacketCapture();
m_pcap.open("\\Device\\NPF_{007262BD-....-7EE83D72EBEA}",true);//param 1 is actual device ID
m_pcap.setFilter("proto ICMP", true);
pktlistener a = new pktlistener(); //handles the packet
m_pcap.addPacketListener(a);
System.out.println("going to sleep");
Thread.sleep(1 * 1000);// Waiting for 1 second before ending capture
System.out.println("woken up");
m_pcap.removePacketListener(a);
m_pcap.endCapture();
m_pcap.close();
a = null;
m_pcap = null;
} catch (Exception e) {
e.printStackTrace();
}
}
Now the above code starts a new capture after every one second. The problem with the above is that after 10 runs of the loop, it throws the exception :
Exception in thread "Thread-6" java.lang.Error: Too many instances, exceeds 10
at net.sourceforge.jpcap.capture.PacketCapture.<init>(PacketCapture.java:51)
Q1. How do i prevent this. I need to start a new PacketCapture every second.
Q2. Is there any other simpler way to capture ping messages recived on a system through java?
You cannot use the constructor of PacketCapture
more than ten times. This behavior is hardcoded as the constructor looks like this:
/**
* Create a new packet capture instance.
*/
public PacketCapture() {
if (nextInstance >= INSTANCE_MAX) {
throw new Error("Too many instances, exceeds " + INSTANCE_MAX);
}
instanceNum = nextInstance++;
}
To capture ping requests, you should try the following code
public class Main {
public static void main(String[] args) throws CaptureDeviceLookupException {
Capture cap = new Capture();
cap.doCapture();
}
}
class PingListener implements PacketListener {
@Override
public void packetArrived(Packet packet) {
try {
// only ICMP packages
if (packet instanceof ICMPPacket) {
ICMPPacket tcpPacket = (ICMPPacket) packet;
int data = tcpPacket.getMessageCode();
// only echo request packages
if (data == ICMPMessages.ECHO) {
// print source and destination.
String srcHost = tcpPacket.getSourceAddress();
String dstHost = tcpPacket.getDestinationAddress();
System.out.println("Ping from: " + srcHost + " to " + dstHost);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Capture {
public void doCapture() {
// create capture instance
PacketCapture capture = new PacketCapture();
// add listener that handles incomming and outgoing packages
PingListener pingListener = new PingListener();
capture.addPacketListener(pingListener);
// m_pcap.setFilter("filter here or in handler", true);
try {
capture.open("\\Device\\NPF_{...}", true); // connect capture to device
while (true) {
capture.capture(1); // capture one package
}
} catch (Exception e) {
e.printStackTrace(); // exception during capture or handling of
// packages
} finally {
// technically never reached as the loop goes on forever.
// if loop terminates after a while then:
// remove listener
capture.removePacketListener(pingListener);
// end capture (only necessary, if PacketCapture still waits for
// other packages)
capture.endCapture();
// close connection to capture device
capture.close();
}
}
}
I think there is a misunderstanding of the class PacketCapture
. It does not actually capture one package and is then discarded. It opens a connection to the device you want to capture packages of and then starts listening for as long as you hold that connection. You then start capturing n
packages by calling capture.capture(n)
. For each package arriving while "capture" blocks your program, the listener is called.
Alternatively you can drop the while-loop and use capture.capture(-1)
. This will block your program forever until you close the capture from another device.