restemplate/indy/Core/IdRawFunctions.pas

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.