色々なサイトを参考にしながら、自分書いていて、なんでWriteするのはICMPヘッダだけで大丈夫なのかな?と思っていて、Microsoftのネットワークモニターツールでパケットをキャプチャすると、IPヘッダが勝手に付加されてる?!不思議!などと思っていたのですが、
プロトコルにIPPROTO_ICMPを指定しているからなんだと、急に気づきました。相当、寝ぼけています

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#ifdef _WIN32
#include <tchar.h>
#endif
#include "RawSocket.h"
#define ICMP_ECHO_REPLY 0
#define ICMP_ECHO_REQUEST 8
struct reply {
struct iphdr stIpHdr;
struct icmphdr stIcmpHdr;
};
#ifdef _WIN32
int _tmain(int argc, _TCHAR* argv[])
#else
int main()
#endif
{
Socket::StartUp();
RawSocket sock(IPPROTO_ICMP);
sock.Open("localhost");
struct icmphdr stIcmpHdr;
memset( &stIcmpHdr, 0, sizeof(struct icmphdr) );
stIcmpHdr.type = ICMP_ECHO_REQUEST;
stIcmpHdr.code = 0;
stIcmpHdr.un.echo.id = 999;
stIcmpHdr.un.echo.sequence = 0;
stIcmpHdr.checksum = RawSocket::GetIpCheckSum((ushort*)&stIcmpHdr, sizeof(struct icmphdr));
sock.Write(&stIcmpHdr, sizeof(struct icmphdr));
struct reply stReply;
memset( &stReply, 0, sizeof(struct reply) );
sock.Read(&stReply, sizeof(struct reply));
printf(
"ihl %x\n"
"ver %x\n"
"tos %x\n"
"len %x\n"
"id %x\n"
"frag %x\n"
"ttl %x\n"
"proto %x\n"
"check %x\n"
"type %x\n"
"code %x\n"
"check %x\n"
"id %x\n"
"seq %x\n"
,stReply.stIpHdr.ihl
,stReply.stIpHdr.version
,stReply.stIpHdr.tos
,stReply.stIpHdr.tot_len
,stReply.stIpHdr.id
,stReply.stIpHdr.frag_off
,stReply.stIpHdr.ttl
,stReply.stIpHdr.protocol
,stReply.stIpHdr.check
,stReply.stIcmpHdr.type
,stReply.stIcmpHdr.code
,stReply.stIcmpHdr.checksum
,stReply.stIcmpHdr.un.echo.id
,stReply.stIcmpHdr.un.echo.sequence
);
printf("src[%s]\n", Socket::N2A(stReply.stIpHdr.saddr));
printf("dst[%s]\n", Socket::N2A(stReply.stIpHdr.daddr));
sock.Close();
Socket::CleanUp();
return 0;
}