您的位置:首页 > 其它

深度剖析WinPcap之(九)——数据包的发送过程(1)

2010-06-23 10:38 465 查看
本文转自http://eslxf.blog.51cto.com/918801/211982



NPF允许把原始数据包发送到网络上,而且针对不同的应用提供了下列四种发送方式:
n 应用软件每次发送一个数据包一次;
n 应用软件每次发送一个数据包大于一次,次数预先设定;
n 应用软件每次发送一个数据包队列,并根据时间戳发送各数据包;
n 应用软件每次发送一个数据包队列,不根据时间戳,而是尽所能得快速发送各数据包;
数据包被发送到网络时,NPF并不对数据包作任何协议封装,因此应用程序必须构建每个数据包的不同协议头。一般情况下应用程序不需要生成FCS,它通常由网络适配器硬件计算,并在发送到网络前自动添加到每个数据包的尾部。



图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 WIN32

#define H***E_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所接收的数据包
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: