com.devoteam.srit.xmlloader.core.protocol.Probe.java Source code

Java tutorial

Introduction

Here is the source code for com.devoteam.srit.xmlloader.core.protocol.Probe.java

Source

/* 
 * Copyright 2012 Devoteam http://www.devoteam.com
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * 
 * This file is part of Multi-Protocol Test Suite (MTS).
 * 
 * Multi-Protocol Test Suite (MTS) is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 3 of the
 * License.
 * 
 * Multi-Protocol Test Suite (MTS) is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Multi-Protocol Test Suite (MTS).
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.devoteam.srit.xmlloader.core.protocol;

import com.devoteam.srit.xmlloader.core.exception.ExecutionException;
import com.devoteam.srit.xmlloader.core.log.GlobalLogger;
import com.devoteam.srit.xmlloader.core.log.TextEvent;
import com.devoteam.srit.xmlloader.core.newstats.StatPool;
import com.devoteam.srit.xmlloader.core.protocol.probe.PIPReassembler;
import com.devoteam.srit.xmlloader.core.protocol.probe.PJpcapThread;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.devoteam.srit.xmlloader.core.Parameter;
import com.devoteam.srit.xmlloader.core.protocol.probe.PTCPPacket;
import com.devoteam.srit.xmlloader.core.protocol.probe.PTCPSocket;
import com.devoteam.srit.xmlloader.core.protocol.probe.PUDPPacket;
import com.devoteam.srit.xmlloader.core.utils.expireshashmap.ExpireHashMap;
import com.devoteam.srit.xmlloader.core.utils.Utils;
import com.devoteam.srit.xmlloader.ethernet.MsgEthernet;
import com.devoteam.srit.xmlloader.ethernet.StackEthernet;
import com.devoteam.srit.xmlloader.genscript.ScriptGenerator;

import gp.utils.arrays.Array;
import java.util.Map;

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.packet.EthernetPacket;
import jpcap.packet.Packet;

import org.dom4j.Element;

/**
 * Interface generique servant a identifier un probe : point de capture
 * @author fhenry
 */
public class Probe {
    private static boolean DEFAULT_PROMISCUOUS_MODE = true;

    // name of the probe
    private String name;
    // name of the network interface to capture on
    private String networkInterface;
    // capture filter (the same syntax as tcpdump or Wireshark tool)
    private String captureFilter;
    // filename to capture
    private String filename;
    // Regular expression specific filter
    private String regexFilter;
    // True if you want to open the interface in promiscuous mode, and otherwise false.
    // In non-promiscuous mode, you can only capture packets send and received by your host.
    private String promiscuousMode;

    private Pattern pattern;
    private Matcher matcher;

    private String protocol;
    private Stack stack;

    private PJpcapThread probeJpcapThread;

    private ExpireHashMap<String, PTCPSocket> sockets;

    private long startTimestamp = 0;

    // ## flag for know if we are in capture or generation
    private boolean genScript = false;

    private ScriptGenerator generator;

    /** Creates a Probe specific from XML tree*/
    public Probe(Stack stack, Element root) throws Exception {
        this.stack = stack;
        this.name = root.attributeValue("name");
        this.networkInterface = root.attributeValue("networkInterface");
        String capFilter = root.attributeValue("captureFilter");
        if (capFilter != null) {
            capFilter = Utils.replaceNoRegex(capFilter, "[", "");
            capFilter = Utils.replaceNoRegex(capFilter, "]", "");
        }
        this.captureFilter = capFilter;
        this.filename = root.attributeValue("filename");
        this.regexFilter = root.attributeValue("regexFilter");
        this.sockets = new ExpireHashMap<String, PTCPSocket>("captured TCP streams", 600000);
        if (regexFilter != null && !regexFilter.equals("")) {
            this.pattern = Pattern.compile(regexFilter);
        } else {
            this.pattern = null;
        }
        this.promiscuousMode = root.attributeValue("promiscuousMode");
        this.probeJpcapThread = new PJpcapThread(this);
        PIPReassembler.start();

        // ETHERNET protocol only
        // To avoid using two jpcap capture at the same time
        // enable isEthernetProbeCreated in EthernetStack
        if (stack instanceof StackEthernet)
            ((StackEthernet) stack).setEthernetProbeCreated(true);
    }

