网络 C 代码中的数据损坏

发布于 2024-09-06 20:34:07 字数 6117 浏览 5 评论 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   

I am using windows and ANSI-c, I have an application that sniffs data from network card then decodes it and sent to and other application via UDP. The problem is my application starts with fine working but after some time its all variables int, float and strings are corrupted I have checked it many times but can't be able to dig out the problem. This very application works very fine when I take data straight to my IP without sniffing data from network.

Can anyone suggest me how to tackle this problem, any testing tool or else that can help?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苦妄 2024-09-13 20:34:07

只有 2 或 3 分

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

ProcessPacket 中,您声明了 2 个数组,并对其进行初始化,然后用 strcpy 填充。删除不必要的初始化程序(它们是隐藏的 memset 调用)。

然后,您使用 Ip 地址比较的结果声明 2 个变量 ab,到目前为止一切顺利,但在 case 17 中您不这样做不要使用它们并使用 strcmp 重新检查,这不太好。因此,要么重用 ab 变量,要么完全删除它们。

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

Just 2 or 3 points

Your StartSniffing function has no loop so I suppose it is called for each received packet, in this case allocating/freeing for every call is wastefull. Use a stack array or let the caller allocate the buffer once and pass it to the callee. Allocation can be costly due to locking.

In ProcessPacket you declare 2 arrays that you initialize and then fill with strcpy. Remove the initializers they are not necessary (they are hidden memset calls).

You then declare 2 variable a and b with the result of the comparisons of Ip addresses, so far so good but then in case 17 you don't use them and recheck with strcmp which is not so good. So either reuse the a and b vars or remove them altogether.

In PrintIpHeader and other avoid these printf call fests. printf is costly so it is better to have only one big call than 10 smaller ones. Here an exapmple of what I mean.

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

Notice that the %u is the format for unsigned int not %d and your format in the 2nd printf is false. You should compile with warnings enabled, gcc would have warned about that.

情感失落者 2024-09-13 20:34:07

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

Another suggestion is to run your program under a memory checker, e.g. valgrind.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文