Java之Pcap文件解析(二:建立数据结构)

数据结构

根据上一篇文章的内容,可以建立如下数据结构

Pcap 文件头

/**
     * Pcap 文件头结构
     * @author johnnie
     *
     */
    public class PcapFileHeader {

        private int magic;                  // 标识位,这个标识位的值是16进制的 0xa1b2c3d4(4个字节)
        private short magorVersion;     // 主版本号(2个字节)
        private short minorVersion;     // 副版本号(2个字节)
        private int timezone;               // 区域时间(4个字节)
        private int sigflags;               // 精确时间戳(4个字节)
        private int snaplen;                // 数据包最大长度(4个字节)
        private int linktype;               // 链路层类型(4个字节)

        public int getMagic() {
            return magic;
        }

        public void setMagic(int magic) {
            this.magic = magic;
        }

        public short getMagorVersion() {
            return magorVersion;
        }

        public void setMagorVersion(short magorVersion) {
            this.magorVersion = magorVersion;
        }

        public short getMinorVersion() {
            return minorVersion;
        }

        public void setMinorVersion(short minorVersion) {
            this.minorVersion = minorVersion;
        }

        public int getTimezone() {
            return timezone;
        }

        public void setTimezone(int timezone) {
            this.timezone = timezone;
        }

        public int getSigflags() {
            return sigflags;
        }

        public void setSigflags(int sigflags) {
            this.sigflags = sigflags;
        }

        public int getSnaplen() {
            return snaplen;
        }

        public void setSnaplen(int snaplen) {
            this.snaplen = snaplen;
        }

        public int getLinktype() {
            return linktype;
        }

        public void setLinktype(int linktype) {
            this.linktype = linktype;
        }

        public PcapFileHeader() {}

        public PcapFileHeader(int magic, short magorVersion, short minorVersion,
                int timezone, int sigflags, int snaplen, int linktype) {
            this.magic = magic;
            this.magorVersion = magorVersion;
            this.minorVersion = minorVersion;
            this.timezone = timezone;
            this.sigflags = sigflags;
            this.snaplen = snaplen;
            this.linktype = linktype;
        }

        @Override
        public String toString() {
            return "PcapFileHeader [magic=" + DataUtils.intToHexString(magic)
                    + ", magorVersion=" + DataUtils.shortToHexString(magorVersion)
                    + ", minorVersion=" + DataUtils.shortToHexString(minorVersion)
                    + ", timezone=" + DataUtils.intToHexString(timezone)
                    + ", sigflags=" +  DataUtils.intToHexString(sigflags)
                    + ", snaplen=" +  DataUtils.intToHexString(snaplen)
                    + ", linktype=" +  DataUtils.intToHexString(linktype)
                    + "]";
        }

    }   

Pcap 数据头

/**
 * Pcap 数据包头
 * @author johnnie
 *
 */
public class PcapDataHeader {

    /**
     * 时间戳(秒):记录数据包抓获的时间
     * 记录方式是从格林尼治时间的1970年1月1日 00:00:00 到抓包时经过的秒数(4个字节)
     */
    private int timeS;  
    /**
     * 时间戳(微秒):抓取数据包时的微秒值(4个字节)
     */
    private int timeMs;                     
    /**
     * 数据包长度:标识所抓获的数据包保存在 pcap 文件中的实际长度,以字节为单位(4个字节)
     */
    private int caplen;
    /**
     * 数据包实际长度: 所抓获的数据包的真实长度(4个字节)
     * 如果文件中保存不是完整的数据包,那么这个值可能要比前面的数据包长度的值大。
     */
    private int len;                        

    public int getTimeS() {
        return timeS;
    }

    public void setTimeS(int timeS) {
        this.timeS = timeS;
    }

    public int getTimeMs() {
        return timeMs;
    }

    public void setTimeMs(int timeMs) {
        this.timeMs = timeMs;
    }

    public int getCaplen() {
        return caplen;
    }

    public void setCaplen(int caplen) {
        this.caplen = caplen;
    }

    public int getLen() {
        return len;
    }

    public void setLen(int len) {
        this.len = len;
    }

    public PcapDataHeader() {}

    @Override
    public String toString() {
        return "PcapDataHeader [timeS=" +  DataUtils.intToHexString(timeS)
                + ", timeMs=" +  DataUtils.intToHexString(timeMs)
                + ", caplen=" +  caplen
                + ", len=" +  len
                + "]";
    }

}

以太网数据帧

/**
 * Pcap 捕获的数据帧头:以太网帧,14 个字节,可以不做处理,直接跳过
 * @author johnnie
 *
 */
public class PcapDataFrame {

    /**
     * 目的 MAC 地址:6 byte
     */
    private byte[] desMac;

    /**
     * 源 MAC 地址:6 byte
     */
    private byte[] srcMac;

    /**
     * 数据帧类型:2 字节
     */
    private short frameType;

    public byte[] getDesMac() {
        return desMac;
    }

    public void setDesMac(byte[] desMac) {
        this.desMac = desMac;
    }

    public byte[] getSrcMac() {
        return srcMac;
    }