    public Map<String, PTCPSocket> getPTCPSockets() {
        return sockets;
    }

    public String getName() {
        return this.name;
    }

    public String getNetworkInterface() {
        return this.networkInterface;
    }

    public String getFilename() {
        return this.filename;
    }

    public String getCaptureFilter() {
        return this.captureFilter;
    }

    public String getRegexFilter() {
        return this.regexFilter;
    }

    public String getProtocol() {
        return protocol;
    }

    /** create a probe  */
    public boolean create(String protocol) throws Exception {
        StatPool.beginStatisticProtocol(StatPool.PROBE_KEY, "", StackFactory.PROTOCOL_IP, protocol);
        this.startTimestamp = System.currentTimeMillis();

        this.protocol = protocol;
        probeJpcapThread.create();

        return true;
    }

    /** Remove a probe */
    public boolean remove() {
        StatPool.endStatisticProtocol(StatPool.PROBE_KEY, "", StackFactory.PROTOCOL_IP, this.protocol,
                startTimestamp);

        this.probeJpcapThread.stop();
        return true;
    }

    public boolean sendETHMessage(Msg msg) throws ExecutionException {
        return this.probeJpcapThread.sendETHMessage(msg);
    }

    /** display method */
    @Override
    public String toString() {
        String str = "";
        str += "name=\"" + this.name + "\"";
        str += ", networkInterface = \"" + this.networkInterface + "\"";
        str += ", captureFilter = \"" + this.captureFilter + "\"";
        if (null != filename) {
            str += ", filename = \"" + this.filename + "\"";
        }
        if (null != regexFilter && !regexFilter.equals("")) {
            str += ", regexFilter = \"" + this.regexFilter + "\"";
        }
        return str;
    }

    /** equals method */
    public boolean equals(Probe probe) {
        if (probe == null) {
            return false;
        }

        String name = probe.getName();
        if (null != this.name) {
            if (!this.name.equals(name)) {
                return false;
            }
        }

        String network = probe.getNetworkInterface();
        if (null != this.networkInterface) {
            if (!this.networkInterface.equals(network)) {
                return false;
            }
        }

        String filter = probe.getCaptureFilter();
        if (null != this.captureFilter) {
            if (!this.captureFilter.equals(filter)) {
                return false;
            }
        }

        String filename = probe.getFilename();
        if (null != this.filename) {
            if (!this.filename.equals(filename)) {
                return false;
            }
        }

        return true;
    }

    public Parameter getParameter(String path) throws Exception {
        String[] params = Utils.splitPath(path);
        if (params.length < 2) {
            return null;
        }

        Parameter parameter = new Parameter();

        if (params[1].equalsIgnoreCase("name")) {
            parameter.add(this.name);
        } else if (params[1].equalsIgnoreCase("networkInterface")) {
            parameter.add(this.networkInterface);
        } else if (params[1].equalsIgnoreCase("captureFilter")) {
            parameter.add(this.captureFilter);
        } else if (params[1].equalsIgnoreCase("filename")) {
            parameter.add(this.filename);
        } else if (params[1].equalsIgnoreCase("regexFilter")) {
            parameter.add(this.regexFilter);
        } else if (params[1].equalsIgnoreCase("promiscuousMode")) {
            parameter.add(this.promiscuousMode);
        } else {
            Parameter.throwBadPathKeywordException(path);
        }
        return parameter;
    }

    public boolean getPromiscuousMode() {
        boolean promisc;

        if (null == promiscuousMode || "".equals(promiscuousMode)) {
            promisc = DEFAULT_PROMISCUOUS_MODE;
            this.promiscuousMode = Boolean.toString(DEFAULT_PROMISCUOUS_MODE);
        } else {
            promisc = new Boolean(this.promiscuousMode);
        }

        return promisc;
    }

