【问题标题】:tcp header & flagstcp 标头和标志
【发布时间】: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 函数)声明为类的成员吗? (因为我注意到它没有类型,当我尝试将其设为类成员时,编译器向我抛出了一个错误)。

提前致谢。

【问题讨论】:

    标签: tcp header flags libpcap


    【解决方案1】:

    紧急指针后的TCP头中没有数据偏移字段; the TCP header 在紧急指针之后有选项。相反,删除

    #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_offx2;               /* data offset, rsvd */
    #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
    

    向上替换它,所以结构看起来像

    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 */
        u_char  th_offx2; /* data offset, rsvd */
    #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
        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 */
    };
    

    然后重新编译你的程序,看看是否可行。

    【讨论】:

    • 感谢您的提示,但不幸的是结果是一样的:(
    • 如果您在调用pcap_open_live()、pcap_open_offline() 或pcap_activate() 之后调用pcap_datalink(),它会返回什么值,并且您是否正确处理该类型的链路层标头标头,如描述于the tcpdump.org link-layer headers page?
    【解决方案2】:

    这对我有用。

    u_short th_seq;   /* sequence number        */
    u_short th_ack;   /* acknowledgement number */
    

    改为:

    u_int th_seq;   /* sequence number        */
    u_int th_ack;   /* acknowledgement number */
    

    【讨论】:

      猜你喜欢
      • 2021-12-25
      • 2010-12-01
      • 2023-03-26
      • 2016-12-29
      • 1970-01-01
      • 2018-07-09
      • 2019-04-29
      • 1970-01-01
      • 2014-03-12
      相关资源
      最近更新 更多