IdNetworkCalculator.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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: 10269: IdNetworkCalculator.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:47:10 PM czhower
  13. }
  14. unit IdNetworkCalculator;
  15. interface
  16. uses
  17. SysUtils, Classes, IdBaseComponent;
  18. type
  19. TIpStruct = record
  20. case integer of
  21. 0: (Byte4, Byte3, Byte2, Byte1: byte);
  22. 1: (FullAddr: Longword);
  23. end;
  24. TNetworkClass = (ID_NET_CLASS_A, ID_NET_CLASS_B, ID_NET_CLASS_C,
  25. ID_NET_CLASS_D, ID_NET_CLASS_E);
  26. const
  27. ID_NC_MASK_LENGTH = 32;
  28. ID_NETWORKCLASS = ID_NET_CLASS_A;
  29. type
  30. TIdIPAddressType = (IPLocalHost, IPLocalNetwork, IPReserved, IPInternetHost,
  31. IPPrivateNetwork, IPLoopback, IPMulticast, IPFutureUse, IPGlobalBroadcast);
  32. TIpProperty = Class(TPersistent)
  33. protected
  34. FReadOnly: boolean;
  35. FOnChange: TNotifyEvent;
  36. FByteArray: array[0..31] of boolean;
  37. FDoubleWordValue: Longword;
  38. FAsString: String;
  39. FAsBinaryString: String;
  40. FByte3: Byte;
  41. FByte4: Byte;
  42. FByte2: Byte;
  43. FByte1: byte;
  44. function GetAddressType: TIdIPAddressType;
  45. procedure SetReadOnly(const Value: boolean);
  46. procedure SetOnChange(const Value: TNotifyEvent);
  47. function GetByteArray(Index: cardinal): boolean;
  48. procedure SetAsBinaryString(const Value: String);
  49. procedure SetAsDoubleWord(const Value: Longword);
  50. procedure SetAsString(const Value: String);
  51. procedure SetByteArray(Index: cardinal; const Value: boolean);
  52. procedure SetByte4(const Value: Byte);
  53. procedure SetByte1(const Value: byte);
  54. procedure SetByte3(const Value: Byte);
  55. procedure SetByte2(const Value: Byte);
  56. //
  57. property ReadOnly: boolean read FReadOnly write SetReadOnly default false;
  58. public
  59. procedure SetAll(One, Two, Three, Four: Byte); virtual;
  60. procedure Assign(Source: Tpersistent); override;
  61. //
  62. property ByteArray[Index: cardinal]: boolean read GetByteArray write SetByteArray;
  63. property AddressType: TIdIPAddressType read GetAddressType;
  64. published
  65. property Byte1: byte read FByte1 write SetByte1 stored false;
  66. property Byte2: Byte read FByte2 write SetByte2 stored false;
  67. property Byte3: Byte read FByte3 write SetByte3 stored false;
  68. property Byte4: Byte read FByte4 write SetByte4 stored false;
  69. property AsDoubleWord: Longword read FDoubleWordValue write SetAsDoubleWord stored false;
  70. property AsBinaryString: String read FAsBinaryString write SetAsBinaryString stored false;
  71. property AsString: String read FAsString write SetAsString;
  72. property OnChange: TNotifyEvent read FOnChange write SetOnChange;
  73. end;
  74. TIdNetworkCalculator = class(TIdBaseComponent)
  75. protected
  76. FListIP: TStrings;
  77. FNetworkMaskLength: cardinal;
  78. FNetworkMask: TIpProperty;
  79. FNetworkAddress: TIpProperty;
  80. FNetworkClass: TNetworkClass;
  81. FOnChange: TNotifyEvent;
  82. FOnGenIPList: TNotifyEvent;
  83. function GetNetworkClassAsString: String;
  84. function GetIsAddressRoutable: Boolean;
  85. procedure SetOnChange(const Value: TNotifyEvent);
  86. procedure SetOnGenIPList(const Value: TNotifyEvent);
  87. function GetListIP: TStrings;
  88. procedure SetNetworkAddress(const Value: TIpProperty);
  89. procedure SetNetworkMask(const Value: TIpProperty);
  90. procedure SetNetworkMaskLength(const Value: cardinal);
  91. procedure OnNetMaskChange(Sender: TObject);
  92. procedure OnNetAddressChange(Sender: TObject);
  93. public
  94. function NumIP: integer;
  95. function StartIP: String;
  96. function EndIP: String;
  97. procedure FillIPList;
  98. constructor Create(AOwner: TComponent); override;
  99. destructor Destroy; override;
  100. //
  101. property ListIP: TStrings read GetListIP;
  102. property NetworkClass: TNetworkClass read FNetworkClass;
  103. property NetworkClassAsString: String read GetNetworkClassAsString;
  104. property IsAddressRoutable: Boolean read GetIsAddressRoutable;
  105. published
  106. function IsAddressInNetwork(Address: String): Boolean;
  107. property NetworkAddress: TIpProperty read FNetworkAddress write SetNetworkAddress;
  108. property NetworkMask: TIpProperty read FNetworkMask write SetNetworkMask;
  109. property NetworkMaskLength: cardinal read FNetworkMaskLength write SetNetworkMaskLength
  110. default ID_NC_MASK_LENGTH;
  111. property OnGenIPList: TNotifyEvent read FOnGenIPList write SetOnGenIPList;
  112. property OnChange: TNotifyEvent read FOnChange write SetOnChange;
  113. end;
  114. implementation
  115. uses
  116. IdException, IdGlobal, IdResourceStrings;
  117. { TIdNetworkCalculator }
  118. function IP(Byte1, Byte2, Byte3, Byte4: byte): TIpStruct;
  119. begin
  120. result.Byte1 := Byte1;
  121. result.Byte2 := Byte2;
  122. result.Byte3 := Byte3;
  123. result.Byte4 := Byte4;
  124. end;
  125. function StrToIP(const value: string): TIPStruct;
  126. var
  127. strBuffers: Array [0..3] of String;
  128. cardBuffers: Array[0..3] of cardinal;
  129. StrWork: String;
  130. begin
  131. StrWork := Value;
  132. // Separate the strings
  133. strBuffers[0] := Fetch(StrWork, '.', true); {Do not Localize}
  134. strBuffers[1] := Fetch(StrWork, '.', true); {Do not Localize}
  135. strBuffers[2] := Fetch(StrWork, '.', true); {Do not Localize}
  136. strBuffers[3] := StrWork;
  137. try
  138. cardBuffers[0] := StrToInt(strBuffers[0]);
  139. cardBuffers[1] := StrToInt(strBuffers[1]);
  140. cardBuffers[2] := StrToInt(strBuffers[2]);
  141. cardBuffers[3] := StrToInt(strBuffers[3]);
  142. except
  143. on e: exception do
  144. Raise exception.Create(Format( RSNETCALInvalidIPString, [Value]));
  145. end;
  146. // range check
  147. if not(cardBuffers[0] in [0..255]) then
  148. raise EIdException.Create(Format( RSNETCALInvalidIPString, [Value]));
  149. if not(cardBuffers[1] in [0..255]) then
  150. raise EIdException.Create(Format( RSNETCALInvalidIPString, [Value]));
  151. if not(cardBuffers[2] in [0..255]) then
  152. raise EIdException.Create(Format( RSNETCALInvalidIPString, [Value]));
  153. if not(cardBuffers[3] in [0..255]) then
  154. raise EIdException.Create(Format( RSNETCALInvalidIPString, [Value]));
  155. result := IP(cardBuffers[0], cardBuffers[1], cardBuffers[2], cardBuffers[3]);
  156. end;
  157. constructor TIdNetworkCalculator.Create(AOwner: TComponent);
  158. begin
  159. inherited;
  160. FNetworkMask := TIpProperty.Create;
  161. FNetworkAddress := TIpProperty.Create;
  162. FNetworkMask.OnChange := OnNetMaskChange;
  163. FNetworkAddress.OnChange := OnNetAddressChange;
  164. FListIP := TStringList.Create;
  165. FNetworkClass := ID_NETWORKCLASS;
  166. NetworkMaskLength := ID_NC_MASK_LENGTH;
  167. end;
  168. destructor TIdNetworkCalculator.Destroy;
  169. begin
  170. FNetworkMask.Free;
  171. FNetworkAddress.Free;
  172. FListIP.Free;
  173. inherited;
  174. end;
  175. procedure TIdNetworkCalculator.FillIPList;
  176. var
  177. i: Cardinal;
  178. BaseIP: TIpStruct;
  179. begin
  180. if FListIP.Count = 0 then
  181. begin
  182. // prevent to start a long loop in the IDE (will lock delphi)
  183. if (csDesigning in ComponentState) and (NumIP > 1024) then
  184. begin
  185. FListIP.text := Format(RSNETCALConfirmLongIPList,[NumIP]);
  186. end
  187. else
  188. begin
  189. BaseIP.FullAddr := NetworkAddress.AsDoubleWord AND NetworkMask.AsDoubleWord;
  190. // preallocate the memory for the list
  191. FListIP.Capacity := NumIP;
  192. // Lock the list so we won't be "repainting" the whole time... {Do not Localize}
  193. FListIP.BeginUpdate;
  194. try
  195. for i := 1 to (NumIP - 1) do
  196. begin
  197. Inc(BaseIP.FullAddr);
  198. FListIP.append(format('%d.%d.%d.%d', [BaseIP.Byte1, BaseIP.Byte2, BaseIP.Byte3, BaseIP.Byte4])); {Do not Localize}
  199. end;
  200. finally
  201. FListIP.EndUpdate;
  202. end;
  203. end;
  204. end;
  205. end;
  206. function TIdNetworkCalculator.GetListIP: TStrings;
  207. begin
  208. FillIPList;
  209. result := FListIP;
  210. end;
  211. function TIdNetworkCalculator.IsAddressInNetwork(Address: String): Boolean;
  212. var
  213. IPStruct: TIPStruct;
  214. begin
  215. IPStruct := StrToIP(Address);
  216. result := (IPStruct.FullAddr AND NetworkMask.FDoubleWordValue) = (NetworkAddress.FDoubleWordValue AND NetworkMask.FDoubleWordValue);
  217. end;
  218. procedure TIdNetworkCalculator.OnNetAddressChange(Sender: TObject);
  219. begin
  220. FListIP.Clear;
  221. // RFC 1365
  222. if IndyPos('0', NetworkAddress.AsBinaryString) = 1 then {Do not Localize}
  223. begin
  224. fNetworkClass := ID_NET_CLASS_A;
  225. end;
  226. if IndyPos('10', NetworkAddress.AsBinaryString) = 1 then {Do not Localize}
  227. begin
  228. fNetworkClass := ID_NET_CLASS_B;
  229. end;
  230. if IndyPos('110', NetworkAddress.AsBinaryString) = 1 then {Do not Localize}
  231. begin
  232. fNetworkClass := ID_NET_CLASS_C;
  233. end;
  234. // Network class D is reserved for multicast
  235. if IndyPos('1110', NetworkAddress.AsBinaryString) = 1 then {Do not Localize}
  236. begin
  237. fNetworkClass := ID_NET_CLASS_D;
  238. end;
  239. // network class E is reserved and shouldn't be used {Do not Localize}
  240. if IndyPos('1111', NetworkAddress.AsBinaryString) = 1 then {Do not Localize}
  241. begin
  242. fNetworkClass := ID_NET_CLASS_E;
  243. end;
  244. if assigned( FOnChange ) then
  245. FOnChange(Self);
  246. end;
  247. procedure TIdNetworkCalculator.OnNetMaskChange(Sender: TObject);
  248. var
  249. sBuffer: string;
  250. InitialMaskLength: Cardinal;
  251. begin
  252. FListIP.Clear;
  253. InitialMaskLength := FNetworkMaskLength;
  254. // A network mask MUST NOT contains holes.
  255. sBuffer := FNetworkMask.AsBinaryString;
  256. while (length(sBuffer) > 0) and (sBuffer[1] = '1') do {Do not Localize}
  257. begin
  258. Delete(sBuffer, 1, 1);
  259. end; { while }
  260. if IndyPos('1', sBuffer) > 0 then {Do not Localize}
  261. begin
  262. NetworkMaskLength := InitialMaskLength;
  263. raise EIdexception.Create(RSNETCALCInvalidNetworkMask); // 'Invalid network mask' {Do not Localize}
  264. end
  265. else
  266. begin
  267. // set the net mask length
  268. NetworkMaskLength := 32 - Length(sBuffer);
  269. end;
  270. if assigned( FOnChange ) then
  271. FOnChange(Self);
  272. end;
  273. procedure TIdNetworkCalculator.SetNetworkAddress(const Value: TIpProperty);
  274. begin
  275. FNetworkAddress.Assign(Value);
  276. end;
  277. procedure TIdNetworkCalculator.SetNetworkMask(const Value: TIpProperty);
  278. begin
  279. FNetworkMask.Assign(Value);
  280. end;
  281. procedure TIdNetworkCalculator.SetNetworkMaskLength(const Value: cardinal);
  282. var
  283. LBuffer: Cardinal;
  284. begin
  285. FNetworkMaskLength := Value;
  286. if Value > 0 then begin
  287. LBuffer := High(Cardinal) shl (32 - Value);
  288. end else begin
  289. LBuffer := 0;
  290. end;
  291. FNetworkMask.AsDoubleWord := LBuffer;
  292. end;
  293. procedure TIdNetworkCalculator.SetOnGenIPList(const Value: TNotifyEvent);
  294. begin
  295. FOnGenIPList := Value;
  296. end;
  297. procedure TIdNetworkCalculator.SetOnChange(const Value: TNotifyEvent);
  298. begin
  299. FOnChange := Value;
  300. end;
  301. function TIdNetworkCalculator.GetNetworkClassAsString: String;
  302. begin
  303. Case FNetworkClass of
  304. ID_NET_CLASS_A:
  305. result := 'A'; {Do not Localize}
  306. ID_NET_CLASS_B:
  307. result := 'B'; {Do not Localize}
  308. ID_NET_CLASS_C:
  309. result := 'C'; {Do not Localize}
  310. ID_NET_CLASS_D:
  311. result := 'D'; {Do not Localize}
  312. ID_NET_CLASS_E:
  313. result := 'E'; {Do not Localize}
  314. end; // case
  315. end;
  316. function TIdNetworkCalculator.GetIsAddressRoutable: Boolean;
  317. begin
  318. // RFC
  319. result := (NetworkAddress.Byte1 = 10) or
  320. ((NetworkAddress.Byte1 = 172) and (NetworkAddress.Byte2 in [16..31])) or
  321. ((NetworkAddress.Byte1 = 192) and (NetworkAddress.Byte2 = 168));
  322. end;
  323. { TIpProperty }
  324. procedure TIpProperty.Assign(Source: Tpersistent);
  325. begin
  326. if Source is TIpProperty then
  327. with source as TIpProperty do
  328. begin
  329. Self.SetAll(Byte1, Byte2, Byte3, Byte4);
  330. end; { with }
  331. if assigned( FOnChange ) then
  332. FOnChange( Self );
  333. inherited;
  334. end;
  335. function TIpProperty.GetByteArray(Index: cardinal): boolean;
  336. begin
  337. result := FByteArray[index]
  338. end;
  339. procedure TIpProperty.SetAll(One, Two, Three, Four: Byte);
  340. var
  341. i: Integer;
  342. InitialIP, IpStruct: TIpStruct;
  343. begin
  344. // Set the individual bytes
  345. InitialIP := IP(FByte1, FByte2, FByte3, FByte4);
  346. FByte1 := One;
  347. FByte2 := Two;
  348. FByte3 := Three;
  349. FByte4 := Four;
  350. // Set the DWord Value
  351. IpStruct.Byte1 := Byte1;
  352. IpStruct.Byte2 := Byte2;
  353. IpStruct.Byte3 := Byte3;
  354. IpStruct.Byte4 := Byte4;
  355. FDoubleWordValue := IpStruct.FullAddr;
  356. // Set the bits array and the binary string
  357. SetLength(FAsBinaryString, 32);
  358. // Second, fill the array
  359. for i := 1 to 32 do
  360. begin
  361. FByteArray[i - 1] := ((FDoubleWordValue shl (i-1)) shr 31) = 1;
  362. if FByteArray[i - 1] then
  363. FAsBinaryString[i] := '1' {Do not Localize}
  364. else
  365. FAsBinaryString[i] := '0'; {Do not Localize}
  366. end;
  367. // Set the string
  368. FAsString := Format('%d.%d.%d.%d', [FByte1, FByte2, FByte3, FByte4]); {Do not Localize}
  369. IpStruct := IP(FByte1, FByte2, FByte3, FByte4);
  370. if IpStruct.FullAddr <> InitialIP.FullAddr then
  371. begin
  372. if assigned( FOnChange ) then
  373. FOnChange( self );
  374. end;
  375. end;
  376. procedure TIpProperty.SetAsBinaryString(const Value: String);
  377. var
  378. IPStruct: TIPStruct;
  379. i: Integer;
  380. begin
  381. if ReadOnly then
  382. exit;
  383. if Length(Value) <> 32 then
  384. raise EIdException.Create(RSNETCALCInvalidValueLength) // 'Invalid value length: Should be 32.' {Do not Localize}
  385. else
  386. begin
  387. if not AnsiSameText( Value, FAsBinaryString) then
  388. begin
  389. IPStruct.FullAddr := 0;
  390. for i := 1 to 32 do
  391. begin
  392. if Value[i] <> '0' then {Do not Localize}
  393. IPStruct.FullAddr := IPStruct.FullAddr + (1 shl (32 - i));
  394. SetAll(IPStruct.Byte1, IPStruct.Byte2, IPStruct.Byte3, IPStruct.Byte4);
  395. end;
  396. end;
  397. end;
  398. end;
  399. procedure TIpProperty.SetAsDoubleWord(const Value: Cardinal);
  400. var
  401. IpStruct: TIpStruct;
  402. begin
  403. if ReadOnly then
  404. exit;
  405. IpStruct.FullAddr := value;
  406. SetAll(IpStruct.Byte1, IpStruct.Byte2, IpStruct.Byte3, IpStruct.Byte4);
  407. end;
  408. procedure TIpProperty.SetAsString(const Value: String);
  409. var
  410. IPStruct: TIPStruct;
  411. begin
  412. if ReadOnly then
  413. exit;
  414. IPStruct := StrToIP(value);
  415. SetAll(IPStruct.Byte1, IPStruct.Byte2, IPStruct.Byte3, IPStruct.Byte4);
  416. end;
  417. procedure TIpProperty.SetByteArray(Index: cardinal; const Value: boolean);
  418. var
  419. IPStruct: TIpStruct;
  420. begin
  421. if ReadOnly then
  422. exit;
  423. if FByteArray[Index] <> value then
  424. begin
  425. FByteArray[Index] := Value;
  426. IPStruct.FullAddr := FDoubleWordValue;
  427. if Value then
  428. IPStruct.FullAddr := IPStruct.FullAddr + (1 shl index)
  429. else
  430. IPStruct.FullAddr := IPStruct.FullAddr - (1 shl index);
  431. SetAll(IPStruct.Byte1, IPStruct.Byte2, IPStruct.Byte3, IPStruct.Byte4);
  432. end;
  433. end;
  434. procedure TIpProperty.SetByte4(const Value: Byte);
  435. begin
  436. if ReadOnly then
  437. exit;
  438. if FByte4 <> value then
  439. begin
  440. FByte4 := Value;
  441. SetAll(FByte1, FByte2, FByte3, FByte4);
  442. end;
  443. end;
  444. procedure TIpProperty.SetByte1(const Value: byte);
  445. begin
  446. if FByte1 <> value then
  447. begin
  448. FByte1 := Value;
  449. SetAll(FByte1, FByte2, FByte3, FByte4);
  450. end;
  451. end;
  452. procedure TIpProperty.SetByte3(const Value: Byte);
  453. begin
  454. if FByte3 <> value then
  455. begin
  456. FByte3 := Value;
  457. SetAll(FByte1, FByte2, FByte3, FByte4);
  458. end;
  459. end;
  460. procedure TIpProperty.SetByte2(const Value: Byte);
  461. begin
  462. if ReadOnly then
  463. exit;
  464. if FByte2 <> value then
  465. begin
  466. FByte2 := Value;
  467. SetAll(FByte1, FByte2, FByte3, FByte4);
  468. end;
  469. end;
  470. procedure TIpProperty.SetOnChange(const Value: TNotifyEvent);
  471. begin
  472. FOnChange := Value;
  473. end;
  474. procedure TIpProperty.SetReadOnly(const Value: boolean);
  475. begin
  476. FReadOnly := Value;
  477. end;
  478. function TIdNetworkCalculator.EndIP: String;
  479. var
  480. IP: TIpStruct;
  481. begin
  482. IP.FullAddr := NetworkAddress.AsDoubleWord AND NetworkMask.AsDoubleWord;
  483. Inc(IP.FullAddr, NumIP - 1);
  484. result := Format('%d.%d.%d.%d', [IP.Byte1, IP.Byte2, IP.Byte3, IP.Byte4]); {Do not Localize}
  485. end;
  486. function TIdNetworkCalculator.NumIP: integer;
  487. begin
  488. NumIP := 1 shl (32 - NetworkMaskLength);
  489. end;
  490. function TIdNetworkCalculator.StartIP: String;
  491. var
  492. IP: TIpStruct;
  493. begin
  494. IP.FullAddr := NetworkAddress.AsDoubleWord AND NetworkMask.AsDoubleWord;
  495. result := Format('%d.%d.%d.%d', [IP.Byte1, IP.Byte2, IP.Byte3, IP.Byte4]); {Do not Localize}
  496. end;
  497. function TIpProperty.GetAddressType: TIdIPAddressType;
  498. // based on http://www.ora.com/reference/dictionary/terms/I/IP_Address.htm
  499. begin
  500. Result := IPInternetHost;
  501. case FByte1 of
  502. {localhost or local network}
  503. 0 : if AsDoubleWord = 0 then
  504. begin
  505. Result := IPLocalHost;
  506. end
  507. else
  508. begin
  509. Result := IPLocalNetwork;
  510. end;
  511. {Private network allocations}
  512. 10 : Result := IPPrivateNetwork;
  513. 172 : if Byte2 = 16 then
  514. begin
  515. Result := IPPrivateNetwork;
  516. end;
  517. 192 : if Byte2 = 68 then
  518. begin
  519. Result := IPPrivateNetwork;
  520. end
  521. else
  522. begin
  523. if (Byte2 = 0) and (Byte3 = 0) then
  524. begin
  525. Result := IPReserved;
  526. end;
  527. end;
  528. {loopback}
  529. 127 : Result := IPLoopback;
  530. 255 : if AsDoubleWord = $FFFFFFFF then
  531. begin
  532. Result := IPGlobalBroadcast;
  533. end
  534. else
  535. begin
  536. Result := IPFutureUse;
  537. end;
  538. {Reserved}
  539. 128 : if Byte2 = 0 then
  540. begin
  541. Result := IPReserved;
  542. end;
  543. 191 : if (Byte2 = 255) and (Byte3 = 255) then
  544. begin
  545. Result := IPReserved;
  546. end;
  547. 223 : if (Byte2 = 255) and (Byte3 = 255) then
  548. begin
  549. Result := IPReserved;
  550. end;
  551. end;
  552. {Multicast}
  553. if (Byte1 >= 224) and (Byte1 <= 239) then
  554. begin
  555. Result := IPMulticast;
  556. end;
  557. {Future Use}
  558. if (Byte1 >= 240) and (Byte1 <= 254) then
  559. begin
  560. Result := IPFutureUse;
  561. end;
  562. end;
  563. end.