package com.aionemu.packetsamurai; import java.io.IOException; import java.net.InetAddress; import java.util.Iterator; import java.util.Map; import java.util.Set; import javolution.util.FastMap; import jpcap.JpcapCaptor; import jpcap.NetworkInterface; import jpcap.NetworkInterfaceAddress; import jpcap.PacketReceiver; import jpcap.packet.TCPPacket; import com.aionemu.packetsamurai.gui.ChoiceDialog; import com.aionemu.packetsamurai.protocol.Protocol; import com.aionemu.packetsamurai.protocol.ProtocolManager; /** * * @author Ulysses R. Ribeiro * @author Gilles Duboscq * */ public class Captor implements Runnable { protected JpcapCaptor _packetCaptor; protected NetworkInterfaceAddress[] _networkAddress; private boolean _captorEnabled = false; private static final int SNAPSHOT_LENGHT = 4*65536; private int _deviceId = -1; protected PacketReceiver _packetHandler; protected static Map<Integer, Protocol> _activeProtocols; private static class SingletonHolder { private final static Captor singleton = Captor.initCaptor(); } public static Captor getInstance() { return SingletonHolder.singleton; } private static Captor initCaptor() { try { Captor captor = new Captor(); captor.initDevice(); Thread captorThread = new Thread(captor, "CaptorThread"); captorThread.setPriority(Thread.MAX_PRIORITY); captorThread.start(); return captor; } catch (Exception e) { Captor.showSetActiveProtocols(); // try to init again (will ask user to set procotol agains if he canceled this previous one) return Captor.initCaptor(); } } public Captor() { _packetHandler = new PacketHandler(this); } public void initDevice() throws Exception { this.configureProtocols(); NetworkInterface[] niList = null; try { niList = JpcapCaptor.getDeviceList(); } catch(UnsatisfiedLinkError ule) { PacketSamurai.getUserInterface().log("ERROR: You are missing the JPcap lib :\n"+ule.getLocalizedMessage()); setCaptor(false); return; } int deviceCount = niList.length; // Check if there is a device to sniff if (deviceCount <= 0) { setCaptor(false); PacketSamurai.getUserInterface().log("ERROR: No Network Interfaces have been found!"); } //if there is only one we bind it else if (deviceCount == 1) { openDevice(niList[0]); } else { if (!PacketSamurai.configExists("NetworkInterface")) { selectNetWorkInterface(); } else { int deviceNumber = Integer.parseInt(PacketSamurai.getConfigProperty("NetworkInterface")); openDevice(deviceNumber); } } } public void selectNetWorkInterface() { NetworkInterface niList[] = JpcapCaptor.getDeviceList(); int deviceCount = niList.length; String nameList[] = new String[deviceCount]; for (int i = 0; i < deviceCount; i++) { PacketSamurai.getUserInterface().log("Found Interface: "+niList[i].description); nameList[i]=(niList[i].addresses.length >= 1 ? niList[i].addresses[0].address.getHostAddress()+": " : "") +niList[i].description; } String[][] choices = new String[1][]; choices[0] = nameList; int[] ret = ChoiceDialog.choiceDialog("Select Interface for Sniffing", new String[]{"Interfaces"} , choices); if (ret != null) { this.openDevice(ret[0]); PacketSamurai.setConfigProperty("NetworkInterface",Integer.toString(ret[0])); } else { PacketSamurai.getUserInterface().log("No interface selected."); } // TODO delete its stuff //Main.getInstance().showInterfaceSelector(nameList); } public void openDevice(int deviceNumber) { openDevice(JpcapCaptor.getDeviceList()[deviceNumber]); _deviceId = deviceNumber; } private void configureProtocols() throws Exception { Captor.setActiveProtocols(PacketSamurai.loadSnifferActiveProtocols()); if (Captor.getActiveProtocols() == null) { Captor.setActiveProtocols(new FastMap<Integer, Protocol>()); for (Protocol p : ProtocolManager.getInstance().getProtocols()) { if (Captor.getActiveProtocols().containsKey(p.getPort())) { // invalidate the map being built Captor.setActiveProtocols(null); throw new Exception("More then one protocol with same port, only one protocol per port can be active for the sniffer."); } Captor.getActiveProtocols().put(p.getPort(), p); } } } public void openDevice(NetworkInterface ni) { try { if (_packetCaptor != null) { setCaptor(false); _packetCaptor.close(); } _packetCaptor = JpcapCaptor.openDevice(ni,SNAPSHOT_LENGHT,false,10); setCaptor(true); _networkAddress = ni.addresses; PacketSamurai.getUserInterface().log("Successfully opened device ("+ni.description+")."); Set<Integer> ports = Captor.getActiveProtocols().keySet(); Iterator<Integer> i = ports.iterator(); String filter = PacketSamurai.getConfigProperty("filter", "").trim(); if (filter.length() > 0) { PacketSamurai.getUserInterface().log("Sniffing with filter: "+filter); _packetCaptor.setFilter(filter, false); } else if (i.hasNext()) { StringBuilder sb = new StringBuilder("(tcp port"); StringBuilder portsSB = new StringBuilder(); for(; i.hasNext();) { Integer port = i.next(); sb.append(" "+port+")"); portsSB.append(port); if(i.hasNext()) { portsSB.append(' '); sb.append(" or (tcp port"); } } PacketSamurai.getUserInterface().log("Sniffing with filter: "+sb.toString()); _packetCaptor.setFilter(sb.toString(),false); PacketSamurai.getUserInterface().log("Sniffing on port(s): "+portsSB); } } catch (IOException ioe) { PacketSamurai.getUserInterface().log("ERROR: Failed to open device ("+ni.description+") for capture "+ioe); } } public void setCaptor(boolean val) { if (val == false && _captorEnabled == true) { _packetCaptor.breakLoop(); } _captorEnabled = val; } public boolean isCaptorEnabled() { return _captorEnabled; } public void run() { if(!this.isCaptorEnabled()) return; // capture packets indefinitely _packetCaptor.loopPacket( -1, _packetHandler); } public JpcapCaptor getPcapCaptor() { return _packetCaptor; } public boolean isClientAddress(InetAddress address) { for (int i = 0; i < _networkAddress.length; i++) { if (_networkAddress[i].address.equals(address)) return true; } return false; } public int getCurrentDeviceId() { return _deviceId; } public static void setActiveProtocols(Map<Integer, Protocol> activeProtocols) { _activeProtocols = activeProtocols; } public static Protocol getActiveProtocolForPort(int port) { return Captor.getActiveProtocols().get(port); } protected static Map<Integer, Protocol> getActiveProtocols() { return _activeProtocols; } public String getPacketDump(TCPPacket tcpPacket) { StringBuffer sb = new StringBuffer(); sb.append("Received a packet: "+PacketSamurai.hexDump(tcpPacket.data)+ " - Flags: "); sb.append(" - ACK: "+(tcpPacket.ack ? "1 : "+tcpPacket.ack_num : "0")); sb.append(" - Fin: "+(tcpPacket.fin ? "1" : "0")); sb.append(" - SYN: "+(tcpPacket.syn ? "1" : "0")); sb.append(" - FIN: "+(tcpPacket.fin ? "1" : "0")); sb.append(" - RST: "+(tcpPacket.rst ? "1" : "0")); sb.append(" - Seq:"+tcpPacket.sequence); sb.append(" - "+(this.isClientAddress(tcpPacket.src_ip) ? "C->S" : "S->C")); sb.append(" - psh: "+(tcpPacket.psh ? "1" : "0")); sb.append(" - Delay: "+(tcpPacket.d_flag ? "1" : "0")); sb.append(" - Dont Fragment: "+(tcpPacket.dont_frag ? "1" : "0")); sb.append(" - More Fragment: "+(tcpPacket.more_frag ? "1" : "0")); sb.append(" - Realibility: "+(tcpPacket.more_frag ? "1" : "0")); sb.append(" - Frag Reservation: "+(tcpPacket.rsv_frag ? "1" : "0")); return sb.toString(); } public static void showSetActiveProtocols() { int total = ProtocolManager.getInstance().getProtocolsByPort().size(); String[] titles = new String[total]; String[][] choices = new String[total][]; Protocol[][] protocols = new Protocol[total][]; int i = 0; for (int port : ProtocolManager.getInstance().getProtocolsByPort().keySet()) { Set<Protocol> prots = ProtocolManager.getInstance().getProtocolForPort(port); titles[i] = "Port "+port; int count = prots.size(); int j = 0; choices[i] = new String[count]; protocols[i] = new Protocol[count]; for (Protocol prot : prots) { protocols[i][j] = prot; choices[i][j++] = prot.getName(); } i++; } PacketSamurai.getUserInterface().log("Please select the active protocols for Sniffing, non active protocols are used for opening old logs."); int[] ret = ChoiceDialog.choiceDialog("Select Active Protocols for Sniffing", titles, choices); // u are doomed to properly set it if (ret != null) { Map<Integer,Protocol> activeProtocols = new FastMap<Integer, Protocol>(); i = 0; for (int sel : ret) { Protocol p = protocols[i++][sel]; activeProtocols.put(p.getPort(), p); } Captor.setActiveProtocols(activeProtocols); PacketSamurai.saveSnifferActiveProtocols(); } } }