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

另一个建议是在内存检查器下运行您的程序,例如 valgrind。

于 2010-06-23T09:25:08.517 回答
1

只需2或3分

你的StartSniffing函数没有循环,所以我想它是为每个接收到的数据包调用的,在这种情况下,为每个调用分配/释放是浪费的。使用堆栈数组或让调用者分配一次缓冲区并将其传递给被调用者。由于锁定,分配可能代价高昂。

ProcessPacket您声明 2 个您初始化的数组,然后用strcpy. 删除它们不是必需的初始化程序(它们是隐藏memset调用)。

然后,您声明 2 个变量a,并b根据 Ip 地址比较的结果,到目前为止一切都很好,但是case 17您不使用它们并重新检查strcmp哪个不太好。因此,要么重用aand bvar,要么完全删除它们。

PrintIpHeader和其他避免这些printf呼叫节。printf 的成本很高,因此最好只进行一次大调用而不是 10 个较小的调用。这是我的意思的一个例子。

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并且您在第二个 printf 中的格式为 false。您应该在启用警告的情况下进行编译,gcc 会对此发出警告。

于 2010-06-23T09:49:41.180 回答