    public void setSrcMac(byte[] srcMac) {
        this.srcMac = srcMac;
    }

    public short getFrameType() {
        return frameType;
    }

    public void setFrameType(short frameType) {
        this.frameType = frameType;
    }

    public PcapDataFrame() {}

    /**
     * 按照 Wireshark 的格式显示信息
     */
    @Override
    public String toString() {
        // frameType 以 十六进制显示
        return "PcapDataFrame [frameType=" + DataUtils.shortToHexString(frameType) + "]";
    }

}

IP 头

/**
 * IP 数据报头
 * @author johnnie
 *
 */
public class IPHeader {

    /**
     * 协议版本号(4 bit)及包头长度(4bit) =(1 字节)
     * 版本号(Version):一般的值为0100(IPv4),0110(IPv6)
     * IP包头最小长度为20字节
     */
    private byte varHLen;

    /**
     * Type of  Service:服务类型,(1 字节)
     */
    private byte tos;

    /**
     * 总长度(2 字节)
     */
    private short totalLen;

    /**
     * 标识(2 字节)
     */
    private short id;

    /**
     * 标志与偏移量(2 字节)
     */
    private short flagSegment;

    /**
     * Time to Live:生存周期(1 字节)
     */
    private byte ttl;

    /**
     * 协议类型(1 字节)
     */
    private byte protocol;

    /**
     * 头部校验和(2 字节)
     */
    private short checkSum;

    /**
     * 源 IP(4 字节)
     */
    private int srcIP;

    /**
     * 目的 IP(4 字节)
     */
    private int dstIP;

    public byte getVarHLen() {
        return varHLen;
    }

    public void setVarHLen(byte varHLen) {
        this.varHLen = varHLen;
    }

    public byte getTos() {
        return tos;
    }

    public void setTos(byte tos) {
        this.tos = tos;
    }

    public short getTotalLen() {
        return totalLen;
    }

    public void setTotalLen(short totalLen) {
        this.totalLen = totalLen;
    }

    public short getId() {
        return id;
    }

    public void setId(short id) {
        this.id = id;
    }

    public short getFlagSegment() {
        return flagSegment;
    }

    public void setFlagSegment(short flagSegment) {
        this.flagSegment = flagSegment;
    }

    public byte getTtl() {
        return ttl;
    }

    public void setTtl(byte ttl) {
        this.ttl = ttl;
    }

    public byte getProtocol() {
        return protocol;
    }

    public void setProtocol(byte protocol) {
        this.protocol = protocol;
    }

    public short getCheckSum() {
        return checkSum;
    }

    public void setCheckSum(short checkSum) {
        this.checkSum = checkSum;
    }

    public int getSrcIP() {
        return srcIP;
    }

    public void setSrcIP(int srcIP) {
        this.srcIP = srcIP;
    }

    public int getDstIP() {
        return dstIP;
    }

    public void setDstIP(int dstIP) {
        this.dstIP = dstIP;
    }

    public IPHeader() { }

    @Override
    public String toString() {
        return "IPHeader [varHLen=" + DataUtils.byteToHexString(varHLen)
                + ", tos=" + DataUtils.byteToHexString(tos)
                + ", totalLen=" + totalLen
                + ", id=" + DataUtils.shortToHexString(id)
                + ", flagSegment=" + DataUtils.shortToHexString(flagSegment)
                + ", ttl=" + ttl
                + ", protocol=" + protocol
                + ", checkSum=" + DataUtils.shortToHexString(checkSum)
                + ", srcIP=" + DataUtils.intToHexString(srcIP)
                + ", dstIP=" + DataUtils.intToHexString(dstIP)
                + "]";
    }
}

TCP 头

/**
 * TCP 包头:20 字节
 * @author johnnie
 *
 */
public class TCPHeader {

    /**
     * 源端口(2 字节)
     */
    private short srcPort;

    /**
     * 目的端口(2 字节)
     */
    private short dstPort;

    /**
     * Sequence Number:发送数据包中的第一个字节的序列号(4 字节)
     */
    private int seqNum;

    /**
     * 确认序列号(4 字节)
     */
    private int ackNum;

    /**
     * 数据报头的长度(4 bit) + 保留(4 bit) = 1 byte
     */
    private byte headerLen;

    /**
     * 标识TCP不同的控制消息(1 字节)
     */
    private byte flags;

    /**
     * 接收缓冲区的空闲空间,用来告诉TCP连接对端自己能够接收的最大数据长度(2 字节)
     */
    private short window;

    /**
     * 校验和(2 字节)
     */
    private short checkSum;

    /**
     * 紧急指针(2 字节)
     */
    private short urgentPointer;

    public short getSrcPort() {
        return srcPort;
    }

    public void setSrcPort(short srcPort) {
        this.srcPort = srcPort;
    }

    public short getDstPort() {
        return dstPort;
    }

    public void setDstPort(short dstPort) {
        this.dstPort = dstPort;
    }

    public int getSeqNum() {
        return seqNum;
    }

    public void setSeqNum(int seqNum) {
        this.seqNum = seqNum;
    }

    public int getAckNum() {
        return ackNum;
    }