    /**
     *
     * @return true if this data should be captured
     */
    private boolean isValidCapture(byte[] data) {
        // the message is valid because part of an existing transaction or
        // session
        boolean result = stack.isValidCapture(data);
        if (result) {
            return true;
        }
        // the message is valid because matching the regex filter given by
        // the user
        if (null != pattern) {
            matcher = pattern.matcher(new String(data));

            result = matcher.find();
            this.matcher.reset();
        } else {
            result = true;
        }
        if (!result) {
            return false;
        }

        return result;
    }

    synchronized public void capturedETHPacket(Packet packet) throws Exception {

        int length = packet.header.length + packet.data.length - 14; // 14 is the ethernet headder length we have to substract in order to get good length of ethernet frame payload
        EthernetPacket eth = (EthernetPacket) packet.datalink;
        int type = eth.frametype;
        byte[] srcMac = eth.src_mac;
        byte[] dstMac = eth.dst_mac;
        byte[] data = new byte[length];
        MsgEthernet msg = null;
        int j = 0;

        for (int i = 14; i < packet.header.length; i++) {
            data[j++] = packet.header[i];
        }
        for (int i = 0; i < packet.data.length; i++) {
            data[j++] = packet.data[i];
        }

        try {
            msg = (MsgEthernet) stack.readFromDatas(data, length);
            msg.setProbe(this);
            msg.setType(type);
            msg.setdstMac(dstMac);
            msg.setSrcMac(srcMac);
            stack.captureMessage(msg);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    synchronized public void capturedUDPPacket(PUDPPacket packet) throws Exception {
        byte[] data = packet.getData().getBytes();

        GlobalLogger.instance().getApplicationLogger().debug(TextEvent.Topic.PROTOCOL, Stack.CAPTURE,
                "the UDP message :\n", packet, "\n", new String(data));

        boolean result = stack.isValidCapture(data);
        if (!result) {
            result = isValidCapture(data);
        }
        if (result) {
            Msg msg = stack.readFromDatas(data, data.length);
            msg.setProbe(this);
            msg.setChannel(packet);

            if (genScript) {
                msg.setTimestampCaptureFile(packet.getIPHeader().getTimestamp());
                generator.generateMsg(msg);
            } else {
                stack.captureMessage(msg);
            }
        }
    }

    public void handlePTCPSocket(PTCPSocket socket) throws Exception {

        Msg msg = stack.readFromStream(socket.getInputStream(), socket);

        if (msg != null) {
            GlobalLogger.instance().getApplicationLogger().debug(TextEvent.Topic.PROTOCOL, Stack.CAPTURE,
                    " TCP message :\n", msg);

            msg.setChannel(socket);
            msg.setProbe(this);

            if (genScript) {
                msg.setTimestampCaptureFile(socket.getLastTimestamp());
                generator.generateMsg(msg);
            } else {
                stack.captureMessage(msg);
            }
        }
    }

    synchronized public void capturedTCPPacket(PTCPPacket packet) throws Exception {
        if (packet.getTCPHeader().ack()) {

            // compute capture socket ID
            StringBuilder builder = new StringBuilder(12);
            builder.append(Array.toHexString(packet.getIPHeader().getSrcIP()));
            builder.append(Array.toHexString(packet.getTCPHeader().getSrcPort()));
            builder.append(Array.toHexString(packet.getIPHeader().getDstIP()));
            builder.append(Array.toHexString(packet.getTCPHeader().getDstPort()));

            String socketID = builder.toString();

            PTCPSocket socket = sockets.get(socketID);

            boolean newData = true;
            if (null == socket) {
                socket = new PTCPSocket(packet, this);
            } else {
                newData = socket.addPacket(packet);
            }

            if (newData) {
                sockets.remove(socketID);
                sockets.put(socketID, socket);
            }
        }
    }

    // Methode pour activer le mode generation de script de Probe
    public void genScript(ScriptGenerator sg) {
        genScript = true;
        generator = sg;
    }

    public PJpcapThread getProbeJpcapThread() {
        return probeJpcapThread;
    }
}