【发布时间】:2012-04-13 03:11:06
【问题描述】:
我最近开始使用 libpcap 和 linux 特定库和头文件(如 netinet/tcp.h)编写数据包嗅探器。 问题是:当我使用 TH_OFF(tcp)*4 获取 tcp 标头时,它的值通常小于 20 个字节。好的,我知道,它的格式不正确,但 Wireshark 显示的是其他值(20
代码如下:
struct nread_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
u_short th_seq; /* sequence number */
u_short th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */
#endif
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_NS 0x100
#define TH_RS 0xE00
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
};
const struct nread_tcp* tcp = (struct nread_tcp*)(pachet + sizeof(struct ether_header) + sizeof(struct crt_ip));
...
int hlen = TH_OFF(tcp)*4;
char * tmp = new char[strlen("000000000000")+1];
strcpy(tmp,"000000000000");
if (tcp->th_flags & TH_NS){
tmp[3] = '1';
}
else
tmp[3] = '0';
if (tcp->th_flags & TH_ECE){
tmp[4] = '1';
}
else
tmp[4] = '0';
if (tcp->th_flags & TH_CWR){
tmp[5] = '1';
}
else
tmp[5] = '0';
if (tcp->th_flags & TH_URG){
tmp[6] = '1';
}
else
tmp[6] = '0';
if (tcp->th_flags & TH_ACK){
tmp[7] = '1';
}
else
tmp[7] = '0';
if (tcp->th_flags & TH_PUSH){
tmp[8] = '1';
}
else
tmp[8] = '0';
if (tcp->th_flags & TH_RST){
tmp[9] = '1';
}
else
tmp[9] = '0';
if (tcp->th_flags & TH_SYN){
tmp[10] = '1';
}
else
tmp[10] = '0';
if (tcp->th_flags & TH_FIN){
tmp[11] = '1';
}
else
tmp[11] = '0';
我用谷歌搜索了很多,但没有找到有用的东西。也许这是另一个初学者的错误,但我无法弄清楚。 提前致谢。
再次感谢您的提示/想法。
所有 pcap 处理函数,包括处理链路层标头都是正确的。我的应用程序是用 Qt 4.7.4 编写的。让我给你一些关于我的逻辑的更多信息。也许我m using pointers that are not pointing correctly. I wish to emphasize the fact that tcp is the only protocol with this issue. The others that Im 详细分析了以太网帧头、IP 头、UDP 头、ARP/RARP 头和ICMP 头。
至于逻辑,它是这样的:
我有一个线程女巫在听
-pcap_loop(captureHandler,-1,packetHandler,(unsigned char*)dumpfile);
packetHandler 位于名为“engine.cpp”的单独 .cpp 上
在那个 .cpp 中,我有数据包解释器女巫,根据协议类型,实例化正确的类(tcpPacketHandler 用于 tcp 协议)。
我的 tcp 结构在 engine.h 中声明(不是 tcpPacketHandler 标头)。
tcp 结构是我最初的问题中发布的结构。
tcpPacketHandler 构造函数如下所示:
tcpPacketHandler::tcpPacketHandler(u_char *arg, const pcap_pkthdr * header,const u_char * pachet)
{
(void)arg;
(void)header;
const struct nread_tcp* tcp = (struct nread_tcp*)(pachet + sizeof(struct ether_header) + sizeof(struct crt_ip));
//fprintf(stdout,"\nSEQUENCE NUMBER %u \nACK %u \nWINDOW %u\nURGENT POINTER %u\n", tcp->th_seq, tcp->th_ack, tcp->th_win,tcp->th_urp);
//qDebug() <<sizeof(struct ether_header)<< " "<< sizeof(struct crt_ip);
this->seqNr = ntohs(tcp->th_seq);
this->ackNr = ntohs(tcp->th_ack);
this->window = ntohs(tcp->th_win);
this->urgentPointer = ntohs(tcp->th_urp);
this->portSursa = ntohs(tcp->th_sport);
this->portDestinatie = ntohs(tcp->th_dport);
this->checksum = ntohs(tcp->th_sum);
char * tmp = new char[strlen("000000000000")+1];
strcpy(tmp,"000000000000");
if (tcp->th_flags & TH_NS){
tmp[3] = '1';
}
else
tmp[3] = '0';
if (tcp->th_flags & TH_ECE){
tmp[4] = '1';
}
else
tmp[4] = '0';
if (tcp->th_flags & TH_CWR){
tmp[5] = '1';
}
else
tmp[5] = '0';
if (tcp->th_flags & TH_URG){
tmp[6] = '1';
}
else
tmp[6] = '0';
if (tcp->th_flags & TH_ACK){
tmp[7] = '1';
}
else
tmp[7] = '0';
if (tcp->th_flags & TH_PUSH){
tmp[8] = '1';
}
else
tmp[8] = '0';
if (tcp->th_flags & TH_RST){
tmp[9] = '1';
}
else
tmp[9] = '0';
if (tcp->th_flags & TH_SYN){
tmp[10] = '1';
}
else
tmp[10] = '0';
if (tcp->th_flags & TH_FIN){
tmp[11] = '1';
}
else
tmp[11] = '0';
this->hdrLen = TH_OFF(tcp)*4;
// qDebug() << this->hdrLen;
this->flags = new char[13];
strcpy(this->flags,tmp);
if(tmp)
{
delete [] tmp;
tmp = NULL;
}
}
在我点击“数据偏移字段”之前,所有 tcp 标头字段都正确显示
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
从此时起,tcp 头数据的其余部分与 Wireshark 结果(数据偏移量、标志和有效负载)不对应。
可能问题在于 nread_tcp 结构体在多个数据包共享的文件中声明,并且在短时间内捕获大量数据包时指针出错。
我真的一点头绪都没有。
我在 Google 上找到的所有东西都使用这个结构,但我在代码中没有t know whats 的问题。
作为第二个问题:可以将 packetHandler 函数(来自 pcap_loop 函数)声明为类的成员吗? (因为我注意到它没有类型,当我尝试将其设为类成员时,编译器向我抛出了一个错误)。
提前致谢。
【问题讨论】: