网络 C 代码中的数据损坏
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只有 2 或 3 分
你的 StartSniffing 函数没有循环,所以我想它会为每个收到的数据包调用,在这种情况下,为每个调用分配/释放是浪费的。使用堆栈数组或让调用者分配一次缓冲区并将其传递给被调用者。由于锁定,分配的成本可能很高。
在
ProcessPacket
中,您声明了 2 个数组,并对其进行初始化,然后用strcpy
填充。删除不必要的初始化程序(它们是隐藏的 memset 调用)。然后,您使用 Ip 地址比较的结果声明 2 个变量
a
和b
,到目前为止一切顺利,但在case 17
中您不这样做不要使用它们并使用strcmp
重新检查,这不太好。因此,要么重用a
和b
变量,要么完全删除它们。在
PrintIpHeader
等中避免这些printf
调用。 printf 的成本很高,因此最好只进行一次大调用,而不是 10 个较小的调用。这是我的意思的一个例子。请注意,
%u
是unsigned 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 withstrcpy
. Remove the initializers they are not necessary (they are hiddenmemset
calls).You then declare 2 variable
a
andb
with the result of the comparisons of Ip addresses, so far so good but then incase 17
you don't use them and recheck withstrcmp
which is not so good. So either reuse thea
andb
vars or remove them altogether.In
PrintIpHeader
and other avoid theseprintf
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.Notice that the
%u
is the format forunsigned int
not%d
and your format in the 2nd printf is false. You should compile with warnings enabled, gcc would have warned about that.另一个建议是在内存检查器(例如 valgrind)下运行程序。
Another suggestion is to run your program under a memory checker, e.g. valgrind.