我已使用
连接到现有的Tap设备fd = open(...)
现在我想逐包读取它。 如果我使用
read(fd,buffer,sizeof(buffer));
我不会读到1个数据包。
我怎样才能准确读取1个数据包? 是否有某种标题表示数据包长度,或者在最坏的情况下,我将不得不解析数据包并自己计算长度?
答案 0 :(得分:3)
我错误地认为read()
从点击设备读取字节的方式。
事实证明,当我使用read()
时,它正好读取1帧,(如果n小于帧大小,则为n个字节)
答案 1 :(得分:0)
Libpcap的: http://www.tcpdump.org/pcap3_man.html
您可以通过您指定的任何接口读取进入的数据包,在本例中为wlan1。
int main(){
char *device = NULL;
pcap_t* descr;
if(argc > 0)
device = "wlan1";
if(device == NULL)
{
printf("%s\n",errbuf);
exit(1);
}
descr = pcap_open_live(device,BUFSIZ,0,-1,errbuf);
if(descr == NULL){ printf("pcap_open_live(): %s\n",errbuf); exit(1); }
errbuf[0] = 0;
handle = pcap_open_live(device, BUFSIZ,1,0,errbuf);
pcap_loop(handle,-1, process_packet, NULL);
pcap_close(handle);
return 0;
}
在pcap_loop
中,process_packet是进来的数据包的回调。
如果您有什么不确定的地方,请告诉我。
P.S。以下是一些可以帮助您解析802.11 /以太网标头的链接。
http://madwifi-project.org/wiki/DevDocs/RadiotapHeader http://yuba.stanford.edu/~casado/pcap/section2.html http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf
答案 2 :(得分:0)
这是我解析来自原始layer3网络流的数据包的方式。
#include "bigendian.h"
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
int pb_packet_read(PacketBuffer *b, int fd, int count, PacketCallback cb) {
int i = 0;
int result;
Packet *p;
unsigned char *start;
size_t remaining;
while (i < count) {
if (b->packet == NULL) {
if (b->level < 20 ) {
// Read up to MTU bytes to determine packet header.
result = read(fd, b->blob + b->level, MTU - b->level);
if (result <= 0) {
return i;
}
b->level += result;
}
if (b->level < 20 ) {
return i;
}
// Now, can read the packet total length
start = b->blob;
p = (Packet*) malloc(sizeof(Packet));
p->start = start;
p->version = start[0] >> 4;
p->total_length = bigendian_deserialize_uint16(start + 2);
memcpy(&(p->src.s_addr), start + 12, 4);
memcpy(&(p->dst.s_addr), start + 16, 4);
b->packet = p;
}
else {
L_DEBUG("Using prev stored complete packet.");
p = b->packet;
}
// Read the rest of the packet
if (p->total_length > b->level) {
remaining = p->total_length - b->level;
L_DEBUG("Packet not completed, trying read more.");
result = read(fd, b->blob + b->level, remaining);
if(result <= 0) {
if (result == EAGAIN) {
L_DEBUG("EAGAIN");
}
perror("READ BODY");
return i;
}
b->level += result;
if (result < remaining) {
L_DEBUG("Not enough data");
return i;
}
}
if (b->level > p->total_length) {
remaining = b->level - p->total_length;
memcpy(b->blob, b->blob + p->total_length, remaining);
b->level = remaining;
L_DEBUG("Remaining data: %lu", remaining);
}
// Packet is ready to pass to callback.
if(cb) {
cb(p);
}
// Cleanup for the next packet
i++;
b->level = 0;
free(b->packet);
b->packet = NULL;
}
return i;
}