/** * Pcap capture multiplexor * * @author ETSI / STF424 * @version $URL$ * $Id$ * Note Copy jnetpcap.jar in C:\WINDOWS\Sun\Java\lib\ext, location of jpcap library */ package org.etsi.its.pcapdump; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.etsi.common.ByteHelper; import org.jnetpcap.Pcap; import org.jnetpcap.PcapBpfProgram; import org.jnetpcap.PcapDumper; import org.jnetpcap.PcapIf; import org.jnetpcap.packet.PcapPacket; import org.jnetpcap.packet.PcapPacketHandler; public class PcapMultiplexer implements Runnable { private static String ExpectedIface = "D4BED91269BD"; /** * Unique instance of the factory */ private static PcapMultiplexer instance = null; private StringBuilder errbuf = new StringBuilder(); // For any error msgs private ILayer _client; private PcapDumper dumper; private PcapMultiplexer() { filter = ""; // Obtain the list of network interfaces List alldevs = new ArrayList(); // Will be filled with NICs int r = Pcap.findAllDevs(alldevs, errbuf); if (r != Pcap.OK || alldevs.isEmpty()) { System.err.printf("Can't read list of devices, error is %s", errbuf.toString()); return; } // Find the right interface int ifaceIndex = 0; String expectedIface = PcapMultiplexer.ExpectedIface; for( ; ifaceIndex < alldevs.size(); ifaceIndex++) { try { if (expectedIface.equalsIgnoreCase(ByteHelper.byteArrayToString(alldevs.get(ifaceIndex).getHardwareAddress()))) { // Interface found break; } } catch (IOException e) { // ignore } } // Check result if (ifaceIndex == alldevs.size()) { throw new RuntimeException(String.format("EthernetLayer.register: Network interface %s not found", expectedIface)); } device = alldevs.get(ifaceIndex); System.out.println("Listening: " + device.getName()); } /** * Gets the unique factory instance * @return PcapMultiplexer instance */ public static PcapMultiplexer getInstance(final String macAddress){ ExpectedIface = macAddress; return (instance = new PcapMultiplexer()); } /** * Gets the unique factory instance * @return PcapMultiplexer instance */ public static PcapMultiplexer getInstance(){ return instance; } public synchronized void register(ILayer client, short frameType) { // Open interface int snaplen = 64 * 1024; // Capture all packets, no truncation int flags = Pcap.MODE_PROMISCUOUS; // capture all packets int timeout = 10; // 10 millis pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf); if (pcap == null) { System.err.printf("Error while opening device for capture: " + errbuf.toString()); return; } captureThread = new Thread(this); captureThread.start(); filter = String.format("ether proto 0x%04x", frameType); System.out.println("New filter: " + filter); // Apply filter PcapBpfProgram bpfFilter = new PcapBpfProgram(); int optimize = 0; // 1 means true, 0 means false int netmask = 0; int r = pcap.compile(bpfFilter, filter, optimize, netmask); if (r != Pcap.OK) { System.out.println("Filter error: " + pcap.getErr()); } pcap.setFilter(bpfFilter); dumper = pcap.dumpOpen(client.getFileName()); _client = client; } public synchronized void unregister(ILayer client) { pcap.breakloop(); dumper.close(); try { captureThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } pcap.close(); } /** * Thread function for jpcap capture loop * @see java.lang.Runnable#run() */ @Override public void run() { PcapPacketHandler dumpHandler = new PcapPacketHandler() { private int counter = 0; @Override public void nextPacket(PcapPacket packet, String user) { dumper.dump(packet); counter += 1; if (counter == 500) { System.out.println("nextPacket: Flushing file"); dumper.flush(); counter = 0; } } }; pcap.loop(-1, dumpHandler, "pcapdump"); } /** * Jpcap capture device */ private Pcap pcap; /** * Jpcap capture thread instance. */ private Thread captureThread; PcapIf device; private String filter; }