PCAP文件头:
-------- 24字节 ----------------
PCAP文件标识:4字节
当前主要版本:2字节
当前次要版本:2字节
当地标准时间:4字节
时间戳的精度:4字节
最大存储长度:4字节
数据链路类型: 4字节
--------------------------------------
Packet数据包头:
-------- 16字节 ------------------
时间戳秒:4字节
时间戳毫秒:4字节
数据包长度:4字节
实际数据包长度:4字节
--------------------------------------
Packet数据包包头结构
struct pcap_pkthdr
{
struct timeval ts; // 时间秒、毫秒
bpf_u_int32 caplen; // 数据长度
bpf_u_int32 len; // 实际长度
};
完整数据:
----------------------------------
数据链路包头 :14字节
IP层包头 :20字节
TCP/UDP包头 :20字节
负载数据
----------------------------------
数据链路头14字节
typedef struct EthernetHdr_
{
uint8_t eth_dst[6]; // 目的mac
uint8_t eth_src[6]; // 源mac
uint16_t eth_type; // 类型
} EthernetHdr;
IP头20字节 + options字节
typedef struct IPV4Hdr_
{
uint8_t ip_verhl; 1字节:版本(4bit)+长度(4bit)
uint8_t ip_tos; 1字节:服务类型(没有用)
uint16_t ip_len; 2字节:总长度(IP头+TCP头+数据长度)
uint16_t ip_id; 2字节:标识,数据包计数器
每产生一个数据包+1
分片后该字段相同
uint16_t ip_off; 2字节:flags(2bit)+偏移(13bit)
标志占3位,只有两位有意义,中间位DF = 0 才允许分片
最低位MF=1还有分片,0后面无分片
偏移占13位,某片在原分组中的相对位置(字节/8)
uint8_t ip_ttl; 1字节:生成时间TTL==0时丢弃
表明数据包在因特网中至多可经过的路由器
最大255,每经过一个减1
uint8_t ip_proto; 1字节:协议类型
ICMP、IGMP、TCP、UDP、IPv6
uint16_t ip_csum; 2字节:首部检验和
只检验数据报的首部,不包括数据部分
union {
struct {
struct in_addr ip_src; 4字节源IP地址
struct in_addr ip_dst; 4字节目的IP地址
} ip4_un1;
uint16_t ip_addrs[4];
} ip4_hdrun1;
} IPV4Hdr;
TCP头 前20字节固定 + options字节
typedef struct TCPHdr_
{
uint16_t th_sport; 2字节:源端口号
uint16_t th_dport; 2字节:目的端口号
uint32_t th_seq; 4字节:序号
uint32_t th_ack; 4字节:确定号
uint8_t th_offx2; 1字节:偏移量(4bit)和保留(4bit)
TCP首部的长度
16进制0x80 转2进制10000000,取前4bit,
2进制1000转10进制=8,8*4=32字节(偏移单位是4)
uint8_t th_flags; 1字节:保留(2bit)和标记(6bit)
URG紧急 紧急数据设置=1
ACK确定 连接建立后所有传送报文都设置=1
PSH推送 很少使用
RST复位 TCP连接出现严重错误设置=1,
释放连接,然后重新建立连接
SYN同步 SYN=1 & ACK=0 请求
SYN=1 & ACK=1 相应
FIN终止 释放连接设置=1
uint16_t th_win; 2字节:窗口
指明允许对方发送的数据量
uint16_t th_sum; 2字节:检验和
检验首部和数据两部分
uint16_t th_urp; 2字节:紧急指针
仅在URG=1时有意义,指出紧急数据字节数
} TCPHdr;