用pcap_loop和回调函数的方法抓包问题

baidu926 2010-12-21 12:28:44
抓包的程序有了,我想问抓到的数据包我要怎么读出数据包里的内容呢, 数据包不考虑什么加密的问题。。。
网上看到说要写解码函数,不知道怎么动手呢,对协议不是很熟悉。。。
谁能给了范例看下,或者是讲解一下。。。
#include "stdafx.h"

#include "pcap.h"
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

typedef struct ip_address
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}ip_address;
//IPv4 首部
typedef struct ip_header
{
u_char ver_ihl; //版本(4 bits) + 首部长度(4 bits)
u_char tos; //服务类型(Type of service)
u_short tlen; //总长(Total length)
u_short identification; //标识(Identification)
u_short flags_fo; //标志位(Flags)(3 bits) + 段偏移量(Fragment offset)(13 bits)
u_char ttl; //存活时间(Time to live)
u_char proto; //协议(Protocol)
u_short crc; //首部校验和(Header checkSum)
ip_address saddr; //源地址(Source address)
ip_address daddr; //目的地址(Destination address)
u_int op_pad; //选项与填充(Option + Padding)
}ip_header;
//UDP 首部
typedef struct udp_header
{
u_short sport; //源端口(Source port)
u_short dport; //目的端口(Destination port)
u_short len; //UDP数据包长度(Datagram length)
u_short crc; //校验和(Checksum)
}udp_header;
//函数原型
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i = 0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip and udp";
struct bpf_program fcode;
//获得设备列表
if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
printf("Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
//打印列表
for(d = alldevs; d != NULL; d = d->next)
{
printf("%d. %s", ++i, d->name);
if(d->description)
printf(" (%s)\n", d->description);
}
printf("Enter the interface number (1-%d):", i);
scanf("%d", &inum);
if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
//释放设备列表
pcap_freealldevs(alldevs);
exit(1);
}
//跳转到已选设备
for(d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
//打开适配器
if((adhandle = pcap_open(d->name, 65536, 0, 1000, NULL, errbuf)) == NULL)
{
printf("\nUnable to open the adapter. %s is not supported by WinPcap\n");
//释放设备列表
pcap_freealldevs(alldevs);
exit(1);
}
//检查数据链路层,为了简单,我们只考虑以太网
if(pcap_datalink(adhandle) != DLT_EN10MB)
{
printf("\nThis program works only on Ethernet networks.\n");
//释放设备列表
pcap_freealldevs(alldevs);
exit(1);
}
if(d->addresses != NULL)
//获得接口第一个地址的掩码
netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
//如果接口没有地址,那么我们假设一个C类的掩码
netmask = 0xffffff;
//编译过滤器
if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
{
printf("\nUnable to compile the packet filter. Check the syntax.\n");
//释放设备列表
pcap_freealldevs(alldevs);
exit(1);
}
//设置过滤器
if(pcap_setfilter(adhandle, &fcode) < 0)
{
printf("\nError setting the filter.\n");
//释放设备列表
pcap_freealldevs(alldevs);
exit(1);
}
printf("\nlistening on %s...\n", d->description);
//释放设备列表
pcap_freealldevs(alldevs);
//开始捕捉
//函数名称:int pcap_loop(pcap_t * p,int cnt, pcap_handler callback, uchar * user);
//函数功能:捕获数据包,不会响应pcap_open_live()函数设置的超时时间
// 参数说明:p 是由pcap_open_live()返回的所打的网卡的指针;cnt用于设置所捕获数据包的个数;pcap_handler 是与void packet_handler()使用的一个参数,即回调函数的名称;user值一般为NULL
pcap_loop(adhandle,10000, packet_handler, NULL);////抓包函数
return 0;
}
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)///回调函数
{
struct tm *ltime;
ip_header *ih;
udp_header *uh;
u_int ip_len;
u_short sport, dport;
time_t local_tv_sec;
local_tv_sec = header->ts.tv_sec;

//打印数据包的时间戳和长度
printf("%s len: %d", ctime(&local_tv_sec), header->len);
//获取IP数据包头部的位置
ih = (ip_header *)(pkt_data + 14);
//获取UDP首部的位置
ip_len = (ih->ver_ihl & 0xf) * 4;

uh = (udp_header *)((u_char*)ih + ip_len);
sport = ntohs(uh->sport);
dport = ntohs(uh->dport);
printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
sport,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4,
dport);
}
...全文
688 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
nuomitutu 2010-12-21
  • 打赏
  • 举报
回复
起一个线程openlive后读取数据包:
// 从网卡或者文件中不停读取数据包信息
while ((re = pcap_next_ex(pHandle, &header, (const u_int8_t**)&pkt_data)) >= 0)
,然后将pkt_data的数据memcpy到你的包格式里, 就可以获取各个字段了

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