IdRawFunctions.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.5 2004.02.03 4:16:50 PM czhower
  18. For unit name changes.
  19. Rev 1.4 2/1/2004 4:52:30 PM JPMugaas
  20. Removed the rest of the Todo; items.
  21. Rev 1.3 2/1/2004 4:20:30 PM JPMugaas
  22. Should work in Win32. TODO: See about DotNET.
  23. Rev 1.2 2003.10.11 5:49:06 PM czhower
  24. -VCL fixes for servers
  25. -Chain suport for servers (Super core)
  26. -Scheduler upgrades
  27. -Full yarn support
  28. Rev 1.1 2003.09.30 1:23:00 PM czhower
  29. Stack split for DotNet
  30. Rev 1.0 11/13/2002 08:45:36 AM JPMugaas
  31. }
  32. unit IdRawFunctions;
  33. interface
  34. {$i IdCompilerDefines.inc}
  35. uses
  36. IdGlobal, IdRawHeaders, IdStack;
  37. // ARP
  38. procedure IdRawBuildArp(const AHwAddressFormat, AProtocolFormat: UInt16;
  39. const AHwAddressLen, AProtocolLen: UInt8; const AnOpType: UInt16;
  40. ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr;
  41. ATargetPr: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes);
  42. // DNS
  43. procedure IdRawBuildDns(const AnId, AFlags, ANumQuestions, ANumAnswerRecs, ANumAuthRecs, ANumAddRecs: UInt16;
  44. const APayload: TIdBytes; var VBuffer: TIdBytes);
  45. // Ethernet
  46. procedure IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: UInt16;
  47. const APayload: TIdBytes; var VBuffer: TIdBytes);
  48. // ICMP
  49. procedure IdRawBuildIcmpEcho(AType, ACode: UInt8; AnId, ASeq: UInt16;
  50. const APayload: TIdBytes; var VBuffer: TIdBytes);
  51. procedure IdRawBuildIcmpMask(AType, ACode: UInt8; AnId, ASeq: UInt16; AMask: UInt32;
  52. const APayload: TIdBytes; var VBuffer: TIdBytes);
  53. procedure IdRawBuildIcmpRedirect(const AType, ACode: UInt8; AGateway: TIdInAddr;
  54. const AnOrigLen: UInt16; const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
  55. const AnOrigTtl, AnOrigProtocol: UInt8; AnOrigSource, AnOrigDest: TIdInAddr;
  56. const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
  57. procedure IdRawBuildIcmpTimeExceed(const AType, ACode: UInt8; const AnOrigLen: UInt16;
  58. const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
  59. const AnOrigTtl, AnOrigProtocol: UInt8; const AnOrigSource, AnOrigDest: TIdInAddr;
  60. const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
  61. procedure IdRawBuildIcmpTimestamp(const AType, ACode: UInt8; const AnId, ASeq: UInt16;
  62. const AnOtime, AnRtime, ATtime: TIdNetTime; const APayload: TIdBytes;
  63. var VBuffer: TIdBytes);
  64. procedure IdRawBuildIcmpUnreach(AType, ACode: UInt8; AnOrigLen: UInt16;
  65. AnOrigTos: UInt8; AnOrigId, AnOrigFrag: UInt16; AnOrigTtl, AnOrigProtocol: UInt8;
  66. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: Integer;
  67. var VBuffer: TIdBytes);
  68. // IGMP
  69. procedure IdRawBuildIgmp(AType, ACode: UInt8; AnIp: TIdInAddr;
  70. const APayload: UInt16; var VBuffer: TIdBytes);
  71. // IP
  72. procedure IdRawBuildIp(ALen: UInt16; ATos: UInt8; AnId, AFrag: UInt16;
  73. ATtl, AProtocol: UInt8; ASource, ADest: TIdInAddr; const APayload: TIdBytes;
  74. var VBuffer: TIdBytes; const AIdx: Integer = 0);
  75. // RIP
  76. procedure IdRawBuildRip(const ACommand, AVersion: UInt8;
  77. const ARoutingDomain, AnAddressFamily, ARoutingTag: UInt16;
  78. const AnAddr, AMask, ANextHop, AMetric: UInt32;
  79. const APayload: TIdBytes; var VBuffer: TIdBytes);
  80. // TCP
  81. procedure IdRawBuildTcp(const ASourcePort, ADestPort: UInt16;
  82. const ASeq, AnAck: UInt32; const AControl: UInt8;
  83. const AWindowSize, AnUrgent: UInt16; const APayload: TIdBytes;
  84. var VBuffer: TIdBytes);
  85. // UDP
  86. procedure IdRawBuildUdp(const ASourcePort, ADestPort: UInt16;
  87. const APayload: TIdBytes; var VBuffer: TIdBytes);
  88. implementation
  89. uses
  90. SysUtils;
  91. procedure IdRawBuildArp(const AHwAddressFormat, AProtocolFormat: UInt16;
  92. const AHwAddressLen, AProtocolLen: UInt8; const AnOpType: UInt16;
  93. ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr;
  94. ATargetPr: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes);
  95. var
  96. HdrArp: TIdArpHdr;
  97. LIdx: UInt32;
  98. LLen : UInt32;
  99. begin
  100. // check input
  101. LIdx := Id_ARP_HSIZE + Length(VBuffer);
  102. LLen := Length(VBuffer);
  103. if LLen < LIdx then begin
  104. SetLength(VBuffer, LIdx);
  105. end;
  106. // construct header
  107. HdrArp := TIdArpHdr.Create;
  108. try
  109. HdrArp.arp_hrd := GStack.HostToNetwork(AHwAddressFormat);
  110. HdrArp.arp_pro := GStack.HostToNetwork(AProtocolFormat);
  111. HdrArp.arp_hln := AHwAddressLen;
  112. HdrArp.arp_pln := AProtocolLen;
  113. HdrArp.arp_op := GStack.HostToNetwork(AnOpType);
  114. HdrArp.arp_sha.CopyFrom(ASenderHw);
  115. HdrArp.arp_spa.s_l := ASenderPr.s_l;
  116. HdrArp.arp_tha.CopyFrom(ATargetHw);
  117. HdrArp.arp_tpa.CopyFrom(ATargetPr);
  118. // copy payload
  119. if Length(APayload) > 0 then begin
  120. CopyTIdBytes(APayload, 0, VBuffer, Id_ICMP_ECHO_HSIZE, Length(APayload));
  121. end;
  122. // copy header
  123. LIdx := 0;
  124. HdrArp.WriteStruct(VBuffer, LIdx);
  125. finally
  126. FreeAndNil(HdrArp);
  127. end;
  128. end;
  129. procedure IdRawBuildDns(const AnId, AFlags, ANumQuestions, ANumAnswerRecs,
  130. ANumAuthRecs, ANumAddRecs: UInt16; const APayload: TIdBytes;
  131. var VBuffer: TIdBytes);
  132. var
  133. HdrDns: TIdDnsHdr;
  134. LIdx: UInt32;
  135. LLen : UInt32;
  136. begin
  137. // check input
  138. LIdx := Length(APayload) + Id_DNS_HSIZE;
  139. LLen := UInt32(Length(VBuffer));
  140. if LLen < LIdx then begin
  141. SetLength(VBuffer, LIdx);
  142. end;
  143. // construct header
  144. HdrDns := TIdDnsHdr.Create;
  145. try
  146. HdrDns.dns_id := GStack.HostToNetwork(AnId);
  147. HdrDns.dns_flags := GStack.HostToNetwork(AFlags);
  148. HdrDns.dns_num_q := GStack.HostToNetwork(ANumQuestions);
  149. HdrDns.dns_num_answ_rr := GStack.HostToNetwork(ANumAnswerRecs);
  150. HdrDns.dns_num_auth_rr := GStack.HostToNetwork(ANumAuthRecs);
  151. HdrDns.dns_num_addi_rr := GStack.HostToNetwork(ANumAddRecs);
  152. // copy payload
  153. if Length(APayload) > 0 then begin
  154. CopyTIdBytes(APayload, 0, VBuffer, Id_DNS_HSIZE, Length(APayload));
  155. end;
  156. // copy header
  157. LIdx := 0;
  158. HdrDns.WriteStruct(VBuffer, LIdx);
  159. finally
  160. FreeAndNil(HdrDns);
  161. end;
  162. end;
  163. procedure IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: UInt16;
  164. const APayload: TIdBytes; var VBuffer: TIdBytes);
  165. var
  166. HdrEth: TIdEthernetHdr;
  167. LIdx: UInt32;
  168. LLen : UInt32;
  169. begin
  170. // make sure VBuffer will be long enough
  171. LIdx := Length(ASource.Data) + Length(ADest.Data) + 2 + Length(APayload);
  172. LLen := Length(VBuffer);
  173. if LLen < LIdx then begin
  174. SetLength(VBuffer, LIdx);
  175. end;
  176. // construct header
  177. HdrEth := TIdEthernetHdr.Create;
  178. try
  179. HdrEth.ether_dhost.CopyFrom(ADest);
  180. HdrEth.ether_shost.CopyFrom(ASource);
  181. HdrEth.ether_type := GStack.HostToNetwork(AType);
  182. // copy header
  183. LIdx := 0;
  184. HdrEth.WriteStruct(VBuffer, LIdx);
  185. // copy payload if present
  186. if Length(APayload) > 0 then begin
  187. CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
  188. end;
  189. finally
  190. FreeAndNil(HdrEth);
  191. end;
  192. end;
  193. // TODO: check nibbles in IP header
  194. procedure IdRawBuildIp(ALen: UInt16; ATos: UInt8; AnId, AFrag: UInt16; ATtl, AProtocol: UInt8;
  195. ASource, ADest: TIdInAddr; const APayload: TIdBytes; var VBuffer: TIdBytes;
  196. const AIdx: Integer = 0);
  197. var
  198. HdrIp: TIdIpHdr;
  199. LIdx: UInt32;
  200. LLen : UInt32;
  201. begin
  202. // check input
  203. LIdx := Id_IP_HSIZE + Length(APayload) + AIdx;
  204. LLen := Length(VBuffer);
  205. if LLen < LIdx then begin
  206. SetLength(VBuffer, LIdx);
  207. end;
  208. // construct header
  209. HdrIp := TIdIpHdr.Create;
  210. try
  211. HdrIp.ip_verlen := (4 shl 4) + (Id_IP_HSIZE div 4); // IPv4 shl 4, 20 bytes div 4
  212. HdrIp.ip_tos := ATos;
  213. HdrIp.ip_len := GStack.HostToNetwork(UInt16(ALen + Id_IP_HSIZE));
  214. HdrIp.ip_id := GStack.HostToNetwork(AnId);
  215. HdrIp.ip_off := GStack.HostToNetwork(AFrag);
  216. HdrIp.ip_ttl := ATtl;
  217. HdrIp.ip_p := AProtocol;
  218. HdrIp.ip_sum := 0; // do checksum later
  219. HdrIp.ip_src.CopyFrom(ASource);
  220. HdrIp.ip_dst.CopyFrom(ADest);
  221. // copy header
  222. LIdx := AIdx;
  223. HdrIp.WriteStruct(VBuffer, LIdx);
  224. // copy payload
  225. if Length(APayload) > 0 then begin
  226. CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
  227. end;
  228. finally
  229. FreeANdNil(HdrIp);
  230. end;
  231. end;
  232. procedure IdRawBuildIcmpEcho(AType, ACode: UInt8; AnId, ASeq: UInt16;
  233. const APayload: TIdBytes; var VBuffer: TIdBytes);
  234. var
  235. HdrIcmp: TIdIcmpHdr;
  236. LIdx, LLen : UInt32;
  237. begin
  238. // check input
  239. LIdx := Id_ICMP_ECHO_HSIZE + Length(APayload);
  240. LLen := Length(VBuffer);
  241. if LLen < LIdx then begin
  242. SetLength(VBuffer, LIdx);
  243. end;
  244. // construct header
  245. HdrIcmp := TIdIcmpHdr.Create;
  246. try
  247. HdrIcmp.icmp_type := AType;
  248. HdrIcmp.icmp_code := ACode;
  249. HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
  250. HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
  251. // copy payload
  252. if Length(APayload) > 0 then begin
  253. CopyTIdBytes(APayload, 0, VBuffer, Id_ICMP_ECHO_HSIZE, Length(APayload));
  254. end;
  255. // copy header
  256. LIdx := 0;
  257. HdrIcmp.WriteStruct(VBuffer, LIdx);
  258. finally
  259. FreeAndNil(HdrIcmp);
  260. end;
  261. end;
  262. type
  263. TIdICMPMask = class(TIdICMPHdr)
  264. protected
  265. Ficmp_mask: UInt32;
  266. function GetBytesLen: UInt32; override;
  267. public
  268. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  269. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  270. property icmp_mask: UInt32 read Ficmp_mask write Ficmp_mask;
  271. end;
  272. function TIdICMPMask.GetBytesLen: UInt32;
  273. begin
  274. Result := inherited GetBytesLen + 4;
  275. end;
  276. procedure TIdICMPMask.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  277. begin
  278. inherited ReadStruct(ABytes, VIndex);
  279. Ficmp_mask := BytesToUInt32(ABytes, VIndex);
  280. Inc(VIndex, 4);
  281. end;
  282. procedure TIdICMPMask.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  283. begin
  284. inherited WriteStruct(VBytes, VIndex);
  285. CopyTIdUInt32(Ficmp_mask, VBytes, VIndex);
  286. Inc(VIndex, 4);
  287. end;
  288. procedure IdRawBuildIcmpMask(AType, ACode: UInt8; AnId, ASeq: UInt16; AMask: UInt32;
  289. const APayload: TIdBytes; var VBuffer: TIdBytes);
  290. var
  291. HdrIcmp: TIdICMPMask;
  292. LIdx: UInt32;
  293. LLen : UInt32;
  294. begin
  295. // check input
  296. LIdx := Id_ICMP_MASK_HSIZE + Length(APayload);
  297. LLen := Length(VBuffer);
  298. if LLen < LIdx then begin
  299. SetLength(VBuffer, LIdx);
  300. end;
  301. // construct header
  302. HdrIcmp := TIdICMPMask.Create;
  303. try
  304. HdrIcmp.icmp_type := AType;
  305. HdrIcmp.icmp_code := ACode;
  306. HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
  307. HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
  308. HdrIcmp.icmp_mask := GStack.HostToNetwork(AMask);
  309. // copy header
  310. LIdx := 0;
  311. HdrIcmp.WriteStruct(VBuffer, LIdx);
  312. // copy payload
  313. if Length(APayload) > 0 then begin
  314. CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
  315. end;
  316. finally
  317. FreeAndNil(HdrIcmp);
  318. end;
  319. end;
  320. procedure IdRawBuildIcmpUnreach(AType, ACode: UInt8; AnOrigLen: UInt16;
  321. AnOrigTos: UInt8; AnOrigId, AnOrigFrag: UInt16; AnOrigTtl, AnOrigProtocol: UInt8;
  322. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: Integer;
  323. var VBuffer: TIdBytes);
  324. var
  325. HdrIcmp: TIdIcmpHdr;
  326. LIdx: UInt32;
  327. LLen : UInt32;
  328. begin
  329. // check input
  330. LIdx := Id_ICMP_UNREACH_HSIZE + Id_IP_HSIZE + 2;
  331. LLen := Length(VBuffer);
  332. if LLen < LIdx then begin
  333. SetLength(VBuffer, LIdx);
  334. end;
  335. // construct header
  336. HdrIcmp := TIdIcmpHdr.Create;
  337. try
  338. HdrIcmp.icmp_type := AType;
  339. HdrIcmp.icmp_code := ACode;
  340. HdrIcmp.icmp_hun.echo_id := 0;
  341. HdrIcmp.icmp_hun.echo_seq := 0;
  342. // attach original header
  343. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  344. AnOrigSource, AnOrigDest, ToBytes(AnOrigPayload), VBuffer, Id_ICMP_UNREACH_HSIZE);
  345. // copy header
  346. LIdx := 0;
  347. HdrIcmp.WriteStruct(VBuffer, LIdx);
  348. finally
  349. FreeAndNil(HdrIcmp);
  350. end;
  351. end;
  352. procedure IdRawBuildIcmpTimeExceed(const AType, ACode: UInt8; const AnOrigLen: UInt16;
  353. const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
  354. const AnOrigTtl, AnOrigProtocol: UInt8; const AnOrigSource, AnOrigDest: TIdInAddr;
  355. const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
  356. var
  357. HdrIcmp: TIdIcmpHdr;
  358. LIdx: UInt32;
  359. LLen : UInt32;
  360. begin
  361. // check input
  362. LIdx := Id_ICMP_TIMEXCEED_HSIZE + Id_IP_HSIZE + Length(AnOrigPayload);
  363. Llen := Length(VBuffer);
  364. if Llen < LIdx then begin
  365. SetLength(VBuffer, LIdx);
  366. end;
  367. // construct header
  368. HdrIcmp := TIdIcmpHdr.Create;
  369. try
  370. HdrIcmp.icmp_type := AType;
  371. HdrIcmp.icmp_code := ACode;
  372. HdrIcmp.icmp_hun.echo_id := 0;
  373. HdrIcmp.icmp_hun.echo_seq := 0;
  374. // attach original header
  375. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  376. AnOrigSource, AnOrigDest, AnOrigPayload, VBuffer, Id_ICMP_TIMEXCEED_HSIZE);
  377. // copy header
  378. LIdx := 0;
  379. HdrIcmp.WriteStruct(VBuffer, LIdx);
  380. finally
  381. FreeAndNil(HdrIcmp);
  382. end;
  383. end;
  384. type
  385. TIdIcmpTS = class(TIdIcmpHdr)
  386. protected
  387. Ficmp_dun: TIdicmp_dun;
  388. function GetBytesLen: UInt32; override;
  389. public
  390. constructor Create; override;
  391. destructor Destroy; override;
  392. procedure ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32); override;
  393. procedure WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32); override;
  394. property icmp_dun: TIdicmp_dun read Ficmp_dun;
  395. end;
  396. constructor TIdIcmpTS.Create;
  397. begin
  398. inherited Create;
  399. Ficmp_dun := TIdicmp_dun.Create;
  400. end;
  401. destructor TIdIcmpTS.Destroy;
  402. begin
  403. Ficmp_dun.Free;
  404. inherited Destroy;
  405. end;
  406. function TIdIcmpTS.GetBytesLen: UInt32;
  407. begin
  408. Result := inherited GetBytesLen + Ficmp_dun.BytesLen;
  409. end;
  410. procedure TIdIcmpTS.ReadStruct(const ABytes : TIdBytes; var VIndex : UInt32);
  411. begin
  412. inherited ReadStruct(ABytes, VIndex);
  413. Ficmp_dun.ReadStruct(ABytes, VIndex);
  414. end;
  415. procedure TIdIcmpTS.WriteStruct(var VBytes : TIdBytes; var VIndex : UInt32);
  416. begin
  417. inherited WriteStruct(VBytes, VIndex);
  418. Ficmp_dun.WriteStruct(VBytes, VIndex);
  419. end;
  420. procedure IdRawBuildIcmpTimestamp(const AType, ACode: UInt8; const AnId, ASeq: UInt16;
  421. const AnOtime, AnRtime, ATtime: TIdNetTime; const APayload: TIdBytes;
  422. var VBuffer: TIdBytes);
  423. var
  424. HdrIcmp: TIdIcmpTS;
  425. LIdx, LLen : UInt32;
  426. begin
  427. // check input
  428. LIdx := Id_ICMP_TS_HSIZE + Length(APayload);
  429. LLen := Length(VBuffer);
  430. if LLen < LIdx then begin
  431. SetLength(VBuffer, LIdx);
  432. end;
  433. // construct header
  434. HdrIcmp := TIdIcmpTS.Create;
  435. try
  436. HdrIcmp.icmp_type := AType;
  437. HdrIcmp.icmp_code := ACode;
  438. HdrIcmp.icmp_hun.echo_id := GStack.HostToNetwork(AnId);
  439. HdrIcmp.icmp_hun.echo_seq := GStack.HostToNetwork(ASeq);
  440. HdrIcmp.icmp_dun.ts_otime := GStack.HostToNetwork(AnOtime); // original timestamp
  441. HdrIcmp.icmp_dun.ts_rtime := GStack.HostToNetwork(AnRtime); // receive timestamp
  442. HdrIcmp.icmp_dun.ts_ttime := GStack.HostToNetwork(ATtime); // transmit timestamp
  443. // copy header
  444. LIdx := 0;
  445. HdrIcmp.WriteStruct(VBuffer, LIdx);
  446. // copy payload
  447. if Length(APayload) > 0 then begin
  448. CopyTIdBytes(APayload, 0, VBuffer, LIdx, Length(APayload));
  449. end;
  450. finally
  451. FreeAndNil(HdrIcmp);
  452. end;
  453. end;
  454. procedure IdRawBuildIcmpRedirect(const AType, ACode: UInt8; AGateway: TIdInAddr;
  455. const AnOrigLen: UInt16; const AnOrigTos: UInt8; const AnOrigId, AnOrigFrag: UInt16;
  456. const AnOrigTtl, AnOrigProtocol: UInt8; AnOrigSource, AnOrigDest: TIdInAddr;
  457. const AnOrigPayload: TIdBytes; var VBuffer: TIdBytes);
  458. var
  459. HdrIcmp: TIdIcmpHdr;
  460. LIdx, LLen : UInt32;
  461. begin
  462. // check input
  463. LIdx := Id_ICMP_REDIRECT_HSIZE + Id_IP_HSIZE + Length(AnOrigPayload);
  464. LLen := Length(VBuffer);
  465. if LLen < LIdx then begin
  466. SetLength(VBuffer, LIdx);
  467. end;
  468. // construct header
  469. HdrIcmp := TIdIcmpHdr.Create;
  470. try
  471. HdrIcmp.icmp_type := AType;
  472. HdrIcmp.icmp_code := ACode;
  473. HdrIcmp.icmp_hun.gateway_s_b1 := AGateway.s_l; // gateway address
  474. // attach original header
  475. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  476. AnOrigSource, AnOrigDest, AnOrigPayload, VBuffer, Id_ICMP_REDIRECT_HSIZE);
  477. // copy header
  478. LIdx := 0;
  479. HdrIcmp.WriteStruct(VBuffer, LIdx);
  480. finally
  481. FreeAndNil(HdrIcmp);
  482. end;
  483. end;
  484. procedure IdRawBuildIgmp(AType, ACode: UInt8; AnIp: TIdInAddr;
  485. const APayload: UInt16; var VBuffer: TIdBytes);
  486. var
  487. HdrIgmp: TIdIgmpHdr;
  488. LIdx: UInt32;
  489. LLen : UInt32;
  490. begin
  491. // check input
  492. LIdx := 2 + Id_IGMP_HSIZE;
  493. LLen := Length(VBuffer);
  494. if LLen < LIdx then begin
  495. SetLength(VBuffer, LIdx);
  496. end;
  497. // construct header
  498. HdrIgmp := TIdIgmpHdr.Create;
  499. try
  500. HdrIgmp.igmp_type := AType;
  501. HdrIgmp.igmp_code := ACode;
  502. HdrIgmp.igmp_sum := 0;
  503. HdrIgmp.igmp_group.s_l := AnIp.s_l; // group address or 0
  504. // copy payload
  505. CopyTIdUInt16(APayload, VBuffer, Id_IGMP_HSIZE);
  506. // copy header
  507. LIdx := 0;
  508. HdrIgmp.WriteStruct(VBuffer, LIdx);
  509. finally
  510. FreeAndNil(HdrIgmp);
  511. end;
  512. end;
  513. procedure IdRawBuildRip(const ACommand, AVersion: UInt8;
  514. const ARoutingDomain, AnAddressFamily, ARoutingTag: UInt16;
  515. const AnAddr, AMask, ANextHop, AMetric: UInt32;
  516. const APayload: TIdBytes; var VBuffer: TIdBytes);
  517. var
  518. HdrRip: TIdRipHdr;
  519. LIdx: UInt32;
  520. LLen : UInt32;
  521. begin
  522. // check input
  523. LIdx := Id_RIP_HSIZE + Length(APayload);
  524. LLen := Length(VBuffer);
  525. if LLen < LIdx then begin
  526. SetLength(VBuffer, LIdx);
  527. end;
  528. // construct header
  529. HdrRip := TIdRipHdr.Create;
  530. try
  531. HdrRip.rip_cmd := ACommand;
  532. HdrRip.rip_ver := AVersion;
  533. HdrRip.rip_rd := GStack.HostToNetwork(ARoutingDomain);
  534. HdrRip.rip_af := GStack.HostToNetwork(AnAddressFamily);
  535. HdrRip.rip_rt := GStack.HostToNetwork(ARoutingTag);
  536. HdrRip.rip_addr := GStack.HostToNetwork(AnAddr);
  537. HdrRip.rip_mask := GStack.HostToNetwork(AMask);
  538. HdrRip.rip_next_hop := GStack.HostToNetwork(ANextHop);
  539. HdrRip.rip_metric := GStack.HostToNetwork(AMetric);
  540. // copy payload
  541. if Length(APayload) > 0 then begin
  542. CopyTIdBytes(APayload, 0, VBuffer, Id_RIP_HSIZE, Length(APayload));
  543. end;
  544. // copy header
  545. LIdx := 0;
  546. HdrRip.WriteStruct(VBuffer, LIdx);
  547. finally
  548. FreeAndNil(HdrRip);
  549. end;
  550. end;
  551. // TODO: check nibbles in TCP header
  552. procedure IdRawBuildTcp(const ASourcePort, ADestPort: UInt16;
  553. const ASeq, AnAck: UInt32; const AControl: UInt8;
  554. const AWindowSize, AnUrgent: UInt16; const APayload: TIdBytes;
  555. var VBuffer: TIdBytes);
  556. var
  557. HdrTcp: TIdTcpHdr;
  558. LIdx, LLen: UInt32;
  559. begin
  560. // check input
  561. LIdx := Id_TCP_HSIZE + Length(VBuffer);
  562. LLen := Length(VBuffer);
  563. if LLen < LIdx then begin
  564. SetLength(VBuffer, LIdx);
  565. end;
  566. // construct header
  567. HdrTcp := TIdTcpHdr.Create;
  568. try
  569. HdrTcp.tcp_sport := GStack.HostToNetwork(ASourcePort);
  570. HdrTcp.tcp_dport := GStack.HostToNetwork(ADestPort);
  571. HdrTcp.tcp_seq := GStack.HostToNetwork(ASeq);
  572. HdrTcp.tcp_ack := GStack.HostToNetwork(AnAck); // acknowledgement number
  573. HdrTcp.tcp_flags := AControl; // control flags
  574. HdrTcp.tcp_x2off := ((Id_TCP_HSIZE div 4) shl 4) + 0; // 20 bytes div 4, x2 unused
  575. HdrTcp.tcp_win := GStack.HostToNetwork(AWindowSize); // window size
  576. HdrTcp.tcp_sum := 0;
  577. HdrTcp.tcp_urp := AnUrgent; // urgent pointer
  578. // copy payload
  579. if Length(APayload) > 0 then begin
  580. CopyTIdBytes(APayload, 0, VBuffer, Id_TCP_HSIZE, Length(APayload));
  581. end;
  582. // copy header
  583. LIdx := 0;
  584. HdrTcp.WriteStruct(VBuffer, LIdx);
  585. finally
  586. FreeAndNil(HdrTcp);
  587. end;
  588. end;
  589. procedure IdRawBuildUdp(const ASourcePort, ADestPort: UInt16;
  590. const APayload: TIdBytes; var VBuffer: TIdBytes);
  591. var
  592. HdrUdp: TIdUdpHdr;
  593. LIdx: UInt32;
  594. LLen : UInt32;
  595. begin
  596. // check input
  597. LIdx := Id_UDP_HSIZE + Length(APayload);
  598. LLen := Length(VBuffer);
  599. if LLen < Lidx then begin
  600. SetLength(VBuffer, LIdx);
  601. end;
  602. // construct header
  603. HdrUdp := TIdUdpHdr.Create;
  604. try
  605. HdrUdp.udp_sport := GStack.HostToNetwork(ASourcePort);
  606. HdrUdp.udp_dport := GStack.HostToNetwork(ADestPort);
  607. //LIdx should be okay here since we set that to the packet length earlier
  608. HdrUdp.udp_ulen := GStack.HostToNetwork(LIdx);
  609. HdrUdp.udp_sum := 0;
  610. // copy payload
  611. if Length(APayload) > 0 then begin
  612. CopyTIdBytes(APayload, 0, VBuffer, Id_UDP_HSIZE, Length(APayload));
  613. end;
  614. // copy header
  615. LIdx := 0;
  616. HdrUdp.WriteStruct(VBuffer, LIdx);
  617. finally
  618. FreeAndNil(HdrUdp);
  619. end;
  620. end;
  621. end.