⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pingsourcecode.c

📁 PING (Packet Internet Grope)
💻 C
字号:
/ Module Name: Ping.c 
// 
// Description: 
// This sample illustrates how an ICMP ping app can be written 
// using the SOCK_RAW socket type and IPPROTO_ICMP protocol. 
// By creating a raw socket, the underlying layer does not change 
// the protocol header so that when we submit the ICMP header 
// nothing is changed so that the receiving end will see an 
// ICMP packet. Additionally, we use the record route IP option 
// to get a round trip path to the endpoint. Note that the size 
// of the IP option header that records the route is limited to 
// nine IP addresses. 
// 
// Compile: 
// cl -o Ping Ping.c ws2_32.lib /Zp1 
// 
// Command Line Options/Parameters: 
// Ping [host] [packet-size] 
// 
// host String name of host to ping 
// packet-size Integer size of packet to send 
// (smaller than 1024 bytes) 
// 
//#pragma pack(1) 

#define WIN32_LEAN_AND_MEAN 
#include 
#include 
#include 
#include 

#define IP_RECORD_ROUTE 0x7 
// 
// IP header structure 
// 
typedef struct _iphdr 
{ 
unsigned int h_len:4; // Length of the header 
unsigned int version:4; // Version of IP 
unsigned char tos; // Type of service 
unsigned short total_len; // Total length of the packet 
unsigned short ident; // Unique identifier 
unsigned short frag_and_flags; // Flags 
unsigned char ttl; // Time to live 
unsigned char proto; // Protocol (TCP, UDP etc) 
unsigned short checksum; // IP checksum 

unsigned int sourceIP; 
unsigned int destIP; 
} IpHeader; 

#define ICMP_ECHO 8 
#define ICMP_ECHOREPLY 0 
#define ICMP_MIN 8 // Minimum 8-byte ICMP packet (header) 

// 
// ICMP header structure 
// 
typedef struct _icmphdr 
{ 
BYTE i_type; 
BYTE i_code; // Type sub code 
USHORT i_cksum; 
USHORT i_id; 
USHORT i_seq; 
// This is not the standard header, but we reserve space for time 
ULONG timestamp; 
} IcmpHeader; 

// 
// IP option header - use with socket option IP_OPTIONS 
// 
typedef struct _ipoptionhdr 
{ 
unsigned char code; // Option type 
unsigned char len; // Length of option hdr 
unsigned char ptr; // Offset into options 
unsigned long addr[9]; // List of IP addrs 
} IpOptionHeader; 

#define DEF_PACKET_SIZE 32 // Default packet size 
#define MAX_PACKET 1024 // Max ICMP packet size 
#define MAX_IP_HDR_SIZE 60 // Max IP header size w/options 

BOOL bRecordRoute; 
int datasize; 
char *lpdest; 

// 
// Function: usage 
// 
// Description: 
// Print usage information 
// 
void usage(char *progname) 
{ 
printf("usage: ping -r [data size]\n"); 
printf(" -r record route\n"); 
printf(" host remote machine to ping\n"); 
printf(" datasize can be up to 1KB\n"); 
ExitProcess(-1); 
} 

// 
// Function: FillICMPData 
// 
// Description: 
// Helper function to fill in various fields for our ICMP request 
// 
void FillICMPData(char *icmp_data, int datasize) 
{ 
IcmpHeader *icmp_hdr = NULL; 
char *datapart = NULL; 

icmp_hdr = (IcmpHeader*)icmp_data; 
icmp_hdr->i_type = ICMP_ECHO; // Request an ICMP echo 
icmp_hdr->i_code = 0; 
icmp_hdr->i_id = (USHORT)GetCurrentProcessId(); 
icmp_hdr->i_cksum = 0; 
icmp_hdr->i_seq = 0; 

datapart = icmp_data + sizeof(IcmpHeader); 
// 
// Place some junk in the buffer 
// 
memset(datapart,'E', datasize - sizeof(IcmpHeader)); 
} 

// 
// Function: checksum 
// 
// Description: 
// This function calculates the 16-bit one's complement sum 
// of the supplied buffer (ICMP) header 
// 
USHORT checksum(USHORT *buffer, int 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); 
} 