    public void setAckNum(int ackNum) {
        this.ackNum = ackNum;
    }

    public byte getHeaderLen() {
        return headerLen;
    }

    public void setHeaderLen(byte headerLen) {
        this.headerLen = headerLen;
    }

    public byte getFlags() {
        return flags;
    }

    public void setFlags(byte flags) {
        this.flags = flags;
    }

    public short getWindow() {
        return window;
    }

    public void setWindow(short window) {
        this.window = window;
    }

    public short getCheckSum() {
        return checkSum;
    }

    public void setCheckSum(short checkSum) {
        this.checkSum = checkSum;
    }

    public short getUrgentPointer() {
        return urgentPointer;
    }

    public void setUrgentPointer(short urgentPointer) {
        this.urgentPointer = urgentPointer;
    }

    public TCPHeader() {}

    @Override
    public String toString() {
        return "TCPHeader [srcPort=" + srcPort
                + ", dstPort=" + dstPort
                + ", seqNum=" + seqNum
                + ", ackNum=" + ackNum
                + ", headerLen=" + headerLen
                + ", flags=" + DataUtils.byteToHexString(flags)
                + ", window=" + window
                + ", checkSum=" + DataUtils.shortToHexString(checkSum)
                + ", urgentPointer=" + urgentPointer
                + "]";
    }


}

UDP 头

/**
 * UDP 包头:由4个域组成,每个域各占用2个字节
 * @author johnnie
 *
 */
public class UDPHeader {

    private short srcPort;          // 源端口
    private short dstPort;          // 目的端口
    private short length;           // 数据包长
    private short checkSum;     // 校验和

    public short getSrcPort() {
        return srcPort;
    }
    public void setSrcPort(short srcPort) {
        this.srcPort = srcPort;
    }
    public short getDstPort() {
        return dstPort;
    }
    public void setDstPort(short dstPort) {
        this.dstPort = dstPort;
    }
    public short getLength() {
        return length;
    }
    public void setLength(short length) {
        this.length = length;
    }
    public short getCheckSum() {
        return checkSum;
    }
    public void setCheckSum(short checkSum) {
        this.checkSum = checkSum;
    }

    public UDPHeader() {}

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "UDPHeader [srcPort=" + srcPort
                + ", dstPort=" + dstPort
                + ", length=" + length
                + ", checkSum=" + DataUtils.shortToHexString(checkSum)
                + "]";
    }

}

协议类型

/**
 * 协议类型
 * @author johnnie
 *
 */
public enum ProtocolType {

    OTHER("0"),                 // 其他协议号:默认为0
    TCP("6"),                   // TCP 协议号:6
    UDP("17");                  // UDP 协议号:17

    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    private ProtocolType(String type) {
        this.type = type;
    }

}

协议五元组

/**
 * 协议数据,五元组
 * @author johnnie
 *
 */
public class ProtocolData {

    String srcIP;                                       // 源 IP
    String desIP;                                       // 目的 IP

    String srcPort;                                     // 源端口
    String desPort;                                     // 目的端口

    ProtocolType protocolType = ProtocolType.OTHER;     // 协议类型

    public String getSrcIP() {
        return srcIP;
    }

    public void setSrcIP(String srcIP) {
        this.srcIP = srcIP;
    }

    public String getDesIP() {
        return desIP;
    }

    public void setDesIP(String desIP) {
        this.desIP = desIP;
    }

    public String getSrcPort() {
        return srcPort;
    }

    public void setSrcPort(String srcPort) {
        this.srcPort = srcPort;
    }

    public String getDesPort() {
        return desPort;
    }

    public void setDesPort(String desPort) {
        this.desPort = desPort;
    }

    public ProtocolType getProtocolType() {
        return protocolType;
    }

    public void setProtocolType(ProtocolType protocolType) {
        this.protocolType = protocolType;
    }

    public ProtocolData() {
        // TODO Auto-generated constructor stub
    }

    public ProtocolData(String srcIP, String desIP, String srcPort,
            String desPort, ProtocolType protocolType) {
        this.srcIP = srcIP;
        this.desIP = desIP;
        this.srcPort = srcPort;
        this.desPort = desPort;
        this.protocolType = protocolType;
    }

    @Override
    public String toString() {
        return "ProtocolData [srcIP=" + srcIP
                + ", desIP=" + desIP
                + ", srcPort=" + srcPort
                + ", desPort=" + desPort
                + ", protocolType=" + protocolType
                + "]";
    }

}

Pcap结构

/**
 * Pcap 结构
 * @author johnnie
 *
 */
public class PcapStruct {

    private PcapFileHeader fileHeader;
    private List dataHeaders;

    public PcapFileHeader getFileHeader() {
        return fileHeader;
    }
    public void setFileHeader(PcapFileHeader fileHeader) {
        this.fileHeader = fileHeader;
    }
    public List getDataHeaders() {
        return dataHeaders;
    }
    public void setDataHeaders(List dataHeaders) {
        this.dataHeaders = dataHeaders;
    }

    public PcapStruct() {}


}

前往 bascker/javaworld 获取更多 Java 知识

你可能感兴趣的:(Pcap文件解析)