www.pudn.com > indyprelim.zip > IdRawHeaders.pas
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.3 2/8/2004 12:59:40 PM JPMugaas
Start on DotNET port.
Rev 1.2 10/16/2003 11:05:38 PM SPerry
Reorganization
Rev 1.1 2003.09.30 1:23:02 PM czhower
Stack split for DotNet
Rev 1.0 11/13/2002 08:45:44 AM JPMugaas
}
unit IdRawHeaders;
interface
{$I IdCompilerDefines.inc}
{$IFNDEF DOTNET}
uses
// IdStackBSDBase;
{$ELSE}
uses
System.Net,
{$ENDIF}
IdGlobal,
IdStruct;
// TODO: research subtypes of ICMP header
type
//RFC 3542 definitions
//IPv6 Extension Headers
uint32_t = LongWord;
uint16_t = word;
uint8_t = byte;
// types redeclared to avoid dependencies on stack declarations
TIdSunB = class(TIdStruct)
protected
Fs_b1,
Fs_b2,
Fs_b3,
Fs_b4: byte;
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property s_b1 : byte read Fs_b1 write Fs_b1;
property s_b2 : byte read Fs_b2 write Fs_b2;
property s_b3 : byte read Fs_b3 write Fs_b3;
property s_b4 : byte read Fs_b4 write Fs_b4;
end;
TIdSunW = class(TIdStruct)
protected
Fs_w1, Fs_w2: word;
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property s_w1 : word read Fs_w1 write FS_w1;
property s_w2 : word read Fs_w2 write FS_w2;
end;
TIdInAddr = class (TIdLongWord)
public
procedure CopyFrom(const ASource : TIdInAddr);
end;
{ PIdInAddr = ^TIdInAddr;
TIdInAddr = record
case integer of
0: (S_un_b: TIdSunB);
1: (S_un_w: TIdSunW);
2: (S_addr: longword);
end; }
TIdNetTime = longword; // network byte order
const
//header sizes----------------------------------------------------------------//
Id_ARP_HSIZE = $1C; // ARP header: 28 bytes
Id_DNS_HSIZE = $0C; // DNS header base: 12 bytes
Id_ETH_HSIZE = $0E; // Etherner header: 14 bytes
Id_ICMP_HSIZE = $04; // ICMP header base: 4 bytes
Id_ICMP_ECHO_HSIZE = $08; // ICMP_ECHO header: 8 bytes
Id_ICMP6_ECHO_HSIZE = $08; // ICMPv6_ECHO header: 8 bytes icmp echo header len excluding time */
Id_ICMP_MASK_HSIZE = $0C; // ICMP_MASK header: 12 bytes
Id_ICMP_UNREACH_HSIZE = $08; // ICMP_UNREACH header: 8 bytes
Id_ICMP_TIMEXCEED_HSIZE = $08; // ICMP_TIMXCEED header: 8 bytes
Id_ICMP_REDIRECT_HSIZE = $08; // ICMP_REDIRECT header: 8 bytes
Id_ICMP_TS_HSIZE = $14; // ICMP_TIMESTAMP header: 20 bytes
Id_IGMP_HSIZE = $08; // IGMP header: 8 bytes
Id_IP_HSIZE = $14; // IP header: 20 bytes
Id_IPv6_HSIZE = $28; // IPv6 header
Id_RIP_HSIZE = $18; // RIP header base: 24 bytes
Id_TCP_HSIZE = $14; // TCP header: 20 bytes
Id_UDP_HSIZE = $08; // UDP header: 8 bytes
//fragmentation flags---------------------------------------------------------//
Id_IP_RF = $8000; // reserved fragment flag
Id_IP_DF = $4000; // dont fragment flag
Id_IP_MF = $2000; // more fragments flag
Id_IP_OFFMASK = $1FFF; // mask for fragmenting bits
//TCP control flags-----------------------------------------------------------//
Id_TCP_FIN = $01;
Id_TCP_SYN = $02;
Id_TCP_RST = $04;
Id_TCP_PUSH = $08;
Id_TCP_ACK = $10;
Id_TCP_URG = $20;
//ICMP types------------------------------------------------------------------//
Id_ICMP_ECHOREPLY = 0;
Id_ICMP_UNREACH = 3;
Id_ICMP_SOURCEQUENCH = 4;
Id_ICMP_REDIRECT = 5;
Id_ICMP_ECHO = 8;
Id_ICMP_ROUTERADVERT = 9;
Id_ICMP_ROUTERSOLICIT = 10;
Id_ICMP_TIMXCEED = 11;
Id_ICMP_PARAMPROB = 12;
Id_ICMP_TSTAMP = 13;
Id_ICMP_TSTAMPREPLY = 14;
Id_ICMP_IREQ = 15;
Id_ICMP_IREQREPLY = 16;
Id_ICMP_MASKREQ = 17;
Id_ICMP_MASKREPLY = 18;
Id_ICMP_TRACEROUTE = 30;//RFC1393 Traceroute
Id_ICMP_DATAGRAM_CONV = 31;//RFC1475
Id_ICMP_MOB_HOST_REDIR = 32; // Mobile Host Redirect
Id_ICMP_IPv6_WHERE_ARE_YOU = 33;
Id_ICMP_IPv6_I_AM_HERE = 34;
Id_ICMP_MOB_REG_REQ = 35;
Id_ICMP_MOB_REG_REPLY = 36;
Id_ICMP_SKIP = 39;
Id_ICMP_PHOTURIS = 40; //Photuris [RFC2521]
//ICMP codes------------------------------------------------------------------//
Id_ICMP_UNREACH_NET = 0;
Id_ICMP_UNREACH_HOST = 1;
Id_ICMP_UNREACH_PROTOCOL = 2;
Id_ICMP_UNREACH_PORT = 3;
Id_ICMP_UNREACH_NEEDFRAG = 4;
Id_ICMP_UNREACH_SRCFAIL = 5;
Id_ICMP_UNREACH_NET_UNKNOWN = 6;
Id_ICMP_UNREACH_HOST_UNKNOWN = 7;
Id_ICMP_UNREACH_ISOLATED = 8;
Id_ICMP_UNREACH_NET_PROHIB = 9;
Id_ICMP_UNREACH_HOST_PROHIB = 10;
Id_ICMP_UNREACH_TOSNET = 11;
Id_ICMP_UNREACH_TOSHOST = 12;
Id_ICMP_UNREACH_FILTER_PROHIB = 13;
Id_ICMP_UNREACH_HOST_PRECEDENCE = 14;
Id_ICMP_UNREACH_PRECEDENCE_CUTOFF = 15;
Id_ICMP_REDIRECT_NET = 0;
Id_ICMP_REDIRECT_HOST = 1;
Id_ICMP_REDIRECT_TOSNET = 2;
Id_ICMP_REDIRECT_TOSHOST = 3;
Id_ICMP_TIMXCEED_INTRANS = 0;
Id_ICMP_TIMXCEED_REASS = 1;
Id_ICMP_PARAMPROB_OPTABSENT = 1;
// RFC 1393
Id_ICMP_TRACEROUTE_PACKET_FORWARDED = 0;
Id_ICMP_TRACEROUTE_NO_ROUTE = 1;
Id_ICMP_BAD_SPI = 0; //security parameter error 40
Id_ICMP_AUTH_FAILED = 1;
Id_ICMP_DECOMPRESS_FAILED = 2;
Id_ICMP_DECRYPTION_FAILED = 3;
Id_ICMP_NEED_AUTHENTICATION = 4;
Id_ICMP_NEED_AUTHORIZATION = 5;
//RFC 1475 error codes
// The type for Conversion Failed is 31
Id_ICMP_CONV_UNSPEC = 0;
Id_ICMP_CONV_DONTCONV_OPTION = 1;
Id_ICMP_CONV_UNKNOWN_MAN_OPTION = 2;
Id_ICMP_CONV_UNKNWON_UNSEP_OPTION = 3;
Id_ICMP_CONV_UNSEP_TRANSPORT = 4;
Id_ICMP_CONV_OVERALL_LENGTH_EXCEEDED = 5;
Id_ICMP_CONV_IP_HEADER_LEN_EXCEEDED = 6;
Id_ICMP_CONV_TRANS_PROT_255 = 7; //transport protocol > 255
Id_ICMP_CONV_PORT_OUT_OF_RANGE = 8;
Id_ICMP_CONV_TRANS_HEADER_LEN_EXCEEDED = 9;
Id_ICMP_CONV_32BIT_ROLLOVER_AND_ACK = 10; //32 Bit Rollover missing and ACK set
Id_ICMP_CONV_UNKNOWN_MAN_TRANS_OPTION = 11;
ICMP_MIN = 8;
//ICMPv6 types----------------------------------------------------------------//
ICMP6_DST_UNREACH = 1;
ICMP6_PACKET_TOO_BIG = 2;
ICMP6_TIME_EXCEEDED = 3;
ICMP6_PARAM_PROB = 4;
//Informational Messages
ICMP6_INFOMSG_MASK =$80; //* all informational messages */
ICMP6_ECHO_REQUEST =128;
ICMP6_ECHO_REPLY =129;
ICMP6_MEMBERSHIP_QUERY = 130;
ICMP6_MEMBERSHIP_REPORT = 131;
ICMP6_MEMBERSHIP_REDUCTION = 132;
//ICMPv6 codes----------------------------------------------------------------//
ICMP6_DST_UNREACH_NOROUTE = 0; //* no route to destination */
ICMP6_DST_UNREACH_ADMIN = 1; //* communication with */
//* destination */
//* administratively */
//* prohibited */
ICMP6_DST_UNREACH_NOTNEIGHBOR = 2; //* not a neighbor */
ICMP6_DST_UNREACH_ADDR = 3; //* address unreachable */
ICMP6_DST_UNREACH_NOPORT = 4; //* bad port */
ICMP6_DST_UNREACH_SOURCE_FILTERING = 5; //source address failed ingress/egress policy
ICMP6_DST_UNREACH_REJCT_DST = 6; //reject route to destination
ICMP6_TIME_EXCEED_TRANSIT = 0; //* Hop Limit == 0 in transit */
ICMP6_TIME_EXCEED_REASSEMBLY = 1; //* Reassembly time out */
ICMP6_PARAMPROB_HEADER = 0; //* erroneous header field */
ICMP6_PARAMPROB_NEXTHEADER = 1; //* unrecognized Next Header */
ICMP6_PARAMPROB_OPTION = 2; //* unrecognized IPv6 option */
//ICMPv6 Neighbor Discovery Definitions
ND_ROUTER_SOLICIT = 133;
ND_ROUTER_ADVERT = 134;
ND_NEIGHBOR_SOLICIT = 135;
ND_NEIGHBOR_ADVERT = 136;
ND_REDIRECT = 137;
//IGMP types------------------------------------------------------------------//
Id_IGMP_MEMBERSHIP_QUERY = $11; // membership query
Id_IGMP_V1_MEMBERSHIP_REPORT = $12; // v1 membership report
Id_IGMP_V2_MEMBERSHIP_REPORT = $16; // v2 membership report
Id_IGMP_LEAVE_GROUP = $17; // leave-group message
//ethernet packet types-------------------------------------------------------//
Id_ETHERTYPE_PUP = $0200; // PUP protocol
Id_ETHERTYPE_IP = $0800; // IP protocol
Id_ETHERTYPE_ARP = $0806; // ARP protocol
Id_ETHERTYPE_REVARP = $8035; // reverse ARP protocol
Id_ETHERTYPE_VLAN = $8100; // IEEE 802.1Q VLAN tagging
Id_ETHERTYPE_LOOPBACK = $9000; // used to test interfaces
//hardware address formats----------------------------------------------------//
Id_ARPHRD_ETHER = 1; // ethernet hardware format
//ARP operation types---------------------------------------------------------//
Id_ARPOP_REQUEST = 1; // req to resolve address
Id_ARPOP_REPLY = 2; // resp to previous request
Id_ARPOP_REVREQUEST = 3; // req protocol address given hardware
Id_ARPOP_REVREPLY = 4; // resp giving protocol address
Id_ARPOP_INVREQUEST = 8; // req to identify peer
Id_ARPOP_INVREPLY = 9; // resp identifying peer
//RIP commands----------------------------------------------------------------//
Id_RIPCMD_REQUEST = 1; // want info
Id_RIPCMD_RESPONSE = 2; // responding to request
Id_RIPCMD_TRACEON = 3; // turn tracing on
Id_RIPCMD_TRACEOFF = 4; // turn it off
Id_RIPCMD_POLL = 5; // like request, but anyone answers
Id_RIPCMD_POLLENTRY = 6; // like poll, but for entire entry
Id_RIPCMD_MAX = 7;
//RIP versions----------------------------------------------------------------//
Id_RIPVER_0 = 0;
Id_RIPVER_1 = 1;
Id_RIPVER_2 = 2;
//----------------------------------------------------------------------------//
Id_MAX_IPOPTLEN = 40;
Id_IP_MAXPACKET = 65535;
Id_ETHER_ADDR_LEN = 6;
type
////////////////////////////////////////////////////////////////////////////////
//ICMP//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
TIdICMPEcho = class(TIdStruct)
protected
Fid: word; // identifier to match requests with replies
Fseq: word; // sequence number to match requests with replies
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property id: word read Fid write FId; // identifier to match requests with replies
property seq: word read Fseq write FSeq; // sequence number to match requests with replies
end;
TIdICMPFrag = class(TIdStruct)
protected
Fpad: word;
Fmtu: word;
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property pad: word read Fpad write Fpad;
property mtu: word read Fmtu write Fmtu;
end;
TIdICMPTs = class(TIdStruct)
protected
Fotime: TIdNetTime; // time message was sent, to calc roundtrip time
Frtime: TIdNetTime;
Fttime: TIdNetTime;
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property otime: TIdNetTime read Fotime write Fotime; // time message was sent, to calc roundtrip time
property rtime: TIdNetTime read Frtime write Frtime;
property ttime: TIdNetTime read Fttime write Fttime;
end;
{ packet header }
TIdicmp_hun = class(TIdUnion)
protected
function Getecho_id: word;
function Getecho_seq: word;
function Getfrag_mtu: word;
function Getfrag_pad: word;
function Getgateway_s_b1: Byte;
function Getgateway_s_b2: Byte;
function Getgateway_s_b3: Byte;
function Getgateway_s_b4: Byte;
function Getgateway_s_l: LongWord;
function Getgateway_s_w1: word;
function Getgateway_s_w2: word;
procedure Setecho_id(const Value: word);
procedure Setecho_seq(const Value: word);
procedure Setfrag_mtu(const Value: word);
procedure Setfrag_pad(const Value: word);
procedure Setgateway_s_b1(const Value: Byte);
procedure Setgateway_s_b2(const Value: Byte);
procedure Setgateway_s_b3(const Value: Byte);
procedure Setgateway_s_b4(const Value: Byte);
procedure Setgateway_s_l(const Value: LongWord);
procedure Setgateway_s_w1(const Value: word);
procedure Setgateway_s_w2(const Value: word);
public
constructor create; override;
property echo_id: word read Getecho_id write Setecho_id; // identifier to match requests with replies
property echo_seq: word read Getecho_seq write Setecho_seq;
property gateway_s_b1 : Byte read Getgateway_s_b1 write Setgateway_s_b1;
property gateway_s_b2 : Byte read Getgateway_s_b2 write Setgateway_s_b2;
property gateway_s_b3 : Byte read Getgateway_s_b3 write Setgateway_s_b3;
property gateway_s_b4 : Byte read Getgateway_s_b4 write Setgateway_s_b4;
property gateway_s_w1 : word read Getgateway_s_w1 write Setgateway_s_w1;
property gateway_s_w2 : word read Getgateway_s_w2 write Setgateway_s_w2;
property gateway_s_l : LongWord read Getgateway_s_l write Setgateway_s_l;
property frag_pad: word read Getfrag_pad write Setfrag_pad;
property frag_mtu: word read Getfrag_mtu write Setfrag_mtu;
end;
TIdicmp_dun = class(TIdUnion)
protected
function Getdata: Byte;
function Getmask: LongWord;
procedure setdata(const Value: Byte);
procedure Setmask(const Value: LongWord);
function Getts_otime: TIdNetTime;
function Getts_rtime: TIdNetTime;
function Getts_ttime: TIdNetTime;
procedure Setts_otime(const Value: TIdNetTime);
procedure Setts_rtime(const Value: TIdNetTime);
procedure Setts_ttime(const Value: TIdNetTime);
public
constructor create; override;
property ts_otime: TIdNetTime read Getts_otime write Setts_otime; // time message was sent, to calc roundtrip time
property ts_rtime: TIdNetTime read Getts_rtime write Setts_rtime;
property ts_ttime: TIdNetTime read Getts_ttime write Setts_ttime;
property mask : LongWord read Getmask write Setmask;
property data : Byte read Getdata write setdata;
end;
TIdICMPHdr = class(TIdStruct)
protected
Ficmp_type: byte; // message type
Ficmp_code: byte; // error code
Ficmp_sum: word; // one's complement checksum {Do not Localize}
Ficmp_hun: TIdicmp_hun;
Ficmp_dun: TIdicmp_dun;
public
constructor create; override;
destructor Destroy; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property icmp_type: byte read Ficmp_type write Ficmp_type; // message type
property icmp_code: byte read Ficmp_code write Ficmp_code; // error code
property icmp_sum: word read Ficmp_sum write Ficmp_sum; // one's complement checksum {Do not Localize}
property icmp_hun: TIdicmp_hun read Ficmp_hun;
property icmp_dun: TIdicmp_dun read Ficmp_dun;
end;
//ICMPv6
TIdicmp6_un = class(TIdUnion)
protected
function Geticmp6_data16: uint16_t;
function Geticmp6_data8: uint8_t;
procedure Seticmp6_data16(const Value: uint16_t);
procedure Seticmp6_data8(const Value: uint8_t);
function Geticmp6_seq: uint16_t;
procedure Seticmp6_seq(const Value: uint16_t);
function Geticmp6_un_data16(Index: Integer): uint16_t;
function Geticmp6_un_data32: uint32_t;
function Geticmp6_un_data8(Index: Integer): uint8_t;
procedure Seticmp6_un_data16(Index: Integer; const Value: uint16_t);
procedure Seticmp6_un_data32(const Value: uint32_t);
procedure Seticmp6_un_data8(Index: Integer; const Value: uint8_t);
{ Ficmp6_un_data32 : uint32_t; //* type-specific field */
Ficmp6_un_data16 : array[0..1] of uint16_t; //* type-specific field */
icmp6_un_data8 : array[0..3] of uint8_t); //* type-specific field */
}
public
constructor create; override;
property icmp6_un_data32 : uint32_t read Geticmp6_un_data32 write Seticmp6_un_data32; //* type-specific field */
property icmp6_un_data16[Index:Integer] : uint16_t read Geticmp6_un_data16 write Seticmp6_un_data16; //array 0-1 * type-specific field */
property icmp6_un_data8[Index:Integer] : uint8_t read Geticmp6_un_data8 write Seticmp6_un_data8; //array[0-3] * type-specific field */
property icmp6_data32 : uint32_t read Geticmp6_un_data32 write Seticmp6_un_data32;
property icmp6_data16 : uint16_t read Geticmp6_data16 write Seticmp6_data16;
property icmp6_data8 : uint8_t read Geticmp6_data8 write Seticmp6_data8;
property icmp6_pptr : uint32_t read Geticmp6_un_data32 write Seticmp6_un_data32;
property icmp6_mtu : uint32_t read Geticmp6_un_data32 write Seticmp6_un_data32;
property icmp6_id : uint16_t read Geticmp6_data16 write Seticmp6_data16;
property icmp6_seq : uint16_t read Geticmp6_seq write Seticmp6_seq;
property icmp6_maxdelay : uint16_t read Geticmp6_data16 write Seticmp6_data16;
end;
TIdicmp6_hdr = class(TIdStruct)
protected
Ficmp6_type : uint8_t; //* type field */
FIcmp6_code : uint8_t; //* code field */
Ficmp6_cksum : uint16_t; //* checksum field */
Fdata : TIdicmp6_un;
public
constructor create; override;
destructor Destroy; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property icmp6_type : uint8_t read Ficmp6_type write Ficmp6_type; //* type field */
property icmp6_code : uint8_t read Ficmp6_code write Ficmp6_code; //* code field */
property icmp6_cksum : uint16_t read Ficmp6_cksum write Ficmp6_cksum; //* checksum field */
property data : TIdicmp6_un read Fdata;
{ case Integer of
1: (icmp6_un_data32 : uint32_t); //* type-specific field */
2: (icmp6_un_data16 : array[0..1] of uint16_t); //* type-specific field */
3: (icmp6_un_data8 : array[0..3] of uint8_t); //* type-specific field */
}
end;
////////////////////////////////////////////////////////////////////////////////
//IP////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ options struct }
TIdIPOptions = class(TIdStruct)
protected
Fipopt_list : TIdBytes;
public
{$IFDEF LINUX}
//ipopt_dst: TIdInAddr; // first-hop dst if source routed (Linux only)
{$ENDIF}
public
constructor create; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
function get_ipopt_list(Index: Integer): byte;
procedure set_ipopt_list(Index: Integer; const Value: byte);
//Delphi outputs warnings such as:
//[Hint] IdRawHeaders.pas(339): H2368 Visibility of property accessor method TIdIPOptions.get_ipopt_list should match property TIdIPOptions.ipopt_list
//[Hint] IdRawHeaders.pas(339): H2368 Visibility of property accessor method TIdIPOptions.set_ipopt_list should match property TIdIPOptions.ipopt_list
//for if these aren't public
property ipopt_list[Index : Integer] : byte read get_ipopt_list write set_ipopt_list; default; //options proper
end;
{ packet header }
TIdIPHdr = class(TIdStruct)
protected
Fip_verlen: byte; // 1st nibble version, 2nd nibble header length div 4 (little-endian)
Fip_tos: byte; // type of service
Fip_len: word; // total length
Fip_id: word; // identification
Fip_off: word; // 1st nibble flags, next 3 nibbles fragment offset (little-endian)
Fip_ttl: byte; // time to live
Fip_p: byte; // protocol
Fip_sum: word; // checksum
Fip_src: TIdInAddr; // source address
Fip_dst: TIdInAddr; // dest address
Fip_options: longword; // options + padding
public
constructor create; override;
destructor Destroy; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
procedure CopyFrom(const ASource : TIdIPHdr);
property ip_verlen: byte read Fip_verlen write Fip_verlen; // 1st nibble version, 2nd nibble header length div 4 (little-endian)
property ip_tos: byte read Fip_tos write Fip_tos; // type of service
property ip_len: word read Fip_len write Fip_len; // total length
property ip_id: word read Fip_id write Fip_id; // identification
property ip_off: word read Fip_off write Fip_off; // 1st nibble flags, next 3 nibbles fragment offset (little-endian)
property ip_ttl: byte read Fip_ttl write Fip_ttl; // time to live
property ip_p: byte read Fip_p write Fip_p; // protocol
property ip_sum: word read Fip_sum write Fip_sum; // checksum
property ip_src: TIdInAddr read Fip_src; // source address
property ip_dst: TIdInAddr read Fip_dst; // dest address
property ip_options: longword read Fip_options write Fip_options; // options + padding
end;
////////////////////////////////////////////////////////////////////////////////
//TCP///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ options structure }
TIdTCPOptions = class(TIdStruct)
protected
Ftcpopt_list: TIdBytes;
public
function gettcpopt_list(Index: Integer): Byte;
procedure settcpopt_list(Index: Integer; const Value: Byte);
public
constructor create; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property tcpopt_list[Index : Integer] : Byte read gettcpopt_list write settcpopt_list; default;
end;
{ packet header }
TIdTCPHdr = class(TIdStruct)
protected
Ftcp_sport: word; // source port
Ftcp_dport: word; // destination port
Ftcp_seq: longword; // sequence number
Ftcp_ack: longword; // acknowledgement number
Ftcp_x2off: byte; // data offset
Ftcp_flags: byte; // control flags
Ftcp_win: word; // window
Ftcp_sum: word; // checksum
Ftcp_urp: word; // urgent pointer
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property tcp_sport: word read Ftcp_sport write Ftcp_sport; // source port
property tcp_dport: word read Ftcp_dport write Ftcp_dport; // destination port
property tcp_seq: longword read Ftcp_seq write Ftcp_seq; // sequence number
property tcp_ack: longword read Ftcp_ack write Ftcp_ack; // acknowledgement number
property tcp_x2off: byte read Ftcp_x2off write Ftcp_x2off; // data offset
property tcp_flags: byte read Ftcp_flags write Ftcp_flags; // control flags
property tcp_win: word read Ftcp_win write Ftcp_win; // window
property tcp_sum: word read Ftcp_sum write Ftcp_sum; // checksum
property tcp_urp: word read Ftcp_urp write Ftcp_urp; // urgent pointer
end;
////////////////////////////////////////////////////////////////////////////////
//UDP///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ packet header }
TIdUDPHdr = class(TIdStruct)
protected
Fudp_sport: word; // source port
Fudp_dport: word; // destination port
Fudp_ulen: word; // length
Fudp_sum: word; // checksum
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property udp_sport: word read Fudp_sport write Fudp_sport; // source port
property udp_dport: word read Fudp_dport write Fudp_dport; // destination port
property udp_ulen: word read Fudp_ulen write Fudp_ulen; // length
property udp_sum: word read Fudp_sum write Fudp_sum; // checksum
end;
////////////////////////////////////////////////////////////////////////////////
//IGMP//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ packet header }
TIdIGMPHdr = class(TIdStruct)
protected
Figmp_type: byte;
Figmp_code: byte;
Figmp_sum: word;
Figmp_group: TIdInAddr;
public
constructor create; override;
destructor Destroy; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property igmp_type: byte read Figmp_type write Figmp_type;
property igmp_code: byte read Figmp_code write Figmp_code;
property igmp_sum: word read Figmp_sum write Figmp_sum;
property igmp_group: TIdInAddr read Figmp_group;
end;
////////////////////////////////////////////////////////////////////////////////
//ETHERNET//////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
TIdEtherAddr = class(TIdStruct)
protected
Fether_addr_octet: TIdBytes;
public
procedure SetData(const Value: TIdBytes);
public
constructor create; override;
procedure CopyFrom(const ASource : TIdEtherAddr);
function getether_addr_octet(Index: Integer): Byte;
procedure setether_addr_octet(Index: Integer; const Value: Byte);
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property ether_addr_octet[Index:Integer] : Byte read getether_addr_octet write setether_addr_octet;
property Data : TIdBytes read Fether_addr_octet write SetData;
end;
{ packet header }
TIdEthernetHdr = class(TIdStruct)
protected
Fether_dhost: TIdEtherAddr; // destination ethernet address
Fether_shost: TIdEtherAddr; // source ethernet address
Fether_type: word; // packet type ID
public
constructor create; override;
destructor Destroy; override;
procedure CopyFrom(const ASource : TIdEthernetHdr);
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property ether_dhost: TIdEtherAddr read Fether_dhost; // destination ethernet address
property ether_shost: TIdEtherAddr read Fether_shost; // source ethernet address
property ether_type: word read Fether_type write Fether_type; // packet type ID
end;
////////////////////////////////////////////////////////////////////////////////
//ARP///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ packet header }
TIdARPHdr = class(TIdStruct)
protected
Farp_hrd: word; // format of hardware address
Farp_pro: word; // format of protocol address
Farp_hln: byte; // length of hardware address
Farp_pln: byte; // length of protocol addres
Farp_op: word; // operation type
// following hardcoded for ethernet/IP
Farp_sha: TIdEtherAddr; // sender hardware address
Farp_spa: TIdInAddr; // sender protocol address
Farp_tha: TIdEtherAddr; // target hardware address
Farp_tpa: TIdInAddr; // target protocol address
public
constructor create; override;
destructor Destroy; override;
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property arp_hrd: word read Farp_hrd write Farp_hrd; // format of hardware address
property arp_pro: word read Farp_pro write Farp_pro; // format of protocol address
property arp_hln: byte read Farp_hln write Farp_hln; // length of hardware address
property arp_pln: byte read Farp_pln write Farp_pln; // length of protocol addres
property arp_op: word read Farp_op write Farp_op; // operation type
// following hardcoded for ethernet/IP
property arp_sha: TIdEtherAddr read Farp_sha; // sender hardware address
property arp_spa: TIdInAddr read Farp_spa; // sender protocol address
property arp_tha: TIdEtherAddr read Farp_tha; // target hardware address
property arp_tpa: TIdInAddr read Farp_tpa; // target protocol address
end;
////////////////////////////////////////////////////////////////////////////////
//DNS///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ header }
TIdDNSHdr = class(TIdStruct)
protected
Fdns_id: word; // DNS packet ID
Fdns_flags: word; // DNS flags
Fdns_num_q: word; // number of questions
Fdns_num_answ_rr: word; // number of answer resource records
Fdns_num_auth_rr: word; // number of authority resource records
Fdns_num_addi_rr: word; // number of additional resource records
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property dns_id: word read Fdns_id write Fdns_id; // DNS packet ID
property dns_flags: word read Fdns_flags write Fdns_flags; // DNS flags
property dns_num_q: word read Fdns_num_q write Fdns_num_q; // number of questions
property dns_num_answ_rr: word read Fdns_num_answ_rr write Fdns_num_answ_rr; // number of answer resource records
property dns_num_auth_rr: word read Fdns_num_auth_rr write Fdns_num_auth_rr;// number of authority resource records
property dns_num_addi_rr: word read Fdns_num_addi_rr write Fdns_num_addi_rr; // number of additional resource records
end;
////////////////////////////////////////////////////////////////////////////////
//RIP///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
{ header }
TIdRIPHdr = class(TIdStruct)
protected
Frip_cmd: byte; // RIP command
Frip_ver: byte; // RIP version
Frip_rd: word; // zero (v1) or routing domain (v2)
Frip_af: word; // address family
Frip_rt: word; // zero (v1) or route tag (v2)
Frip_addr: longword; // IP address
Frip_mask: longword; // zero (v1) or subnet mask (v2)
Frip_next_hop: longword; // zero (v1) or next hop IP address (v2)
Frip_metric: longword; // metric
public
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : Integer); override;
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : Integer); override;
property rip_cmd: byte read Frip_cmd write Frip_cmd; // RIP command
property rip_ver: byte read Frip_ver write Frip_ver; // RIP version
property rip_rd: word read Frip_rd write Frip_rd; // zero (v1) or routing domain (v2)
property rip_af: word read Frip_af write Frip_af; // address family
property rip_rt: word read Frip_rt write Frip_rt; // zero (v1) or route tag (v2)
property rip_addr: longword read Frip_addr write Frip_addr; // IP address
property rip_mask: longword read Frip_mask write Frip_mask; // zero (v1) or subnet mask (v2)
property rip_next_hop: longword read Frip_next_hop write Frip_next_hop; // zero (v1) or next hop IP address (v2)
property rip_metric: longword read Frip_metric write Frip_metric; // metric
end;
////////////////////////////////////////////////////////////////////////////////
implementation
uses IdSys;
{ TIdSunB }
procedure TIdSunB.ReadStruct(const ABytes: TIdBytes; var VIndex: Integer);
begin
inherited ReadStruct(ABytes, VIndex);
// Assert(Length(ABytes)>=VIndex+3,'not enough bytes');
Fs_b1 := ABytes[VIndex];
inc(VIndex);
Fs_b2 := ABytes[VIndex];
inc(VIndex);
Fs_b3 := ABytes[VIndex];
inc(VIndex);
Fs_b4 := ABytes[VIndex];
inc(VIndex);
end;
procedure TIdSunB.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)=VIndex+3,'not enough bytes');
Self.Fs_w1 := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
Self.Fs_w2 := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
end;
procedure TIdSunW.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)=VIndex+3,'not enough bytes');
Fid := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
seq := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
end;
procedure TIdICMPEcho.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)=VIndex+3,'not enough bytes');
Fpad := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
Fmtu := BytesToWord(ABytes,VIndex);
inc(VIndex,2);
end;
procedure TIdICMPFrag.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)=VIndex+11,'not enough bytes');
Fotime := BytesToLongWord(ABytes,VIndex); // time message was sent, to calc roundtrip time
inc(VIndex,4);
Frtime := BytesToLongWord(ABytes,VIndex);
inc(VIndex,4);
Fttime := BytesToLongWord(ABytes,VIndex);
inc(VIndex,4);
end;
procedure TIdICMPTs.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)(VIndex+4+Ficmp_hun.BytesLen+ Ficmp_dun.BytesLen-1),
'not enough bytes');
Ficmp_type := ABytes[VIndex];
Inc(VIndex);
Ficmp_code := ABytes[Vindex];
Inc(VIndex);
Ficmp_hun.ReadStruct(ABytes,VIndex);
Ficmp_dun.ReadStruct(ABytes,VIndex);
end;
procedure TIdICMPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
if Length(VBytes)=VIndex+Id_MAX_IPOPTLEN-1,'not enough bytes');
CopyTIdBytes(ABytes,VIndex,Fipopt_list,0,Id_MAX_IPOPTLEN);
end;
procedure TIdIPOptions.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes,VIndex);
if Length(VBytes)=(VIndex+16+Fip_src.BytesLen+ Fip_dst.BytesLen-1),
// 'not enough bytes');
Fip_verlen := ABytes[VIndex]; // 1st nibble version, 2nd nibble header length div 4 (little-endian)
Inc(VIndex);
Fip_tos := ABytes[VIndex]; // type of service
Inc(VIndex);
Fip_len := BytesToWord(ABytes,VIndex); // total length
Inc(VIndex,2);
Fip_id := BytesToWord(ABytes,VIndex); // identification
Inc(VIndex,2);
Fip_off := BytesToWord(ABytes,VIndex); // 1st nibble flags, next 3 nibbles fragment offset (little-endian)
Inc(VIndex,2);
Fip_ttl:= ABytes[VIndex]; // time to live
Inc(VIndex);
Fip_p := ABytes[VIndex]; // protocol
Inc(VIndex);
Fip_sum := BytesToWord(ABytes,VIndex); // checksum
Inc(VIndex,2);
Fip_src.ReadStruct(ABytes,VIndex); // source address
Fip_dst.ReadStruct(ABytes,VIndex); // dest address
Fip_options:= BytesToLongWord(ABytes,VIndex); // options + padding
Inc(VIndex,4);
end;
procedure TIdIPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
var LMinLen : Integer;
begin
inherited WriteStruct(VBytes, VIndex);
LMinLen := VIndex+16+Fip_src.BytesLen+ Fip_dst.BytesLen;
if Length(VBytes)=VIndex+18-1,'not enough bytes');
Ftcp_sport := BytesToWord(ABytes,VIndex); // source port
Inc(VIndex,2);
Ftcp_dport:= BytesToWord(ABytes,VIndex); // destination port
Inc(VIndex,2);
Ftcp_seq := BytesToLongWord(ABytes,VIndex); // sequence number
Inc(VIndex,4);
Ftcp_ack := BytesToLongWord(ABytes,VIndex); // acknowledgement number
Inc(VIndex,4);
Ftcp_x2off := ABytes[VIndex]; // data offset
Inc(VIndex);
Ftcp_flags := ABytes[VIndex]; // control flags
Inc(VIndex);
Ftcp_win := BytesToWord(ABytes,VIndex); // window
Inc(VIndex,2);
Ftcp_sum := BytesToWord(ABytes,VIndex); // checksum
Inc(VIndex,2);
Ftcp_urp := BytesToWord(ABytes,VIndex); // urgent pointer
Inc(VIndex,2);
end;
procedure TIdTCPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)VIndex+8,'not enough bytes');
Fudp_sport := BytesToWord(ABytes,VIndex); // source port
Inc(VIndex,2);
Fudp_dport := BytesToWord(ABytes,VIndex); // destination port
Inc(VIndex,2);
Fudp_ulen := BytesToWord(ABytes,VIndex); // length
Inc(VIndex,2);
Fudp_sum := BytesToWord(ABytes,VIndex); // checksum
Inc(VIndex,2);
end;
procedure TIdUDPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes,VIndex);
if Length(VBytes)=VIndex+8+Figmp_group.BytesLen-1,'not enough bytes');
Figmp_type := ABytes[VIndex];
Inc(VIndex);
Figmp_code := ABytes[VIndex];
Inc(VIndex);
Figmp_sum := BytesToWord(ABytes,VIndex);
Inc(VIndex,2);
Figmp_group.ReadStruct(ABytes,VIndex);
end;
procedure TIdIGMPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
if Length(VBytes)=VIndex+Length(Fether_addr_octet)-1,'not enough bytes');
CopyTIdBytes(ABytes,VIndex,Self.Fether_addr_octet,0,Length(Fether_addr_octet));
inc(VIndex,Length(Fether_addr_octet));
end;
procedure TIdEtherAddr.setether_addr_octet(Index: Integer; const Value: Byte);
begin
Assert(Index0,'must never be 0 length');
Assert(Length(Value)<=Id_ETHER_ADDR_LEN,'Out of range');
Fether_addr_octet := Value;
end;
{ TIdEthernetHdr }
constructor TIdEthernetHdr.create;
begin
inherited create;
Fether_dhost:= TIdEtherAddr.create;
Fether_shost:= TIdEtherAddr.create;
end;
procedure TIdEthernetHdr.ReadStruct(const ABytes: TIdBytes;
var VIndex: Integer);
begin
inherited ReadStruct(ABytes,VIndex);
Assert(Length(ABytes)=VIndex+(Id_ETHER_ADDR_LEN*2)+8-1,'not enough bytes');
inherited ReadStruct(ABytes, VIndex);
Farp_hrd := BytesToWord(ABytes,VIndex); // format of hardware address
Inc(VIndex,2);
Farp_pro := BytesToWord(ABytes,VIndex); // format of protocol address
Inc(VIndex,2);
Farp_hln := ABytes[VIndex]; // length of hardware address
Inc(VIndex,1);
Farp_pln:= ABytes[VIndex]; // length of protocol addres
Inc(VIndex,1);
Farp_op:= BytesToWord(ABytes,VIndex); // operation type
Inc(VIndex,2);
// following hardcoded for ethernet/IP
Farp_sha.ReadStruct(ABytes,VIndex); // sender hardware address
Farp_spa.ReadStruct(ABytes,VIndex); // sender protocol address
Farp_tha.ReadStruct(ABytes,VIndex); // target hardware address
Farp_tpa.ReadStruct(ABytes,VIndex); // target protocol address
end;
procedure TIdARPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
var Len : Integer;
begin
inherited WriteStruct(VBytes, VIndex);
Len := VIndex+(Id_ETHER_ADDR_LEN*2+8);
if Length(VBytes)=VIndex+12-1,'not enough bytes');
inherited ReadStruct(ABytes, VIndex);
Fdns_id := BytesToWord(ABytes,VIndex); // DNS packet ID
Inc(VIndex,2);
Fdns_flags:= BytesToWord(ABytes,VIndex); // DNS flags
Inc(VIndex,2);
Fdns_num_q:= BytesToWord(ABytes,VIndex); // number of questions
Inc(VIndex,2);
Fdns_num_answ_rr:= BytesToWord(ABytes,VIndex);// number of answer resource records
Inc(VIndex,2);
Fdns_num_auth_rr:= BytesToWord(ABytes,VIndex); // number of authority resource records
Inc(VIndex,2);
Fdns_num_addi_rr:= BytesToWord(ABytes,VIndex); // number of additional resource records
Inc(VIndex,2);
end;
procedure TIdDNSHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
if Length(VBytes)=VIndex+24-1,'not enough bytes');
inherited ReadStruct(ABytes, VIndex);
Frip_cmd:= ABytes[VIndex]; // RIP command
Inc(VIndex);
Frip_ver:= ABytes[VIndex]; // RIP version
Inc(VIndex);
Frip_rd := BytesToWord(ABytes,VIndex); // zero (v1) or routing domain (v2)
Inc(VIndex,2); //6
Frip_af:= BytesToWord(ABytes,VIndex); // address family
Inc(VIndex,2); //8
Frip_rt:= BytesToWord(ABytes,VIndex); // zero (v1) or route tag (v2)
Inc(VIndex,2); //10
Frip_addr:= BytesToLongWord(ABytes,VIndex); // IP address
Inc(VIndex,4); //14
Frip_mask:= BytesToLongWord(ABytes,VIndex); // zero (v1) or subnet mask (v2)
Inc(VIndex,4); //18
Frip_next_hop:= BytesToLongWord(ABytes,VIndex); // zero (v1) or next hop IP address (v2)
Inc(VIndex,4); //22
Frip_metric:= BytesToLongWord(ABytes,VIndex); // metric
Inc(VIndex,4); //26
end;
procedure TIdRIPHdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
if Length(VBytes)-1) and (Index<4),'Out of range');
Result := FBuffer[Index];
end;
procedure TIdicmp6_un.Seticmp6_un_data8(Index: Integer; const Value: uint8_t);
begin
Assert((Index>-1) and (Index<4),'Out of range');
FBuffer[Index] := Value;
end;
constructor TIdicmp6_un.create;
begin
inherited create;
FBytesLen := 4;
SetLength(FBuffer,FBytesLen);
end;
function TIdicmp6_un.Geticmp6_data8: uint8_t;
begin
Result := FBuffer[0];
end;
procedure TIdicmp6_un.Seticmp6_data8(const Value: uint8_t);
begin
FBuffer[0] := Value;
end;
function TIdicmp6_un.Geticmp6_data16: uint16_t;
begin
Result := BytesToWord(FBuffer,0);
end;
procedure TIdicmp6_un.Seticmp6_data16(const Value: uint16_t);
begin
CopyTIdWord(Value,FBuffer,0);
end;
function TIdicmp6_un.Geticmp6_seq: uint16_t;
begin
Result := Geticmp6_un_data16(1);
end;
procedure TIdicmp6_un.Seticmp6_seq(const Value: uint16_t);
begin
Seticmp6_un_data16(1, Value);
end;
{ TIdicmp6_hdr }
constructor TIdicmp6_hdr.create;
begin
inherited create;
Fdata := TIdicmp6_un.create;
end;
destructor TIdicmp6_hdr.Destroy;
begin
Sys.FreeAndNil(Fdata);
inherited Destroy;
end;
procedure TIdicmp6_hdr.ReadStruct(const ABytes: TIdBytes; var VIndex: Integer);
begin
Assert(Length(ABytes)>=VIndex+8-1,'not enough bytes');
inherited ReadStruct(ABytes, VIndex);
{
Ficmp6_type : uint8_t; //* type field */
FIcmp6_code : uint8_t; //* code field */
Ficmp6_cksum : uint16_t; //* checksum field */
Fdata : TIdicmp6_un;
}
Ficmp6_type := ABytes[VIndex];
Inc(VIndex);
FIcmp6_code := ABytes[VIndex];
Inc(VIndex);
Ficmp6_cksum := BytesToWord(ABytes,VIndex);
Inc(VIndex,2);
Fdata.ReadStruct(ABytes,VIndex);
end;
procedure TIdicmp6_hdr.WriteStruct(var VBytes: TIdBytes; var VIndex: Integer);
begin
inherited WriteStruct(VBytes, VIndex);
{
Ficmp6_type : uint8_t; //* type field */
FIcmp6_code : uint8_t; //* code field */
Ficmp6_cksum : uint16_t; //* checksum field */
Fdata : TIdicmp6_un;
}
if Length(VBytes)