0

私はWindowsとANSI-cを使用しています。ネットワークカードからデータを盗聴し、それをデコードしてUDP経由で他のアプリケーションに送信するアプリケーションがあります。問題は、私のアプリケーションが正常に動作することから始まりますが、しばらくするとすべての変数 int、float、および文字列が破損し、何度もチェックしましたが、問題を掘り下げることができません。このアプリケーションは、ネットワークからデータを傍受せずに自分の IP にデータを直接送信すると、非常にうまく機能します。

この問題に取り組む方法、テストツール、または役立つ他の方法を誰かに提案してもらえますか?

//method for start sniffing the raw port
void StartSniffing(SOCKET sniffer)
{
    unsigned char *Buffer = ( unsigned char *)malloc(65536);
    int iPacketLength;
    if (Buffer == NULL)
    {
        printf("malloc() failed.\n");
        return;
    }//end if

    iPacketLength = recvfrom(sniffer,(char *)Buffer,65536,0,0,0); 

    if(iPacketLength > 0 && iPacketLength <50)
        ProcessPacket(Buffer, iPacketLength);
    else
        printf( "recvfrom() failed.\n");

    free(Buffer);
}//end method
//*****************************************************************************************
// method for pecket processing filters udp
void ProcessPacket(unsigned char* Buffer, int Size)
{
    char srtPacketSourceIp[16]={'\0'};
    char strPacketDestinationIp[16] ={'\0'} ;
    strcpy_s(srtPacketSourceIp,inet_ntoa(source.sin_addr));
    strcpy_s(strPacketDestinationIp,inet_ntoa(dest.sin_addr));

    int a=strcmp(srtPacketSourceIp, strSourceIp );
    int b=strcmp(strPacketDestinationIp,strDestinationIp);

    iphdr = (IPV4_HDR *)Buffer;


    switch (iphdr->ip_protocol) //Check the Protocol and do accordingly...
    {
        case 1: //ICMP Protocol
            //PrintIcmpPacket(Buffer,Size);
            break;
        case 2: //IGMP Protocol
            break;
        case 6: //TCP Protocol
            //PrintTcpPacket(Buffer,Size);
            break;
        case 17: //UDP Protocol
            ++udp;          
            if(!strcmp(srtPacketSourceIp, strSourceIp )&& !strcmp(strPacketDestinationIp,strDestinationIp))
                PrintUdpPacket(Buffer,Size);
            break;
        default: //Some Other Protocol like ARP etc.
            break;
    }//end switch

}//end method
//*****************************************************************************************
//method to print ip header for displaing data
void PrintIpHeader (unsigned char* Buffer, int Size)
{
    unsigned short iphdrlen;
    iphdr = (IPV4_HDR *)Buffer;
    iphdrlen = iphdr->ip_header_len*4;
    memset(&source, 0, sizeof(source));
    source.sin_addr.s_addr = iphdr->ip_srcaddr;
    memset(&dest, 0, sizeof(dest));
    dest.sin_addr.s_addr = iphdr->ip_destaddr;
    /*printf("\n");
    printf("IP Header\n");
    printf(" |-IP Version : %d\n",(unsigned int)iphdr->ip_version);
    printf(" |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iphdr->ip_header_len);
    printf(" |-Type Of Service : %d\n",(unsigned int)iphdr->ip_tos);
    printf(" |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iphdr->ip_total_length));
    printf(" |-Identification : %d\n",ntohs(iphdr->ip_id));
    printf(" |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero);
    printf(" |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment);
    printf(" |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment);
    printf(" |-TTL : %d\n",(unsigned int)iphdr->ip_ttl);
    printf(" |-Protocol : %d\n",(unsigned int)iphdr->ip_protocol);
    printf(" |-Checksum : %d\n",ntohs(iphdr->ip_checksum));
    printf(" |-Source IP : %s\n",inet_ntoa(source.sin_addr));
    printf(" |-Destination IP : %s\n",inet_ntoa(dest.sin_addr));*/

}//end method
//*****************************************************************************************
//method to print udp packet for displaying data
void PrintUdpPacket(unsigned char *Buffer,int Size)
{
    unsigned short iphdrlen;
    iphdr = (IPV4_HDR *)Buffer;
    iphdrlen = iphdr->ip_header_len*4;
    udpheader = (UDP_HDR *)(Buffer + iphdrlen);
    /*printf("\n\n***********************UDP Packet*************************\n");
    PrintIpHeader(Buffer,Size);
    printf("\nUDP Header\n");
    printf(" |-Source Port : %d\n",ntohs(udpheader->source_port));
    printf(" |-Destination Port : %d\n",ntohs(udpheader->dest_port));
    printf(" |-UDP Length : %d\n",ntohs(udpheader->udp_length));
    printf(" |-UDP Checksum : %d\n",ntohs(udpheader->udp_checksum));
    printf("\n");
    printf("IP Header\n");
    PrintData(Buffer,iphdrlen);
    printf("UDP Header\n");
    PrintData(Buffer+iphdrlen,sizeof(UDP_HDR));
    printf("Data Payload\n");
    PrintData(Buffer+iphdrlen+sizeof(UDP_HDR),(Size - sizeof(UDP_HDR) - iphdr->ip_header_len*4));*/
    memcpy(strRecievedDump,Buffer+iphdrlen+sizeof(UDP_HDR),(Size - sizeof(UDP_HDR) - iphdr->ip_header_len*4));
    DumpDecoderAndSender();//this just decodes and sends the data
    //printf("\n###########################################################");

}//end method
//*****************************************************************************************
//method to print data
void PrintData (unsigned char* data , int Size)
{
    for(int i=0 ; i < Size ; i++)
    {
        if( i!=0 && i%16==0) //if one line of hex printing is complete...
        {
            printf(" ");

            for(int j=i-16 ; j<i ; j++)
            {
                if(data[j]>=32 && data[j]<=128)
                    printf("%c",(unsigned char)data[j]); //if its a number or alphabet
                else 
                    printf("."); //otherwise print a dot
            }//end for
            printf("\n");

        }//end if

        if(i%16==0)
            printf(" ");

        printf(" %02X",(unsigned int)data[i]);

        if( i==Size-1) //print the last spaces
        {
            for(int j=0;j<15-i%16;j++)
                (" "); //extra spaces

            printf(" ");

            for(int j=i-i%16 ; j<=i ; j++)
            {
                if(data[j]>=32 && data[j]<=128)
                    printf("%c",(unsigned char)data[j]);
                else 
                    printf(".");
            }//end if
            printf("\n");
        }//end if
    }//end for loop
}//end method   
4

