/ ************************************************** *************************************** / * Ping.c - Simple Ping Utility Using Sock_Raw * * This Is A Part of The Microsoft Source code Samples. * Copyright 1996-1997 Microsoft Corporation. * All rights reserved. * This source code is only intended as a supplement to * Microsoft Development Tools and / or WinHelp documentation. * See these sources for detailed information regarding the * Microsoft samples programs . / ************************************************* ***************************** /
#pragma Pack (4)
#define Win32_Lean_and_mean #include
#define icmp_echo 8 #define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 // minimum 8 Byte ICMP Packet (Just Head)
/ * The IP header * / 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; unsigned char proto; // protocol (TCP, UDP etc) unsigned short checksum; // IP checksum
Unsigned int sourceip; unsigned int desip;
} Ipheader;
// // ICMP header // typedef struct _ihdr {BYTE i_type; BYTE i_code; / * type sub code * / USHORT i_cksum; USHORT i_id; USHORT i_seq; / * This is not the std header, but we reserve space for time * / Ulong timestamp;} icmpheader;
#define status_failed 0xfff #define def_packet_size 32 #define max_packet 1024
#define xmalloc (s) Heapalloc (GetProcessHeap (), Heap_zero_memory, (s)) #define xfree (p) Heapfree (getProcessHeap (), 0, (P))
Void fill_icmp_data (char *, int); ushort checksum; void decode_resp (char *, int, struct sockaddr_in *); void usage (char * progName) {
FPRINTF (stderr, "usage: / n"); fprintf (stderr, "% s
} int Main (int Argc, char ** argv) {
WSADATA wsaData; SOCKET sockRaw; struct sockaddr_in dest, from; struct hostent * hp; int bread, datasize; int fromlen = sizeof (from); int timeout = 1000; char * dest_ip; char * icmp_data; char * recvbuf; unsigned int addr = 0; ushort seq_no = 0;
IF (WsaStartup (MakeWord (2, 1), & WSADATA! = 0) {fprintf (stderr, "wsastartup failed:% d / n", getLastError ()); EXITPROCESS (STATUS_FAILED);}
IF (argc <2) {usage (argv [0]);} SockRaw = WSASOCKET (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);
if (sockRaw == INVALID_SOCKET) {fprintf (stderr, "WSASocket () failed:% d / n", WSAGetLastError ()); ExitProcess (STATUS_FAILED);} bread = setsockopt (sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeout SIZEOF (TIMEOUT); if (Bread == Socket_ERROR) {FPrintf (stderr, "failed to set recv timeout:% d / n", wsagetlasterror ()); EXITPROCESS (STATUS_FAILED);} Timeout = 1000; Bread = setsockopt (SockRaw, SOL_SOCKET, SO_SNDTIMEO, (CHAR *) & Timeout, SizeOf (Timeout)); if (Bread == Socket_ERROR) {FPrintf (stderr, "failed to set send timeout:% d / n", wsagetlasterror (); EXITPROCESS (Status_failed);} MEMSET (& DEST, 0, SIZEOF (DEST));
HP = gethostbyname (Argv [1]);
IF (! hp) {addr = inet_addr (argv [1]);} if ((! hp) && (addr == inaddr_none)) {fprintf (stderr, "unable to resolve% s / n", argv [1] ); Exitprocess;} if (hp! = Null) Memcpy (& (dest.sin_addr), hp-> h_addr, hp-> h_length); Else dest.sin_addr.s_addr = addr;
IF (hp) dest.sin_family = hp-> h_addrtype; else dest.sin_family = AF_INET;
Dest_ip = inet_ntoa (dest.sin_addr);
IF (argc> 2) {dataize = ATOI (Argv [2]); if (DataSize == 0) DataSize = DEF_PACKET_SIZE;
} else DataSize = Def_packet_size;
DataSize = Sizeof (Icmpheader);
ICMP_DATA = Xmalloc (MAX_PACKET); Recvbuf = Xmalloc (max_packet);
IF (! iCMP_DATA) {fprintf (stderr, "heapalloc failed% d / n", getLastError ()); EXITPROCESS (STATUS_FAILED);}
MEMSET (ICMP_DATA, 0, MAX_PACKET); Fill_ICMP_DATA (ICMP_DATA, DATASIZE);
While (1) {Int Bwrote;
((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;} fprintf (stderr," sendto failed:% d / n ", wsagetlasterror (); EXITPROCESS (STATUS_FAILED);} if (bwrote } / * The response is an ip packet. We must decode the ip header to locate the icmp data * / void decode_resp (char * buf, int tentes, struct sockaddr_in * from) { Ipheter * iPhdr; ICMPHEADER * ICMPHDR; UNSIGNED SHORT IPHDRLEN iPhdr = (ipheader *) BUF; iphdrlen = iphdr-> h_len * 4; // Number of 32-bit Words * 4 = bytes IF (Bytes ICMPHDR = (ICMPHEADER *) (BUF IPHDRLEN); IF (ICMPHDR-> i_TYPE! = ICMP_ECHOREPLY) {FPRINTF (stderr, "non-echo type% d Recvd / n", ICMphDR-> i_type); return;} if (Icmphdr-> i_id! = (usort) getCurrentProcessid () ) {fprintf (stderr, "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 ", GettickCount () - ICMphdr-> TimeStamp); Printf (" / n ");} 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 & 0xFFF); CKSUM = (CKSUM >> 16); Return (~ CKSUM);} / * helper function to fill in various stuff in in ipe request. * / void fill_icmp_data (char * icmp_data, int dataize) { ICMPHEADER * ICMP_HDR; Char * DataPart; ICMP_HDR = (ICMPHEADER *) ICMP_DATA; ICMP_HDR-> i_TYPE = 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');} You can study something