一个ICMP单元
unit ICMPUtils; interface {$IFDEF VER80}
{
This source file is *NOT* compatible with Delphi 1 because it uses
Win 32 features.
}
{$ENDIF} uses
Windows, SysUtils, Classes, WinSock; const
IcmpVersion = ;
IcmpDLL = 'icmp.dll'; {IP status codes returned to transports and user IOCTLs.}
IP_SUCCESS = ;
IP_STATUS_BASE = ;
IP_BUF_TOO_SMALL = (IP_STATUS_BASE + );
IP_DEST_NET_UNREACHABLE = (IP_STATUS_BASE + );
IP_DEST_HOST_UNREACHABLE = (IP_STATUS_BASE + );
IP_DEST_PROT_UNREACHABLE = (IP_STATUS_BASE + );
IP_DEST_PORT_UNREACHABLE = (IP_STATUS_BASE + );
IP_NO_RESOURCES = (IP_STATUS_BASE + );
IP_BAD_OPTION = (IP_STATUS_BASE + );
IP_HW_ERROR = (IP_STATUS_BASE + );
IP_PACKET_TOO_BIG = (IP_STATUS_BASE + );
IP_REQ_TIMED_OUT = (IP_STATUS_BASE + );
IP_BAD_REQ = (IP_STATUS_BASE + );
IP_BAD_ROUTE = (IP_STATUS_BASE + );
IP_TTL_EXPIRED_TRANSIT = (IP_STATUS_BASE + );
IP_TTL_EXPIRED_REASSEM = (IP_STATUS_BASE + );
IP_PARAM_PROBLEM = (IP_STATUS_BASE + );
IP_SOURCE_QUENCH = (IP_STATUS_BASE + );
IP_OPTION_TOO_BIG = (IP_STATUS_BASE + );
IP_BAD_DESTINATION = (IP_STATUS_BASE + ); {status codes passed up on status indications.}
IP_ADDR_DELETED = (IP_STATUS_BASE + );
IP_SPEC_MTU_CHANGE = (IP_STATUS_BASE + );
IP_MTU_CHANGE = (IP_STATUS_BASE + ); IP_GENERAL_FAILURE = (IP_STATUS_BASE + ); MAX_IP_STATUS = IP_GENERAL_FAILURE; IP_PENDING = (IP_STATUS_BASE + ); {IP header flags}
IP_FLAG_DF = $; {Don't fragment this packet.} {IP Option Types}
IP_OPT_EOL = $; {End of list option}
IP_OPT_NOP = $; {No operation}
IP_OPT_SECURITY = $; {Security option.}
IP_OPT_LSRR = $; {Loose source route.}
IP_OPT_SSRR = $; {Strict source route.}
IP_OPT_RR = $; {Record route.}
IP_OPT_TS = $; {Timestamp.}
IP_OPT_SID = $; {Stream ID (obsolete)}
MAX_OPT_SIZE = $; type
{IP types}
TIPAddr = DWORD; {An IP address.}
TIPMask = DWORD; {An IP subnet mask.}
TIPStatus = DWORD; {Status code returned from IP APIs.} PIPOptionInformation = ^TIPOptionInformation;
TIPOptionInformation = packed record
TTL: Byte; {Time To Live (used for traceroute)}
TOS: Byte; {Type Of Service (usually 0)}
Flags: Byte; {IP header flags (usually 0)}
OptionsSize: Byte; {Size of options data (usually 0, max 40)}
OptionsData: PChar; {Options data buffer}
end; PIcmpEchoReply = ^TIcmpEchoReply;
TIcmpEchoReply = packed record
Address: TIPAddr; {Replying address}
Status: DWord; {IP status value}
RTT: DWord; {Round Trip Time in milliseconds}
DataSize: Word; {Reply data size}
Reserved: Word; {Reserved}
Data: Pointer; {Pointer to reply data buffer}
Options: TIPOptionInformation; {Reply options}
end; {
IcmpCreateFile:
Opens a handle on which ICMP Echo Requests can be issued.
Arguments:
None.
Return Value:
An open file handle or INVALID_HANDLE_VALUE. Extended error information
is available by calling GetLastError().
}
TIcmpCreateFile = function: THandle; stdcall; {
IcmpCloseHandle:
Closes a handle opened by ICMPOpenFile.
Arguments:
IcmpHandle - The handle to close.
Return Value:
TRUE if the handle was closed successfully, otherwise FALSE. Extended
error information is available by calling GetLastError().
}
TIcmpCloseHandle = function(IcmpHandle: THandle): Boolean; stdcall; {
IcmpSendEcho:
Sends an ICMP Echo request and returns one or more replies. The
call returns when the timeout has expired or the reply buffer
is filled.
Arguments:
IcmpHandle - An open handle returned by ICMPCreateFile.
DestinationAddress - The destination of the echo request.
RequestData - A buffer containing the data to send in the
request.
RequestSize - The number of bytes in the request data buffer.
RequestOptions - Pointer to the IP header options for the request.
May be NULL.
ReplyBuffer - A buffer to hold any replies to the request.
On return, the buffer will contain an array of
ICMP_ECHO_REPLY structures followed by options
and data. The buffer should be large enough to
hold at least one ICMP_ECHO_REPLY structure
and 8 bytes of data - this is the size of
an ICMP error message.
ReplySize - The size in bytes of the reply buffer.
Timeout - The time in milliseconds to wait for replies.
Return Value:
Returns the number of replies received and stored in ReplyBuffer. If
the return value is zero, extended error information is available
via GetLastError().
}
TIcmpSendEcho = function(IcmpHandle: THandle;
DestinationAddress: TIPAddr;
RequestData: Pointer;
RequestSize: Word;
RequestOptions: PIPOptionInformation;
ReplyBuffer: Pointer;
ReplySize: DWord;
Timeout: DWord
): DWord; stdcall; {Event handler type declaration for TICMP.OnDisplay event.}
TICMPDisplay = procedure(Sender: TObject; Msg : String) of object;
TICMPReply = procedure(Sender: TObject; Error : Integer) of object; {The object wich encapsulate the ICMP.DLL}
TICMP = class(TObject)
private
hICMPdll : HModule; {Handle for ICMP.DLL}
IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;
hICMP : THandle; {Handle for the ICMP Calls}
FReply : TIcmpEchoReply; {ICMP Echo reply buffer}
FAddress : String; {Address given}
FHostName : String; {Dotted IP of host (output)}
FHostIP : String; {Name of host (Output)}
FIPAddress : TIPAddr; {Address of host to contact}
FSize : Integer; {Packet size (default to 56)}
FTimeOut : Integer; {Timeout (default to 4000mS)}
FTTL : Integer; {Time To Live (for send)}
FOnDisplay : TICMPDisplay; {Event handler to display}
FOnEchoRequest : TNotifyEvent;
FOnEchoReply : TICMPReply;
FLastError : DWORD; {After sending ICMP packet}
FAddrResolved : Boolean;
procedure ResolveAddr;
public
constructor Create; virtual;
destructor Destroy; override;
function Ping : Integer;
procedure SetAddress(Value : String);
function GetErrorString : String; property Address : String read FAddress write SetAddress;
property Size : Integer read FSize write FSize;
property Timeout : Integer read FTimeout write FTimeout;
property Reply : TIcmpEchoReply read FReply;
property TTL : Integer read FTTL write FTTL;
property ErrorCode : Cardinal read FLastError;
property ErrorString : String read GetErrorString;
property HostName : String read FHostName;
property HostIP : String read FHostIP;
property OnDisplay : TICMPDisplay read FOnDisplay write FOnDisplay;
property OnEchoRequest : TNotifyEvent read FOnEchoRequest
write FOnEchoRequest;
property OnEchoReply : TICMPReply read FOnEchoReply
write FOnEchoReply;
end; TICMPException = class(Exception); implementation {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
constructor TICMP.Create;
var
WSAData: TWSAData;
begin
hICMP := INVALID_HANDLE_VALUE;
FSize := ;
FTTL := ;
FTimeOut := ; {initialise winsock}
if WSAStartup($, WSAData) <> then
raise TICMPException.Create('Error initialising Winsock'); {register the icmp.dll stuff}
hICMPdll := LoadLibrary(icmpDLL);
if hICMPdll = then
raise TICMPException.Create('Unable to register ' + icmpDLL); @ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho'); if (@ICMPCreateFile = nil)
or (@IcmpCloseHandle = nil)
or (@IcmpSendEcho = nil) then
raise TICMPException.Create('Error loading dll functions'); hICMP := IcmpCreateFile;
if hICMP = INVALID_HANDLE_VALUE then
raise TICMPException.Create('Unable to get ping handle');
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
destructor TICMP.Destroy;
begin
if hICMP <> INVALID_HANDLE_VALUE then
IcmpCloseHandle(hICMP);
if hICMPdll <> then
FreeLibrary(hICMPdll);
WSACleanup;
inherited Destroy;
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function MinInteger(X, Y: Integer): Integer;
begin
if X >= Y then
Result := Y
else
Result := X;
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TICMP.ResolveAddr;
var
Phe: PHostEnt; {HostEntry buffer for name lookup}
begin
{Convert host address to IP address}
FIPAddress := inet_addr(PAnsiChar(AnsiString(FAddress)));
if FIPAddress <> INADDR_NONE then
{Was a numeric dotted address let it in this format}
FHostName := FAddress
else begin
{Not a numeric dotted address, try to resolve by name}
Phe := GetHostByName(PAnsiChar(AnsiString(FAddress)));
if Phe = nil then
begin
FLastError := GetLastError;
if Assigned(FOnDisplay) then
FOnDisplay(Self, 'Unable to resolve ' + FAddress);
Exit;
end; FIPAddress := longint(plongint(Phe^.h_addr_list^)^);
FHostName := Phe^.h_name;
end; FHostIP := StrPas(inet_ntoa(TInAddr(FIPAddress)));
FAddrResolved := TRUE;
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TICMP.SetAddress(Value : String);
begin
{Only change if needed (could take a long time)}
if FAddress = Value then
Exit;
FAddress := Value;
FAddrResolved := FALSE;
// ResolveAddr;
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TICMP.GetErrorString : String;
begin
case FLastError of
IP_SUCCESS: Result := 'No error';
IP_BUF_TOO_SMALL: Result := 'Buffer too small';
IP_DEST_NET_UNREACHABLE: Result := 'Destination network unreachable';
IP_DEST_HOST_UNREACHABLE: Result := 'Destination host unreachable';
IP_DEST_PROT_UNREACHABLE: Result := 'Destination protocol unreachable';
IP_DEST_PORT_UNREACHABLE: Result := 'Destination port unreachable';
IP_NO_RESOURCES: Result := 'No resources';
IP_BAD_OPTION: Result := 'Bad option';
IP_HW_ERROR: Result := 'Hardware error';
IP_PACKET_TOO_BIG: Result := 'Packet too big';
IP_REQ_TIMED_OUT: Result := 'Request timed out';
IP_BAD_REQ: Result := 'Bad request';
IP_BAD_ROUTE: Result := 'Bad route';
IP_TTL_EXPIRED_TRANSIT: Result := 'TTL expired in transit';
IP_TTL_EXPIRED_REASSEM: Result := 'TTL expired in reassembly';
IP_PARAM_PROBLEM: Result := 'Parameter problem';
IP_SOURCE_QUENCH: Result := 'Source quench';
IP_OPTION_TOO_BIG: Result := 'Option too big';
IP_BAD_DESTINATION: Result := 'Bad Destination';
IP_ADDR_DELETED: Result := 'Address deleted';
IP_SPEC_MTU_CHANGE: Result := 'Spec MTU change';
IP_MTU_CHANGE: Result := 'MTU change';
IP_GENERAL_FAILURE: Result := 'General failure';
IP_PENDING: Result := 'Pending';
else
Result := 'ICMP error #' + IntToStr(FLastError);
end;
end; {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TICMP.Ping : Integer;
var
BufferSize: Integer;
pReqData, pData: Pointer;
pIPE: PIcmpEchoReply; {ICMP Echo reply buffer}
IPOpt: TIPOptionInformation; {IP Options for packet to send}
Msg: String;
begin
Result := ;
FLastError := ; if not FAddrResolved then
ResolveAddr; if FIPAddress = INADDR_NONE then
begin
FLastError := IP_BAD_DESTINATION;
if Assigned(FOnDisplay) then
FOnDisplay(Self, 'Invalid host address');
Exit;
end; {Allocate space for data buffer space}
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pReqData, FSize);
GetMem(pData, FSize);
GetMem(pIPE, BufferSize); try
{Fill data buffer with some data bytes}
FillChar(pReqData^, FSize, $);
Msg := 'Pinging from Delphi code written by F. Piette';
Move(Msg[], pReqData^, MinInteger(FSize, Length(Msg))); pIPE^.Data := pData;
FillChar(pIPE^, SizeOf(pIPE^), ); if Assigned(FOnEchoRequest) then
FOnEchoRequest(Self); FillChar(IPOpt, SizeOf(IPOpt), );
IPOpt.TTL := FTTL;
Result := IcmpSendEcho(hICMP, FIPAddress, pReqData, FSize,
@IPOpt, pIPE, BufferSize, FTimeOut);
FLastError := GetLastError;
FReply := pIPE^; if Assigned(FOnEchoReply) then
FOnEchoReply(Self, Result);
finally
{Free those buffers}
FreeMem(pIPE);
FreeMem(pData);
FreeMem(pReqData);
end;
end; end.
一个ICMP单元的更多相关文章
- 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面两篇文章已 ...
- PING的原理以及ICMP协议
主要内容: 1.ping的原理以及工作过程 2.ICMP协议 3.ICMP的应用:ping,traceroute 1.ping的原理以及工作过程 ping的原理 ping 程序是用来探测主机到主机 ...
- UNIX网络编程——利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit) ...
- 利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit).如果IP ...
- ping 原理与ICMP协议[转]
原文:http://blog.csdn.net/inject2006/article/details/2139149 ping 的原理 ping 程序是用来探测主机到主机之间是否可通信,如果不 ...
- Firewalld防火墙与ICMP攻击
原文地址:http://www.excelib.com/article/293/show 提到ICMP大家应该都很熟悉,可能有人会说:不就是ping吗?但是说到ICMP攻击以及相关防御措施可能就有的人 ...
- ping 原理与ICMP协议
ping 的原理 ping 程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接.ping 使用的是ICMP协议,它发送icmp回送请求消息给目的主机 ...
- 一个完整的http请求响应过程
一. HTTP请求和响应步骤 图片来自:理解Http请求与响应 以上完整表示了HTTP请求和响应的7个步骤,下面从TCP/IP协议模型的角度来理解HTTP请求和响应如何传递的. 二.TCP/IP协 ...
- ICMP&&PING
ICMP 1.定位:互联网控制报文协议(Internet Control Message Protocol),是TCP/IP协议族的一个子协议,位于网络层.它被IP用于提供许多不同的服务.ICMP是一 ...
随机推荐
- Codeforces Round #332 (Div. 2)
水 A - Patrick and Shopping #include <bits/stdc++.h> using namespace std; int main(void) { int ...
- CentOS 命令【备忘】
1.查看物理cpu个数 grep 'physical id' /proc/cpuinfo | sort -u | wc -l 2.查看核心数量 grep 'core id' /proc/cpuinfo ...
- Codeforces Round #228 (Div. 2) B. Fox and Cross
#include <iostream> #include <string> #include <vector> #include <algorithm> ...
- 隐藏Jquery dialog 按钮
$(".ui-dialog-buttonpane button").hide(); //隐藏dialog中所有button $(".ui-dialog-buttonpan ...
- 通过hibernate session.connection()获得数据库连接时,导致的查询缓慢甚至假死机问题
在使用hibernate的应用中,如果需要直接使用Java.sql.Connection,一般我们是通过hibernate的session.connection()获得的,然后session.clos ...
- 二 、打开地图《苹果iOS实例编程入门教程》
该app为应用的功能为给你的iPhone打开google地图有效地址连接 现版本 SDK 8.4 Xcode 运行Xcode 选择 Create a new Xcode project ->Si ...
- petapoco定制,比较SQL事务,存储过程,分布式事务(MSDTC)的区别和场景
使用分布式事务时 就锁死了,而且是只锁编辑的行 使用.netSQL事务一定要执行了一个CUD的SQL才会锁死,而且也是锁行,但是也锁读的行 .netSQL事务要在这里才锁死 结论,对于产品要求细粒度的 ...
- 小Experience__要懂得努力
来到郎沃这么久了,在这里学到了很多,对于一个从未摸过电脑的农村孩子来说,我为自己感到自豪,我不自卑,also.也不会骄傲. 我很清楚的记得爸妈给我说的什么,for myself,for parents ...
- Setting start page of Windows Phone dynamically through code
Essentially this one line of code will set the start page of the application. var navTo = new Uri(&q ...
- CSS3+HTML5实现块阴影与文字阴影
CSS 3 + HTML 5 是未来的 Web,它们都还没有正式到来,虽然不少浏览器已经开始对它们提供部分支持.本教程分5节介绍了 5 个 CSS3 技巧,可以帮你实现未来的 Web,不过,这些技术不 ...