基于LINUX系统设计并实现一个网络流量的分析系统。该系统具有以下功能:(1)实时抓取网络数据。(2)网络协议分析与显示。(3)将网络数据包聚合成数据流,以源IP、目的IP、源端口、目的端口及协议等五元组的形式存储。(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。在这些统计数据的基础上分析不同网络应用的流量特征。
关键词:linux,libpcap,流量分析,网络抓包,协议分析,哈希链表,文件操作,C语言
(1)能够实时抓取网络中的数据包。并实时显示在程序界面上。用户可自定义过滤条件以抓取所需要的数据包。
(2)分析各个网络协议格式,能够显示各协议字段的实际意义。例如,能够通过该程序反映TCP三次握手的实现过程。
(3)采用Hash链表的形式将网络数据以连接(双向流)的形式存储。
(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。例如,抓取一段时间(如30分钟)的网络流量,将该段时间以固定时长(如1分钟)为单位分成若干个时间片,计算网络连接在每一个时间片内的相关统计量。并在上述统计数据的基础上分析不同应用如WEB、DNS、在线视频等服务的流量特征。注意,可根据实际的流量分析需要自己定义相关的统计量。
硬件设备:
(1)MAC笔记本
软件设备:
(2)MACOS(UNIX内核)
(3)网络数据包捕获函数包,Linux平台下为libpcap
(4)编程语言选用C,IDE使用Xcode
实验环境的配置:
Lipcap 下载地址为:http://www.tcpdump.org/release/libpcap-1.7.3.tar.gz
libpcap(Packet Capture library)即数据包捕获函数库。该库提供的C函数接口可用于需要捕获经过网络接口(只要经过该接口,目标地址不一定为本机)数据包的系统开发上。由 Berkeley大学Lawrence Berkeley National Laboratory研究院的Van Jacobson、Craig Leres和Steven McCanne编写。该函数库支持Linux、Solaris和*BSD系统平台。libpcap主要由两部份组成:网络分接头(Network Tap)和数据过滤器(Packet Filter)。
lipcap的安装过程:
1)tar zxvf libpcap-1.7.3.tar.gz 解压文件,并将其放入自定义的安装目录。
2)打开网址:flex.sourceforge.net/ 下载 flex-2.5.35.tar.gz (1.40MB) 软件包,通过 tar zxvf flex-2.5.35.tar.gz 解压文件,并将其放入上述自定义的安装目录中。
注:如果没有编译安装此文件,在编译安装libpcap时,可能会出现 “configure: error: Your operating system’s lex is insufficient to compile libpcap.”的错误提示。
3)打开网址:ftp.gnu.org/gnu/bison/ 下载 bison-2.4.1.tar.gz (1.9MB) 软件包,通过 tar zxvf bison-2.4.1.tar.gz 解压文件,并将其放入上述自定义的安装目录中。
如果没有编译安装此文件,在编译安装libpcap时,可能会出现 “configure: WARNING: don’t have both flex and bison; reverting to lex/yacc checking for capable lex… insufficient” 的错误提示。
4)打开网址:ftp.gnu.org/gnu/m4/ 下载 m4-1.4.13.tar.gz (1.2MB)软件包,通过 tar zxvf m4-1.4.13.tar.gz 解压文件,并将其放入上述自定义的安装目录中。
注:如果没有编译安装此文件,在编译安装bison-2.4.1时,就会出现 “configure: error: GNU M4 1.4 is required”的错误提示。
5)依次进入目录m4-1.4.13,bison-2.4.1,flex-2.5.35,libpcap-1.0.0 并执行以下命令:
./configure
make
make instal
(备注:使用linux或unix系统的需要进入终端用shell指令安装,Xcode中使用libpcap将其当作第三方函数库使用时,需要手动点击蓝色的工程文件,在右边的BuildPhase中LinkBinaryWithLibraries中手动添加libpcap的函数库,并且c中支持的一些基于win平台的函数和头文件在MACOS中有所差异,如#include
(分为头文件与主c文件两部分)
/main.h 包括网络抓包与流量分析/
#include
#include
#include
#include
#include
#include
#include “protocol.h”
#include
#include
#include
#include
typedef struct _argument
{
pcap_t *handle;
int timeLen;
}argument;
void *thread_clock(void argv)
{
pcap_t handle = ((argument)argv)->handle;
int timeLen = ((argument)argv)->timeLen; // set time
sleep(timeLen);
pcap_breakloop(handle);
return 2;
}
void cb_getPacket(u_char *dumpfile, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
// ip_header seg_ip = (ip_header)(package + ETHER_LEN);
pcap_dump(dumpfile, pkthdr, packet);
static int id = 0;
printf(". ");
if(++id % 30 == 0)
{
printf("\n");
}
}
//timeval结构
typedef struct _shh_timeval{
int tv_sec; /* seconds 1900之后的秒数 /
int tv_usec; / and microseconds */
}shh_timeval;
// pcap_next()方法执行后,pcap_pkthdr类型的指针指向抓包的信息
typedef struct _shh_pkthdr {
shh_timeval ts; /* time stamp 时间 /
bpf_u_int32 caplen; / length of portion present 包的数据长度?? /
bpf_u_int32 len; / length this packet (off wire) 包的实际长度 */
}shh_pkthdr;
typedef struct _net5set
{
u_int sip;
u_short sport;
u_int dip;
u_short dport;
u_char protocol;
}net5set;
typedef struct _net_link_node
{
net5set nln_5set;
int nln_upl_size;
int nln_downl_size;
int nln_upl_pkt;
int nln_downl_pkt;
u_char nln_status;
#define CLOSED 0x00
#define SYN_SENT 0x01 // client sent SYN
#define SYN_RECVD 0x02 // recieve SYN, and send SYN ACK
#define ESTABLISHED 0x03 // client get SYN & ACK, server get ACK
#define FIN_WAIT_1 0x04 // client send FIN
#define CLOSE_WAIT 0x05 // server recv FIN, and send ACK
#define FIN_WAIT_2 0x06 // client recv ACK
#define LAST_ACK 0x07 // server send FIN
#define TIME_WAIT 0x08 // client recv FIN
// CLOSED: client send ACK, server recv ACK
#define UNDEFINED 0xff
struct _net_link_node *next;
}net_link_node, *p_net_link;
typedef struct _net_link_header
{
int count_conn;
int count_upl_pkt;
int count_downl_pkt;
int count_upl;
int count_downl;
p_net_link link;
}net_link_header;
#define IPTOSBUFFERS 12
static char iptos(bpf_u_int32 in)
{
static char output[IPTOSBUFFERS][34+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
char *long2time(long ltime)
{
time_t t;
struct tm *p;
static char s[100];
t = ltime;
p = gmtime(&t);
strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", p);
return s;
}
// 需要三个链表,一个哈希链表,保存处于连接状态的包
// 另两个链表分别保存tcp和udp的流量
net_link_header *FLowLink_TCP;
net_link_header *FLowLink_UDP;
/* ========== hash table ============= */
#define HASH_TABLE_SIZE 0xffff
p_net_link HashTable[HASH_TABLE_SIZE];
void init_flowLink(net_link_header *head)
{
head->count_conn = 0;
head->count_upl_pkt = 0;
head->count_downl_pkt = 0;
head->count_upl = 0;
head->count_downl = 0;
head->link = NULL;
}
void add_to_flowLink(net_link_header *head, const net_link_node *theNode)
{
net_link_node *newNode = (net_link_node *)malloc(sizeof(net_link_node));
memcpy(newNode, theNode, sizeof(net_link_node));
head->count_conn ++;
head->count_upl_pkt += newNode->nln_upl_pkt;
head->count_downl_pkt += newNode->nln_downl_pkt;
head->count_upl += newNode->nln_upl_size;
head->count_downl += newNode->nln_downl_size;
newNode->next = head->link;
head->link = newNode;
}
void clear_flowLink(net_link_header *head)
{
if( head->link == NULL ){ return;}
net_link_node *pTemp1 = NULL;
net_link_node *pTemp2 = NULL;
pTemp1 = head->link;
pTemp2 = pTemp1->next;
while( pTemp2 != NULL )
{
free(pTemp1);
pTemp1 = pTemp2;
pTemp2 = pTemp1->next;
}
free(pTemp1);
head->link = NULL;
}
void parse_flowLink_TCP(FILE *fOutput)
{
fprintf(fOutput, “TCP连接个数:\t%d\n”, FLowLink_TCP->count_conn);
fprintf(fOutput, “TCP数据包个数:\t%d\n”, FLowLink_TCP->count_upl_pkt + FLowLink_TCP->count_upl_pkt);
fprintf(fOutput, “TCP数据总流量:\t%d bytes\n”, FLowLink_TCP->count_upl + FLowLink_TCP->count_downl);
fprintf(fOutput, “TCP数据上传量:\t%d bytes\n”, FLowLink_TCP->count_upl);
fprintf(fOutput, “TCP数据下载量:\t%d bytes\n”, FLowLink_TCP->count_downl);
fprintf(fOutput, “-----------------------\n”);
net_link_node *pTemp = NULL;
pTemp = FLowLink_TCP->link;
while( pTemp != NULL )
{
fprintf(fOutput, "%s\t%u\t", iptos(pTemp->nln_5set.sip), pTemp->nln_5set.sport);
fprintf(fOutput, "==>\t%s\t%u\t", iptos(pTemp->nln_5set.dip), pTemp->nln_5set.dport);
fprintf(fOutput, "上传包数量:%d\t", pTemp->nln_upl_pkt);
fprintf(fOutput, "下载包数量:%d\t", pTemp->nln_downl_pkt);
fprintf(fOutput, "upload:%d bytes\t", pTemp->nln_upl_size);
fprintf(fOutput, "download:%d bytes\t", pTemp->nln_downl_size);
fprintf(fOutput, "\n");
pTemp = pTemp->next;
}
clear_flowLink(FLowLink_TCP);
}
void parse_flowLink_UDP(FILE *fOutput)
{
fprintf(fOutput, “UDP数据包个数:\t%d\n”, FLowLink_UDP->count_upl_pkt + FLowLink_UDP->count_upl_pkt);
fprintf(fOutput, “UDP数据流量:\t%d bytes\n”, FLowLink_UDP->count_upl + FLowLink_UDP->count_downl);
clear_flowLink(FLowLink_UDP);
}
u_short get_ushort_net(u_short virtu)
{
return (u_short)(virtu >> 8 | virtu << 8);
}
u_short get_hash(const net5set *theSet)
{
u_int srcIP = theSet->sip;
u_int desIP = theSet->dip;
u_int port = (u_int)(theSet->sport * theSet->dport);
u_int res = (srcIPdesIP)port;
u_short hash= (u_short)((res & 0x00ff)^(res >> 16));
return hash;
}
void add_to_hashTable(u_short hash, const net_link_node *theNode, u_char flags)
{
net_link_node *HashNode = (net_link_node *)malloc(sizeof(net_link_node));
memcpy(HashNode, theNode, sizeof(net_link_node));
if(HashTable[hash] == NULL)
{
HashTable[hash] = HashNode;
return;
}
net_link_node *pTemp = HashTable[hash];
net_link_node *pBack = NULL;
int isSame_up = 0;
int isSame_down = 0;
while(pTemp != NULL)
{
isSame_up = (pTemp->nln_5set.sip == HashNode->nln_5set.sip)
&& (pTemp->nln_5set.dip == HashNode->nln_5set.dip)
&& (pTemp->nln_5set.sport == HashNode->nln_5set.sport)
&& (pTemp->nln_5set.dport == HashNode->nln_5set.dport);
isSame_down = (pTemp->nln_5set.dip == HashNode->nln_5set.sip)
&& (pTemp->nln_5set.sip == HashNode->nln_5set.dip)
&& (pTemp->nln_5set.dport == HashNode->nln_5set.sport)
&& (pTemp->nln_5set.sport == HashNode->nln_5set.dport);
if( isSame_up )
{
pTemp->nln_upl_size += HashNode->nln_upl_size;
pTemp->nln_upl_pkt ++;
if(pTemp->nln_status == ESTABLISHED && (flags & TH_FIN) )
{
pTemp->nln_status = FIN_WAIT_1;
}
else if (pTemp->nln_status == TIME_WAIT && (flags & TH_ACK))
{
pTemp->nln_status = CLOSED;
if(pBack == NULL)
{
HashTable[hash] = NULL;
}
else
{
pBack->next = pTemp->next;
}
add_to_flowLink(FLowLink_TCP, pTemp);
free(pTemp);
}
else if(pTemp->nln_status == CLOSE_WAIT && (flags & TH_FIN))
{
pTemp->nln_status = LAST_ACK;
}
free(HashNode);
break;
}
else if( isSame_down )
{
pTemp->nln_downl_size += HashNode->nln_upl_size;
pTemp->nln_downl_pkt ++;
if(pTemp->nln_status == ESTABLISHED && (flags & TH_FIN))
{
pTemp->nln_status = CLOSE_WAIT;
}
else if(pTemp->nln_status == LAST_ACK && (flags & TH_ACK))
{
pTemp->nln_status = CLOSED;
if(pBack == NULL)
{
HashTable[hash] = NULL;
}
else
{
pBack->next = pTemp->next;
}
add_to_flowLink(FLowLink_TCP, pTemp);
free(pTemp);
}
else if(pTemp->nln_status == FIN_WAIT_1 && (flags & TH_ACK))
{
pTemp->nln_status = FIN_WAIT_2;
}
else if(pTemp->nln_status == FIN_WAIT_2 && (flags & TH_FIN))
{
pTemp->nln_status = TIME_WAIT;
}
free(HashNode);
break;
}
pBack = pTemp;
pTemp = pTemp->next;
}
if(pTemp == NULL)
{
pBack->next = HashNode;
}
}
void clear_hashTable()
{
int i = 0;
net_link_node *pTemp1 = NULL;
net_link_node *pTemp2 = NULL;
for(i = 0; i < HASH_TABLE_SIZE; i++)
{
if(HashTable[i] == NULL){ continue;}
pTemp1 = HashTable[i];
while(pTemp1 != NULL)
{
pTemp2 = pTemp1->next;
add_to_flowLink(FLowLink_TCP, pTemp1);
free(pTemp1);
pTemp1 = pTemp2;
}
HashTable[i] = NULL;
}
}
/*
在以太网中,规定最小的数据包为64个字节,如果数据包不足64字节,则会由网卡填充。
*/
int main(int argc, char const *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
pcap_t *dev_handle;
bpf_u_int32 net, mask;
char packet_filter[] = “ip”;
struct bpf_program fcode;
dev = pcap_lookupdev(errbuf);
if(dev == NULL){
printf("No Device:%s\n", errbuf);
return 0;
} // */
/*char *wlan_dev = "wlan0";
dev = wlan_dev; // */
printf("开始抓取数据,设备:%s\n", dev);
dev_handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
if(dev_handle == NULL){
printf("pcap_open_live:%s\n", errbuf);
return 0;
}
//args->handle = dev_handle;
pcap_lookupnet(dev, &net, &mask, errbuf);
//compile the filter
if (pcap_compile(dev_handle, &fcode, packet_filter, 1, mask) <0 )
{
printf("\nUnable to compile the packet filter. Check the syntax.\n");
return 0;
}
//set the filter
if (pcap_setfilter(dev_handle, &fcode) < 0)
{
printf("\nError setting the filter.\n");
return 0;
}
// open file to save pcap
pcap_dumper_t *dumpfile;
dumpfile = pcap_dump_open(dev_handle, "traffic.data");
if(dumpfile == NULL){
printf("\nError opening output file\n");
return 0;
}
// build a new thread
pthread_t ptClock;
argument args;
args.handle = dev_handle;
int argv_time = 30;
args.timeLen = (argv_time > 0) ? argv_time : 60;
printf("抓取时长:%d s\n", argv_time);
if(pthread_create(&ptClock, NULL, thread_clock, &args))
{
printf("pthread_create(): Error!\n");
return -1;
}
pcap_loop(dev_handle, -1, cb_getPacket, (u_char*)dumpfile);
// close all handle
pcap_dump_close(dumpfile);
pcap_close(dev_handle);
printf("\nDone!\n");
//以上为抓包
char *file_output = "/Users/ganyu/Desktop/result.data";
FILE *fOutput = fopen(file_output, "w");
fclose(fOutput); // clear file
fOutput = fopen(file_output, "a+");
char *filename = "traffic.data";
fprintf(fOutput, "数据文件:%s\n", filename);
printf("载入文件...\n");
FILE *fp = fopen(filename, "r");
shh_pkthdr *pkthdr = (shh_pkthdr *)malloc(sizeof(shh_pkthdr));
ether_header *segEther = (ether_header*)malloc(sizeof(ether_header));
ip_header *segIP = (ip_header*)malloc(sizeof(ip_header));
tcp_header *segTCP = (tcp_header*)malloc(sizeof(tcp_header));
udp_header *segUDP = (udp_header*)malloc(sizeof(udp_header));
net5set *Cur5Set = (net5set *)malloc(sizeof(net5set));
net_link_node *LinkNode = (net_link_node *)malloc(sizeof(net_link_node));
FLowLink_TCP = (net_link_header *)malloc(sizeof(net_link_header));
init_flowLink(FLowLink_TCP);
FLowLink_UDP = (net_link_header *)malloc(sizeof(net_link_header));
init_flowLink(FLowLink_UDP);
long fileLen = 0;
int pktLen = 0; // pktLen = Ether + IP
int trailerLen = 0;
u_short ipLen_real = 0;
u_short ipLen_total = 0;
u_short tcpLen_real = 0;
u_short dataLen = 0;
// get length of file
fseek(fp, 0, SEEK_END);
fileLen = ftell(fp);
fseek(fp, PCAP_HEADER_LEN, SEEK_SET);
// 移动文件位置指针。
// If successful, the function returns zero.
// Otherwise, it returns non-zero value.
// SEEK_SET:文件开头;SEEK_CUR:当前位置;SEEK_END:文件结尾
fread(pkthdr, PACKET_HEADER_LEN, 1, fp);
fseek(fp, - PACKET_HEADER_LEN, SEEK_CUR);
int tstamp_start = pkthdr->ts.tv_sec;
int tstamp_offset = tstamp_start;
int tstamp_now = tstamp_start;
int cycle = 5;
cycle = (cycle > 0) ? cycle : 10;
fprintf(fOutput, "分析周期:%d s\n", cycle);
// int i = 0;
while( ftell(fp) > 0 && ftell(fp) < fileLen )
{
fread(pkthdr, PACKET_HEADER_LEN, 1, fp);
pktLen = pkthdr->caplen;
tstamp_now = pkthdr->ts.tv_sec;
if(tstamp_now - tstamp_offset >= cycle)
{
fprintf(fOutput, "\n\n>>>>> 时间段:%s", long2time(tstamp_offset));
fprintf(fOutput, " --> %s\n", long2time(tstamp_offset + cycle));
fprintf(fOutput, "----------------------\n");
clear_hashTable();
parse_flowLink_UDP(fOutput);
init_flowLink(FLowLink_UDP);
fprintf(fOutput, "----------------------\n");
parse_flowLink_TCP(fOutput);
init_flowLink(FLowLink_TCP);
tstamp_offset = tstamp_now;
}
//printf("%d\t", pktLen);
//printf("\n%d\t", ++i);
fread(segEther, ETHER_LEN, 1, fp);
if( get_ushort_net(segEther->type) != ETHER_TYPE_IP )
{
//printf("------\t");
fseek(fp, pktLen - ETHER_LEN, SEEK_CUR);
continue;
}
fread(segIP, IP_LEN_MIN, 1, fp);
ipLen_real = (segIP->ver_ihl & 0x0f)*4;
ipLen_total = get_ushort_net(segIP->tlen);
trailerLen = pktLen - ETHER_LEN - ipLen_total;
fseek(fp, ipLen_real - IP_LEN_MIN, SEEK_CUR);
if( segIP->proto != IP_TCP && segIP->proto != IP_UDP )
{
//printf("------\t");
fseek(fp, ipLen_total - ipLen_real + trailerLen, SEEK_CUR);
continue;
}
Cur5Set->sip = segIP->saddr;
Cur5Set->dip = segIP->daddr;
Cur5Set->protocol = segIP->proto;
//printf("src:%s\t", iptos(Cur5Set->sip));
//printf("des:%s\t", iptos(Cur5Set->dip));
if(segIP->proto == IP_TCP)
{
//printf("TCP\t");
fread(segTCP, TCP_LEN_MIN, 1, fp);
tcpLen_real = (((segTCP->th_len)>>4) & 0x0f) * 4;
dataLen = ipLen_total - ipLen_real - tcpLen_real;
Cur5Set->sport = get_ushort_net(segTCP->th_sport);
Cur5Set->dport = get_ushort_net(segTCP->th_dport);
fseek(fp, (tcpLen_real - TCP_LEN_MIN) + dataLen + trailerLen, SEEK_CUR);
}
else if(segIP->proto == IP_UDP)
{
//printf("UDP\t");
fread(segUDP, UDP_LEN, 1, fp);
dataLen = ipLen_total - ipLen_real - UDP_LEN;
Cur5Set->sport = get_ushort_net(segUDP->uh_sport);
Cur5Set->dport = get_ushort_net(segUDP->uh_dport);
fseek(fp, dataLen + trailerLen, SEEK_CUR);
}
LinkNode->nln_5set = *Cur5Set;
LinkNode->nln_upl_size = dataLen;
LinkNode->nln_downl_size= 0;
LinkNode->nln_upl_pkt = 1;
LinkNode->nln_downl_pkt = 0;
LinkNode->nln_status = ESTABLISHED;
LinkNode->next = NULL;
if(segIP->proto == IP_TCP)
{
add_to_hashTable(get_hash(Cur5Set), LinkNode, segTCP->th_flags);
}
else
{
add_to_flowLink(FLowLink_UDP, LinkNode);
}
}
fprintf(fOutput, "\nover\n");
free(pkthdr);
free(segEther);
free(segIP);
free(segTCP);
free(segUDP);
free(Cur5Set);
free(LinkNode);
free(FLowLink_TCP);
free(FLowLink_UDP);
fclose(fOutput);
printf("Done!\n");
return 0;
}
/** protocol.h
structs of ethernet, ip, tcp, udp
*/
#define PCAP_HEADER_LEN 24
#define PACKET_HEADER_LEN 16
/* ============= Ethernet ============ */
#define ETHER_LEN 14
#define ETHER_ADDR_LEN 6
#define ETHER_TYPE_LEN 2
#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN)
#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN)
#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN)
typedef struct _ether_header{
u_char host_dest[ETHER_ADDR_LEN];
u_char host_src[ETHER_ADDR_LEN];
u_short type;
#define ETHER_TYPE_MIN 0x0600
#define ETHER_TYPE_IP 0x0800
#define ETHER_TYPE_ARP 0x0806
#define ETHER_TYPE_8021Q 0x8100
#define ETHER_TYPE_BRCM 0x886c
#define ETHER_TYPE_802_1X 0x888e
#define ETHER_TYPE_802_1X_PREAUTH 0x88c7
}ether_header;
/============== IP ================/
#define IP_LEN_MIN 20
/* IPv4 header */
typedef struct _ip_header{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short ident; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
#define IP_ICMP 1
#define IP_IGMP 2
#define IP_TCP 6
#define IP_UDP 17
#define IP_IGRP 88
#define IP_OSPF 89
u_short crc; // Header checksum
u_int saddr; // Source address
u_int daddr; // Destination address
}ip_header;
/=============== TCP ================/
#define TCP_LEN_MIN 20
typedef struct _tcp_header
{
u_short th_sport; // source port
u_short th_dport; // destination port
u_int th_seq; // sequence number field
u_int th_ack; // acknowledgement number field
u_char th_len:4; // header length
u_char th_x2:4; // unused
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
u_short th_win; /* window /
u_short th_sum; / checksum /
u_short th_urp; / urgent pointer /
}tcp_header; ///
/================ UDP ==================/
#define UDP_LEN 8
typedef struct _udp_header{
u_short uh_sport; // Source port
u_short uh_dport; // Destination port
u_short uh_len; // Datagram length
u_short uh_sum; // Checksum
}udp_header;
程序会先抓包,存在traffic.data文件中,也可以自定义,建议不要动,容易出错,然后对包的内容进行分析,输出结果到result.data中,这个建议自定义文件目录,方便查看。抓取时长和分析周期可以自定义。