2012-03-29 13 views
0

私は最近、libpcap &のLinux固有のライブラリとnetinet/tcp.hのようなヘッダを使ってパケットスニファを書き始めました。 問題は次のとおりです。TH_OFF(tcp)* 4を使用してtcpヘッダーを取得すると、値が20バイト未満になることがよくあります。うわー、私は知っています、それは不正な形式ですが、Wiresharkは他の値(20 <)を表示しています。同じことがフラグで起こります。ここでtcpヘッダーとフラグ

コードです:

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で書かれています。私の論理についてもう少し詳しく説明しましょう。おそらくI 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 mは、イーサネットフレームヘッダ、IPヘッダ、UDPヘッダ、ARP/RARPヘッダ、ICMPヘッダを詳細に分析しています。 ロジックについては、次のようになります。 スレッド・ウィッチがあります。
-pcap_loop(captureHandler、-1、packetHandler、(unsigned char *)dumpfile); packetHandlerは "engine.cpp"という名前の別の.cppにあります。 .cppには、プロトコルタイプに応じてパケットインタープリタの魔法使いがあり、正しいクラス(TCPプロトコル用のtcpPacketHandler)をインスタンス化します。 私のtcp構造体は、tcpPacketHandlerヘッダーではなく、engine.hで宣言されています。 tcp構造体は私の最初の質問で掲示されたものです。 tcpPacketHandlerコンストラクタは次のようになります。私は、TCPヘッダデータの残りの部分にこの時点から

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

「データフィールドのオフセット」ヒットまで

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ヘッダフィールドが正しく表示されますWiresharkの結果(Data offset、Flags、およびPayload)に対応していません。

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 

を削除して、構造が

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

のように見えるので、それを交換して、プログラムを再コンパイルし、それが動作するかどうかを確認するために

u_char th_offx2;    /* data offset, rsvd */ 
#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4) 

上に移動。

+0

おかげで、しかし、あなたは、 'は、pcap_open_live()'、 'pcap_open_offlineを(呼び出した後' pcap_datalinkを() 'を呼び出す場合は、残念ながら結果は同じ:( – user1300795

+0

です:

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

に変更します)、 'pcap_activate()'、どの値を返すのか、[tcpdump.org link-layer headers page](http:// www)に記述されているように、そのタイプのリンク層ヘッダーヘッダーを適切に処理していますか? .tcpdump.org/linktypes.html)? –

0

ここは私の仕事です。先端のために

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