IdRawFunctions.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10293: IdRawFunctions.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:49:30 PM czhower
  13. }
  14. unit IdRawFunctions;
  15. interface
  16. uses
  17. IdStack, IdRawHeaders;
  18. // ARP
  19. function IdRawBuildArp(AHwAddressFormat, AProtocolFormat: word; AHwAddressLen, AProtocolLen: byte;
  20. AnOpType: word; ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr; ATargetPr: TIdInAddr;
  21. const APayload; APayloadSize: integer; var ABuffer): boolean;
  22. // DNS
  23. function IdRawBuildDns(AnId, AFlags, ANumQuestions, ANumAnswerRecs, ANumAuthRecs, ANumAddRecs: word;
  24. const APayload; APayloadSize: integer; var ABuffer): boolean;
  25. // Ethernet
  26. function IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: word;
  27. const APayload; APayloadSize: integer; var ABuffer): boolean;
  28. // ICMP
  29. function IdRawBuildIcmpEcho(AType, ACode: byte; AnId, ASeq: word;
  30. const APayload; APayloadSize: integer; var ABuffer): boolean;
  31. function IdRawBuildIcmpMask(AType, ACode: byte; AnId, ASeq: word; AMask: longword;
  32. const APayload; APayloadSize: integer; var ABuffer): boolean;
  33. function IdRawBuildIcmpRedirect(AType, ACode: byte; AGateway: TIdInAddr;
  34. AnOrigLen: word; AnOrigTos: byte; AnOrigId, AnOrigFrag: word; AnOrigTtl, AnOrigProtocol: byte;
  35. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload; APayloadSize: integer; var ABuffer): boolean;
  36. function IdRawBuildIcmpTimeExceed(AType, ACode: byte; AnOrigLen: word; AnOrigTos: byte;
  37. AnOrigId, AnOrigFrag: word; AnOrigTtl: byte; AnOrigProtocol: byte;
  38. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload; APayloadSize: integer; var ABuffer): boolean;
  39. function IdRawBuildIcmpTimestamp(AType, ACode: byte; AnId, ASeq: word;
  40. AnOtime, AnRtime, ATtime: TIdNetTime; const APayload; APayloadSize: integer; var ABuffer): boolean;
  41. function IdRawBuildIcmpUnreach(AType, ACode: byte; AnOrigLen: word;
  42. AnOrigTos: byte; AnOrigId, AnOrigFrag: word; AnOrigTtl, AnOrigProtocol: byte;
  43. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: integer; var ABuffer): boolean;
  44. // IGMP
  45. function IdRawBuildIgmp(AType, ACode: byte; AnIp: TIdInAddr;
  46. const APayload, APayloadSize: integer; var ABuffer): boolean;
  47. // IP
  48. function IdRawBuildIp(ALen: word; ATos: byte; AnId, AFrag: word; ATtl, AProtocol: byte;
  49. ASource, ADest: TIdInAddr; const APayload; APayloadSize: integer; var ABuffer): boolean;
  50. // RIP
  51. function IdRawBuildRip(ACommand, AVersion: byte; ARoutingDomain, AnAddressFamily,
  52. ARoutingTag: word; AnAddr, AMask, ANextHop, AMetric: longword;
  53. const APayload; APayloadSize: integer; var ABuffer): boolean;
  54. // TCP
  55. function IdRawBuildTcp(ASourcePort, ADestPort: word; ASeq, AnAck: longword;
  56. AControl: byte; AWindowSize, AnUrgent: word;
  57. const APayload, APayloadSize: integer; var ABuffer): boolean;
  58. // UDP
  59. function IdRawBuildUdp(ASourcePort, ADestPort: word; const APayload;
  60. APayloadSize: integer; var ABuffer): boolean;
  61. implementation
  62. // TODO: is it okay to call GStack?
  63. function IdRawBuildArp(AHwAddressFormat, AProtocolFormat: word; AHwAddressLen, AProtocolLen: byte;
  64. AnOpType: word; ASenderHw: TIdEtherAddr; ASenderPr: TIdInAddr; ATargetHw: TIdEtherAddr; ATargetPr: TIdInAddr;
  65. const APayload; APayloadSize: integer; var ABuffer): boolean;
  66. var
  67. HdrArp: TIdArpHdr;
  68. begin
  69. // init result
  70. Result := FALSE;
  71. // check input
  72. if (@ABuffer = nil) then
  73. Exit;
  74. // construct header
  75. HdrArp.arp_hrd := GStack.WSHToNS(AHwAddressFormat);
  76. HdrArp.arp_pro := GStack.WSHToNS(AProtocolFormat);
  77. HdrArp.arp_hln := AHwAddressLen;
  78. HdrArp.arp_pln := AProtocolLen;
  79. HdrArp.arp_op := GStack.WSHToNS(AnOpType);
  80. Move(ASenderHw, HdrArp.arp_sha, AHwAddressLen);
  81. Move(ASenderPr, HdrArp.arp_spa, AProtocolLen);
  82. Move(ATargetHw, HdrArp.arp_tha, AHwAddressLen);
  83. Move(ATargetPr, HdrArp.arp_tpa, AProtocolLen);
  84. // copy payload
  85. if ((@APayload <> nil) and (APayloadSize > 0)) then
  86. Move(APayload, pointer(integer(@ABuffer) + Id_ARP_HSIZE)^, APayloadSize);
  87. // copy header
  88. Move(HdrArp, ABuffer, sizeof(HdrArp));
  89. Result := TRUE;
  90. end;
  91. function IdRawBuildDns(AnId, AFlags, ANumQuestions, ANumAnswerRecs, ANumAuthRecs, ANumAddRecs: word;
  92. const APayload; APayloadSize: integer; var ABuffer): boolean;
  93. var
  94. HdrDns: TIdDnsHdr;
  95. begin
  96. // init result
  97. Result := FALSE;
  98. // check input
  99. if (@ABuffer = nil) then
  100. Exit;
  101. // construct header
  102. HdrDns.dns_id := GStack.WSHToNS(AnId);
  103. HdrDns.dns_flags := GStack.WSHToNS(AFlags);
  104. HdrDns.dns_num_q := GStack.WSHToNS(ANumQuestions);
  105. HdrDns.dns_num_answ_rr := GStack.WSHToNS(ANumAnswerRecs);
  106. HdrDns.dns_num_auth_rr := GStack.WSHToNS(ANumAuthRecs);
  107. HdrDns.dns_num_addi_rr := GStack.WSHToNS(ANumAddRecs);
  108. // copy payload
  109. if ((@APayload <> nil) and (APayloadSize > 0)) then
  110. Move(APayload, pointer(integer(@ABuffer) + Id_DNS_HSIZE)^, APayloadSize);
  111. // copy header
  112. Move(HdrDns, ABuffer, sizeof(HdrDns));
  113. Result := TRUE;
  114. end;
  115. function IdRawBuildEthernet(ADest, ASource: TIdEtherAddr; AType: word;
  116. const APayload; APayloadSize: integer; var ABuffer): boolean;
  117. var
  118. HdrEth: TIdEthernetHdr;
  119. begin
  120. // init result
  121. Result := FALSE;
  122. // check input
  123. if (@ABuffer = nil) then
  124. Exit;
  125. // construct header
  126. Move(ADest, HdrEth.ether_dhost, Id_ETHER_ADDR_LEN);
  127. Move(ASource, HdrEth.ether_shost, Id_ETHER_ADDR_LEN);
  128. HdrEth.ether_type := GStack.WSHToNS(AType);
  129. // copy payload
  130. if ((@APayload <> nil) and (APayloadSize > 0)) then
  131. Move(APayload, pointer(integer(@ABuffer) + Id_ETH_HSIZE)^, APayloadSize);
  132. // copy header
  133. Move(HdrEth, ABuffer, sizeof(HdrEth));
  134. Result := TRUE;
  135. end;
  136. // TODO: check nibbles in IP header
  137. function IdRawBuildIp(ALen: word; ATos: byte; AnId, AFrag: word; ATtl, AProtocol: byte;
  138. ASource, ADest: TIdInAddr; const APayload; APayloadSize: integer; var ABuffer): boolean;
  139. var
  140. HdrIp: TIdIpHdr;
  141. begin
  142. // init result
  143. Result := FALSE;
  144. // check input
  145. if (@ABuffer = nil) then
  146. Exit;
  147. // construct header
  148. HdrIp.ip_verlen := (4 shl 4) + (Id_IP_HSIZE div 4); // IPv4 shl 4, 20 bytes div 4
  149. HdrIp.ip_tos := ATos;
  150. HdrIp.ip_len := GStack.WSHToNs(Id_IP_HSIZE + ALen);
  151. HdrIp.ip_id := GStack.WSHToNs(AnId);
  152. HdrIp.ip_off := GStack.WSHToNs(AFrag);
  153. HdrIp.ip_ttl := ATtl;
  154. HdrIp.ip_p := AProtocol;
  155. HdrIp.ip_sum := 0; // do checksum later
  156. HdrIp.ip_src := ASource;
  157. HdrIp.ip_dst := ADest;
  158. // copy payload
  159. if ((@APayload <> nil) and (APayloadSize > 0)) then
  160. Move(APayload, pointer(integer(@ABuffer) + Id_IP_HSIZE)^, APayloadSize);
  161. // copy header
  162. Move(HdrIp, ABuffer, Id_IP_HSIZE);
  163. Result := TRUE;
  164. end;
  165. function IdRawBuildIcmpEcho(AType, ACode: byte; AnId, ASeq: word;
  166. const APayload; APayloadSize: integer; var ABuffer): boolean;
  167. var
  168. HdrIcmp: TIdIcmpHdr;
  169. begin
  170. // init result
  171. Result := FALSE;
  172. // check input
  173. if (@ABuffer = nil) then
  174. Exit;
  175. // construct header
  176. HdrIcmp.icmp_type := AType;
  177. HdrIcmp.icmp_code := ACode;
  178. HdrIcmp.icmp_hun.echo.id := GStack.WSHToNs(AnId);
  179. HdrIcmp.icmp_hun.echo.seq := GStack.WSHToNs(ASeq);
  180. // copy payload
  181. if ((@APayload <> nil) and (APayloadSize > 0)) then
  182. Move(APayload, pointer(integer(@ABuffer) + Id_ICMP_ECHO_HSIZE)^, APayloadSize);
  183. // copy header
  184. Move(HdrIcmp, ABuffer, Id_ICMP_ECHO_HSIZE);
  185. Result := TRUE;
  186. end;
  187. function IdRawBuildIcmpMask(AType, ACode: byte; AnId, ASeq: word; AMask: longword;
  188. const APayload; APayloadSize: integer; var ABuffer): boolean;
  189. var
  190. HdrIcmp: TIdIcmpHdr;
  191. begin
  192. // init result
  193. Result := FALSE;
  194. // check input
  195. if (@ABuffer = nil) then
  196. Exit;
  197. // construct header
  198. HdrIcmp.icmp_type := AType;
  199. HdrIcmp.icmp_code := ACode;
  200. HdrIcmp.icmp_hun.echo.id := GStack.WSHToNs(AnId);
  201. HdrIcmp.icmp_hun.echo.seq := GStack.WSHToNs(ASeq);
  202. HdrIcmp.icmp_dun.mask := GStack.WSHToNL(AMask);
  203. // copy payload
  204. if ((@APayload <> nil) and (APayloadSize > 0)) then
  205. Move(APayload, pointer(integer(@ABuffer) + Id_ICMP_MASK_HSIZE)^, APayloadSize);
  206. // copy header
  207. Move(HdrIcmp, ABuffer, Id_ICMP_MASK_HSIZE);
  208. Result := TRUE;
  209. end;
  210. function IdRawBuildIcmpUnreach(AType, ACode: byte; AnOrigLen: word;
  211. AnOrigTos: byte; AnOrigId, AnOrigFrag: word; AnOrigTtl, AnOrigProtocol: byte;
  212. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload, APayloadSize: integer; var ABuffer): boolean;
  213. var
  214. HdrIcmp: TIdIcmpHdr;
  215. begin
  216. // init result
  217. Result := FALSE;
  218. // check input
  219. if (@ABuffer = nil) then
  220. Exit;
  221. // construct header
  222. HdrIcmp.icmp_type := AType;
  223. HdrIcmp.icmp_code := ACode;
  224. HdrIcmp.icmp_hun.echo.id := 0;
  225. HdrIcmp.icmp_hun.echo.seq := 0;
  226. // attach original header
  227. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  228. AnOrigSource, AnOrigDest, AnOrigPayload, APayloadSize,
  229. pointer(integer(@ABuffer) + Id_ICMP_UNREACH_HSIZE)^);
  230. // copy header
  231. Move(HdrIcmp, ABuffer, Id_ICMP_UNREACH_HSIZE);
  232. Result := TRUE;
  233. end;
  234. function IdRawBuildIcmpTimeExceed(AType, ACode: byte; AnOrigLen: word; AnOrigTos: byte;
  235. AnOrigId, AnOrigFrag: word; AnOrigTtl: byte; AnOrigProtocol: byte;
  236. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload; APayloadSize: integer; var ABuffer): boolean;
  237. var
  238. HdrIcmp: TIdIcmpHdr;
  239. begin
  240. // init result
  241. Result := FALSE;
  242. // check input
  243. if (@ABuffer = nil) then
  244. Exit;
  245. // construct header
  246. HdrIcmp.icmp_type := AType;
  247. HdrIcmp.icmp_code := ACode;
  248. HdrIcmp.icmp_hun.echo.id := 0;
  249. HdrIcmp.icmp_hun.echo.seq := 0;
  250. // attach original header
  251. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  252. AnOrigSource, AnOrigDest, AnOrigPayload, APayloadSize,
  253. pointer(integer(@ABuffer) + Id_ICMP_TIMEXCEED_HSIZE)^);
  254. // copy header
  255. Move(HdrIcmp, ABuffer, Id_ICMP_TIMEXCEED_HSIZE);
  256. Result := TRUE;
  257. end;
  258. function IdRawBuildIcmpTimestamp(AType, ACode: byte; AnId, ASeq: word;
  259. AnOtime, AnRtime, ATtime: TIdNetTime; const APayload; APayloadSize: integer; var ABuffer): boolean;
  260. var
  261. HdrIcmp: TIdIcmpHdr;
  262. begin
  263. // init result
  264. Result := FALSE;
  265. // check input
  266. if (@ABuffer = nil) then
  267. Exit;
  268. // construct header
  269. HdrIcmp.icmp_type := AType;
  270. HdrIcmp.icmp_code := ACode;
  271. HdrIcmp.icmp_hun.echo.id := GStack.WSHToNs(AnId);
  272. HdrIcmp.icmp_hun.echo.seq := GStack.WSHToNs(ASeq);
  273. HdrIcmp.icmp_dun.ts.otime := GStack.WSHToNL(AnOtime); // original timestamp
  274. HdrIcmp.icmp_dun.ts.rtime := GStack.WSHToNL(AnRtime); // receive timestamp
  275. HdrIcmp.icmp_dun.ts.ttime := GStack.WSHToNL(ATtime); // transmit timestamp
  276. // copy payload
  277. if ((@APayload <> nil) and (APayloadSize > 0)) then
  278. Move(APayload, pointer(integer(@ABuffer) + Id_ICMP_TS_HSIZE)^, APayloadSize);
  279. // copy header
  280. Move(HdrIcmp, ABuffer, Id_ICMP_TS_HSIZE);
  281. Result := TRUE;
  282. end;
  283. function IdRawBuildIcmpRedirect(AType, ACode: byte; AGateway: TIdInAddr;
  284. AnOrigLen: word; AnOrigTos: byte; AnOrigId, AnOrigFrag: word; AnOrigTtl, AnOrigProtocol: byte;
  285. AnOrigSource, AnOrigDest: TIdInAddr; const AnOrigPayload; APayloadSize: integer; var ABuffer): boolean;
  286. var
  287. HdrIcmp: TIdIcmpHdr;
  288. begin
  289. // init result
  290. Result := FALSE;
  291. // check input
  292. if (@ABuffer = nil) then
  293. Exit;
  294. // construct header
  295. HdrIcmp.icmp_type := AType;
  296. HdrIcmp.icmp_code := ACode;
  297. HdrIcmp.icmp_hun.gateway := AGateway; // gateway address
  298. // attach original header
  299. IdRawBuildIp(0, AnOrigTos, AnOrigId, AnOrigFrag, AnOrigTtl, AnOrigProtocol,
  300. AnOrigSource, AnOrigDest, AnOrigPayload, APayloadSize,
  301. pointer(integer(@ABuffer) + Id_ICMP_REDIRECT_HSIZE)^);
  302. // copy header
  303. Move(HdrIcmp, ABuffer, Id_ICMP_REDIRECT_HSIZE);
  304. Result := TRUE;
  305. end;
  306. function IdRawBuildIgmp(AType, ACode: byte; AnIp: TIdInAddr;
  307. const APayload, APayloadSize: integer; var ABuffer): boolean;
  308. var
  309. HdrIgmp: TIdIgmpHdr;
  310. begin
  311. // init result
  312. Result := FALSE;
  313. // check input
  314. if (@ABuffer = nil) then
  315. Exit;
  316. // construct header
  317. HdrIgmp.igmp_type := AType;
  318. HdrIgmp.igmp_code := ACode;
  319. HdrIgmp.igmp_sum := 0;
  320. HdrIgmp.igmp_group := AnIp; // group address or 0
  321. // copy payload
  322. if ((@APayload <> nil) and (APayloadSize > 0)) then
  323. Move(APayload, pointer(integer(@ABuffer) + Id_IGMP_HSIZE)^, APayloadSize);
  324. // copy header
  325. Move(HdrIgmp, ABuffer, sizeof(HdrIgmp));
  326. Result := TRUE;
  327. end;
  328. function IdRawBuildRip(ACommand, AVersion: byte; ARoutingDomain, AnAddressFamily,
  329. ARoutingTag: word; AnAddr, AMask, ANextHop, AMetric: longword;
  330. const APayload; APayloadSize: integer; var ABuffer): boolean;
  331. var
  332. HdrRip: TIdRipHdr;
  333. begin
  334. // init result
  335. Result := FALSE;
  336. // check input
  337. if (@ABuffer = nil) then
  338. Exit;
  339. // construct header
  340. HdrRip.rip_cmd := ACommand;
  341. HdrRip.rip_ver := AVersion;
  342. HdrRip.rip_rd := GStack.WSHToNS(ARoutingDomain);
  343. HdrRip.rip_af := GStack.WSHToNS(AnAddressFamily);
  344. HdrRip.rip_rt := GStack.WSHToNS(ARoutingTag);
  345. HdrRip.rip_addr := GStack.WSHToNL(AnAddr);
  346. HdrRip.rip_mask := GStack.WSHToNL(AMask);
  347. HdrRip.rip_next_hop := GStack.WSHToNL(ANextHop);
  348. HdrRip.rip_metric := GStack.WSHToNL(AMetric);
  349. // copy payload
  350. if ((@APayload <> nil) and (APayloadSize > 0)) then
  351. Move(APayload, pointer(integer(@ABuffer) + Id_RIP_HSIZE)^, APayloadSize);
  352. // copy header
  353. Move(HdrRip, ABuffer, sizeof(HdrRip));
  354. Result := TRUE;
  355. end;
  356. // TODO: check nibbles in TCP header
  357. function IdRawBuildTcp(ASourcePort, ADestPort: word; ASeq, AnAck: longword;
  358. AControl: byte; AWindowSize, AnUrgent: word;
  359. const APayload, APayloadSize: integer; var ABuffer): boolean;
  360. var
  361. HdrTcp: TIdTcpHdr;
  362. begin
  363. // init result
  364. Result := FALSE;
  365. // check input
  366. if (@ABuffer = nil) then
  367. Exit;
  368. // construct header
  369. HdrTcp.tcp_sport := GStack.WSHToNS(ASourcePort);
  370. HdrTcp.tcp_dport := GStack.WSHToNS(ADestPort);
  371. HdrTcp.tcp_seq := GStack.WSHToNL(ASeq);
  372. HdrTcp.tcp_ack := GStack.WSHToNL(AnAck); // acknowledgement number
  373. HdrTcp.tcp_flags := AControl; // control flags
  374. HdrTcp.tcp_x2off := ((Id_TCP_HSIZE div 4) shl 4) + 0; // 20 bytes div 4, x2 unused
  375. HdrTcp.tcp_win := GStack.WSHToNS(AWindowSize); // window size
  376. HdrTcp.tcp_sum := 0;
  377. HdrTcp.tcp_urp := AnUrgent; // urgent pointer
  378. // copy payload
  379. if ((@APayload <> nil) and (APayloadSize > 0)) then
  380. Move(APayload, pointer(integer(@ABuffer) + Id_TCP_HSIZE)^, APayloadSize);
  381. // copy header
  382. Move(HdrTcp, ABuffer, sizeof(HdrTcp));
  383. Result := TRUE;
  384. end;
  385. function IdRawBuildUdp(ASourcePort, ADestPort: word; const APayload;
  386. APayloadSize: integer; var ABuffer): boolean;
  387. var
  388. HdrUdp: TIdUdpHdr;
  389. begin
  390. Result := FALSE;
  391. // check input
  392. if (@ABuffer = nil) then
  393. Exit;
  394. // construct header
  395. HdrUdp.udp_dport := GStack.WSHToNS(ASourcePort);
  396. HdrUdp.udp_dport := GStack.WSHToNS(ADestPort);
  397. HdrUdp.udp_ulen := GStack.WSHToNS(Id_UDP_HSIZE + APayloadSize);
  398. HdrUdp.udp_sum := 0;
  399. // copy payload
  400. if ((@APayload <> nil) and (APayloadSize > 0)) then
  401. Move(APayload, pointer(integer(@ABuffer) + Id_UDP_HSIZE)^, APayloadSize);
  402. // copy header
  403. Move(HdrUdp, ABuffer, sizeof(HdrUdp));
  404. Result := TRUE;
  405. end;
  406. end.