// 
// Function: DecodeIPOptions 
// 
// Description: 
// If the IP option header is present, find the IP options 
// within the IP header and print the record route option 
// values 
// 
void DecodeIPOptions(char *buf, int bytes) 
{ 
IpOptionHeader *ipopt = NULL; 
IN_ADDR inaddr; 
int i; 
HOSTENT *host = NULL; 

ipopt = (IpOptionHeader *)(buf + 20); 

printf("RR: "); 
for(i = 0; i < (ipopt->ptr / 4) - 1; i++) 
{ 
inaddr.S_un.S_addr = ipopt->addr[i]; 
if (i != 0) 
printf(" "); 
host = gethostbyaddr((char *)&inaddr.S_un.S_addr, 
sizeof(inaddr.S_un.S_addr), AF_INET); 
if (host) 
printf("(%-15s) %s\n", inet_ntoa(inaddr), host->h_name); 
else 
printf("(%-15s)\n", inet_ntoa(inaddr)); 
} 
return; 
} 

// 
// Function: DecodeICMPHeader 
// 
// Description: 
// The response is an IP packet. We must decode the IP header to 
// locate the ICMP data. 
// 
void DecodeICMPHeader(char *buf, int bytes, 
struct sockaddr_in *from) 
{ 
IpHeader *iphdr = NULL; 
IcmpHeader *icmphdr = NULL; 
unsigned short iphdrlen; 
DWORD tick; 
static int icmpcount = 0; 

iphdr = (IpHeader *)buf; 
// Number of 32-bit words * 4 = bytes 
iphdrlen = iphdr->h_len * 4; 
tick = GetTickCount(); 

if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount)) 
DecodeIPOptions(buf, bytes); 

if (bytes < iphdrlen + ICMP_MIN) 
{ 
printf("Too few bytes from %s\n", 
inet_ntoa(from->sin_addr)); 
} 
icmphdr = (IcmpHeader*)(buf + iphdrlen); 

if (icmphdr->i_type != ICMP_ECHOREPLY) 
{ 
printf("nonecho type %d recvd\n", icmphdr->i_type); 
return; 
} 
// Make sure this is an ICMP reply to something we sent! 
// 
if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) 
{ 
printf("someone else's packet!\n"); 
return ; 
} 
printf("%d bytes from %s:", bytes, inet_ntoa(from->sin_addr)); 
printf(" icmp_seq = %d. ", icmphdr->i_seq); 
printf(" time: %d ms", tick - icmphdr->timestamp); 
printf("\n"); 

icmpcount++; 
return; 
} 

