图9-1
函数调用关系图
1.1 wpcap.dll导出的相应函数接口
库
wpcap.dll
为了完成数据包发送的任务,提供了下列函数:
int pcap_sendpacket(pcap_t *p,u_char * buf,int size);
函数发送单个原始数据包一次
pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
函数分配一个发送队列
void pcap_sendqueue_destroy(pcap_send_queue *queue);
函数销毁一个发送队列,释放与队列相关的所有内存资源
int pcap_sendqueue_queue(pcap_send_queue *queue,const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
函数把一个数据包添加到
queue
参数所指发送队列的尾部
u_int pcap_sendqueue_transmit(pcap_t *p,pcap_send_queue *queue,int sync)
;
1.2 发送单个数据包的示例
我们采用实际代码演示如何通过
pcap_sendpacket
函数发送单个数据包。示例代码如下:
[send工程]
#define
HAVE_REMOTE
#include
<stdio.h>
#include
"pcap.h"
#include
"Win32-Extensions.h"
void
genPacket(unsigned char *buf,int len);
int
main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
int ret=-1;
/*
获取本机网络设备列表
*/
if
(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
&alldevs, errbuf) == -1)
{
fprintf(stderr,
"Error in pcap_findalldevs: %s\n"
, errbuf);
exit(1);
}
/*
打印网络设备列表
*/
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if(i==0)
{
printf("\nNo interfaces found! Make sure
WinPcap is installed.\n"
);
return -1;
}
/*
选择网络设备接口
*/
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);
return -1;
}
/*
跳转到选中的适配器
*/
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
/*
打开设备
*/
if
( (adhandle= pcap_open(d->name, 65536,
PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,errbuf) )
== NULL)
{
fprintf(stderr,"\nUnable to open the adapter.
%s is not supported by WinPcap\n"
, d->name);
/*
释放设备列表
*/
pcap_freealldevs(alldevs);
return -1;
}
/*
在选中的设备接口上监听数据
*/
printf("\nlistening on %s...\n", d->description);
/*
开始数据包发送
*/
int MaxPacketLen=100;
unsigned char *pBuf= (unsigned char *)malloc(MaxPacketLen);
memset(pBuf,0x0,MaxPacketLen);
//
获得生成的数据包,长度为
MaxPacketLen
genPacket(pBuf,MaxPacketLen);
if ( (ret=pcap_sendpacket(adhandle,pBuf,MaxPacketLen))
==-1)
{
printf("
发送失败
\n"
);
pcap_close(adhandle);
pcap_freealldevs(alldevs);
return -1;
}
/*
释放资源
*/
free(pBuf);
pcap_close(adhandle);
pcap_freealldevs(alldevs);
return 0;
其中函数genPacket负责生成数据包,参数buf用来保存所生成数据包的内容,len为要求深成数据包的长度。该函数所生成的数据包没有任何实际意义,仅仅为了演示。函数源代码如下:
void
genPacket(unsigned char *buf,int len)
{
int i=0;
//
设置目标
MAC
地址为
:01:01:01:01:01
for (i=0;i<6;i++)
{
buf[i]=0x01;
}
//
设置源
MAC
地址为
:02:02:02:02:02
for (i=6;i<12;i++)
{
buf[i]=0x02;
}
//
设置协议标识为
xc0xd
,无任何实际意义
buf[12]=0xc;
buf[13]=0xd;
//
填充数据包的内容
for(i=14;i<len;i++)
{
buf[i]=i-14;
}
用
Wireshark
接收示例程序所发送的数据包如图
9-2
所示。
图9-2 Wireshark所接收的数据包