tcp header&旗

时间:2012-03-29 13:04:14

标签: tcp header flags libpcap

我最近开始使用libpcap&amp; amp;编写数据包嗅探器。 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 I详细分析了以太网帧头,IP头,UDP头,ARP / RARP头和ICMP头。 至于逻辑,它是这样的: 我有一个线程女巫听 -pcap_loop(captureHandler,-1,packetHandler,(unsigned char *)dumpfile); packetHandler位于一个名为“engine.cpp”的独立.cpp上 在那个.cpp中我有数据包解释器,相应的协议类型,实例化正确的类(tcp协议的tcpPacketHandler)。 我的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 what问题。 并且作为第二个问题:可以将packetHandler函数(来自pcap_loop函数)声明为类的成员吗? (因为我注意到它没有类型,当我试图使它成为类成员时,编译器抛出了一个错误)。

提前致谢。

2 个答案:

答案 0 :(得分:0)

紧急指针后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 */
};

并重新编译您的程序,看看是否有效。

答案 1 :(得分:0)

这对我有用。

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

更改为:

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