711 lines
21 KiB
Plaintext
711 lines
21 KiB
Plaintext
{
|
|
$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.5 2004.02.03 4:16:50 PM czhower
|
|
For unit name changes.
|
|
|
|
Rev 1.4 2/1/2004 4:52:30 PM JPMugaas
|
|
Removed the rest of the Todo; items.
|
|
|
|
Rev 1.3 2/1/2004 4:20:30 PM JPMugaas
|
|
Should work in Win32. TODO: See about DotNET.
|
|
|
|
Rev 1.2 2003.10.11 5:49:06 PM czhower
|
|
-VCL fixes for servers
|
|
-Chain suport for servers (Super core)
|
|
-Scheduler upgrades
|
|
-Full yarn support
|
|
|
|
Rev 1.1 2003.09.30 1:23:00 PM czhower
|
|
Stack split for DotNet
|
|
|
|
Rev 1.0 11/13/2002 08:45:36 AM JPMugaas
|
|
}
|
|
|
|
unit IdRawFunctions;
|
|
|
|
interface
|
|
|
|
{$i IdCompilerDefines.inc}
|
|
|
|
uses
|
|
IdGlobal, IdRawHeaders, IdStack;
|
|
|
|
// ARP
|
|
procedure IdRawBuildArp(const AHwAddressFormat, AProtocolFormat: UInt16;
|
|
const AHwAddressLen, AProtocolLen: UInt8; const AnOpType: UInt16;
|
|
ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr;
|
|
ATargetPr: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
|
|
// DNS
|
|
procedure IdRawBuildDns(const AnId, AFlags, ANumQuestions, ANumAnswerRecs, ANumAuthRecs, ANumAddRecs: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
|
|
// Ethernet
|
|
procedure IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
|
|
// ICMP
|
|
procedure IdRawBuildIcmpEcho(AType, ACode: UInt8; AnId, ASeq: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
procedure IdRawBuildIcmpMask(AType, ACode: UInt8; AnId, ASeq: UInt16; AMask: UInt32;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
procedure IdRawBuildIcmpRedirect(const AType, ACode: UInt8; AGateway: TIdInAddr;
|
|
const AnOrigLen: UInt16; const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
|
|
const AnOrigTtl, AnOrigProtocol: UInt8; AnOrigSource, AnOrigDest: TIdInAddr;
|
|
const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
|
|
procedure IdRawBuildIcmpTimeExceed(const AType, ACode: UInt8; const AnOrigLen: UInt16;
|
|
const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
|
|
const AnOrigTtl, AnOrigProtocol: UInt8; const AnOrigSource, AnOrigDest: TIdInAddr;
|
|
const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
|
|
procedure IdRawBuildIcmpTimestamp(const AType, ACode: UInt8; const AnId, ASeq: UInt16;
|
|
const AnOtime, AnRtime, ATtime: TIdNetTime; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes);
|
|
procedure IdRawBuildIcmpUnreach(AType, ACode: UInt8; AnOrigLen: UInt16;
|
|
AnOrigTos: UInt8; AnOrigId, AnOrigFrag: UInt16; AnOrigTtl, AnOrigProtocol: UInt8;
|
|
AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: Integer;
|
|
var VBuffer: TIdBytes);
|
|
|
|
// IGMP
|
|
procedure IdRawBuildIgmp(AType, ACode: UInt8; AnIp: TIdInAddr;
|
|
const APayload: UInt16; var VBuffer: TIdBytes);
|
|
|
|
// IP
|
|
procedure IdRawBuildIp(ALen: UInt16; ATos: UInt8; AnId, AFrag: UInt16;
|
|
ATtl, AProtocol: UInt8; ASource, ADest: TIdInAddr; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes; const AIdx: Integer = 0);
|
|
|
|
// RIP
|
|
procedure IdRawBuildRip(const ACommand, AVersion: UInt8;
|
|
const ARoutingDomain, AnAddressFamily, ARoutingTag: UInt16;
|
|
const AnAddr, AMask, ANextHop, AMetric: UInt32;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
|
|
// TCP
|
|
procedure IdRawBuildTcp(const ASourcePort, ADestPort: UInt16;
|
|
const ASeq, AnAck: UInt32; const AControl: UInt8;
|
|
const AWindowSize, AnUrgent: UInt16; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes);
|
|
|
|
// UDP
|
|
procedure IdRawBuildUdp(const ASourcePort, ADestPort: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils;
|
|
|
|
procedure IdRawBuildArp(const AHwAddressFormat, AProtocolFormat: UInt16;
|
|
const AHwAddressLen, AProtocolLen: UInt8; const AnOpType: UInt16;
|
|
ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr;
|
|
ATargetPr: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrArp: TIdArpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ARP_HSIZE + Length(VBuffer);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrArp := TIdArpHdr.Create;
|
|
try
|
|
HdrArp.arp_hrd := GStack.HostToNetwork(AHwAddressFormat);
|
|
HdrArp.arp_pro := GStack.HostToNetwork(AProtocolFormat);
|
|
HdrArp.arp_hln := AHwAddressLen;
|
|
HdrArp.arp_pln := AProtocolLen;
|
|
HdrArp.arp_op := GStack.HostToNetwork(AnOpType);
|
|
HdrArp.arp_sha.CopyFrom(ASenderHw);
|
|
HdrArp.arp_spa.s_l := ASenderPr.s_l;
|
|
HdrArp.arp_tha.CopyFrom(ATargetHw);
|
|
HdrArp.arp_tpa.CopyFrom(ATargetPr);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_ICMP_ECHO_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrArp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrArp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildDns(const AnId, AFlags, ANumQuestions, ANumAnswerRecs,
|
|
ANumAuthRecs, ANumAddRecs: UInt16; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes);
|
|
var
|
|
HdrDns: TIdDnsHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Length(APayload) + Id_DNS_HSIZE;
|
|
LLen := UInt32(Length(VBuffer));
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrDns := TIdDnsHdr.Create;
|
|
try
|
|
HdrDns.dns_id := GStack.HostToNetwork(AnId);
|
|
HdrDns.dns_flags := GStack.HostToNetwork(AFlags);
|
|
HdrDns.dns_num_q := GStack.HostToNetwork(ANumQuestions);
|
|
HdrDns.dns_num_answ_rr := GStack.HostToNetwork(ANumAnswerRecs);
|
|
HdrDns.dns_num_auth_rr := GStack.HostToNetwork(ANumAuthRecs);
|
|
HdrDns.dns_num_addi_rr := GStack.HostToNetwork(ANumAddRecs);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_DNS_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrDns.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrDns);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrEth: TIdEthernetHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// make sure VBuffer will be long enough
|
|
LIdx := Length(ASource.Data) + Length(ADest.Data) + 2 + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrEth := TIdEthernetHdr.Create;
|
|
try
|
|
HdrEth.ether_dhost.CopyFrom(ADest);
|
|
HdrEth.ether_shost.CopyFrom(ASource);
|
|
HdrEth.ether_type := GStack.HostToNetwork(AType);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrEth.WriteStruct(VBuffer, LIdx);
|
|
|
|
// copy payload if present
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
|
|
end;
|
|
finally
|
|
FreeAndNil(HdrEth);
|
|
end;
|
|
end;
|
|
|
|
// TODO: check nibbles in IP header
|
|
procedure IdRawBuildIp(ALen: UInt16; ATos: UInt8; AnId, AFrag: UInt16; ATtl, AProtocol: UInt8;
|
|
ASource, ADest: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes;
|
|
const AIdx: Integer = 0);
|
|
var
|
|
HdrIp: TIdIpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_IP_HSIZE + Length(APayload) + AIdx;
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIp := TIdIpHdr.Create;
|
|
try
|
|
HdrIp.ip_verlen := (4 shl 4) + (Id_IP_HSIZE div 4); // IPv4 shl 4, 20 bytes div 4
|
|
HdrIp.ip_tos := ATos;
|
|
HdrIp.ip_len := GStack.HostToNetwork(UInt16(ALen + Id_IP_HSIZE));
|
|
HdrIp.ip_id := GStack.HostToNetwork(AnId);
|
|
HdrIp.ip_off := GStack.HostToNetwork(AFrag);
|
|
HdrIp.ip_ttl := ATtl;
|
|
HdrIp.ip_p := AProtocol;
|
|
HdrIp.ip_sum := 0; // do checksum later
|
|
HdrIp.ip_src.CopyFrom(ASource);
|
|
HdrIp.ip_dst.CopyFrom(ADest);
|
|
|
|
// copy header
|
|
LIdx := AIdx;
|
|
HdrIp.WriteStruct(VBuffer, LIdx);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
|
|
end;
|
|
finally
|
|
FreeANdNil(HdrIp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpEcho(AType, ACode: UInt8; AnId, ASeq: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdIcmpHdr;
|
|
LIdx, LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_ECHO_HSIZE + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdIcmpHdr.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
|
|
HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_ICMP_ECHO_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
type
|
|
TIdICMPMask = class(TIdICMPHdr)
|
|
protected
|
|
Ficmp_mask: UInt32;
|
|
function GetBytesLen: UInt32; override;
|
|
public
|
|
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
|
|
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
|
|
property icmp_mask: UInt32 read Ficmp_mask write Ficmp_mask;
|
|
end;
|
|
|
|
function TIdICMPMask.GetBytesLen: UInt32;
|
|
begin
|
|
Result := inherited GetBytesLen + 4;
|
|
end;
|
|
|
|
procedure TIdICMPMask.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
|
|
begin
|
|
inherited ReadStruct(ABytes, VIndex);
|
|
Ficmp_mask := BytesToUInt32(ABytes, VIndex);
|
|
Inc(VIndex, 4);
|
|
end;
|
|
|
|
procedure TIdICMPMask.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
|
|
begin
|
|
inherited WriteStruct(VBytes, VIndex);
|
|
CopyTIdUInt32(Ficmp_mask, VBytes, VIndex);
|
|
Inc(VIndex, 4);
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpMask(AType, ACode: UInt8; AnId, ASeq: UInt16; AMask: UInt32;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdICMPMask;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_MASK_HSIZE + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdICMPMask.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
|
|
HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
|
|
HdrIcmp.icmp_mask := GStack.HostToNetwork(AMask);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
|
|
end;
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpUnreach(AType, ACode: UInt8; AnOrigLen: UInt16;
|
|
AnOrigTos: UInt8; AnOrigId, AnOrigFrag: UInt16; AnOrigTtl, AnOrigProtocol: UInt8;
|
|
AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: Integer;
|
|
var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdIcmpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_UNREACH_HSIZE + Id_IP_HSIZE + 2;
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdIcmpHdr.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.echo_id := 0;
|
|
HdrIcmp.icmp_hun.echo_seq := 0;
|
|
|
|
// attach original header
|
|
IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
|
|
AnOrigSource, AnOrigDest, ToBytes(AnOrigPayload), VBuffer, Id_ICMP_UNREACH_HSIZE);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpTimeExceed(const AType, ACode: UInt8; const AnOrigLen: UInt16;
|
|
const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
|
|
const AnOrigTtl, AnOrigProtocol: UInt8; const AnOrigSource, AnOrigDest: TIdInAddr;
|
|
const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdIcmpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_TIMEXCEED_HSIZE + Id_IP_HSIZE + Length(AnOrigPayload);
|
|
Llen := Length(VBuffer);
|
|
if Llen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdIcmpHdr.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.echo_id := 0;
|
|
HdrIcmp.icmp_hun.echo_seq := 0;
|
|
|
|
// attach original header
|
|
IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
|
|
AnOrigSource, AnOrigDest, AnOrigPayload, VBuffer, Id_ICMP_TIMEXCEED_HSIZE);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
type
|
|
TIdIcmpTS = class(TIdIcmpHdr)
|
|
protected
|
|
Ficmp_dun: TIdicmp_dun;
|
|
function GetBytesLen: UInt32; override;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
|
|
procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
|
|
property icmp_dun: TIdicmp_dun read Ficmp_dun;
|
|
end;
|
|
|
|
constructor TIdIcmpTS.Create;
|
|
begin
|
|
inherited Create;
|
|
Ficmp_dun := TIdicmp_dun.Create;
|
|
end;
|
|
|
|
destructor TIdIcmpTS.Destroy;
|
|
begin
|
|
Ficmp_dun.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TIdIcmpTS.GetBytesLen: UInt32;
|
|
begin
|
|
Result := inherited GetBytesLen + Ficmp_dun.BytesLen;
|
|
end;
|
|
|
|
procedure TIdIcmpTS.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
|
|
begin
|
|
inherited ReadStruct(ABytes, VIndex);
|
|
Ficmp_dun.ReadStruct(ABytes, VIndex);
|
|
end;
|
|
|
|
procedure TIdIcmpTS.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
|
|
begin
|
|
inherited WriteStruct(VBytes, VIndex);
|
|
Ficmp_dun.WriteStruct(VBytes, VIndex);
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpTimestamp(const AType, ACode: UInt8; const AnId, ASeq: UInt16;
|
|
const AnOtime, AnRtime, ATtime: TIdNetTime; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdIcmpTS;
|
|
LIdx, LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_TS_HSIZE + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdIcmpTS.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
|
|
HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
|
|
HdrIcmp.icmp_dun.ts_otime := GStack.HostToNetwork(AnOtime); // original timestamp
|
|
HdrIcmp.icmp_dun.ts_rtime := GStack.HostToNetwork(AnRtime); // receive timestamp
|
|
HdrIcmp.icmp_dun.ts_ttime := GStack.HostToNetwork(ATtime); // transmit timestamp
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
|
|
end;
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildIcmpRedirect(const AType, ACode: UInt8; AGateway: TIdInAddr;
|
|
const AnOrigLen: UInt16; const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
|
|
const AnOrigTtl, AnOrigProtocol: UInt8; AnOrigSource, AnOrigDest: TIdInAddr;
|
|
const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrIcmp: TIdIcmpHdr;
|
|
LIdx, LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_ICMP_REDIRECT_HSIZE + Id_IP_HSIZE + Length(AnOrigPayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIcmp := TIdIcmpHdr.Create;
|
|
try
|
|
HdrIcmp.icmp_type := AType;
|
|
HdrIcmp.icmp_code := ACode;
|
|
HdrIcmp.icmp_hun.gateway_s_b1 := AGateway.s_l; // gateway address
|
|
|
|
// attach original header
|
|
IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
|
|
AnOrigSource, AnOrigDest, AnOrigPayload, VBuffer, Id_ICMP_REDIRECT_HSIZE);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIcmp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrIcmp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildIgmp(AType, ACode: UInt8; AnIp: TIdInAddr;
|
|
const APayload: UInt16; var VBuffer: TIdBytes);
|
|
var
|
|
HdrIgmp: TIdIgmpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := 2 + Id_IGMP_HSIZE;
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrIgmp := TIdIgmpHdr.Create;
|
|
try
|
|
HdrIgmp.igmp_type := AType;
|
|
HdrIgmp.igmp_code := ACode;
|
|
HdrIgmp.igmp_sum := 0;
|
|
HdrIgmp.igmp_group.s_l := AnIp.s_l; // group address or 0
|
|
|
|
// copy payload
|
|
CopyTIdUInt16(APayload, VBuffer, Id_IGMP_HSIZE);
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrIgmp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrIgmp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildRip(const ACommand, AVersion: UInt8;
|
|
const ARoutingDomain, AnAddressFamily, ARoutingTag: UInt16;
|
|
const AnAddr, AMask, ANextHop, AMetric: UInt32;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrRip: TIdRipHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_RIP_HSIZE + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrRip := TIdRipHdr.Create;
|
|
try
|
|
HdrRip.rip_cmd := ACommand;
|
|
HdrRip.rip_ver := AVersion;
|
|
HdrRip.rip_rd := GStack.HostToNetwork(ARoutingDomain);
|
|
HdrRip.rip_af := GStack.HostToNetwork(AnAddressFamily);
|
|
HdrRip.rip_rt := GStack.HostToNetwork(ARoutingTag);
|
|
HdrRip.rip_addr := GStack.HostToNetwork(AnAddr);
|
|
HdrRip.rip_mask := GStack.HostToNetwork(AMask);
|
|
HdrRip.rip_next_hop := GStack.HostToNetwork(ANextHop);
|
|
HdrRip.rip_metric := GStack.HostToNetwork(AMetric);
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_RIP_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrRip.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrRip);
|
|
end;
|
|
end;
|
|
|
|
// TODO: check nibbles in TCP header
|
|
procedure IdRawBuildTcp(const ASourcePort, ADestPort: UInt16;
|
|
const ASeq, AnAck: UInt32; const AControl: UInt8;
|
|
const AWindowSize, AnUrgent: UInt16; const APayload: TIdBytes;
|
|
var VBuffer: TIdBytes);
|
|
var
|
|
HdrTcp: TIdTcpHdr;
|
|
LIdx, LLen: UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_TCP_HSIZE + Length(VBuffer);
|
|
LLen := Length(VBuffer);
|
|
if LLen < LIdx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrTcp := TIdTcpHdr.Create;
|
|
try
|
|
HdrTcp.tcp_sport := GStack.HostToNetwork(ASourcePort);
|
|
HdrTcp.tcp_dport := GStack.HostToNetwork(ADestPort);
|
|
HdrTcp.tcp_seq := GStack.HostToNetwork(ASeq);
|
|
HdrTcp.tcp_ack := GStack.HostToNetwork(AnAck); // acknowledgement number
|
|
HdrTcp.tcp_flags := AControl; // control flags
|
|
HdrTcp.tcp_x2off := ((Id_TCP_HSIZE div 4) shl 4) + 0; // 20 bytes div 4, x2 unused
|
|
HdrTcp.tcp_win := GStack.HostToNetwork(AWindowSize); // window size
|
|
HdrTcp.tcp_sum := 0;
|
|
HdrTcp.tcp_urp := AnUrgent; // urgent pointer
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_TCP_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrTcp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrTcp);
|
|
end;
|
|
end;
|
|
|
|
procedure IdRawBuildUdp(const ASourcePort, ADestPort: UInt16;
|
|
const APayload: TIdBytes; var VBuffer: TIdBytes);
|
|
var
|
|
HdrUdp: TIdUdpHdr;
|
|
LIdx: UInt32;
|
|
LLen : UInt32;
|
|
begin
|
|
// check input
|
|
LIdx := Id_UDP_HSIZE + Length(APayload);
|
|
LLen := Length(VBuffer);
|
|
if LLen < Lidx then begin
|
|
SetLength(VBuffer, LIdx);
|
|
end;
|
|
|
|
// construct header
|
|
HdrUdp := TIdUdpHdr.Create;
|
|
try
|
|
HdrUdp.udp_dport := GStack.HostToNetwork(ASourcePort);
|
|
HdrUdp.udp_dport := GStack.HostToNetwork(ADestPort);
|
|
//LIdx should be okay here since we set that to the packet length earlier
|
|
HdrUdp.udp_ulen := GStack.HostToNetwork(LIdx);
|
|
HdrUdp.udp_sum := 0;
|
|
|
|
// copy payload
|
|
if Length(APayload) > 0 then begin
|
|
CopyTIdBytes(APayload, 0, VBuffer, Id_UDP_HSIZE, Length(APayload));
|
|
end;
|
|
|
|
// copy header
|
|
LIdx := 0;
|
|
HdrUdp.WriteStruct(VBuffer, LIdx);
|
|
finally
|
|
FreeAndNil(HdrUdp);
|
|
end;
|
|
end;
|
|
|
|
end.
|