⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packetanalyzer.java

📁 基于Jpcap开发的流量监控软件
💻 JAVA
字号:
package joel.ethernettools;
/**
 * MAIN PACKET ANALYZER CLASS.
 * SUPPORTED PROTOCOLS:
 * DATA-LINK-LAYER:
 * ETHERNET->RFC894
 * ARP/RARP->RFC826
 * PPPOE[USED FOR xDSL]
 * NETWORK-LAYER:
 * ICMP->RFC792
 * IP->RFC791
 * TCP
 * UDP->RFC768
 */
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.GregorianCalendar;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;

import jpcap.packet.DatalinkPacket;
import jpcap.packet.EthernetPacket;
import jpcap.packet.Packet;

public class PacketAnalyzer implements Runnable {
	//3rd layer protocols,load from .xml file.
	private Properties  ProtocolTypes;
	//packet property container temporarily.
	private Properties info = new Properties();
	private Packet packet;
	private ProcessedPacket prsdPacket;
	//standard ethernet head length.
	private int ETHERNET_HEAD_LENGTH = 14;
	//PPPoE & PPP protocol difinition.not included in jpcap.
	private final int PPPoE_SESSION_LENTH = 6, PPP_LENTH = 2;
	//PPPoE protocol flag.not included in jpcap.
	private final int ETHERNET_PPPoE = -30620;
	//standard ip-head-length=20 bytes
	//xxxEntrance means the start byte of xxxProtocol in CompleteData(byte[]).
	private int ipHeadLength = 0, TCPUDPEntrance = 0, IPEntrance = 0;
	//packet pool is for holding packet/OriginalPacket/ProcessedPacket temporarily for further log or analyze.
	private PacketPool pool;
	//second-layer=datalink-layer(like pppoe/ppp/arp/rarp,etc)
	//third-layer=network-layer(like ip,ipx,etc)
	private String SecondLayerProtocolType, ThirdLayerProtocolType;
	//system message outputer
	private MsgProvider provider;
	//record current thread fetched/processed packet count.
	private int PacketFetched=0,PacketProcessed=0;
	/**
	 * default constructor.
	 */
	public PacketAnalyzer() {
		this.loadProtocolTypes();		
		provider = new MsgProvider();
	}
	/**
	 * set the <code>PacketPool</code> for getting Packet/OriginalPacket/ProcessedPacket.
	 * @param pool
	 * 
	 */
	protected void setPacketPool(PacketPool pool) {
		this.pool = pool;
	}

	protected void setMsgReceiver(MsgReceiver m) {
		provider.addMsgReceiver(m);
	}

	private void processCaptureInfo() {
		info.put("CAPTURED_TIME", GregorianCalendar.getInstance().getTime()
				.toString());
		info.put("PACKET_LENGTH", Integer.toString(packet.len));
	}

	private byte[] combineCompleteData(byte[] head, byte[] data) {
		byte[] temp = new byte[head.length + data.length];
		int i = 0;
		for (; i < head.length; i++)
			temp[i] = head[i];
		for (int k = 0; i < temp.length; k++, i++)
			temp[i] = data[k];
		return temp;
	}

