C ++ - 构造ICMP数据包时的访问冲突

时间:2013-08-14 21:31:22

标签: c++ runtime-error access-violation checksum icmp

我正在使用ping工具,当使用45041或更大的数据包大小(包括ICMP标头)计算ICMP校验和时,我一直在发送缓冲区周围遇到访问冲突。任何大小为45040或更小的数据包都不会引发错误,并使用正确的校验和进行正确传输。缩写代码如下;在第一次迭代时在校验和函数中取消引用while循环内的缓冲区时会发生访问冲突。

typedef struct ICMPHeader 
{
  BYTE type;          // ICMP packet type
  BYTE code;          // Type sub code
  USHORT checksum;
  USHORT id;
  USHORT seq;
} ICMPHeader;

typedef struct echoRequest
{
  ICMPHeader icmpHead;
  char *data;
} EchoRequest;

// ...
EchoRequest *sendBuffer = new EchoRequest();
sendBuffer->data = new char[packetSize];

memset((void *)sendBuffer->data, 0xfa, packetSize);

sendBuffer->icmpHead.checksum = ipChecksum((USHORT *)sendBuffer, 
                                     packetSize + sizeof(sendBuffer->icmpHead));
// ...

// checksum function
USHORT ipChecksum(USHORT *buffer, unsigned long size)
{
  unsigned long cksum = 0;

  while (size > 1) 
  {
    cksum += *buffer++;
    size -= sizeof(USHORT);
  }

  if (size)
    cksum += *(UCHAR *)buffer;

  cksum = (cksum >> 16) + (cksum & 0xffff);
  cksum += (cksum >> 16);

  return (USHORT)(~cksum);
}

有关为何发生这种情况的任何想法?

确切的错误措辞:Unhandled exception at 0x009C2582 in PingProject.exe: 0xC0000005: Access violation reading location 0x004D5000.

将Visual Studio Professional 2012与平台工具集v100 for .NET 4.0一起使用

2 个答案:

答案 0 :(得分:1)

您的ipChecksum函数需要指向它应该校验和的数据的指针,而不是指向包含指向校验和的数据的指针的结构的指针。首先是校验和icmpHead,这很好。但是它会将指针校验到data,这没有任何意义。然后它在EchoRequest结构的末尾进行校验和。

答案 1 :(得分:0)

如果您希望读者将此代码解释为c++,则需要修改一些内容。

    真的是
  • memset吗?

  • 使用reinterpret_cast将一种指针类型转换为另一种指针类型。

  • 使用size_t代替unsigned long

  • 通常被认为是更好的做法
  • 改为使用smart pointers

  • 使用static_cast将ulong转换为ushort。

  • USHORT 保证为16位。改为使用其他类型。

编辑:您在MTU之上 waaaay 。保持您的数据包低于1k字节。 IEEE 802.3预计1492可能会有所不同。