<< |
Winsock Programmer's FAQ |
>> |
This example shows how to "ping" another machine using Microsoft's ICMP.DLL. This DLL is an undocumented API for sending ICMP echo packets, also called "pings," after the submariner's term for sonar signals. This API works fine and is present on all current Windows boxes with Microsoft Winsocks, but Microsoft says they'll replace it as soon as something better comes along. (Microsoft's been saying this since the Windows 95 days, however, yet this functionality still exists in Windows 2000.) For more information on the ICMP.DLL API, check out sockets.com's ICMP API page. There is also a ping example program on MarkG's Win32 page; the following console mode program was distilled from his GUI version. By the way, you might be wondering why the program has to load the ICMP.DLL manually and get the procedure addresses manually. I'm not sure of the reasons, but I spent an hour trying to get import libraries and DEF files to work. I can only suggest that some higher power is dead set against you linking this way. :-) dllping.cpp// Borland C++ 5.0: bcc32.cpp ping.cpp // Visual C++ 5.0: cl ping.cpp wsock32.lib #include <iostream.h> #include <winsock.h> #include <windowsx.h> #include "icmpdefs.h" int doit(int argc, char* argv[]) { // Check for correct command-line args if (argc < 2) { cerr << "usage: ping <host>" << endl; return 1; } // Load the ICMP.DLL HINSTANCE hIcmp = LoadLibrary("ICMP.DLL"); if (hIcmp == 0) { cerr << "Unable to locate ICMP.DLL!" << endl; return 2; } // Look up an IP address for the given host name struct hostent* phe; if ((phe = gethostbyname(argv[1])) == 0) { cerr << "Could not find IP address for " << argv[1] << endl; return 3; } // Get handles to the functions inside ICMP.DLL that we'll need typedef HANDLE (WINAPI* pfnHV)(VOID); typedef BOOL (WINAPI* pfnBH)(HANDLE); typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD); // evil, no? pfnHV pIcmpCreateFile; pfnBH pIcmpCloseHandle; pfnDHDPWPipPDD pIcmpSendEcho; pIcmpCreateFile = (pfnHV)GetProcAddress(hIcmp, "IcmpCreateFile"); pIcmpCloseHandle = (pfnBH)GetProcAddress(hIcmp, "IcmpCloseHandle"); pIcmpSendEcho = (pfnDHDPWPipPDD)GetProcAddress(hIcmp, "IcmpSendEcho"); if ((pIcmpCreateFile == 0) || (pIcmpCloseHandle == 0) || (pIcmpSendEcho == 0)) { cerr << "Failed to get proc addr for function." << endl; return 4; } // Open the ping service HANDLE hIP = pIcmpCreateFile(); if (hIP == INVALID_HANDLE_VALUE) { cerr << "Unable to open ping service." << endl; return 5; } // Build ping packet char acPingBuffer[64]; memset(acPingBuffer, '\xAA', sizeof(acPingBuffer)); PIP_ECHO_REPLY pIpe = (PIP_ECHO_REPLY)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer)); if (pIpe == 0) { cerr << "Failed to allocate global ping packet buffer." << endl; return 6; } pIpe->Data = acPingBuffer; pIpe->DataSize = sizeof(acPingBuffer); // Send the ping packet DWORD dwStatus = pIcmpSendEcho(hIP, *((DWORD*)phe->h_addr_list[0]), acPingBuffer, sizeof(acPingBuffer), NULL, pIpe, sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer), 5000); if (dwStatus != 0) { cout << "Addr: " << int(LOBYTE(LOWORD(pIpe->Address))) << "." << int(HIBYTE(LOWORD(pIpe->Address))) << "." << int(LOBYTE(HIWORD(pIpe->Address))) << "." << int(HIBYTE(HIWORD(pIpe->Address))) << ", " << "RTT: " << int(pIpe->RoundTripTime) << "ms, " << "TTL: " << int(pIpe->Options.Ttl) << endl; } else { cerr << "Error obtaining info from ping packet." << endl; } // Shut down... GlobalFree(pIpe); FreeLibrary(hIcmp); return 0; } int main(int argc, char* argv[]) { WSAData wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { return 255; } int retval = doit(argc, argv); WSACleanup(); return retval; } icmpdefs.h// Structures required to use functions in ICMP.DLL typedef struct { unsigned char Ttl; // Time To Live unsigned char Tos; // Type Of Service unsigned char Flags; // IP header flags unsigned char OptionsSize; // Size in bytes of options data unsigned char *OptionsData; // Pointer to options data } IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION; typedef struct { DWORD Address; // Replying address unsigned long Status; // Reply status unsigned long RoundTripTime; // RTT in milliseconds unsigned short DataSize; // Echo data size unsigned short Reserved; // Reserved for system use void *Data; // Pointer to the echo data IP_OPTION_INFORMATION Options; // Reply options } IP_ECHO_REPLY, * PIP_ECHO_REPLY; Back to the Advanced Issues page... |
<< Basic Blocking Server | Ping: Raw Sockets Method >> |
Last modified on 29 April 2000 at 15:52 UTC-7 | Please send corrections to tangent@cyberport.com. |
< Go to the main FAQ page |
|
<<< Go to my Home Page |