	public void run() {
		provider.addNewMsg("analyze thread started.name="
				+ Thread.currentThread().getName());
		byte[] CompleteData;
		while (true) {
			while ((this.packet = pool.getNewPacket()) == null) {
				try {
					Thread.currentThread().sleep(
							Math.round(Math.random() * 1000 * 10));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// skip PPPoE echo/reply packets.
			if (packet.len == 30 || packet.len == 60)
				continue;
			PacketFetched++;
			info.clear();
			this.processCaptureInfo();
			this.processDatalinkProperties(packet.datalink);

			if (SecondLayerProtocolType.equals("ARP")) {
				prsdPacket=new ProcessedPacket(info);
				pool.addNewProcessedPacket(prsdPacket);
				continue;
			}
			CompleteData = this.combineCompleteData(packet.header, packet.data);
			if (SecondLayerProtocolType.equals("PPPoE"))
				this.IPEntrance = this.ETHERNET_HEAD_LENGTH
						+ this.PPPoE_SESSION_LENTH + this.PPP_LENTH;
			else
				this.IPEntrance = this.ETHERNET_HEAD_LENGTH;
			this.ipHeadLength = this.convertBintoInt(
					new byte[] { CompleteData[this.IPEntrance] }, 4, 8) * 4;
			this.TCPUDPEntrance = this.IPEntrance + this.ipHeadLength;
			this.setIPHeadProperties(CompleteData, IPEntrance);
			if (SecondLayerProtocolType.equals("ICMP")) {
				prsdPacket=new ProcessedPacket(info);
				pool.addNewProcessedPacket(prsdPacket);
				continue;
			}
			if (ThirdLayerProtocolType.equals("TCP")) {
				this
						.setTCPUDPPacketPortProperties(CompleteData,
								TCPUDPEntrance);
				this.setTCPPacketProperties(CompleteData, TCPUDPEntrance);
			}
			if (ThirdLayerProtocolType.equals("UDP")) {
				this
						.setTCPUDPPacketPortProperties(CompleteData,
								TCPUDPEntrance);
			}
			info.put("PACKET_DATA",OriginalPacket.convertByteArrayToString(CompleteData));
			PacketProcessed++;
			prsdPacket=new ProcessedPacket(info);
			pool.addNewProcessedPacket(prsdPacket);
			CompleteData=null;
			this.prsdPacket=null;
		}
	}

	/**
	 * convert byte to binary,then convert to int.
	 * 
	 * @param b
	 * @see #convertBintoInt(byte[], int, int)
	 * @return
	 */
	private int convertBinToInt(final byte b[]) {
		return this.convertBintoInt(b, 0, 8 * b.length);
	}

	/**
	 * convert byte to binary,then convert to int.
	 * 1.convert each byte in byte[] to BinString.
	 * 2.each byte must be 8 bits,if less,fill with 0 in high-bit.
	 * 3.combine every BinString to one BinString.
	 * 4.convert BinString to int.
	 * @param b
	 * @param start
	 *            ,start position
	 * @param end
	 *            ,end position
	 * @return
	 */

	private int convertBintoInt(final byte[] b, int start, int end) {
		int v = 0, k = 0;
		if (start * end < 0 || start > end || b == null)
			throw new IllegalArgumentException("start=" + start + ",end=" + end
					+ ",b" + b == null ? "=" : "<>" + "null");

		String s, s2 = "";
		for (int i = 0; i < b.length; i++) {
			s = Integer.toBinaryString((int) b[i] & 0xff);
			k = 8 - s.length();
			for (; k > 0; k--)
				s = "0" + s;
			s2 += s;
		}
		char[] str = s2.toCharArray();
		for (int i = start; i < end; i++) {
			if (str[i] == '0')
				continue;
			else
				v += Math.pow(2, str.length - i - 1);
		}

		return v;
	}

	/**
	 * set TCP/UDP src/dst port property.
	 * src/dst port is  2-byte,which can be 0-65535.
	 * @param data which is CompleteData.
	 * @param entrance which is TCPUDPEntrance.
	 */
	private void setTCPUDPPacketPortProperties(final byte[] data, int entrance) {
		byte[] temp = new byte[2];
		int port = 0;
		temp[0] = data[entrance];
		temp[1] = data[entrance + 1];
		port = this.getPortByByteArray(temp);
		info.put("SOURCE_PORT", port == 0 ? "UNKNOWN" : String.valueOf(port));
		temp[0] = data[entrance + 2];
		temp[1] = data[entrance + 3];
		port = this.getPortByByteArray(temp);
		info.put("DESTINATION_PORT", port == 0 ? "UNKNOWN" : String
				.valueOf(port));
	}

	/**
	 * convert data to port NO.
	 * 
	 * @param data
	 *            byte[2]
	 * @return port NO.
	 */
	private int getPortByByteArray(final byte[] data) {
		int port = 0;
		if (data.length != 2)
			return port;
		port = this.convertBinToInt(data);
		return port;
	}

	/**
	 * set TCP Packet property.
	 * including TCP-flag,which is
	 * U=URGENT.
	 * A=ACKNOWLEDGE
	 * P=PUSH
	 * R=RESET
	 * S=SYNCHRONIZE
	 * F=FINISH
	 * 
	 * @param data
	 * @param entrance
	 */
	private void setTCPPacketProperties(final byte[] data, int entrance) {
		String flag = "";
		char[] flags;
		String str = Integer.toBinaryString((int) data[entrance + 13]);
		for (int i = 6 - str.length(); i > 0; i--)
			str = "0" + str;
		flags = str.toCharArray();
		for (int i = 0; i < flags.length; i++) {
			if (flags[i] == '1')
				switch (i) {
				case 0: {
					flag += "U";
					continue;
				}
				case 1: {
					flag += "A";
					continue;
				}
				case 2: {
					flag += "P";
					continue;
				}
				case 3: {
					flag += "R";
					continue;
				}
				case 4: {
					flag += "S";
					continue;
				}
				case 5: {
					flag += "F";
					continue;
				}
				}
		}
		info.put("TCP_FLAG", flag);
	}
	/**
	 * set data-link layer property.
	 * which including:
	 * src mac address
	 * dst mac address
	 * data-link layer frame-type
	 * @param datalink
	 */
	private void processDatalinkProperties(final DatalinkPacket datalink) {
		info.put("DATELINK_ETHERNET_FRAMETYPE", this
				.getEthernetFrameType(datalink));
		info.put("DATELINK_ETHERNET_SRCADDR", this
				.getMACAddr(((EthernetPacket) datalink).src_mac));
		info.put("DATELINK_ETHERNET_DSTADDR", this
				.getMACAddr(((EthernetPacket) datalink).dst_mac));
	}
	/**
	 * set ip-head property.
	 * which including:
	 * ip sub-protocol type
	 * src ip address
	 * dst ip address
	 * @param data
	 * @param ipEntrance
	 */
	private void setIPHeadProperties(byte[] data, int ipEntrance) {
		ThirdLayerProtocolType = this.getIPProtocolType(data, ipEntrance);
		info.put("IP_SUB_PROTOCOL_TYPE", ThirdLayerProtocolType);
		info.put("IP_SRCADDR", this.getIPAddr(data, true, ipEntrance));
		info.put("IP_DSTADDR", this.getIPAddr(data, false, ipEntrance));
	}

	/**
	 * get src/dst ip address from CompleteData.
	 * @param data which is CompleteData.
	 * @param isSrcIPAddr which is a boolean flag.
	 * @param ipEntrance which is the ipEntrance.
	 * @return a String representation of InetAddress.
	 */
	private String getIPAddr(final byte[] data, boolean isSrcIPAddr,
			int ipEntrance) {
		String ip = "UNKNOWN";
		int position = isSrcIPAddr ? ipEntrance + 12 : ipEntrance + 16;
		byte[] temp_ip = new byte[4];
		for (int i = 0; i < temp_ip.length; i++) {
			temp_ip[i] = data[i + position];
		}
		try {
			ip = InetAddress.getByAddress(temp_ip).getHostAddress();
		} catch (UnknownHostException e) {
			ip = "UNKNOWN";
		}
		return ip;
	}
	/**
	 * load third-layer-protocols from xml file.
	 */
	private void loadProtocolTypes() {
		ProtocolTypes = new Properties();
		try {
			ProtocolTypes.loadFromXML(new FileInputStream(System.getProperty("user.dir")+System.getProperty("file.separator")+"XML/protocol_list.xml"));
		} catch (InvalidPropertiesFormatException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("load protocol types end.");
	}

	/**
	 * get a String representation of third-layer-protocol type.
	 * @param data which is CompleteData
	 * @param ipEntrance which is ipEntrance
	 * @return a String representation of third-layer-protocol type.
	 */
	private String getIPProtocolType(final byte[] data, int ipEntrance) {
		// System.out.println("processing ip procotol type.");
		String temp = String.valueOf((int) data[ipEntrance + 9] & 0xff);
		temp = ProtocolTypes.getProperty(temp);
		return temp == null ? "UNKNOWN" : temp;
	}

	private String getMACAddr(final byte[] mac) {
		String temp = "";
		temp = NIC.getMACString(mac);
		return temp;
	}

	/**
	 * get string representation of protocol flag in datalinkhead of the packet.
	 * 
	 * @param p which is a data-link-layer packet from packet.
	 * @return string representation.
	 */
	private String getEthernetFrameType(final DatalinkPacket p) {
		EthernetPacket ether = (EthernetPacket) p;

		switch (ether.frametype) {
		case EthernetPacket.ETHERTYPE_ARP: {
			SecondLayerProtocolType = "ARP";
			break;
		}
		case EthernetPacket.ETHERTYPE_IP: {
			SecondLayerProtocolType = "IP";
			break;
		}
		case EthernetPacket.ETHERTYPE_IPV6: {
			SecondLayerProtocolType = "IPV6";
			break;
		}
		case EthernetPacket.ETHERTYPE_LOOPBACK: {
			SecondLayerProtocolType = "LOOPBACK";
			break;
		}
		case EthernetPacket.ETHERTYPE_PUP: {
			SecondLayerProtocolType = "Xerox PUP";
			break;
		}
		case EthernetPacket.ETHERTYPE_REVARP: {
			SecondLayerProtocolType = "RARP";
			break;
		}
		case EthernetPacket.ETHERTYPE_VLAN: {
			SecondLayerProtocolType = "802.1Q VLAN";
			break;
		}
		case ETHERNET_PPPoE: {
			SecondLayerProtocolType = "PPPoE";
			break;
		}
		default:
			SecondLayerProtocolType = "UNKOWN";
		}
		return SecondLayerProtocolType;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {	
		java.util.Vector v=new java.util.Vector();
		
	}

	protected int getPacketFetched() {
		return PacketFetched;
	}

	protected int getPacketProcessed() {
		return PacketProcessed;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -