アナログICMPプロセス
7006 ワード
まずcommonヘッダファイルを作成する
次に、パケットヘッダファイルを作成します.
common.cpp
最後にメインファイルで、ICMP返信応答メッセージを受信します.typeが0 codeが0
//
// comm.h
//
#ifndef __COMM_H__
#define __COMM_H__
//
// 16 , ,
// 。 32
USHORT checksum(USHORT* buff, int size);
BOOL SetTTL(SOCKET s, int nValue);
BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv = TRUE);
#endif // __COMM_H__
次に、パケットヘッダファイルを作成します.
//
// protoinfo.h
/*
*/
#include
#ifndef __PROTOINFO_H__
#define __PROTOINFO_H__
#define ETHERTYPE_IP 0x0800
#define ETHERTYPE_ARP 0x0806
typedef struct _ETHeader // 14
{
UCHAR dhost[6]; // MAC destination mac address
UCHAR shost[6]; // MAC source mac address
USHORT type; // , IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)
} ETHeader, *PETHeader;
#define ARPHRD_ETHER 1
// ARP opcodes
#define ARPOP_REQUEST 1 // ARP
#define ARPOP_REPLY 2 // ARP
typedef struct _ARPHeader // 28 ARP
{
USHORT hrd; // , ARPHRD_ETHER
USHORT eth_type; // ,ETHERTYPE_IP ??
UCHAR maclen; // MAC , 6
UCHAR iplen; // IP , 4
USHORT opcode; // ,ARPOP_REQUEST ,ARPOP_REPLY
UCHAR smac[6]; // MAC
UCHAR saddr[4]; // IP
UCHAR dmac[6]; // MAC
UCHAR daddr[4]; // IP
} ARPHeader, *PARPHeader;
//
#define PROTO_ICMP 1
#define PROTO_IGMP 2
#define PROTO_TCP 6
#define PROTO_UDP 17
typedef struct _IPHeader // 20 IP
{
UCHAR iphVerLen; // ( 4 )
UCHAR ipTOS; //
USHORT ipLength; // , IP
USHORT ipID; // ,
USHORT ipFlags; //
UCHAR ipTTL; // , TTL
UCHAR ipProtocol; // , TCP、UDP、ICMP
USHORT ipChecksum; //
ULONG ipSource; // IP
ULONG ipDestination; // IP
} IPHeader, *PIPHeader;
// TCP
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20
#define TCP_ACE 0x40
#define TCP_CWR 0x80
typedef struct _TCPHeader // 20 TCP
{
USHORT sourcePort; // 16
USHORT destinationPort; // 16
ULONG sequenceNumber; // 32
ULONG acknowledgeNumber; // 32
UCHAR dataoffset; // 4
UCHAR flags; // 6
//FIN - 0x01
//SYN - 0x02
//RST - 0x04
//PUSH- 0x08
//ACK- 0x10
//URG- 0x20
//ACE- 0x40
//CWR- 0x80
USHORT windows; // 16
USHORT checksum; // 16
USHORT urgentPointer; // 16
} TCPHeader, *PTCPHeader;
typedef struct _UDPHeader
{
USHORT sourcePort; //
USHORT destinationPort;//
USHORT len; //
USHORT checksum; //
} UDPHeader, *PUDPHeader;
#endif // __PROTOINFO_H__
common.cpp
//
// comm.cpp
#include
#include "Ws2tcpip.h"
#include "common.h"
#include
USHORT checksum(USHORT* buff, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buff++;
size -= sizeof(USHORT);
}
//
if(size)
{
cksum += *(UCHAR*)buff;
}
// 32 chsum 16 16 ,
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
BOOL SetTTL(SOCKET s, int nValue)
{
int ret = ::setsockopt(s, IPPROTO_IP, IP_TTL, (char*)&nValue, sizeof(nValue));
return ret != SOCKET_ERROR;
}
BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv)
{
int ret = ::setsockopt(s, SOL_SOCKET,
bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
return ret != SOCKET_ERROR;
}
最後にメインファイルで、ICMP返信応答メッセージを受信します.typeが0 codeが0
///
// ping.cpp
#include "protoinfo.h"
#include "common.h"
#include
#include
typedef struct icmp_hdr
{
unsigned char icmp_type; //
unsigned char icmp_code; //
unsigned short icmp_checksum; //
//
unsigned short icmp_id; // ID , ID
unsigned short icmp_sequence; //
unsigned long icmp_timestamp; //
} ICMP_HDR, *PICMP_HDR;
int main()
{
// IP , Ping IP
char szDestIp[] = "115.25.217.12"; // 127.0.0.1
WSAData w;
if(WSAStartup(MAKEWORD(2,2),&w)==SOCKET_ERROR)
return -1;
//
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
int time=1500;
setsockopt(sRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(int));
//
//
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0);
dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);
// ICMP
char buff[sizeof(ICMP_HDR) + 32];
ICMP_HDR* pIcmp = (ICMP_HDR*)buff;
// ICMP , ICMP
pIcmp->icmp_type = 8;
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
// ,
memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
// ICMP
USHORT nSeq = 0;
char recvBuf[1024];
SOCKADDR_IN from;
int nLen = sizeof(from);
while(TRUE)
{
static int nCount = 0;
int nRet;
// ping
if(nCount++ == 1000)
break;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{
printf(" sendto() failed: %d /n", ::WSAGetLastError());
return -1;
}
nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
if(nRet == SOCKET_ERROR)
{
if(::WSAGetLastError() == WSAETIMEDOUT)
{
printf(" timed out/n");
continue;
}
printf(" recvfrom() failed: %d
", ::WSAGetLastError());
return -1;
}
// ICMP
int nTick = ::GetTickCount();
if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
{
printf(" Too few bytes from %s
", ::inet_ntoa(from.sin_addr));
}
// IP ,IP 20 , 20 ICMP
// (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20);
if(pRecvIcmp->icmp_type != 0) //
{
printf(" nonecho type %d recvd
", pRecvIcmp->icmp_type);
printf("should quit
");
return -1;
}
if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())
{
printf(" someone else's packet!
");
printf("should quit
");
return -1;
}
printf(" %s %d :
", inet_ntoa(from.sin_addr),nRet);
printf(" = %d. \t", pRecvIcmp->icmp_sequence);
printf(" : %d ms
", nTick - pRecvIcmp->icmp_timestamp);
printf("
");
//
::Sleep(1000);
}
return 0;
}