void ValidateArgs(int argc, char **argv) 
{ 
int i; 

bRecordRoute = FALSE; 
lpdest = NULL; 
datasize = DEF_PACKET_SIZE; 

for(i = 1; i < argc; i++) 
{ 
if ((argv[i][0] == '-') || (argv[i][0] == '/')) 
{ 
switch (tolower(argv[i][1])) 
{ 
case 'r': // Record route option 
bRecordRoute = TRUE; 
break; 
default: 
usage(argv[0]); 
break; 
} 
} 
else if (isdigit(argv[i][0])) 
datasize = atoi(argv[i]); 
else 
lpdest = argv[i]; 
} 
} 
// 
// Function: main 
// 
// Description: 
// Setup the ICMP raw socket, and create the ICMP header. Add 
// the appropriate IP option header, and start sending ICMP 
// echo requests to the endpoint. For each send and receive, 
// we set a timeout value so that we don't wait forever for a 
// response in case the endpoint is not responding. When we 
// receive a packet decode it. 
// 
int main(int argc, char **argv) 
{ 

WSADATA wsaData; 
SOCKET sockRaw = INVALID_SOCKET; 
struct sockaddr_in dest, 
from; 
int bread, 
fromlen = sizeof(from), 
timeout = 1000, 
ret; 
char *icmp_data = NULL, 
*recvbuf = NULL; 
unsigned int addr = 0; 
USHORT seq_no = 0; 
struct hostent *hp = NULL; 
IpOptionHeader ipopt; 


if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 
{ 
printf("WSAStartup() failed: %d\n", GetLastError()); 
return -1; 
} 
ValidateArgs(argc, argv); 

// 
// WSA_FLAG_OVERLAPPED flag is required for SO_RCVTIMEO, 
// SO_SNDTIMEO option. If NULL is used as last param for 
// WSASocket, all I/O on the socket is synchronous, the 
// internal user mode wait code never gets a chance to 
// execute, and therefore kernel-mode I/O blocks forever. 
// A socket created via the socket function has the over- 
// lapped I/O attribute set internally. But here we need 
// to use WSASocket to specify a raw socket. 
// 
// If you want to use timeout with a synchronous 
// nonoverlapped socket created by WSASocket with last 
// param set to NULL, you can set the timeout by using 
// the select function, or you can use WSAEventSelect and 
// set the timeout in the WSAWaitForMultipleEvents 
// function. 
// 
sockRaw = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 
WSA_FLAG_OVERLAPPED); 
if (sockRaw == INVALID_SOCKET) 
{ 
printf("WSASocket() failed: %d\n", WSAGetLastError()); 
return -1; 
} 
if (bRecordRoute) 
{ 
// Setup the IP option header to go out on every ICMP packet 
// 
ZeroMemory(&ipopt, sizeof(ipopt)); 
ipopt.code = IP_RECORD_ROUTE; // Record route option 
ipopt.ptr = 4; // Point to the first addr offset 
ipopt.len = 39; // Length of option header 

ret = setsockopt(sockRaw, IPPROTO_IP, IP_OPTIONS, 
(char *)&ipopt, sizeof(ipopt)); 
if (ret == SOCKET_ERROR) 
{ 
printf("setsockopt(IP_OPTIONS) failed: %d\n", 
WSAGetLastError()); 
} 
} 
// Set the send/recv timeout values 
// 
bread = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, 
(char*)&timeout, sizeof(timeout)); 
if(bread == SOCKET_ERROR) 
{ 
printf("setsockopt(SO_RCVTIMEO) failed: %d\n", 
WSAGetLastError()); 
return -1; 
} 
timeout = 1000; 
bread = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, 
(char*)&timeout, sizeof(timeout)); 
if (bread == SOCKET_ERROR) 
{ 
printf("setsockopt(SO_SNDTIMEO) failed: %d\n", 
WSAGetLastError()); 
return -1; 
} 
memset(&dest, 0, sizeof(dest)); 
// 
// Resolve the endpoint's name if necessary 
// 
dest.sin_family = AF_INET; 
if ((dest.sin_addr.s_addr = inet_addr(lpdest)) == INADDR_NONE) 
{ 
if ((hp = gethostbyname(lpdest)) != NULL) 
{ 
memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length); 
dest.sin_family = hp->h_addrtype; 
printf("dest.sin_addr = %s\n", inet_ntoa(dest.sin_addr)); 
} 
else 
{ 
printf("gethostbyname() failed: %d\n", 
WSAGetLastError()); 
return -1; 
} 
} 
// 
// Create the ICMP packet 
// 
datasize += sizeof(IcmpHeader); 

icmp_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
MAX_PACKET); 
recvbuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
MAX_PACKET); 
if (!icmp_data) 
{ 
printf("HeapAlloc() failed: %d\n", GetLastError()); 
return -1; 
} 
memset(icmp_data,0,MAX_PACKET); 
FillICMPData(icmp_data,datasize); 
// 
// Start sending/receiving ICMP packets 
// 
while(1) 
{ 
static int nCount = 0; 
int bwrote; 

if (nCount++ == 4) 
break; 

((IcmpHeader*)icmp_data)->i_cksum = 0; 
((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); 
((IcmpHeader*)icmp_data)->i_seq = seq_no++; 
((IcmpHeader*)icmp_data)->i_cksum = 
checksum((USHORT*)icmp_data, datasize); 

bwrote = sendto(sockRaw, icmp_data, datasize, 0, 
(struct sockaddr*)&dest, sizeof(dest)); 
if (bwrote == SOCKET_ERROR) 
{ 
if (WSAGetLastError() == WSAETIMEDOUT) 
{ 
printf("timed out\n"); 
continue; 
} 
printf("sendto() failed: %d\n", WSAGetLastError()); 
return -1; 
} 
if (bwrote < datasize) 
{ 
printf("Wrote %d bytes\n", bwrote); 
} 
bread = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, 
(struct sockaddr*)&from, &fromlen); 
if (bread == SOCKET_ERROR) 
{ 
if (WSAGetLastError() == WSAETIMEDOUT) 
{ 
printf("timed out\n"); 
continue; 
} 
printf("recvfrom() failed: %d\n", WSAGetLastError()); 
return -1; 
} 
DecodeICMPHeader(recvbuf, bread, &from); 

Sleep(1000); 
} 
// Cleanup 
// 
if (sockRaw != INVALID_SOCKET) 
closesocket(sockRaw); 
HeapFree(GetProcessHeap(), 0, recvbuf); 
HeapFree(GetProcessHeap(), 0, icmp_data); 

WSACleanup(); 
return 0; 
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -