一个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是一 ...
随机推荐
- iOS socket TCP UDP
TCP: 服务器: #import <Foundation/Foundation.h> #include <sys/socket.h> #include <netinet ...
- ie不支持getElementsByName的解决办法
在chrome下getElementsByName运行正常,可在IETester7~11下都不支持 w3c规范中getElementsByName是按着name属性进行检索的,而MS的IE却是按着i ...
- Mac OS Storm+Kafka+Zookeeper配置
先补充一个前两天mac配置的文档. 首先确定由jdk scala环境 JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/Cu ...
- POJ 1681 (开关问题+高斯消元法)
题目链接: http://poj.org/problem?id=1681 题目大意:一堆格子,或白或黄.每次可以把一个改变一个格子颜色,其上下左右四个格子颜色也改变.问最后使格子全部变黄,最少需要改变 ...
- NOIp 2013 #3 转圈游戏 Label:模拟
题目描述 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从0 到 n-1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此 ...
- 【BZOJ】2456: mode
http://www.lydsy.com/JudgeOnline/problem.php?id=2456 题意:给一个$n<=500000$的数列,求出现次数超过$\lfloor \frac{n ...
- Linq to Entities下存储过程的使用方法
1.首先在数据库中创建好存储过程. 2.在实体模型中添加存储过程的映射.此时根据映射过来的查询结果有两种途径:第一种可以选择添加选择的存储过程的函数到实体模型中.这样的话,查询的结果将会是xxx_re ...
- BZOJ4176: Lucas的数论
Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其 ...
- Maven3路程(一)用Maven创建第一个web项目(1)
一.创建项目 1.Eclipse中用Maven创建项目 上图中Next 2.继续Next 3.选maven-archetype-webapp后,next 4.填写相应的信息,Packaged是默认创建 ...
- javascript模块化应用
这是一篇关于js模块化历程的长长的流水账,记录js模块化思想的诞生与变迁,展望ES6模块化标准的未来.经历过这段历史的人或许会感到沧桑,没经历过的人也应该知道这段历史. 无模块时代 在ajax还未提出 ...