Tommorow
Sniffer程序是一种利用以太网的特性把网络适配卡(NIC,一般为以太网卡)置为混杂(promiscuous)模式状态的工具,一旦网卡设置为这种模式,它就能接收传输在网络上的每一个信息包。
普通的情况下,网卡只接收和自己的地址有关的信息包,即传输到本地主机的信息包。要使Sniffer能接收并处理这种方式的信息,系统需要支持 BPF,Linux下需要支持SOCKET-PACKET。但一般情况下,网络硬件和TCP/IP堆栈不支持接收或者发送与本地计算机无关的数据包,所以,为了绕过标准的TCP/IP堆栈,网卡就必须设置为混杂模式。一般情况下,要激活这种方式,内核必须支持这种伪设备BPFilter,而且需要root权限来运行这种程序,所以Sniffer需要root身份安装,如果只是以本地用户的身份进入了系统,那么不可能嗅探到root的密码,因为不能运行Sniffer。
基于Sniffer这样的模式,可以分析各种信息包并描述出网络的结构和使用的机器,由于它接收任何一个在同一网段上传输的数据包,所以也就存在着捕获密码、各种信息、秘密文档等一些没有加密的信息的可能性。
系统设计主要分为以下几个功能模块:
获取当前主机中的网卡
设置过滤规则,并依据过滤规则捕获数据包
捕获数据包在主面板中的实时显示(类似wireshark抓包动态显示)
数据包解析、协议树显示以及数据包内容十六进制显示
捕获数据包统计
捕获数据包的保存以及读取
获取当前运行程序主机中的网卡。
WinPcap中提供了pcap_findalldevs_ex()函数用于获得已连接的网络适配器列表,该函数返回的是一个pcap_if结构的链表,该结构数据域中的name和description表示一个适配器名称和一个适配器的可理解描述。
void MainWindow::initCaps(){
ui->comboBox->addItem("请选择一个网卡接口(必选)");
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&allDevs,errbuf)>0){
qDebug("pcap_findallDevs_ex failed!");
}
QStringList texts;
for(dev=allDevs;dev->next!=NULL;dev=dev->next){
texts.append(dev->description);
}
dev=NULL;
ui->comboBox->addItems(texts);
}
设置过滤规则,并依据过滤规则捕获数据包。
if (dev->addresses != NULL)
/* Retrieve the mask of the first address of the interface */
netmask=((struct sockaddr_in *)(dev->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* If the interface is without an address we suppose to be in a C class network */
netmask=0xffffff;
std::string str = ui->lineEdit->text().toStdString();
const char* c_s = str.c_str();
if (pcap_compile(handle, &fcode, c_s, 1, netmask) <0 )
{
qDebug("语法错误,无法编译过滤器");
return;
}
if (pcap_setfilter(handle,&fcode)<0)
{
qDebug("语法错误,无法设置滤器");
return;
}
嗅探器相关结构体的定义以及主面板数据包的动态显示(类似wireshark抓包动态显示):
通过qt独有的信号与槽机制,抓包线程每读取到一个数据包即将其解析并将其显示到tableView中,当双击某行时,将该数据包解析并显示在treeView和textedit中:
void MainWindow::setData(datapkt *data){
int i=tableModel->rowCount();
QString src_mac,dest_mac,len,src_ip,dest_ip,time;
char* buf=(char*)malloc(80*sizeof(char));
sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",data->ethh->src[0],data->ethh->src[1],data->ethh->src[2],data->ethh->src[3],data->ethh->src[4],data->ethh->src[5]);
src_mac=QString(QLatin1String(buf));
sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",data->ethh->dest[0],data->ethh->dest[1],data->ethh->dest[2],data->ethh->dest[3],data->ethh->dest[4],data->ethh->dest[5]);
dest_mac=QString(QLatin1String(buf));
len=QString::number(data->len);
switch(data->ethh->type)
{
case 0x0806:
sprintf(buf,"%d.%d.%d.%d",data->arph->ar_srcip[0],data->arph->ar_srcip[1],data->arph->ar_srcip[2],data->arph->ar_srcip[3]);
src_ip=QString(QLatin1String(buf));
sprintf(buf,"%d.%d.%d.%d",data->arph->ar_destip[0],data->arph->ar_destip[1],data->arph->ar_destip[2],data->arph->ar_destip[3]);
dest_ip=QString(QLatin1String(buf));
break;
case 0x0800:
ipvalue_to_ipaddr(ntohl(data->iph->saddr),buf);
src_ip=QString(QLatin1String(buf));
ipvalue_to_ipaddr(ntohl(data->iph->daddr),buf);
dest_ip=QString(QLatin1String(buf));
break;
default:
break;
}
current_date_time =QDateTime::currentDateTime();
current_date=current_date_time.toString("yyyy.MM.dd hh:mm:ss");
tableModel->setItem(i,0,new QStandardItem(src_mac));
tableModel->setItem(i,1,new QStandardItem(dest_mac));
tableModel->setItem(i,2,new QStandardItem(len));
tableModel->setItem(i,3,new QStandardItem(data->pktType));
tableModel->setItem(i,4,new QStandardItem(src_ip));
tableModel->setItem(i,5,new QStandardItem(dest_ip));
tableModel->setItem(i,6,new QStandardItem(current_date));
}
void MainWindow::setNum(pktcount *npacket){
QString num_arp=QString::number(npacket->n_arp);
QString num_count=QString::number(npacket->n_sum);
QString num_icmp=QString::number(npacket->n_icmp);
QString num_ip=QString::number(npacket->n_ip);
QString num_tcp=QString::number(npacket->n_tcp);
QString num_udp=QString::number(npacket->n_udp);
QString num_http=QString::number(npacket->n_http);
QString num_others=QString::number(npacket->n_other);
ui->TCP->setText(num_tcp);
ui->UDP->setText(num_udp);
ui->ICMP->setText(num_icmp);
ui->HTTP->setText(num_http);
ui->IPv4->setText(num_ip);
ui->OTHERS->setText(num_others);
ui->COUNT->setText(num_count);
ui->ARP->setText(num_arp);
}
通过print_packet_hex函数将数据包以十六进制存入char数组中:
在实现过程中通过sprintf和strcat函数解决了输出的数值转换问题!
void print_packet_hex(char* pkt,int size_pkt,char *buf)
{
int i=0,j = 0,rowcount;
char ch;
char tempbuf[8];
memset(tempbuf,0,8);
for(i= 0;i<size_pkt;i+=16)
{
sprintf(tempbuf,"%04x: ",i);
strcat(buf,tempbuf);
rowcount= (size_pkt-i) > 16 ? 16 : (size_pkt-i);
for(j = 0; j < rowcount; j++){
sprintf(tempbuf,"%02x ",pkt[i+j]);
strcat(buf,tempbuf);
}
//不足16,用空格补足
for(j=rowcount;j<16;j++){
strcpy(tempbuf," ");
strcat(buf,tempbuf);
}
for(j = 0; j < rowcount; j++)
{
ch = pkt[i+j];
ch = isprint(ch) ? ch : '.';
sprintf(tempbuf,"%c ",ch);
strcat(buf,tempbuf);
}
if(rowcount<16)
return;
}
}
双击tableview将数据包解析的结果显示在treeview和textedit中:
void MainWindow::on_tableView_doubleClicked(const QModelIndex &index)
{
int row=index.row();
QString src_mac,dest_mac;
char* buf=(char*)malloc(108*sizeof(char));
sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",alldatapkt[row]->ethh->src[0],alldatapkt[row]->ethh->src[1],alldatapkt[row]->ethh->src[2],alldatapkt[row]->ethh->src[3],alldatapkt[row]->ethh->src[4],alldatapkt[row]->ethh->src[5]);
src_mac=QString(QLatin1String(buf));
sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",alldatapkt[row]->ethh->dest[0],alldatapkt[row]->ethh->dest[1],alldatapkt[row]->ethh->dest[2],alldatapkt[row]->ethh->dest[3],alldatapkt[row]->ethh->dest[4],alldatapkt[row]->ethh->dest[5]);
dest_mac=QString(QLatin1String(buf));
ui->data->setText("");
int i=0,j = 0,rowcount;char ch;
char tempbuf[8];strcpy(tempbuf,"");strcpy(buf,"");
int size_pkt=alldatapkt[row]->len;u_char* pkt=datavec[row];
for(i= 0;i<size_pkt;i+=16)
{
sprintf(tempbuf,"%04x:",i);
strcat(buf,tempbuf);
rowcount= (size_pkt-i) > 16 ? 16 : (size_pkt-i);
for(j = 0; j < rowcount; j++){
sprintf(tempbuf,"%02x ",pkt[i+j]);strcat(buf,tempbuf);
}
for(j=rowcount;j<16;j++){
strcpy(tempbuf," ");strcat(buf,tempbuf);
}
for(j = 0; j < rowcount; j++){
ch = pkt[i+j];
ch = isprint(ch) ? ch : '.';
sprintf(tempbuf,"%c ",ch);
strcat(buf,tempbuf);
}
strcat(buf,"\n");
ui->data->append(buf);
strcpy(buf,"");
if(rowcount<16)
break;
}
QString h="接受到的第"+QString::number(row+1)+"个数据包";
QStandardItem *head=new QStandardItem(h);
QStandardItem *ethdata=new QStandardItem("链路层数据");
QStandardItem *arpdata=new QStandardItem("ARP协议头");
QStandardItem *ipdata=new QStandardItem("IP协议头");
QStandardItem *tcpdata=new QStandardItem("TCP协议头");
QStandardItem *udpdata=new QStandardItem("UDP协议头");
QStandardItem *icmpdata=new QStandardItem("ICMP协议头");
treeModel->setItem(0,head);
head->setChild(0,ethdata);
ethdata->setChild(0,new QStandardItem("源MAC:"+src_mac));
ethdata->setChild(1,new QStandardItem("目的MAC:"+dest_mac));
sprintf(tempbuf,"0x%04x",alldatapkt[row]->ethh->type);
ethdata->setChild(2,new QStandardItem("类型:"+QString(QLatin1String(tempbuf))));
QModelIndex current_index;
switch (alldatapkt[row]->ethh->type) {
case 0x0806:
head->setChild(1,arpdata);
arpdata->setChild(0,new QStandardItem("硬件类型:"+QString::number(alldatapkt[row]->arph->ar_hrd)));
arpdata->setChild(1,new QStandardItem("协议类型:"+QString::number(alldatapkt[row]->arph->ar_pro)));
arpdata->setChild(2,new QStandardItem("硬件地址长度:"+QString::number(alldatapkt[row]->arph->ar_hln)));
arpdata->setChild(3,new QStandardItem("协议地址长度:"+QString::number(alldatapkt[row]->arph->ar_pln)));
sprintf(buf,"%0d.%d.%d.%d",alldatapkt[row]->arph->ar_srcip[0],alldatapkt[row]->arph->ar_srcip[1],alldatapkt[row]->arph->ar_srcip[2],alldatapkt[row]->arph->ar_srcip[3]);
arpdata->setChild(4,new QStandardItem("发送方IP:"+QString(QLatin1String(buf))));
sprintf(buf,"%0d.%d.%d.%d",alldatapkt[row]->arph->ar_destip[0],alldatapkt[row]->arph->ar_destip[1],alldatapkt[row]->arph->ar_destip[2],alldatapkt[row]->arph->ar_destip[3]);
arpdata->setChild(5,new QStandardItem("接受方IP:"+QString(QLatin1String(buf))));
break;
case 0x0800:
head->setChild(1,ipdata);
ipdata->setChild(0,new QStandardItem("版本号:"+QString::number(alldatapkt[row]->iph->version)));
ipdata->setChild(1,new QStandardItem("头部长度:"+QString::number(alldatapkt[row]->iph->ihl)));
ipdata->setChild(2,new QStandardItem("服务类型TOS:"+QString::number(alldatapkt[row]->iph->tos)));
ipdata->setChild(3,new QStandardItem("总长度:"+QString::number(alldatapkt[row]->iph->tlen)));
sprintf(tempbuf,"0x%04x",alldatapkt[row]->iph->id);
ipdata->setChild(4,new QStandardItem("标识:"+QString(QLatin1String(tempbuf))));
ipdata->setChild(5,new QStandardItem("位偏移:"+QString::number(alldatapkt[row]->iph->frag_off)));
ipdata->setChild(6,new QStandardItem("生存时间TTL:"+QString::number(alldatapkt[row]->iph->ttl)));
ipdata->setChild(7,new QStandardItem("协议:"+QString::number(alldatapkt[row]->iph->proto)));
ipdata->setChild(8,new QStandardItem("头部校验和:"+QString::number(alldatapkt[row]->iph->check)));
current_index=tableModel->index(row,4);
ipdata->setChild(9,new QStandardItem("源IP:"+tableModel->data(current_index).toString()));
current_index=tableModel->index(row,5);
ipdata->setChild(10,new QStandardItem("目的IP:"+tableModel->data(current_index).toString()));
switch (alldatapkt[row]->iph->proto) {
case PROTO_TCP:
head->setChild(2,tcpdata);
tcpdata->setChild(0,new QStandardItem("源端口:"+QString::number(alldatapkt[row]->tcph->sport)));
tcpdata->setChild(1,new QStandardItem("目的端口:"+QString::number(alldatapkt[row]->tcph->dport)));
tcpdata->setChild(2,new QStandardItem("序列号:"+QString::number(alldatapkt[row]->tcph->seq)));
tcpdata->setChild(3,new QStandardItem("确认序列号:"+QString::number(alldatapkt[row]->tcph->ack_seq)));
tcpdata->setChild(4,new QStandardItem("窗口大小:"+QString::number(alldatapkt[row]->tcph->window)));
tcpdata->setChild(5,new QStandardItem("SYN:"+QString::number(alldatapkt[row]->tcph->syn)));
tcpdata->setChild(6,new QStandardItem("ACK:"+QString::number(alldatapkt[row]->tcph->ack)));
tcpdata->setChild(7,new QStandardItem("FIN:"+QString::number(alldatapkt[row]->tcph->fin)));
tcpdata->setChild(8,new QStandardItem("校验和:"+QString::number(alldatapkt[row]->tcph->check)));
tcpdata->setChild(9,new QStandardItem("紧急指针:"+QString::number(alldatapkt[row]->tcph->urg_ptr)));
break;
case PROTO_UDP:
head->setChild(2,udpdata);
udpdata->setChild(0,new QStandardItem("源端口:"+QString::number(alldatapkt[row]->udph->sport)));
udpdata->setChild(1,new QStandardItem("目的端口:"+QString::number(alldatapkt[row]->udph->dport)));
udpdata->setChild(2,new QStandardItem("数据报长度:"+QString::number(alldatapkt[row]->udph->len)));
udpdata->setChild(3,new QStandardItem("校验和:"+QString::number(alldatapkt[row]->udph->check)));
break;
case PROTO_ICMP:
head->setChild(2,icmpdata);
icmpdata->setChild(0,new QStandardItem("类型:"+QString::number(alldatapkt[row]->icmph->type)));
icmpdata->setChild(1,new QStandardItem("代码:"+QString::number(alldatapkt[row]->icmph->code)));
icmpdata->setChild(2,new QStandardItem("序列号:"+QString::number(alldatapkt[row]->icmph->seq)));
icmpdata->setChild(3,new QStandardItem("校验和:"+QString::number(alldatapkt[row]->icmph->chksum)));
break;
default:
break;
}
break;
default:
break;
}
}
接下来介绍数据包协议分析的实现:
在上面的代码中可以看到,在抓包线程的运行函数中很关键的一步是调用analyze类中的analyze_frame函数进行协议分析。
各协议头数据结构定义:
//Mac帧头 占14个字节
typedef struct _ethhdr
{
u_char dest[6]; //6个字节 目标地址
u_char src[6]; //6个字节 源地址
u_short type; //2个字节 类型
}ethhdr;
//ARP头
typedef struct _arphdr
{
u_short ar_hrd; //硬件类型
u_short ar_pro; //协议类型
u_char ar_hln; //硬件地址长度
u_char ar_pln; //协议地址长度
u_short ar_op; //操作码,1为请求 2为回复
u_char ar_srcmac[6]; //发送方MAC
u_char ar_srcip[4]; //发送方IP
u_char ar_destmac[6]; //接收方MAC
u_char ar_destip[4]; //接收方IP
}arphdr;
//定义IP头
typedef struct _iphdr
{
#if defined(LITTLE_ENDIAN)
u_char ihl:4;
u_char version:4;
#elif defined(BIG_ENDIAN)
u_char version:4;
u_char ihl:4;
#endif
u_char tos; //TOS 服务类型
u_short tlen; //包总长 u_short占两个字节
u_short id; //标识
u_short frag_off; //片位移
u_char ttl; //生存时间
u_char proto; //协议
u_short check; //校验和
u_int saddr; //源地址
u_int daddr; //目的地址
u_int op_pad; //选项等
}iphdr;
//定义TCP头
typedef struct _tcphdr
{
u_short sport; //源端口地址 16位
u_short dport; //目的端口地址 16位
u_int seq; //序列号 32位
u_int ack_seq; //确认序列号
#if defined(LITTLE_ENDIAN)
u_short res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(BIG_ENDIAN)
u_short doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#endif
u_short window; //窗口大小 16位
u_short check; //校验和 16位
u_short urg_ptr; //紧急指针 16位
u_int opt; //选项
}tcphdr;
//定义UDP头
typedef struct _udphdr
{
u_short sport; //源端口 16位
u_short dport; //目的端口 16位
u_short len; //数据报长度 16位
u_short check; //校验和 16位
}udphdr;
//定义ICMP
typedef struct _icmphdr
{
u_char type; //8位 类型
u_char code; //8位 代码
u_char seq; //序列号 8位
u_char chksum; //8位校验和
}icmphdr;
//对各种包进行计数
typedef struct _pktcount
{
int n_ip;
int n_arp;
int n_tcp;
int n_udp;
int n_icmp;
int n_http;
int n_other;
int n_sum;
_pktcount(){
n_ip=0;
n_arp=0;
n_tcp=0;
n_udp=0;
n_icmp=0;
n_http=0;
n_other=0;
n_sum=0;
}
}pktcount;
//要保存的数据结构
typedef struct _datapkt
{
char pktType[8]; //包类型
int time[6]; //时间
int len; //长度
ethhdr* ethh; //链路层包头
arphdr* arph; //ARP包头
iphdr* iph; //IP包头
icmphdr* icmph; //ICMP包头
udphdr* udph; //UDP包头
tcphdr* tcph; //TCP包头
bool isHttp;
void *apph; //应用层包头
}datapkt;
#endif
解析数据包函数:
#include "protocol.h"
#include <QDebug>
#include "mainwindow.h"
#include <winsock2.h>
#include <analyze.h>
///*pkt为网络中捕获的包,data为要存为本机上的数据*
///*分析链路层*/
int analyze_frame(const u_char * pkt,datapkt * data,pktcount* npacket)
{
int i;
ethhdr *ethh = (ethhdr*)pkt;
data->ethh = (ethhdr*)malloc(sizeof(ethhdr));
if(NULL == data->ethh)
return -1;
for(i=0;i<6;i++)
{
data->ethh->dest[i] = ethh->dest[i];
data->ethh->src[i] = ethh->src[i];
}
npacket->n_sum++;
/*由于网络字节顺序原因,需要对齐*/
data->ethh->type = ntohs(ethh->type);
//处理ARP还是IP包?
switch(data->ethh->type)
{
case 0x0806:
return analyze_arp((u_char*)pkt+14,data,npacket); //mac 头大小为14个字节
break;
case 0x0800:
return analyze_ip((u_char*)pkt+14,data,npacket);
break;
default:
npacket->n_other++;
return -1;
break;
}
return 1;
}
///*分析网络层:ARP*/
int analyze_arp(const u_char* pkt,datapkt *data,pktcount* npacket)
{
int i;
arphdr *arph = (arphdr*)pkt;
data->arph = (arphdr*)malloc(sizeof(arphdr));
if(NULL == data->arph)
return -1;
//复制IP及MAC
for(i=0;i<6;i++)
{
if(i<4)
{
data->arph->ar_destip[i] = arph->ar_destip[i];
data->arph->ar_srcip[i] = arph->ar_srcip[i];
}
data->arph->ar_destmac[i] = arph->ar_destmac[i];
data->arph->ar_srcmac[i]= arph->ar_srcmac[i];
}
npacket->n_arp++;
data->arph->ar_hln = arph->ar_hln;
data->arph->ar_hrd = ntohs(arph->ar_hrd);
data->arph->ar_op = ntohs(arph->ar_op);
data->arph->ar_pln = arph->ar_pln;
data->arph->ar_pro = ntohs(arph->ar_pro);
// qDebug(""+data->arph->ar_hln);
strcpy(data->pktType,"ARP");
return 1;
}
///*分析网络层:IP*/
int analyze_ip(const u_char* pkt,datapkt *data,pktcount *npacket)
{
int i;
iphdr *iph = (iphdr*)pkt;
data->iph = (iphdr*)malloc(sizeof(iphdr));
if(NULL == data->iph)
return -1;
data->iph->check = iph->check;
npacket->n_ip++;
/*for(i = 0;i<4;i++)
{
data->iph->daddr[i] = iph->daddr[i];
data->iph->saddr[i] = iph->saddr[i];
}*/
data->iph->saddr = iph->saddr;
data->iph->daddr = iph->daddr;
data->iph->frag_off = iph->frag_off;
data->iph->id = iph->id;
data->iph->proto = iph->proto;
data->iph->tlen = ntohs(iph->tlen);
data->iph->tos = iph->tos;
data->iph->ttl = iph->ttl;
data->iph->ihl = iph->ihl;
data->iph->version = iph->version;
//data->iph->ver_ihl= iph->ver_ihl;
data->iph->op_pad = iph->op_pad;
int iplen = iph->ihl*4; //ip头长度
switch(iph->proto)
{
case PROTO_ICMP:
return analyze_icmp((u_char*)iph+iplen,data,npacket);
break;
case PROTO_TCP:
return analyze_tcp((u_char*)iph+iplen,data,npacket);
break;
case PROTO_UDP:
return analyze_udp((u_char*)iph+iplen,data,npacket);
break;
default :
return-1;
break;
}
return 1;
}
///*分析传输层:ICMP*/
int analyze_icmp(const u_char* pkt,datapkt *data,pktcount *npacket)
{
icmphdr* icmph = (icmphdr*)pkt;
data->icmph = (icmphdr*)malloc(sizeof(icmphdr));
if(NULL == data->icmph)
return -1;
data->icmph->chksum = icmph->chksum;
data->icmph->code = icmph->code;
data->icmph->seq =icmph->seq;
data->icmph->type = icmph->type;
strcpy(data->pktType,"ICMP");
npacket->n_icmp++;
return 1;
}
///*分析传输层:TCP*/
int analyze_tcp(const u_char* pkt,datapkt *data,pktcount *npacket)
{
tcphdr *tcph = (tcphdr*)pkt;
data->tcph = (tcphdr*)malloc(sizeof(tcphdr));
if(NULL == data->tcph)
return -1;
data->tcph->ack_seq = tcph->ack_seq;
data->tcph->check = tcph->check;
data->tcph->doff = tcph->doff;
data->tcph->res1 = tcph->res1;
data->tcph->cwr = tcph->cwr;
data->tcph->ece = tcph->ece;
data->tcph->urg = tcph->urg;
data->tcph->ack = tcph->ack;
data->tcph->psh = tcph->psh;
data->tcph->rst = tcph->rst;
data->tcph->syn = tcph->syn;
data->tcph->fin = tcph->fin;
//data->tcph->doff_flag = tcph->doff_flag;
data->tcph->dport = ntohs(tcph->dport);
data->tcph->seq = tcph->seq;
data->tcph->sport = ntohs(tcph->sport);
data->tcph->urg_ptr = tcph->urg_ptr;
data->tcph->window= tcph->window;
data->tcph->opt = tcph->opt;
if(ntohs(tcph->dport) == 80 || ntohs(tcph->sport)==80)
{
npacket->n_http++;
strcpy(data->pktType,"HTTP");
}
else{
npacket->n_tcp++;
strcpy(data->pktType,"TCP");
}
return 1;
}
/*分析传输层:UDP*/
int analyze_udp(const u_char* pkt,datapkt *data,pktcount *npacket)
{
udphdr* udph = (udphdr*)pkt;
data->udph = (udphdr*)malloc(sizeof(udphdr));
if(NULL == data->udph )
return -1;
data->udph->check = udph->check;
data->udph->dport = ntohs(udph->dport);
data->udph->len = ntohs(udph->len);
data->udph->sport = ntohs(udph->sport);
strcpy(data->pktType,"UDP");
npacket->n_udp++;
return 1;
}
运行结果示例:
IP数据包
UDP数据包
TCP数据包
ARP数据包
ICMP数据数据包