2012-03-29 62 views
0

我最近開始使用libpcap & linux專用庫和頭文件(如netinet/tcp.h)編寫數據包嗅探器。 問題是:當我使用TH_OFF(tcp)* 4獲取tcp頭時,其值通常小於20個字節。好吧,我知道,這是畸形的,但Wireshark顯示其他值(20 <)。旗幟也會發生同樣的情況。tcp header&flags

下面是代碼:

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'; 

我GOOGLE了它頗有幾分都沒有找到有用的東西。也許這是另一個begginer的錯誤,但我無法弄清楚。 在此先感謝。


再次,謝謝你的提示/想法。

所有包括處理鏈路層頭的pcap處理函數都是正確的。我的應用程序是用Qt 4.7.4編寫的。讓我給你更多關於我的邏輯的信息。也許我詳細分析了以太網幀頭,IP頭,UDP頭,ARP/RARP頭和ICMP頭。 至於邏輯,它是這樣的: 我有一個線程女巫偵聽
-pcap_loop(captureHandler,-1,packetHandler,(unsigned char *)dumpfile); packetHandler位於一個名爲「engine.cpp」的單獨的.cpp中。在那個.cpp中,我有數據包解釋器女巫,根據協議類型,實例化正確的類(tcpPacketHandler for tcp protocol)。 我的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報頭字段顯示正確,直到我打在TCP報頭數據的其餘部分的「數據偏移字段」

#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4) 

從這點不符合Wireshark結果(數據偏移量,標誌和有效載荷)。

也許問題是nread_tcp結構聲明在多個數據包共享的文件中,並且在短時間間隔內捕獲大量數據包時指針出錯。 我真的沒有線索。 我在Google上找到的每一件東西都使用這個結構,但我不知道t know what是我的代碼中的問題。 作爲第二個問題:packetHandler函數(來自pcap_loop函數)是否可以聲明爲類的成員? (因爲我注意到它沒有類型,當我試圖讓它成爲類成員時,編譯器給我一個錯誤)。

在此先感謝。

回答

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 */ 
}; 

並重新編譯程序,看看是否會工作。

+0

謝謝你的提示,但不幸的是,結果是一樣的:( – user1300795 2012-03-29 18:14:25

+0

如果你調用'pcap_datalink()'調用'pcap_open_live()','pcap_open_offline(後)'或'pcap_activate()',它會返回什麼值,並且您是否正確處理了該類型的鏈接層頭標頭,如[tcpdump.org鏈接層頭頁面]中所述(http:// www .tcpdump.org/linktypes.html)? – 2012-03-30 03:42:38

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 */