2 に答える 2

1

たった2、3ポイント

あなたのStartSniffing関数にはループがないので、受信したパケットごとに呼び出されると思います。この場合、すべての呼び出しに割り当て/解放するのは無駄です。スタック配列を使用するか、呼び出し元にバッファーを1回割り当てて、呼び出し先に渡します。ロックが原因で、割り当てにコストがかかる可能性があります。

で、ProcessPacket初期化してから。で埋める2つの配列を宣言しますstrcpy。不要な初期化子を削除します(非表示のmemset呼び出しです)。

次に、2つの変数aを宣言bし、IPアドレスの比較の結果を使用して、これまでのところ良好ですが、case 17それらを使用せずに、strcmpどちらがあまり良くないかを再確認します。したがって、ab変数を再利用するか、それらを完全に削除します。

PrintIpHeaderその他、これらのprintfコールフェストは避けてください。printfはコストがかかるため、10個の小さな呼び出しよりも大きな呼び出しを1つだけ持つ方が適切です。ここに私が言っていることの例があります。

printf("IP Header\n"
       " |-IP Version : %u\n"
       " |-IP Header Length : %u DWORDS or %u Bytes\n"    /* 2 %u but only 1 parameter??? */
       " |-Type Of Service : %u\n"
       " |-IP Total Length : %u Bytes(Size of Packet)\n"
       " |-Identification : %u\n"
       " |-Reserved ZERO Field : %u\n"
       " |-Dont Fragment Field : %u\n"
       " |-More Fragment Field : %u\n"
       " |-TTL : %d\n"
       " |-Protocol : %d\n"
       " |-Checksum : %d\n"
       " |-Source IP : %s\n"
       " |-Destination IP : %s\n", (unsigned int)iphdr->ip_version
                                 , (unsigned int)iphdr->ip_header_len, 9999 /* Added 9999 because the original code was buggy */
                                 , (unsigned int)iphdr->ip_tos
                                 , ntohs(iphdr->ip_total_length)
                                 , ntohs(iphdr->ip_id)
                                 , (unsigned int)iphdr->ip_reserved_zero
                                 , (unsigned int)iphdr->ip_dont_fragment
                                 , (unsigned int)iphdr->ip_more_fragment
                                 , (unsigned int)iphdr->ip_ttl 
                                 , (unsigned int)iphdr->ip_protocol
                                 , ntohs(iphdr->ip_checksum)
                                 , inet_ntoa(source.sin_addr)
                                 , inet_ntoa(dest.sin_addr));  

%uunsigned intnot%dのフォーマットであり、2番目のprintfのフォーマットはfalseであることに注意してください。警告を有効にしてコンパイルする必要があります。gccはそのことについて警告します。

于 2010-06-23T09:49:41.180 に答える
1

もう 1 つの提案は、メモリ チェッカー (valgrind など) の下でプログラムを実行することです。

于 2010-06-23T09:25:08.517 に答える